git.iko.soy/purestack-dev/purescript-plum
on master help sign in
10 files changed+777−2969
since splitsnapshots
unifiedsplit
.gitignore+1 plum/index.js−1893 plum/spago.dhall+9 plum/src/Main.purs+44−8 plum/src/Maquette.js−953 plum/src/Maquette.purs−33 plum/src/Plum.purs+61−17 plum/src/Plum/View.purs+616−65 plum/src/Snabbdom.js+1 plum/src/Snabbdom.purs+45
.gitignore+1
@@ -8,3 +8,4 @@
88/.purs*
99/.psa*
1010/.spago
11+plum/index.js
plum/index.jsdeleted−1893
@@ -1,1893 +0,0 @@
1−(() => {
2− // output/Data.Function/index.js
3− var flip = function(f) {
4− return function(b) {
5− return function(a) {
6− return f(a)(b);
7− };
8− };
9− };
10− var $$const = function(a) {
11− return function(v) {
12− return a;
13− };
14− };
15−
16− // output/Data.Functor/foreign.js
17− var arrayMap = function(f) {
18− return function(arr) {
19− var l = arr.length;
20− var result = new Array(l);
21− for (var i = 0; i < l; i++) {
22− result[i] = f(arr[i]);
23− }
24− return result;
25− };
26− };
27−
28− // output/Data.Unit/foreign.js
29− var unit = void 0;
30−
31− // output/Data.Functor/index.js
32− var map = function(dict) {
33− return dict.map;
34− };
35− var functorArray = {
36− map: arrayMap
37− };
38−
39− // output/Control.Apply/index.js
40− var apply = function(dict) {
41− return dict.apply;
42− };
43−
44− // output/Control.Applicative/index.js
45− var pure = function(dict) {
46− return dict.pure;
47− };
48− var liftA1 = function(dictApplicative) {
49− var apply2 = apply(dictApplicative.Apply0());
50− var pure1 = pure(dictApplicative);
51− return function(f) {
52− return function(a) {
53− return apply2(pure1(f))(a);
54− };
55− };
56− };
57−
58− // output/Data.Array/foreign.js
59− var rangeImpl = function(start2, end) {
60− var step2 = start2 > end ? -1 : 1;
61− var result = new Array(step2 * (end - start2) + 1);
62− var i = start2, n = 0;
63− while (i !== end) {
64− result[n++] = i;
65− i += step2;
66− }
67− result[n] = i;
68− return result;
69− };
70− var replicateFill = function(count, value12) {
71− if (count < 1) {
72− return [];
73− }
74− var result = new Array(count);
75− return result.fill(value12);
76− };
77− var replicatePolyfill = function(count, value12) {
78− var result = [];
79− var n = 0;
80− for (var i = 0; i < count; i++) {
81− result[n++] = value12;
82− }
83− return result;
84− };
85− var replicateImpl = typeof Array.prototype.fill === "function" ? replicateFill : replicatePolyfill;
86−
87− // output/Data.Semigroup/foreign.js
88− var concatArray = function(xs) {
89− return function(ys) {
90− if (xs.length === 0) return ys;
91− if (ys.length === 0) return xs;
92− return xs.concat(ys);
93− };
94− };
95−
96− // output/Data.Semigroup/index.js
97− var semigroupArray = {
98− append: concatArray
99− };
100− var append = function(dict) {
101− return dict.append;
102− };
103−
104− // output/Control.Bind/foreign.js
105− var arrayBind = typeof Array.prototype.flatMap === "function" ? function(arr) {
106− return function(f) {
107− return arr.flatMap(f);
108− };
109− } : function(arr) {
110− return function(f) {
111− var result = [];
112− var l = arr.length;
113− for (var i = 0; i < l; i++) {
114− var xs = f(arr[i]);
115− var k = xs.length;
116− for (var j = 0; j < k; j++) {
117− result.push(xs[j]);
118− }
119− }
120− return result;
121− };
122− };
123−
124− // output/Control.Bind/index.js
125− var bind = function(dict) {
126− return dict.bind;
127− };
128− var bindFlipped = function(dictBind) {
129− return flip(bind(dictBind));
130− };
131−
132− // output/Control.Monad/index.js
133− var ap = function(dictMonad) {
134− var bind3 = bind(dictMonad.Bind1());
135− var pure3 = pure(dictMonad.Applicative0());
136− return function(f) {
137− return function(a) {
138− return bind3(f)(function(f$prime) {
139− return bind3(a)(function(a$prime) {
140− return pure3(f$prime(a$prime));
141− });
142− });
143− };
144− };
145− };
146−
147− // output/Data.Bounded/foreign.js
148− var topChar = String.fromCharCode(65535);
149− var bottomChar = String.fromCharCode(0);
150− var topNumber = Number.POSITIVE_INFINITY;
151− var bottomNumber = Number.NEGATIVE_INFINITY;
152−
153− // output/Data.Show/foreign.js
154− var showIntImpl = function(n) {
155− return n.toString();
156− };
157−
158− // output/Data.Show/index.js
159− var showInt = {
160− show: showIntImpl
161− };
162− var show = function(dict) {
163− return dict.show;
164− };
165−
166− // output/Data.Maybe/index.js
167− var Nothing = /* @__PURE__ */ function() {
168− function Nothing2() {
169− }
170− ;
171− Nothing2.value = new Nothing2();
172− return Nothing2;
173− }();
174− var Just = /* @__PURE__ */ function() {
175− function Just2(value0) {
176− this.value0 = value0;
177− }
178− ;
179− Just2.create = function(value0) {
180− return new Just2(value0);
181− };
182− return Just2;
183− }();
184−
185− // output/Data.Monoid/index.js
186− var monoidArray = {
187− mempty: [],
188− Semigroup0: function() {
189− return semigroupArray;
190− }
191− };
192− var mempty = function(dict) {
193− return dict.mempty;
194− };
195−
196− // output/Effect/foreign.js
197− var pureE = function(a) {
198− return function() {
199− return a;
200− };
201− };
202− var bindE = function(a) {
203− return function(f) {
204− return function() {
205− return f(a())();
206− };
207− };
208− };
209−
210− // output/Effect/index.js
211− var $runtime_lazy = function(name14, moduleName, init) {
212− var state2 = 0;
213− var val;
214− return function(lineNumber) {
215− if (state2 === 2) return val;
216− if (state2 === 1) throw new ReferenceError(name14 + " was needed before it finished initializing (module " + moduleName + ", line " + lineNumber + ")", moduleName, lineNumber);
217− state2 = 1;
218− val = init();
219− state2 = 2;
220− return val;
221− };
222− };
223− var monadEffect = {
224− Applicative0: function() {
225− return applicativeEffect;
226− },
227− Bind1: function() {
228− return bindEffect;
229− }
230− };
231− var bindEffect = {
232− bind: bindE,
233− Apply0: function() {
234− return $lazy_applyEffect(0);
235− }
236− };
237− var applicativeEffect = {
238− pure: pureE,
239− Apply0: function() {
240− return $lazy_applyEffect(0);
241− }
242− };
243− var $lazy_functorEffect = /* @__PURE__ */ $runtime_lazy("functorEffect", "Effect", function() {
244− return {
245− map: liftA1(applicativeEffect)
246− };
247− });
248− var $lazy_applyEffect = /* @__PURE__ */ $runtime_lazy("applyEffect", "Effect", function() {
249− return {
250− apply: ap(monadEffect),
251− Functor0: function() {
252− return $lazy_functorEffect(0);
253− }
254− };
255− });
256− var functorEffect = /* @__PURE__ */ $lazy_functorEffect(20);
257−
258− // output/Effect.Ref/foreign.js
259− var _new = function(val) {
260− return function() {
261− return { value: val };
262− };
263− };
264− var read = function(ref) {
265− return function() {
266− return ref.value;
267− };
268− };
269− var write = function(val) {
270− return function(ref) {
271− return function() {
272− ref.value = val;
273− };
274− };
275− };
276−
277− // output/Effect.Ref/index.js
278− var $$new = _new;
279−
280− // output/Control.Monad.ST.Internal/foreign.js
281− var map_ = function(f) {
282− return function(a) {
283− return function() {
284− return f(a());
285− };
286− };
287− };
288− var pure_ = function(a) {
289− return function() {
290− return a;
291− };
292− };
293− var bind_ = function(a) {
294− return function(f) {
295− return function() {
296− return f(a())();
297− };
298− };
299− };
300−
301− // output/Control.Monad.ST.Internal/index.js
302− var $runtime_lazy2 = function(name14, moduleName, init) {
303− var state2 = 0;
304− var val;
305− return function(lineNumber) {
306− if (state2 === 2) return val;
307− if (state2 === 1) throw new ReferenceError(name14 + " was needed before it finished initializing (module " + moduleName + ", line " + lineNumber + ")", moduleName, lineNumber);
308− state2 = 1;
309− val = init();
310− state2 = 2;
311− return val;
312− };
313− };
314− var functorST = {
315− map: map_
316− };
317− var monadST = {
318− Applicative0: function() {
319− return applicativeST;
320− },
321− Bind1: function() {
322− return bindST;
323− }
324− };
325− var bindST = {
326− bind: bind_,
327− Apply0: function() {
328− return $lazy_applyST(0);
329− }
330− };
331− var applicativeST = {
332− pure: pure_,
333− Apply0: function() {
334− return $lazy_applyST(0);
335− }
336− };
337− var $lazy_applyST = /* @__PURE__ */ $runtime_lazy2("applyST", "Control.Monad.ST.Internal", function() {
338− return {
339− apply: ap(monadST),
340− Functor0: function() {
341− return functorST;
342− }
343− };
344− });
345−
346− // output/Data.Foldable/foreign.js
347− var foldrArray = function(f) {
348− return function(init) {
349− return function(xs) {
350− var acc = init;
351− var len = xs.length;
352− for (var i = len - 1; i >= 0; i--) {
353− acc = f(xs[i])(acc);
354− }
355− return acc;
356− };
357− };
358− };
359− var foldlArray = function(f) {
360− return function(init) {
361− return function(xs) {
362− var acc = init;
363− var len = xs.length;
364− for (var i = 0; i < len; i++) {
365− acc = f(acc)(xs[i]);
366− }
367− return acc;
368− };
369− };
370− };
371−
372− // output/Data.Tuple/index.js
373− var Tuple = /* @__PURE__ */ function() {
374− function Tuple2(value0, value1) {
375− this.value0 = value0;
376− this.value1 = value1;
377− }
378− ;
379− Tuple2.create = function(value0) {
380− return function(value1) {
381− return new Tuple2(value0, value1);
382− };
383− };
384− return Tuple2;
385− }();
386−
387− // output/Unsafe.Coerce/foreign.js
388− var unsafeCoerce2 = function(x) {
389− return x;
390− };
391−
392− // output/Data.Foldable/index.js
393− var foldr = function(dict) {
394− return dict.foldr;
395− };
396− var foldMapDefaultR = function(dictFoldable) {
397− var foldr2 = foldr(dictFoldable);
398− return function(dictMonoid) {
399− var append3 = append(dictMonoid.Semigroup0());
400− var mempty3 = mempty(dictMonoid);
401− return function(f) {
402− return foldr2(function(x) {
403− return function(acc) {
404− return append3(f(x))(acc);
405− };
406− })(mempty3);
407− };
408− };
409− };
410− var foldableArray = {
411− foldr: foldrArray,
412− foldl: foldlArray,
413− foldMap: function(dictMonoid) {
414− return foldMapDefaultR(foldableArray)(dictMonoid);
415− }
416− };
417− var foldMap = function(dict) {
418− return dict.foldMap;
419− };
420−
421− // output/Data.Function.Uncurried/foreign.js
422− var runFn2 = function(fn) {
423− return function(a) {
424− return function(b) {
425− return fn(a, b);
426− };
427− };
428− };
429−
430− // output/Data.Array/index.js
431− var foldMap1 = /* @__PURE__ */ foldMap(foldableArray);
432− var range2 = /* @__PURE__ */ runFn2(rangeImpl);
433− var foldMap2 = function(dictMonoid) {
434− return foldMap1(dictMonoid);
435− };
436−
437− // output/Maquette/foreign.js
438− var NAMESPACE_W3 = "http://www.w3.org/";
439− var NAMESPACE_SVG = NAMESPACE_W3 + "2000/svg";
440− var NAMESPACE_XLINK = NAMESPACE_W3 + "1999/xlink";
441− var emptyArray = [];
442− var extend2 = function(base, overrides) {
443− var result = {};
444− Object.keys(base).forEach(function(key) {
445− result[key] = base[key];
446− });
447− if (overrides) {
448− Object.keys(overrides).forEach(function(key) {
449− result[key] = overrides[key];
450− });
451− }
452− return result;
453− };
454− var same = function(vnode1, vnode2) {
455− if (vnode1.vnodeSelector !== vnode2.vnodeSelector) {
456− return false;
457− }
458− if (vnode1.properties && vnode2.properties) {
459− if (vnode1.properties.key !== vnode2.properties.key) {
460− return false;
461− }
462− return vnode1.properties.bind === vnode2.properties.bind;
463− }
464− return !vnode1.properties && !vnode2.properties;
465− };
466− var checkStyleValue = function(styleValue) {
467− if (typeof styleValue !== "string") {
468− throw new Error("Style values must be strings");
469− }
470− };
471− var findIndexOfChild = function(children, sameAs, start2) {
472− if (sameAs.vnodeSelector !== "") {
473− for (var i = start2; i < children.length; i++) {
474− if (same(children[i], sameAs)) {
475− return i;
476− }
477− }
478− }
479− return -1;
480− };
481− var checkDistinguishable = function(childNodes, indexToCheck, parentVNode, operation) {
482− var childNode = childNodes[indexToCheck];
483− if (childNode.vnodeSelector === "") {
484− return;
485− }
486− var properties = childNode.properties;
487− var key = properties ? properties.key === void 0 ? properties.bind : properties.key : void 0;
488− if (!key) {
489− for (var i = 0; i < childNodes.length; i++) {
490− if (i !== indexToCheck) {
491− var node = childNodes[i];
492− if (same(node, childNode)) {
493− throw {
494− 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."),
495− parentNode: parentVNode,
496− childNode
497− };
498− }
499− }
500− }
501− }
502− };
503− var nodeAdded = function(vNode) {
504− if (vNode.properties) {
505− var enterAnimation = vNode.properties.enterAnimation;
506− if (enterAnimation) {
507− enterAnimation(vNode.domNode, vNode.properties);
508− }
509− }
510− };
511− var removedNodes = [];
512− var requestedIdleCallback = false;
513− var visitRemovedNode = function(node) {
514− (node.children || []).forEach(visitRemovedNode);
515− if (node.properties && node.properties.afterRemoved) {
516− node.properties.afterRemoved.apply(node.properties.bind || node.properties, [
517− node.domNode
518− ]);
519− }
520− };
521− var processPendingNodeRemovals = function() {
522− requestedIdleCallback = false;
523− removedNodes.forEach(visitRemovedNode);
524− removedNodes.length = 0;
525− };
526− var scheduleNodeRemoval = function(vNode) {
527− removedNodes.push(vNode);
528− if (!requestedIdleCallback) {
529− requestedIdleCallback = true;
530− if (typeof window !== "undefined" && "requestIdleCallback" in window) {
531− window.requestIdleCallback(processPendingNodeRemovals, { timeout: 16 });
532− } else {
533− setTimeout(processPendingNodeRemovals, 16);
534− }
535− }
536− };
537− var nodeToRemove = function(vNode) {
538− var domNode = vNode.domNode;
539− if (vNode.properties) {
540− var exitAnimation = vNode.properties.exitAnimation;
541− if (exitAnimation) {
542− domNode.style.pointerEvents = "none";
543− var removeDomNode = function() {
544− if (domNode.parentNode) {
545− domNode.parentNode.removeChild(domNode);
546− scheduleNodeRemoval(vNode);
547− }
548− };
549− exitAnimation(domNode, removeDomNode, vNode.properties);
550− return;
551− }
552− }
553− if (domNode.parentNode) {
554− domNode.parentNode.removeChild(domNode);
555− scheduleNodeRemoval(vNode);
556− }
557− };
558− var vnodeOnlyProps = [
559− "afterCreate",
560− "afterUpdate",
561− "afterRemoved",
562− "enterAnimation",
563− "exitAnimation",
564− "updateAnimation"
565− ];
566− function filterVNodeOnlyProps(name14) {
567− return !vnodeOnlyProps.includes(name14);
568− }
569− var setProperties = function(domNode, properties, projectionOptions) {
570− if (!properties) {
571− return;
572− }
573− var eventHandlerInterceptor = projectionOptions.eventHandlerInterceptor;
574− var propNames = Object.keys(properties).filter(filterVNodeOnlyProps);
575− var propCount = propNames.length;
576− for (var i = 0; i < propCount; i++) {
577− var propName = propNames[i];
578− var propValue = properties[propName];
579− if (propName === "className") {
580− throw new Error('Property "className" is not supported, use "class".');
581− } else if (propName === "class") {
582− toggleClasses(domNode, propValue, true);
583− } else if (propName === "classes") {
584− var classNames = Object.keys(propValue);
585− var classNameCount = classNames.length;
586− for (var j = 0; j < classNameCount; j++) {
587− var className = classNames[j];
588− if (propValue[className]) {
589− domNode.classList.add(className);
590− }
591− }
592− } else if (propName === "styles") {
593− var styleNames = Object.keys(propValue);
594− var styleCount = styleNames.length;
595− for (var j = 0; j < styleCount; j++) {
596− var styleName = styleNames[j];
597− var styleValue = propValue[styleName];
598− if (styleValue) {
599− checkStyleValue(styleValue);
600− projectionOptions.styleApplyer(domNode, styleName, styleValue);
601− }
602− }
603− } else if (propName === "on" && propValue) {
604− for (var _i = 0, _a = Object.entries(properties.on); _i < _a.length; _i++) {
605− var _b = _a[_i], key = _b[0], handler = _b[1];
606− var listener = typeof handler === "function" ? handler : handler.listener;
607− if (eventHandlerInterceptor) {
608− listener = eventHandlerInterceptor(key, listener, domNode, properties);
609− }
610− if (listener) {
611− domNode.addEventListener(key, listener, typeof handler === "function" ? void 0 : handler.options);
612− }
613− }
614− } else if (propName !== "key" && propValue !== null && propValue !== void 0) {
615− var type = typeof propValue;
616− if (type === "function") {
617− if (propName.lastIndexOf("on", 0) === 0) {
618− if (eventHandlerInterceptor) {
619− propValue = eventHandlerInterceptor(propName, propValue, domNode, properties);
620− }
621− }
622− domNode[propName] = propValue;
623− } else if (projectionOptions.namespace === NAMESPACE_SVG) {
624− if (propName === "href") {
625− domNode.setAttributeNS(NAMESPACE_XLINK, propName, propValue);
626− } else {
627− domNode.setAttribute(propName, propValue);
628− }
629− } else if (type === "string" && propName !== "value" && propName !== "innerHTML") {
630− domNode.setAttribute(propName, propValue);
631− } else {
632− domNode[propName] = propValue;
633− }
634− }
635− }
636− };
637− var addChildren = function(domNode, children, projectionOptions) {
638− if (!children) {
639− return;
640− }
641− for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {
642− var child = children_1[_i];
643− createDom(child, domNode, void 0, projectionOptions);
644− }
645− };
646− var initPropertiesAndChildren = function(domNode, vnode, projectionOptions) {
647− addChildren(domNode, vnode.children, projectionOptions);
648− if (vnode.text) {
649− domNode.textContent = vnode.text;
650− }
651− setProperties(domNode, vnode.properties, projectionOptions);
652− if (vnode.properties && vnode.properties.afterCreate) {
653− vnode.properties.afterCreate.apply(vnode.properties.bind || vnode.properties, [
654− domNode,
655− projectionOptions,
656− vnode.vnodeSelector,
657− vnode.properties,
658− vnode.children
659− ]);
660− }
661− };
662− var createDom = function(vnode, parentNode, insertBefore, projectionOptions) {
663− var _a;
664− var domNode;
665− var start2 = 0;
666− var vnodeSelector = vnode.vnodeSelector;
667− var doc = parentNode.ownerDocument;
668− if (vnodeSelector === "") {
669− if (vnode.domNode) {
670− vnode.domNode.nodeValue = vnode.text;
671− } else {
672− domNode = vnode.domNode = doc.createTextNode(vnode.text);
673− if (insertBefore !== void 0) {
674− parentNode.insertBefore(domNode, insertBefore);
675− } else {
676− parentNode.appendChild(domNode);
677− }
678− }
679− } else {
680− for (var i = 0; i <= vnodeSelector.length; ++i) {
681− var c = vnodeSelector.charAt(i);
682− if (i === vnodeSelector.length || c === "." || c === "#") {
683− var type = vnodeSelector.charAt(start2 - 1);
684− var found = vnodeSelector.slice(start2, i);
685− if (type === ".") {
686− domNode.classList.add(found);
687− } else if (type === "#") {
688− domNode.id = found;
689− } else {
690− if (found === "svg") {
691− projectionOptions = extend2(projectionOptions, {
692− namespace: NAMESPACE_SVG
693− });
694− }
695− if (projectionOptions.namespace !== void 0) {
696− domNode = vnode.domNode = doc.createElementNS(projectionOptions.namespace, found);
697− } else {
698− 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));
699− if (found === "input" && vnode.properties && vnode.properties.type !== void 0) {
700− domNode.setAttribute("type", vnode.properties.type);
701− }
702− }
703− if (insertBefore !== void 0) {
704− parentNode.insertBefore(domNode, insertBefore);
705− } else if (domNode.parentNode !== parentNode) {
706− parentNode.appendChild(domNode);
707− }
708− }
709− start2 = i + 1;
710− }
711− }
712− initPropertiesAndChildren(domNode, vnode, projectionOptions);
713− }
714− };
715− var updateDom;
716− var toggleClasses = function(domNode, classes, on2) {
717− if (!classes) {
718− return;
719− }
720− classes.split(" ").forEach(function(classToToggle) {
721− if (classToToggle) {
722− domNode.classList.toggle(classToToggle, on2);
723− }
724− });
725− };
726− var updateProperties = function(domNode, previousProperties, properties, projectionOptions) {
727− if (!properties) {
728− return;
729− }
730− var propertiesUpdated = false;
731− var propNames = Object.keys(properties).filter(filterVNodeOnlyProps);
732− var propCount = propNames.length;
733− for (var i = 0; i < propCount; i++) {
734− var propName = propNames[i];
735− var propValue = properties[propName];
736− var previousValue = previousProperties[propName];
737− if (propName === "class") {
738− if (previousValue !== propValue) {
739− toggleClasses(domNode, previousValue, false);
740− toggleClasses(domNode, propValue, true);
741− }
742− } else if (propName === "classes") {
743− var classList = domNode.classList;
744− var classNames = Object.keys(propValue);
745− var classNameCount = classNames.length;
746− for (var j = 0; j < classNameCount; j++) {
747− var className = classNames[j];
748− var on2 = !!propValue[className];
749− var previousOn = !!previousValue[className];
750− if (on2 === previousOn) {
751− continue;
752− }
753− propertiesUpdated = true;
754− if (on2) {
755− classList.add(className);
756− } else {
757− classList.remove(className);
758− }
759− }
760− } else if (propName === "styles") {
761− var styleNames = Object.keys(propValue);
762− var styleCount = styleNames.length;
763− for (var j = 0; j < styleCount; j++) {
764− var styleName = styleNames[j];
765− var newStyleValue = propValue[styleName];
766− var oldStyleValue = previousValue[styleName];
767− if (newStyleValue === oldStyleValue) {
768− continue;
769− }
770− propertiesUpdated = true;
771− if (newStyleValue) {
772− checkStyleValue(newStyleValue);
773− projectionOptions.styleApplyer(domNode, styleName, newStyleValue);
774− } else {
775− projectionOptions.styleApplyer(domNode, styleName, "");
776− }
777− }
778− } else {
779− if (!propValue && typeof previousValue === "string") {
780− propValue = "";
781− }
782− if (propName === "value") {
783− var domValue = domNode[propName];
784− if (domValue !== propValue && // The 'value' in the DOM tree !== newValue
785− propValue !== previousValue) {
786− domNode[propName] = propValue;
787− }
788− if (propValue !== previousValue) {
789− propertiesUpdated = true;
790− }
791− } else if (propValue !== previousValue) {
792− var type = typeof propValue;
793− if (type !== "function" || !projectionOptions.eventHandlerInterceptor) {
794− if (projectionOptions.namespace === NAMESPACE_SVG) {
795− if (propName === "href") {
796− domNode.setAttributeNS(NAMESPACE_XLINK, propName, propValue);
797− } else {
798− domNode.setAttribute(propName, propValue);
799− }
800− } else if (type === "string" && propName !== "innerHTML") {
801− if (propName === "role" && propValue === "") {
802− domNode.removeAttribute(propName);
803− } else {
804− domNode.setAttribute(propName, propValue);
805− }
806− } else if (domNode[propName] !== propValue) {
807− domNode[propName] = propValue;
808− }
809− propertiesUpdated = true;
810− }
811− }
812− }
813− }
814− return propertiesUpdated;
815− };
816− var updateChildren = function(vnode, domNode, oldChildren, newChildren, projectionOptions) {
817− if (oldChildren === newChildren) {
818− return false;
819− }
820− oldChildren = oldChildren || emptyArray;
821− newChildren = newChildren || emptyArray;
822− var oldChildrenLength = oldChildren.length;
823− var newChildrenLength = newChildren.length;
824− var oldIndex = 0;
825− var newIndex = 0;
826− var i;
827− var textUpdated = false;
828− while (newIndex < newChildrenLength) {
829− var oldChild = oldIndex < oldChildrenLength ? oldChildren[oldIndex] : void 0;
830− var newChild = newChildren[newIndex];
831− if (oldChild !== void 0 && same(oldChild, newChild)) {
832− textUpdated = updateDom(oldChild, newChild, projectionOptions, domNode, oldChildren) || textUpdated;
833− oldIndex++;
834− } else {
835− var findOldIndex = findIndexOfChild(oldChildren, newChild, oldIndex + 1);
836− if (findOldIndex >= 0) {
837− for (i = oldIndex; i < findOldIndex; i++) {
838− nodeToRemove(oldChildren[i]);
839− checkDistinguishable(oldChildren, i, vnode, "removed");
840− }
841− textUpdated = updateDom(oldChildren[findOldIndex], newChild, projectionOptions, domNode, oldChildren) || textUpdated;
842− oldIndex = findOldIndex + 1;
843− } else {
844− createDom(newChild, domNode, oldIndex < oldChildrenLength ? oldChildren[oldIndex].domNode : void 0, projectionOptions);
845− nodeAdded(newChild);
846− checkDistinguishable(newChildren, newIndex, vnode, "added");
847− }
848− }
849− newIndex++;
850− }
851− if (oldChildrenLength > oldIndex) {
852− for (i = oldIndex; i < oldChildrenLength; i++) {
853− nodeToRemove(oldChildren[i]);
854− checkDistinguishable(oldChildren, i, vnode, "removed");
855− }
856− }
857− return textUpdated;
858− };
859− updateDom = function(previous, vnode, projectionOptions, parentNode, oldChildren) {
860− var domNode = previous.domNode;
861− var textUpdated = false;
862− if (previous === vnode) {
863− return false;
864− }
865− var updated = false;
866− if (vnode.vnodeSelector === "") {
867− if (vnode.text !== previous.text) {
868− var newTextNode = domNode.ownerDocument.createTextNode(vnode.text);
869− try {
870− parentNode.replaceChild(newTextNode, domNode);
871− } catch (e) {
872− parentNode.replaceChild(newTextNode, parentNode.childNodes[oldChildren.indexOf(previous)]);
873− }
874− vnode.domNode = newTextNode;
875− textUpdated = true;
876− return textUpdated;
877− }
878− vnode.domNode = domNode;
879− } else {
880− if (vnode.vnodeSelector.lastIndexOf("svg", 0) === 0) {
881− projectionOptions = extend2(projectionOptions, {
882− namespace: NAMESPACE_SVG
883− });
884− }
885− if (previous.text !== vnode.text) {
886− updated = true;
887− if (vnode.text === void 0) {
888− domNode.removeChild(domNode.firstChild);
889− } else {
890− domNode.textContent = vnode.text;
891− }
892− }
893− vnode.domNode = domNode;
894− updated = updateChildren(vnode, domNode, previous.children, vnode.children, projectionOptions) || updated;
895− updated = updateProperties(domNode, previous.properties, vnode.properties, projectionOptions) || updated;
896− if (vnode.properties && vnode.properties.afterUpdate) {
897− vnode.properties.afterUpdate.apply(vnode.properties.bind || vnode.properties, [
898− domNode,
899− projectionOptions,
900− vnode.vnodeSelector,
901− vnode.properties,
902− vnode.children
903− ]);
904− }
905− }
906− if (updated && vnode.properties && vnode.properties.updateAnimation) {
907− vnode.properties.updateAnimation(domNode, vnode.properties, previous.properties);
908− }
909− return textUpdated;
910− };
911− var createProjection = function(vnode, projectionOptions) {
912− return {
913− getLastRender: function() {
914− return vnode;
915− },
916− update: function(updatedVnode) {
917− if (vnode.vnodeSelector !== updatedVnode.vnodeSelector) {
918− 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)");
919− }
920− var previousVNode = vnode;
921− vnode = updatedVnode;
922− updateDom(previousVNode, updatedVnode, projectionOptions, previousVNode.domNode.parentNode, [previousVNode]);
923− },
924− domNode: vnode.domNode
925− };
926− };
927− var DEFAULT_PROJECTION_OPTIONS = {
928− namespace: void 0,
929− performanceLogger: function() {
930− return void 0;
931− },
932− eventHandlerInterceptor: void 0,
933− styleApplyer: function(domNode, styleName, value12) {
934− if (styleName.charAt(0) === "-") {
935− domNode.style.setProperty(styleName, value12);
936− } else {
937− domNode.style[styleName] = value12;
938− }
939− }
940− };
941− var applyDefaultProjectionOptions = function(projectorOptions) {
942− return extend2(DEFAULT_PROJECTION_OPTIONS, projectorOptions);
943− };
944− var dom = {
945− /**
946− * Creates a real DOM tree from `vnode`. The [[Projection]] object returned will contain the resulting DOM Node in
947− * its [[Projection.domNode|domNode]] property.
948− * This is a low-level method. Users will typically use a [[Projector]] instead.
949− * @param vnode - The root of the virtual DOM tree that was created using the [[h]] function. NOTE: [[VNode]]
950− * objects may only be rendered once.
951− * @param projectionOptions - Options to be used to create and update the projection.
952− * @returns The [[Projection]] which also contains the DOM Node that was created.
953− */
954− create: function(vnode, projectionOptions) {
955− projectionOptions = applyDefaultProjectionOptions(projectionOptions);
956− createDom(vnode, document.createElement("div"), void 0, projectionOptions);
957− return createProjection(vnode, projectionOptions);
958− },
959− /**
960− * Appends a new child node to the DOM which is generated from a [[VNode]].
961− * This is a low-level method. Users will typically use a [[Projector]] instead.
962− * @param parentNode - The parent node for the new child node.
963− * @param vnode - The root of the virtual DOM tree that was created using the [[h]] function. NOTE: [[VNode]]
964− * objects may only be rendered once.
965− * @param projectionOptions - Options to be used to create and update the [[Projection]].
966− * @returns The [[Projection]] that was created.
967− */
968− append: function(parentNode, vnode, projectionOptions) {
969− projectionOptions = applyDefaultProjectionOptions(projectionOptions);
970− createDom(vnode, parentNode, void 0, projectionOptions);
971− return createProjection(vnode, projectionOptions);
972− },
973− /**
974− * Inserts a new DOM node which is generated from a [[VNode]].
975− * This is a low-level method. Users wil typically use a [[Projector]] instead.
976− * @param beforeNode - The node that the DOM Node is inserted before.
977− * @param vnode - The root of the virtual DOM tree that was created using the [[h]] function.
978− * NOTE: [[VNode]] objects may only be rendered once.
979− * @param projectionOptions - Options to be used to create and update the projection, see [[createProjector]].
980− * @returns The [[Projection]] that was created.
981− */
982− insertBefore: function(beforeNode, vnode, projectionOptions) {
983− projectionOptions = applyDefaultProjectionOptions(projectionOptions);
984− createDom(vnode, beforeNode.parentNode, beforeNode, projectionOptions);
985− return createProjection(vnode, projectionOptions);
986− },
987− /**
988− * Merges a new DOM node which is generated from a [[VNode]] with an existing DOM Node.
989− * This means that the virtual DOM and the real DOM will have one overlapping element.
990− * Therefore the selector for the root [[VNode]] will be ignored, but its properties and children will be applied to the Element provided.
991− * This is a low-level method. Users wil typically use a [[Projector]] instead.
992− * @param element - The existing element to adopt as the root of the new virtual DOM. Existing attributes and child nodes are preserved.
993− * @param vnode - The root of the virtual DOM tree that was created using the [[h]] function. NOTE: [[VNode]] objects
994− * may only be rendered once.
995− * @param projectionOptions - Options to be used to create and update the projection, see [[createProjector]].
996− * @returns The [[Projection]] that was created.
997− */
998− merge: function(element, vnode, projectionOptions) {
999− projectionOptions = applyDefaultProjectionOptions(projectionOptions);
1000− vnode.domNode = element;
1001− initPropertiesAndChildren(element, vnode, projectionOptions);
1002− return createProjection(vnode, projectionOptions);
1003− },
1004− /**
1005− * Replaces an existing DOM node with a node generated from a [[VNode]].
1006− * This is a low-level method. Users will typically use a [[Projector]] instead.
1007− * @param element - The node for the [[VNode]] to replace.
1008− * @param vnode - The root of the virtual DOM tree that was created using the [[h]] function. NOTE: [[VNode]]
1009− * objects may only be rendered once.
1010− * @param projectionOptions - Options to be used to create and update the [[Projection]].
1011− * @returns The [[Projection]] that was created.
1012− */
1013− replace: function(element, vnode, projectionOptions) {
1014− projectionOptions = applyDefaultProjectionOptions(projectionOptions);
1015− createDom(vnode, element.parentNode, element, projectionOptions);
1016− element.parentNode.removeChild(element);
1017− return createProjection(vnode, projectionOptions);
1018− }
1019− };
1020− var toTextVNode = function(data) {
1021− return {
1022− vnodeSelector: "",
1023− properties: void 0,
1024− children: void 0,
1025− text: data.toString(),
1026− domNode: null
1027− };
1028− };
1029− var appendChildren = function(parentSelector, insertions, main2) {
1030− for (var i = 0, length_1 = insertions.length; i < length_1; i++) {
1031− var item = insertions[i];
1032− if (Array.isArray(item)) {
1033− appendChildren(parentSelector, item, main2);
1034− } else {
1035− if (item !== null && item !== void 0 && item !== false) {
1036− if (typeof item === "string") {
1037− item = toTextVNode(item);
1038− }
1039− main2.push(item);
1040− }
1041− }
1042− }
1043− };
1044− function h(selector, properties, children) {
1045− if (Array.isArray(properties)) {
1046− children = properties;
1047− properties = void 0;
1048− } else if (properties && (typeof properties === "string" || properties.vnodeSelector) || children && (typeof children === "string" || children.vnodeSelector)) {
1049− throw new Error("h called with invalid arguments");
1050− }
1051− var text5;
1052− var flattenedChildren;
1053− if (children && children.length === 1 && typeof children[0] === "string") {
1054− text5 = children[0];
1055− } else if (children) {
1056− flattenedChildren = [];
1057− appendChildren(selector, children, flattenedChildren);
1058− if (flattenedChildren.length === 0) {
1059− flattenedChildren = void 0;
1060− }
1061− }
1062− return {
1063− vnodeSelector: selector,
1064− properties,
1065− children: flattenedChildren,
1066− text: text5 === "" ? void 0 : text5,
1067− domNode: null
1068− };
1069− }
1070− var createParentNodePath = function(node, rootNode) {
1071− var parentNodePath = [];
1072− while (node && node !== rootNode) {
1073− parentNodePath.push(node);
1074− node = node.parentNode;
1075− }
1076− return parentNodePath;
1077− };
1078− var find2;
1079− if (Array.prototype.find) {
1080− find2 = function(items, predicate) {
1081− return items.find(predicate);
1082− };
1083− } else {
1084− find2 = function(items, predicate) {
1085− return items.filter(predicate)[0];
1086− };
1087− }
1088− var findVNodeByParentNodePath = function(vnode, parentNodePath) {
1089− var result = vnode;
1090− parentNodePath.forEach(function(node) {
1091− result = result && result.children ? find2(result.children, function(child) {
1092− return child.domNode === node;
1093− }) : void 0;
1094− });
1095− return result;
1096− };
1097− var createEventHandlerInterceptor = function(projector, getProjection, performanceLogger) {
1098− return function(propertyName, eventHandler, domNode, properties) {
1099− return modifiedEventHandler;
1100− };
1101− function modifiedEventHandler(evt) {
1102− var _a, _b;
1103− performanceLogger("domEvent", evt);
1104− var projection = getProjection();
1105− var parentNodePath = createParentNodePath(evt.currentTarget, projection.domNode);
1106− parentNodePath.reverse();
1107− var matchingVNode = findVNodeByParentNodePath(projection.getLastRender(), parentNodePath);
1108− projector.scheduleRender();
1109− var result;
1110− if (matchingVNode) {
1111− 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];
1112− result = listener.apply(matchingVNode.properties.bind || this, arguments);
1113− }
1114− performanceLogger("domEventProcessed", evt);
1115− return result;
1116− }
1117− };
1118− var createProjector = function(projectorOptions) {
1119− var projector;
1120− var projectionOptions = applyDefaultProjectionOptions(projectorOptions);
1121− var performanceLogger = projectionOptions.performanceLogger;
1122− var renderCompleted = true;
1123− var scheduled;
1124− var stopped = false;
1125− var projections = [];
1126− var renderFunctions = [];
1127− var addProjection = function(domFunction, node, renderFunction) {
1128− var projection;
1129− var getProjection = function() {
1130− return projection;
1131− };
1132− projectionOptions.eventHandlerInterceptor = createEventHandlerInterceptor(projector, getProjection, performanceLogger);
1133− projection = domFunction(node, renderFunction(), projectionOptions);
1134− projections.push(projection);
1135− renderFunctions.push(renderFunction);
1136− };
1137− var doRender = function() {
1138− scheduled = void 0;
1139− if (!renderCompleted) {
1140− return;
1141− }
1142− renderCompleted = false;
1143− performanceLogger("renderStart", void 0);
1144− for (var i = 0; i < projections.length; i++) {
1145− var updatedVnode = renderFunctions[i]();
1146− performanceLogger("rendered", void 0);
1147− projections[i].update(updatedVnode);
1148− performanceLogger("patched", void 0);
1149− }
1150− performanceLogger("renderDone", void 0);
1151− renderCompleted = true;
1152− };
1153− projector = {
1154− renderNow: doRender,
1155− scheduleRender: function() {
1156− if (!scheduled && !stopped) {
1157− scheduled = requestAnimationFrame(doRender);
1158− }
1159− },
1160− stop: function() {
1161− if (scheduled) {
1162− cancelAnimationFrame(scheduled);
1163− scheduled = void 0;
1164− }
1165− stopped = true;
1166− },
1167− resume: function() {
1168− stopped = false;
1169− renderCompleted = true;
1170− projector.scheduleRender();
1171− },
1172− append: function(parentNode, renderFunction) {
1173− addProjection(dom.append, parentNode, renderFunction);
1174− },
1175− insertBefore: function(beforeNode, renderFunction) {
1176− addProjection(dom.insertBefore, beforeNode, renderFunction);
1177− },
1178− merge: function(domNode, renderFunction) {
1179− addProjection(dom.merge, domNode, renderFunction);
1180− },
1181− replace: function(domNode, renderFunction) {
1182− addProjection(dom.replace, domNode, renderFunction);
1183− },
1184− detach: function(renderFunction) {
1185− for (var i = 0; i < renderFunctions.length; i++) {
1186− if (renderFunctions[i] === renderFunction) {
1187− renderFunctions.splice(i, 1);
1188− return projections.splice(i, 1)[0];
1189− }
1190− }
1191− throw new Error("renderFunction was not found");
1192− }
1193− };
1194− return projector;
1195− };
1196− function _h(selector) {
1197− return function(properties) {
1198− return function(children) {
1199− return h(selector, properties, children);
1200− };
1201− };
1202− }
1203− function replace(projector) {
1204− return function(el) {
1205− return function(render) {
1206− return function() {
1207− projector.replace(el, render);
1208− };
1209− };
1210− };
1211− }
1212−
1213− // output/Maquette/index.js
1214− var string = unsafeCoerce2;
1215− var h2 = _h;
1216−
1217− // output/Foreign.Object/foreign.js
1218− function _copyST(m) {
1219− return function() {
1220− var r = {};
1221− for (var k in m) {
1222− if (hasOwnProperty.call(m, k)) {
1223− r[k] = m[k];
1224− }
1225− }
1226− return r;
1227− };
1228− }
1229− var empty2 = {};
1230− function runST(f) {
1231− return f();
1232− }
1233− function _foldM(bind3) {
1234− return function(f) {
1235− return function(mz) {
1236− return function(m) {
1237− var acc = mz;
1238− function g(k2) {
1239− return function(z) {
1240− return f(z)(k2)(m[k2]);
1241− };
1242− }
1243− for (var k in m) {
1244− if (hasOwnProperty.call(m, k)) {
1245− acc = bind3(acc)(g(k));
1246− }
1247− }
1248− return acc;
1249− };
1250− };
1251− };
1252− }
1253− function toArrayWithKey(f) {
1254− return function(m) {
1255− var r = [];
1256− for (var k in m) {
1257− if (hasOwnProperty.call(m, k)) {
1258− r.push(f(k)(m[k]));
1259− }
1260− }
1261− return r;
1262− };
1263− }
1264− var keys = Object.keys || toArrayWithKey(function(k) {
1265− return function() {
1266− return k;
1267− };
1268− });
1269−
1270− // output/Foreign.Object.ST/foreign.js
1271− var newImpl = function() {
1272− return {};
1273− };
1274− function poke2(k) {
1275− return function(v) {
1276− return function(m) {
1277− return function() {
1278− m[k] = v;
1279− return m;
1280− };
1281− };
1282− };
1283− }
1284−
1285− // output/Foreign.Object/index.js
1286− var bindFlipped2 = /* @__PURE__ */ bindFlipped(bindST);
1287− var thawST = _copyST;
1288− var singleton2 = function(k) {
1289− return function(v) {
1290− return runST(bindFlipped2(poke2(k)(v))(newImpl));
1291− };
1292− };
1293− var mutate = function(f) {
1294− return function(m) {
1295− return runST(function __do() {
1296− var s = thawST(m)();
1297− f(s)();
1298− return s;
1299− });
1300− };
1301− };
1302− var foldM = function(dictMonad) {
1303− var bind1 = bind(dictMonad.Bind1());
1304− var pure1 = pure(dictMonad.Applicative0());
1305− return function(f) {
1306− return function(z) {
1307− return _foldM(bind1)(f)(pure1(z));
1308− };
1309− };
1310− };
1311− var foldM1 = /* @__PURE__ */ foldM(monadST);
1312− var union = function(m) {
1313− return mutate(function(s) {
1314− return foldM1(function(s$prime) {
1315− return function(k) {
1316− return function(v) {
1317− return poke2(k)(v)(s$prime);
1318− };
1319− };
1320− })(s)(m);
1321− });
1322− };
1323−
1324− // output/Plum.View/index.js
1325− var show2 = /* @__PURE__ */ show(showInt);
1326− var append1 = /* @__PURE__ */ append(semigroupArray);
1327− var mempty2 = /* @__PURE__ */ mempty(monoidArray);
1328− var map2 = /* @__PURE__ */ map(functorArray);
1329− var Px = /* @__PURE__ */ function() {
1330− function Px2(value0) {
1331− this.value0 = value0;
1332− }
1333− ;
1334− Px2.create = function(value0) {
1335− return new Px2(value0);
1336− };
1337− return Px2;
1338− }();
1339− var Fill = /* @__PURE__ */ function() {
1340− function Fill2() {
1341− }
1342− ;
1343− Fill2.value = new Fill2();
1344− return Fill2;
1345− }();
1346− var Fit = /* @__PURE__ */ function() {
1347− function Fit2() {
1348− }
1349− ;
1350− Fit2.value = new Fit2();
1351− return Fit2;
1352− }();
1353− var X = /* @__PURE__ */ function() {
1354− function X2() {
1355− }
1356− ;
1357− X2.value = new X2();
1358− return X2;
1359− }();
1360− var Y = /* @__PURE__ */ function() {
1361− function Y2() {
1362− }
1363− ;
1364− Y2.value = new Y2();
1365− return Y2;
1366− }();
1367− var Grid = /* @__PURE__ */ function() {
1368− function Grid2() {
1369− }
1370− ;
1371− Grid2.value = new Grid2();
1372− return Grid2;
1373− }();
1374− var Flexbox = /* @__PURE__ */ function() {
1375− function Flexbox2(value0) {
1376− this.value0 = value0;
1377− }
1378− ;
1379− Flexbox2.create = function(value0) {
1380− return new Flexbox2(value0);
1381− };
1382− return Flexbox2;
1383− }();
1384− var Generic = /* @__PURE__ */ function() {
1385− function Generic2() {
1386− }
1387− ;
1388− Generic2.value = new Generic2();
1389− return Generic2;
1390− }();
1391− var Span = /* @__PURE__ */ function() {
1392− function Span2() {
1393− }
1394− ;
1395− Span2.value = new Span2();
1396− return Span2;
1397− }();
1398− var Start = /* @__PURE__ */ function() {
1399− function Start2() {
1400− }
1401− ;
1402− Start2.value = new Start2();
1403− return Start2;
1404− }();
1405− var Center = /* @__PURE__ */ function() {
1406− function Center2() {
1407− }
1408− ;
1409− Center2.value = new Center2();
1410− return Center2;
1411− }();
1412− var End = /* @__PURE__ */ function() {
1413− function End2() {
1414− }
1415− ;
1416− End2.value = new End2();
1417− return End2;
1418− }();
1419− var Spacing = /* @__PURE__ */ function() {
1420− function Spacing2(value0, value1) {
1421− this.value0 = value0;
1422− this.value1 = value1;
1423− }
1424− ;
1425− Spacing2.create = function(value0) {
1426− return function(value1) {
1427− return new Spacing2(value0, value1);
1428− };
1429− };
1430− return Spacing2;
1431− }();
1432− var Explain = /* @__PURE__ */ function() {
1433− function Explain2() {
1434− }
1435− ;
1436− Explain2.value = new Explain2();
1437− return Explain2;
1438− }();
1439− var Align = /* @__PURE__ */ function() {
1440− function Align2(value0, value1) {
1441− this.value0 = value0;
1442− this.value1 = value1;
1443− }
1444− ;
1445− Align2.create = function(value0) {
1446− return function(value1) {
1447− return new Align2(value0, value1);
1448− };
1449− };
1450− return Align2;
1451− }();
1452− var Width = /* @__PURE__ */ function() {
1453− function Width2(value0) {
1454− this.value0 = value0;
1455− }
1456− ;
1457− Width2.create = function(value0) {
1458− return new Width2(value0);
1459− };
1460− return Width2;
1461− }();
1462− var Height = /* @__PURE__ */ function() {
1463− function Height2(value0) {
1464− this.value0 = value0;
1465− }
1466− ;
1467− Height2.create = function(value0) {
1468− return new Height2(value0);
1469− };
1470− return Height2;
1471− }();
1472− var Wrapped = /* @__PURE__ */ function() {
1473− function Wrapped2() {
1474− }
1475− ;
1476− Wrapped2.value = new Wrapped2();
1477− return Wrapped2;
1478− }();
1479− var Column = /* @__PURE__ */ function() {
1480− function Column2(value0) {
1481− this.value0 = value0;
1482− }
1483− ;
1484− Column2.create = function(value0) {
1485− return new Column2(value0);
1486− };
1487− return Column2;
1488− }();
1489− var Row = /* @__PURE__ */ function() {
1490− function Row2(value0) {
1491− this.value0 = value0;
1492− }
1493− ;
1494− Row2.create = function(value0) {
1495− return new Row2(value0);
1496− };
1497− return Row2;
1498− }();
1499− var Stack = /* @__PURE__ */ function() {
1500− function Stack2(value0) {
1501− this.value0 = value0;
1502− }
1503− ;
1504− Stack2.create = function(value0) {
1505− return new Stack2(value0);
1506− };
1507− return Stack2;
1508− }();
1509− var Wrapper = /* @__PURE__ */ function() {
1510− function Wrapper2(value0) {
1511− this.value0 = value0;
1512− }
1513− ;
1514− Wrapper2.create = function(value0) {
1515− return new Wrapper2(value0);
1516− };
1517− return Wrapper2;
1518− }();
1519− var Text = /* @__PURE__ */ function() {
1520− function Text2(value0) {
1521− this.value0 = value0;
1522− }
1523− ;
1524− Text2.create = function(value0) {
1525− return new Text2(value0);
1526− };
1527− return Text2;
1528− }();
1529− var semigroupSkin = {
1530− append: function(v) {
1531− return function(v1) {
1532− return union(v)(v1);
1533− };
1534− }
1535− };
1536− var append2 = /* @__PURE__ */ append(semigroupSkin);
1537− var semigroupMutation = {
1538− append: function(v) {
1539− return function(v1) {
1540− return {
1541− extraSkin: append2(v.extraSkin)(v1.extraSkin)
1542− };
1543− };
1544− }
1545− };
1546− var monoidSkin = {
1547− mempty: empty2,
1548− Semigroup0: function() {
1549− return semigroupSkin;
1550− }
1551− };
1552− var mempty1 = /* @__PURE__ */ mempty(monoidSkin);
1553− var foldMap3 = /* @__PURE__ */ foldMap2(monoidSkin);
1554− var monoidMutation = {
1555− mempty: {
1556− extraSkin: mempty1
1557− },
1558− Semigroup0: function() {
1559− return semigroupMutation;
1560− }
1561− };
1562− var mempty22 = /* @__PURE__ */ mempty(monoidMutation);
1563− var view = function(nerves) {
1564− return function(meat) {
1565− return function(bones) {
1566− return {
1567− nerves,
1568− meat,
1569− bones
1570− };
1571− };
1572− };
1573− };
1574− var sk = function(key) {
1575− return function(val) {
1576− return singleton2(key)(val);
1577− };
1578− };
1579− var length2 = function(v) {
1580− if (v instanceof Px) {
1581− return show2(v.value0) + "px";
1582− }
1583− ;
1584− if (v instanceof Fit) {
1585− return "fit-content";
1586− }
1587− ;
1588− if (v instanceof Fill) {
1589− return "100%";
1590− }
1591− ;
1592− throw new Error("Failed pattern match at Plum.View (line 99, column 10 - line 102, column 17): " + [v.constructor.name]);
1593− };
1594− var skin = function(ctx) {
1595− return function(v) {
1596− if (v instanceof Spacing) {
1597− return sk("gap")(show2(v.value0) + ("px " + (show2(v.value1) + "px")));
1598− }
1599− ;
1600− if (v instanceof Explain) {
1601− return sk("border")("dashed magenta");
1602− }
1603− ;
1604− if (v instanceof Align) {
1605− if (ctx instanceof Generic) {
1606− return mempty1;
1607− }
1608− ;
1609− if (ctx instanceof Span) {
1610− return mempty1;
1611− }
1612− ;
1613− if (ctx instanceof Grid) {
1614− return sk(function() {
1615− if (v.value0 instanceof X) {
1616− return "justify-items";
1617− }
1618− ;
1619− if (v.value0 instanceof Y) {
1620− return "align-items";
1621− }
1622− ;
1623− throw new Error("Failed pattern match at Plum.View (line 70, column 9 - line 72, column 29): " + [v.value0.constructor.name]);
1624− }())(function() {
1625− if (v.value1 instanceof Start) {
1626− return "start";
1627− }
1628− ;
1629− if (v.value1 instanceof Center) {
1630− return "center";
1631− }
1632− ;
1633− if (v.value1 instanceof End) {
1634− return "end";
1635− }
1636− ;
1637− throw new Error("Failed pattern match at Plum.View (line 74, column 9 - line 77, column 23): " + [v.value1.constructor.name]);
1638− }());
1639− }
1640− ;
1641− if (ctx instanceof Flexbox) {
1642− return sk(function() {
1643− var v1 = new Tuple(ctx.value0, v.value0);
1644− if (v1.value0 instanceof X && v1.value1 instanceof X) {
1645− return "justify-content";
1646− }
1647− ;
1648− if (v1.value0 instanceof X && v1.value1 instanceof Y) {
1649− return "align-items";
1650− }
1651− ;
1652− if (v1.value0 instanceof Y && v1.value1 instanceof X) {
1653− return "align-items";
1654− }
1655− ;
1656− if (v1.value0 instanceof Y && v1.value1 instanceof Y) {
1657− return "justify-content";
1658− }
1659− ;
1660− throw new Error("Failed pattern match at Plum.View (line 81, column 9 - line 85, column 38): " + [v1.constructor.name]);
1661− }())(function() {
1662− if (v.value1 instanceof Start) {
1663− return "flex-start";
1664− }
1665− ;
1666− if (v.value1 instanceof Center) {
1667− return "center";
1668− }
1669− ;
1670− if (v.value1 instanceof End) {
1671− return "flex-end";
1672− }
1673− ;
1674− throw new Error("Failed pattern match at Plum.View (line 87, column 9 - line 90, column 28): " + [v.value1.constructor.name]);
1675− }());
1676− }
1677− ;
1678− throw new Error("Failed pattern match at Plum.View (line 66, column 26 - line 91, column 8): " + [ctx.constructor.name]);
1679− }
1680− ;
1681− if (v instanceof Width) {
1682− return sk("width")(length2(v.value0));
1683− }
1684− ;
1685− if (v instanceof Height) {
1686− return sk("height")(length2(v.value0));
1687− }
1688− ;
1689− if (v instanceof Wrapped) {
1690− if (ctx instanceof Flexbox) {
1691− return sk("flex-wrap")("wrap");
1692− }
1693− ;
1694− return mempty1;
1695− }
1696− ;
1697− throw new Error("Failed pattern match at Plum.View (line 63, column 12 - line 96, column 16): " + [v.constructor.name]);
1698− };
1699− };
1700− var h3 = function(el) {
1701− return function(v) {
1702− return function(children) {
1703− return h2(el)({
1704− styles: v
1705− })(children);
1706− };
1707− };
1708− };
1709− var growSkin = function(fire) {
1710− return function(v) {
1711− return function(v1) {
1712− var widthFill = [new Width(Fill.value), new Height(Fill.value)];
1713− var alignCenter = [new Align(X.value, Center.value), new Align(Y.value, Center.value)];
1714− var skn = function(ctx) {
1715− return append2(foldMap3(skin(ctx))(append1(v1.meat)(append1(function() {
1716− if (ctx instanceof Span) {
1717− return mempty2;
1718− }
1719− ;
1720− if (ctx instanceof Grid) {
1721− return widthFill;
1722− }
1723− ;
1724− if (ctx instanceof Flexbox) {
1725− return widthFill;
1726− }
1727− ;
1728− if (ctx instanceof Generic) {
1729− return widthFill;
1730− }
1731− ;
1732− throw new Error("Failed pattern match at Plum.View (line 128, column 16 - line 132, column 35): " + [ctx.constructor.name]);
1733− }())(function() {
1734− if (ctx instanceof Grid) {
1735− return alignCenter;
1736− }
1737− ;
1738− if (ctx instanceof Flexbox) {
1739− return alignCenter;
1740− }
1741− ;
1742− if (ctx instanceof Span) {
1743− return mempty2;
1744− }
1745− ;
1746− if (ctx instanceof Generic) {
1747− return alignCenter;
1748− }
1749− ;
1750− throw new Error("Failed pattern match at Plum.View (line 133, column 16 - line 137, column 37): " + [ctx.constructor.name]);
1751− }()))))(v.extraSkin);
1752− };
1753− if (v1.bones instanceof Text) {
1754− return h3("span")(skn(Span.value))([string(v1.bones.value0)]);
1755− }
1756− ;
1757− if (v1.bones instanceof Wrapper) {
1758− return h3("div")(append2(skn(new Flexbox(X.value)))(append2(sk("display")("flex"))(sk("flex-direction")("row"))))([growSkin(fire)(mempty22)(v1.bones.value0)]);
1759− }
1760− ;
1761− if (v1.bones instanceof Stack) {
1762− return h3("div")(append2(skn(Grid.value))(sk("display")("grid")))(map2(growSkin(fire)({
1763− extraSkin: append2(sk("grid-row")("1"))(sk("grid-column")("1"))
1764− }))(v1.bones.value0));
1765− }
1766− ;
1767− if (v1.bones instanceof Row) {
1768− return h3("div")(append2(skn(new Flexbox(X.value)))(append2(sk("display")("flex"))(sk("flex-direction")("row"))))(map2(growSkin(fire)(mempty22))(v1.bones.value0));
1769− }
1770− ;
1771− if (v1.bones instanceof Column) {
1772− return h3("div")(append2(skn(new Flexbox(Y.value)))(append2(sk("display")("flex"))(sk("flex-direction")("column"))))(map2(growSkin(fire)(mempty22))(v1.bones.value0));
1773− }
1774− ;
1775− throw new Error("Failed pattern match at Plum.View (line 140, column 5 - line 148, column 46): " + [v1.bones.constructor.name]);
1776− };
1777− };
1778− };
1779− var grow = function(fire) {
1780− return function(v) {
1781− return growSkin(fire)(mempty22)(v);
1782− };
1783− };
1784−
1785− // output/Web.DOM.NonElementParentNode/foreign.js
1786− function _getElementById(id) {
1787− return function(node) {
1788− return function() {
1789− return node.getElementById(id);
1790− };
1791− };
1792− }
1793−
1794− // output/Data.Nullable/foreign.js
1795− function nullable(a, r, f) {
1796− return a == null ? r : f(a);
1797− }
1798−
1799− // output/Data.Nullable/index.js
1800− var toMaybe = function(n) {
1801− return nullable(n, Nothing.value, Just.create);
1802− };
1803−
1804− // output/Web.DOM.NonElementParentNode/index.js
1805− var map3 = /* @__PURE__ */ map(functorEffect);
1806− var getElementById = function(eid) {
1807− var $2 = map3(toMaybe);
1808− var $3 = _getElementById(eid);
1809− return function($4) {
1810− return $2($3($4));
1811− };
1812− };
1813−
1814− // output/Web.HTML/foreign.js
1815− var windowImpl = function() {
1816− return window;
1817− };
1818−
1819− // output/Web.HTML.HTMLDocument/index.js
1820− var toNonElementParentNode = unsafeCoerce2;
1821−
1822− // output/Web.HTML.Window/foreign.js
1823− function document2(window2) {
1824− return function() {
1825− return window2.document;
1826− };
1827− }
1828−
1829− // output/Plum/index.js
1830− var bind2 = /* @__PURE__ */ bind(bindEffect);
1831− var outerStyle = "html,body{height:100%;padding:0;margin:0;}";
1832− var run3 = function(id) {
1833− return function(plum2) {
1834− return function __do() {
1835− var modelRef = bind2(plum2.init)($$new)();
1836− var v = bind2(bind2(windowImpl)(document2))(function() {
1837− var $6 = getElementById(id);
1838− return function($7) {
1839− return $6(toNonElementParentNode($7));
1840− };
1841− }())();
1842− if (v instanceof Just) {
1843− var projector = createProjector();
1844− return replace(projector)(v.value0)(function __do2() {
1845− var model = read(modelRef)();
1846− var el = grow(function(msg) {
1847− return function __do3() {
1848− var m = read(modelRef)();
1849− var m_ = plum2.update(msg)(m)();
1850− return write(m_)(modelRef)();
1851− };
1852− })(plum2.view(model));
1853− return h2("div")({
1854− styles: {
1855− height: "100%",
1856− width: "100%"
1857− }
1858− })([el, h2("style")({})([string(outerStyle)])]);
1859− })();
1860− }
1861− ;
1862− if (v instanceof Nothing) {
1863− return unit;
1864− }
1865− ;
1866− throw new Error("Failed pattern match at Plum (line 25, column 92 - line 39, column 25): " + [v.constructor.name]);
1867− };
1868− };
1869− };
1870−
1871− // output/Main/index.js
1872− var pure2 = /* @__PURE__ */ pure(applicativeEffect);
1873− var map4 = /* @__PURE__ */ map(functorArray);
1874− var plum = {
1875− init: /* @__PURE__ */ pure2({
1876− text: "Test"
1877− }),
1878− view: function(model) {
1879− return view([])([Wrapped.value])(new Column(map4($$const(view([])([])(new Text("hello"))))(range2(1)(100))));
1880− },
1881− update: function(msg) {
1882− return function(model) {
1883− return pure2({
1884− text: "Button pressed"
1885− });
1886− };
1887− }
1888− };
1889− var main = /* @__PURE__ */ run3("plum")(plum);
1890−
1891− // <stdin>
1892− main();
1893−})();
plum/spago.dhall+9
@@ -4,18 +4,27 @@
44 , "console"
55 , "debug"
66 , "effect"
7+ , "foldable-traversable"
78 , "foreign-object"
9+ , "functions"
10+ , "integers"
11+ , "literals"
812 , "maybe"
913 , "numbers"
1014 , "prelude"
15+ , "record"
1116 , "refs"
17+ , "strings"
1218 , "strings-extra"
19+ , "transformers"
1320 , "tuples"
1421 , "typelevel-prelude"
1522 , "unsafe-coerce"
1623 , "untagged-union"
1724 , "web-dom"
25+ , "web-events"
1826 , "web-html"
27+ , "web-uievents"
1928 ]
2029, packages = ../packages.dhall
2130, sources = [ "src/**/*.purs", "test/**/*.purs" ]
plum/src/Main.purs+44−8
@@ -1,9 +1,8 @@
11module Main where
22
3−import Plum.View (Bones(..), view)
3+import Plum.View
44import Prelude
55
6−import Data.Array as Array
76import Effect (Effect)
87import Plum as Plum
98
@@ -11,13 +10,50 @@ main :: Effect Unit
1110main = do
1211 Plum.run "plum" plum
1312
14−type Model = { text :: String }
13+type Model = { text :: String, numberOfClicks :: Int }
1514
16−plum :: Plum.Plum Unit Model
15+data Msg = Clicked | UpdateText String
16+
17+plum :: Plum.Plum Msg Model
1718plum =
18− { init: pure { text: "Test" }
19− , view: \model ->
20− view [] [] (Column $ Array.range 1 100 # map (const $ view [] [] (Text "hello")))
19+ { init: pure { text: "Test", numberOfClicks: 0 }
20+ , view: \model -> do
21+ column do
22+ stack do
23+ align Y End
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
2156 , update: \msg model -> case msg of
22− _ -> pure { text: "Button pressed" }
57+ Clicked -> pure model { text = "Button pressed", numberOfClicks = model.numberOfClicks + 1 }
58+ UpdateText text -> pure model { text = text }
2359 }
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+61−17
@@ -2,12 +2,16 @@ module Plum (Plum, run) where
22
33import Prelude
44
5+import Data.Array as Array
56import Data.Maybe (Maybe(..))
67import Effect (Effect)
8+import Effect.Console (log)
79import Effect.Ref as Ref
8−import Maquette (h)
9−import Maquette as Maquette
10−import Plum.View (View, grow)
10+import Foreign.Object as Object
11+import Literals.Undefined (undefined)
12+import Plum.View (GenericUI(..), UI, grow)
13+import Snabbdom as Snabbdom
14+import Untagged.Union (asOneOf)
1115import Web.DOM.NonElementParentNode (getElementById) as Web
1216import Web.HTML (window) as Web
1317import Web.HTML.HTMLDocument (toNonElementParentNode) as Web
@@ -16,26 +20,66 @@ import Web.HTML.Window (document) as Web
1620type Plum msg model =
1721 { init :: Effect model
1822 , update :: msg -> model -> Effect model
19− , view :: model -> View msg
23+ , view :: model -> UI msg Unit
2024 }
2125
2226run :: forall msg model. String -> Plum msg model -> Effect Unit
2327run id plum = do
24− modelRef <- plum.init >>= Ref.new
2528 Web.window >>= Web.document >>= Web.getElementById id <<< Web.toNonElementParentNode >>= case _ of
2629 Just element -> do
27− projector <- Maquette.createProjector
28− Maquette.replace projector element do
29− model <- Ref.read modelRef
30− let
31− el = grow
32− ( \msg -> do
33− m <- Ref.read modelRef
34− m_ <- plum.update msg m
35− Ref.write m_ modelRef
36− )
37− (plum.view model)
38− pure $ Maquette.h "div" { styles: { height: "100%", width: "100%" } } [ el, Maquette.h "style" {} [ Maquette.string outerStyle ] ]
30+ let node = Snabbdom.toVNode element
31+ patch <- Snabbdom.init
32+ initModel <- plum.init
33+ modelRef <- Ref.new { model: initModel, lastNode: node }
34+ let
35+ view model = do
36+ let UI { children } _ = plum.view model
37+ case Array.uncons children of
38+ Just { head: child } -> do
39+ let
40+ { node, style } = grow
41+ ( \msg -> do
42+ log "in"
43+ { model: m, lastNode } <- Ref.read modelRef
44+ m_ <- plum.update msg m
45+ node <- view m_
46+ newNode <- patch lastNode node
47+ Ref.write { model: m_, lastNode: newNode } modelRef
48+ pure unit
49+ )
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
3983 Nothing -> pure unit
4084
4185outerStyle :: String
plum/src/Plum/View.purs+616−65
@@ -1,34 +1,332 @@
11module Plum.View
22 ( View
3− , view
43 , Nerve(..)
54 , Meat(..)
5+ , Font
6+ , BorderStyle(..)
7+ , Corner(..)
8+ , Shadow(..)
9+ , ShadowCfg
10+ , Side(..)
611 , Bones(..)
712 , grow
813 , Direction(..)
914 , Alignment(..)
1015 , Length(..)
16+ , Color(..)
17+ , rgb255
18+ , rgba255
19+ , rgb
20+ , rgba
21+ , UI
22+ , GenericUI(..)
23+ , GenericUIView
24+ , column
25+ , row
26+ , stack
27+ , text
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
1160 ) where
1261
1362import Prelude
1463
64+import Control.Monad.Writer (Writer, runWriter, tell)
65+import Control.Monad.Writer.Trans (mapWriterT)
66+import Data.Array (foldMap)
1567import Data.Array as Array
16−import Data.Tuple.Nested ((/\))
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 (/\), (/\))
1776import Effect (Effect)
1877import Foreign.Object (Object)
1978import Foreign.Object as Object
20−import Maquette (VNode, string)
21−import Maquette as Maquette
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
84+import Type.Row.Homogeneous (class Homogeneous)
85+import 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
2293
23−h :: String -> Skin -> Array VNode -> VNode
24−h el (Skin styles) children = Maquette.h el { styles } children
94+type GenericUIView children msg =
95+ { nerves :: Array (Nerve msg)
96+ , meat :: Array Meat
97+ , hover :: Array Meat
98+ , down :: Array Meat
99+ , children :: children
100+ }
25101
26−data Length = Px Int | Fill | Fit
102+type UIView msg = GenericUIView (Array (View msg)) msg
103+
104+data GenericUI children msg a = UI (GenericUIView children msg) a
105+
106+instance (Semigroup children, Semigroup a) => Semigroup (GenericUI children msg a) where
107+ append (UI v a) (UI v' a') = UI (v <> v') (a <> a')
108+
109+instance (Monoid children, Monoid a) => Monoid (GenericUI children msg a) where
110+ mempty = UI mempty mempty
111+
112+type UI msg a = GenericUI (Array (View msg)) msg a
113+
114+instance Functor (GenericUI children msg) where
115+ map f (UI v a) = UI v $ f a
116+
117+instance Monoid children => Apply (GenericUI children msg) where
118+ apply (UI views f) (UI views' a) = UI (views <> views') (f a)
119+
120+instance Monoid children => Applicative (GenericUI children msg) where
121+ pure = UI mempty
122+
123+instance Monoid children => Bind (GenericUI children msg) where
124+ bind (UI views a) f =
125+ let
126+ UI views' b = f a
127+ in
128+ UI (views <> views') b
129+
130+instance Monoid children => Monad (GenericUI children msg)
131+
132+column :: forall msg. UI msg Unit -> UI msg Unit
133+column (UI { nerves, meat, hover, down, children } _) =
134+ UI (mempty :: UIView msg) { children = [ { meat, nerves, hover, down } /\ Column children ] } unit
135+
136+row :: forall msg a. UI msg a -> UI msg a
137+row (UI { nerves, meat, hover, down, children } a) =
138+ UI (mempty :: UIView msg) { children = [ { meat, nerves, hover, down } /\ Row children ] } a
139+
140+stack :: forall msg a. UI msg a -> UI msg a
141+stack (UI { nerves, meat, hover, down, children } a) =
142+ UI (mempty :: UIView msg) { children = [ { meat, nerves, hover, down } /\ Stack children ] } a
143+
144+text :: forall msg. String -> GenericUI Unit msg Unit -> UI msg Unit
145+text s (UI { nerves, meat, hover, down } a) = UI (mempty :: UIView msg) { children = [ { meat, nerves, hover, down } /\ Text s ] } a
146+
147+link :: forall msg a. String -> UI msg a -> UI msg a
148+link url (UI { nerves, meat, hover, down, children } a) = UI
149+ (mempty :: UIView msg)
150+ { children =
151+ [ { meat
152+ , nerves
153+ , hover
154+ , down
155+ } /\ Link url { newTab: false } (Maybe.fromMaybe none $ Array.head children)
156+ ]
157+ }
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+ }
226+ children
227+ (asOneOf undefined)
228+
229+hWith :: forall props. Homogeneous props String => String -> Record props -> Classes -> WiredNerves -> Array VNode -> VNode
230+hWith elem props classes (WiredNerves on) children =
231+ Snabbdom.h elem
232+ { attrs: Object.singleton "class" (Array.intercalate " " classes)
233+ , on
234+ , props: Object.fromHomogeneous props
235+ , style: Object.empty
236+ }
237+ children
238+ (asOneOf undefined)
239+
240+data Length = Px Int | Fill | Fit | Max Int Length | Min Int Length
27241
28242data Alignment = Start | Center | End
29243
30244data Direction = X | Y
31245
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+
32330data Meat
33331 = Spacing Int Int
34332 | Explain
@@ -36,18 +334,104 @@ data Meat
36334 | Width Length
37335 | Height Length
38336 | 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
353+
354+type Font = String
355+
356+type ShadowCfg = { offset :: { x :: Int, y :: Int }, size :: Number, blur :: Number, color :: Color }
357+
358+newtype Shadow = ShadowCfg ShadowCfg
359+
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"
39403
40404data Nerve msg = OnClick msg
41405
42−type View msg = { nerves :: Array (Nerve msg), meat :: Array Meat, bones :: Bones msg }
406+newtype WiredNerves = WiredNerves (Object (Event -> Effect Unit))
43407
44−view :: forall msg. Array (Nerve msg) -> Array Meat -> Bones msg -> View msg
45−view nerves meat bones = { nerves, meat, bones }
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
46428
47429newtype Skin = Skin (Object String)
48430
49−sk :: String -> String -> Skin
50−sk key val = Skin $ Object.singleton key val
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 ]
51435
52436instance Semigroup Skin where
53437 append (Skin x) (Skin y) = Skin $ Object.union x y
@@ -57,47 +441,114 @@ instance Monoid Skin where
57441
58442data Context = Grid | Flexbox Direction | Generic | Span
59443
60−skin :: Context -> Meat -> Skin
444+skin :: Context -> Meat -> Writer SkinGrowth Classes
61445skin ctx = case _ of
62− Spacing x y -> sk "gap" (show x <> "px " <> show y <> "px")
63− Explain -> sk "border" "dashed magenta"
446+ Spacing x y -> sk ("spacing-" <> show x <> "-" <> show y) "gap" (show x <> "px " <> show y <> "px")
447+ Explain -> sk "explain" "border" "dashed magenta"
64448 Align dir alignment -> case ctx of
65449 Generic -> mempty
66450 Span -> mempty
67− Grid -> sk
68− ( case dir of
69− X -> "justify-items"
70− Y -> "align-items"
71− )
72− ( case alignment of
73− Start -> "start"
74− Center -> "center"
75− End -> "end"
76− )
77−
78− Flexbox flexDir -> sk
79− ( case flexDir /\ dir of
80− X /\ X -> "justify-content"
81− X /\ Y -> "align-items"
82− Y /\ X -> "align-items"
83− Y /\ Y -> "justify-content"
84− )
85− ( case alignment of
86− Start -> "flex-start"
87− Center -> "center"
88− End -> "flex-end"
89− )
90− Width l -> sk "width" (length l)
91− Height l -> sk "height" (length l)
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)
92487 Wrapped -> case ctx of
93− Flexbox _ -> sk "flex-wrap" "wrap"
94− _ -> mempty
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 }
95539
96−length :: Length -> String
97−length = case _ of
98− Px px -> show px <> "px"
99− Fit -> "fit-content"
100− Fill -> "100%"
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
101552
102553data Bones :: Type -> Type
103554data Bones msg
@@ -106,8 +557,15 @@ data Bones msg
106557 | Stack (Array (View msg))
107558 | Wrapper (View msg)
108559 | 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
109565
110−newtype Mutation = Mutation { extraSkin :: Skin }
566+type Classes = Array String
567+
568+newtype Mutation = Mutation { extraSkin :: Classes }
111569
112570instance Semigroup Mutation where
113571 append (Mutation x) (Mutation y) = Mutation { extraSkin: x.extraSkin <> y.extraSkin }
@@ -115,13 +573,36 @@ instance Semigroup Mutation where
115573instance Monoid Mutation where
116574 mempty = Mutation { extraSkin: mempty }
117575
118−growSkin :: forall msg. (msg -> Effect Unit) -> Mutation -> View msg -> VNode
119−growSkin fire (Mutation mutation) { meat, bones } =
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
120600 let
601+ wiredNerves = Array.foldMap (wireNerve fire) nerves
121602 alignCenter = [ Align X Center, Align Y Center ]
122603 widthFill = [ Width Fill, Height Fill ]
123− skn ctx =
124− Array.foldMap (skin ctx)
604+ skn ctx = do
605+ meatClasses <- ((_ <> mutation.extraSkin) <<< Array.concat) <$> traverse (skin ctx)
125606 ( meat
126607 <> case ctx of
127608 Span -> mempty
@@ -133,17 +614,87 @@ growSkin fire (Mutation mutation) { meat, bones } =
133614 Flexbox _ -> alignCenter
134615 Span -> mempty
135616 Generic -> alignCenter
136− ) <> mutation.extraSkin
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"
666+ }
667+ classes
668+ wiredNerves
669+ [ child' ]
670+
671+ Download href { filename } child -> do
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 []
693+
694+grow :: forall msg. (msg -> Effect Unit) -> View msg -> { node :: VNode, style :: String }
695+grow fire v =
696+ let
697+ node /\ skinGrowth = runWriter (growSkin fire mempty v)
137698 in
138− case bones of
139− Text t -> h "span" (skn Span) [ string t ]
140− Wrapper x -> h "div" (skn (Flexbox X) <> sk "display" "flex" <> sk "flex-direction" "row") [ growSkin fire mempty x ]
141− Stack children -> h "div" (skn Grid <> sk "display" "grid")
142− (map (growSkin fire $ Mutation { extraSkin: sk "grid-row" "1" <> sk "grid-column" "1" }) children)
143− Row children -> h "div" (skn (Flexbox X) <> sk "display" "flex" <> sk "flex-direction" "row")
144− (map (growSkin fire mempty) children)
145− Column children -> h "div" (skn (Flexbox Y) <> sk "display" "flex" <> sk "flex-direction" "column")
146− (map (growSkin fire mempty) children)
147−
148−grow :: forall msg. (msg -> Effect Unit) -> View msg -> VNode
149−grow fire v = growSkin fire mempty v
699+ { node, style: styleSkinGrowth skinGrowth }
700+
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