aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2016-10-05 17:04:57 +0200
committerFlorian Dold <florian.dold@gmail.com>2016-10-05 17:05:05 +0200
commit7fb527b0009a29605c32e663ab9e6a812a8cc5a8 (patch)
tree13305e0f7cc21e46dcc6010e046a3f44e9238b2d
parent39b3fd7fc6a1dcf0e36d3ab8e5081c268a663fad (diff)
downloadwallet-core-7fb527b0009a29605c32e663ab9e6a812a8cc5a8.tar.xz
refactor confirm-contract rendering
-rw-r--r--lib/decl/preact.d.ts556
l---------lib/vendor/preact1
-rw-r--r--lib/vendor/preact.js469
-rw-r--r--lib/wallet/renderHtml.ts24
-rw-r--r--pages/confirm-contract.html3
-rw-r--r--pages/confirm-contract.tsx187
6 files changed, 1159 insertions, 81 deletions
diff --git a/lib/decl/preact.d.ts b/lib/decl/preact.d.ts
new file mode 100644
index 000000000..fb8a0b764
--- /dev/null
+++ b/lib/decl/preact.d.ts
@@ -0,0 +1,556 @@
+declare namespace preact {
+ interface ComponentProps {
+ children?:JSX.Element[];
+ key?:string;
+ }
+
+ interface PreactHTMLAttributes {
+ key?:string;
+ }
+
+ interface VNode {
+ nodeName:ComponentConstructor<any, any>|string;
+ attributes:{[name:string]:any};
+ children:VNode[];
+ key:string;
+ }
+
+ interface ComponentLifecycle<PropsType, StateType> {
+ componentWillMount?():void;
+
+ componentDidMount?():void;
+
+ componentWillUnmount?():void;
+
+ componentDidUnmount?():void;
+
+ componentWillReceiveProps?(props:PropsType):void;
+
+ shouldComponentUpdate?(props:PropsType):boolean;
+
+ componentWillUpdate?():void;
+
+ componentDidUpdate?():void;
+ }
+
+ interface ComponentConstructor<PropsType, StateType> {
+ new (props?:PropsType):Component<PropsType, StateType>;
+ }
+
+ abstract class Component<PropsType, StateType> implements ComponentLifecycle<PropsType, StateType> {
+ constructor(props?:PropsType);
+
+ state:StateType;
+ props:PropsType & ComponentProps;
+ base:HTMLElement;
+
+ linkState:(name:string) => void;
+
+ setState(state:StateType, opts?:any):void;
+
+ forceUpdate():void;
+
+ abstract render(props:PropsType & ComponentProps, state:any):JSX.Element;
+ }
+
+ function h<PropsType>(node:ComponentConstructor<PropsType, any>, params:PropsType, ...children:(JSX.Element|string)[]):JSX.Element;
+ function h(node:string, params:JSX.HTMLAttributes|JSX.SVGAttributes, ...children:(JSX.Element|string)[]):JSX.Element;
+
+ function render(node:JSX.Element, parent:Element, merge?:boolean):Element;
+
+ function rerender():void;
+
+ function cloneElement(element:JSX.Element, props:any):JSX.Element;
+
+ var options:{
+ syncComponentUpdates?:boolean;
+ debounceRendering?:(render:() => void) => void;
+ vnode?:(vnode:VNode) => void;
+ event?:(event:Event) => Event;
+ };
+}
+
+declare module "preact" {
+ export = preact;
+}
+
+declare namespace JSX {
+ interface Element extends preact.VNode {
+
+ }
+
+ interface ElementClass extends preact.Component<any, any> {
+
+ }
+
+ interface ElementAttributesProperty {
+ props:any;
+ }
+
+ interface SVGAttributes {
+ clipPath?:string;
+ cx?:number | string;
+ cy?:number | string;
+ d?:string;
+ dx?:number | string;
+ dy?:number | string;
+ fill?:string;
+ fillOpacity?:number | string;
+ fontFamily?:string;
+ fontSize?:number | string;
+ fx?:number | string;
+ fy?:number | string;
+ gradientTransform?:string;
+ gradientUnits?:string;
+ markerEnd?:string;
+ markerMid?:string;
+ markerStart?:string;
+ offset?:number | string;
+ opacity?:number | string;
+ patternContentUnits?:string;
+ patternUnits?:string;
+ points?:string;
+ preserveAspectRatio?:string;
+ r?:number | string;
+ rx?:number | string;
+ ry?:number | string;
+ spreadMethod?:string;
+ stopColor?:string;
+ stopOpacity?:number | string;
+ stroke?:string;
+ strokeDasharray?:string;
+ strokeLinecap?:string;
+ strokeMiterlimit?:string;
+ strokeOpacity?:number | string;
+ strokeWidth?:number | string;
+ textAnchor?:string;
+ transform?:string;
+ version?:string;
+ viewBox?:string;
+ x1?:number | string;
+ x2?:number | string;
+ x?:number | string;
+ xlinkActuate?:string;
+ xlinkArcrole?:string;
+ xlinkHref?:string;
+ xlinkRole?:string;
+ xlinkShow?:string;
+ xlinkTitle?:string;
+ xlinkType?:string;
+ xmlBase?:string;
+ xmlLang?:string;
+ xmlSpace?:string;
+ y1?:number | string;
+ y2?:number | string;
+ y?:number | string;
+ }
+
+ interface PathAttributes {
+ d:string;
+ }
+
+ interface EventHandler<E extends Event> {
+ (event:E):void;
+ }
+
+ type ClipboardEventHandler = EventHandler<ClipboardEvent>;
+ type CompositionEventHandler = EventHandler<CompositionEvent>;
+ type DragEventHandler = EventHandler<DragEvent>;
+ type FocusEventHandler = EventHandler<FocusEvent>;
+ type KeyboardEventHandler = EventHandler<KeyboardEvent>;
+ type MouseEventHandler = EventHandler<MouseEvent>;
+ type TouchEventHandler = EventHandler<TouchEvent>;
+ type UIEventHandler = EventHandler<UIEvent>;
+ type WheelEventHandler = EventHandler<WheelEvent>;
+ type AnimationEventHandler = EventHandler<AnimationEvent>;
+ type TransitionEventHandler = EventHandler<TransitionEvent>;
+
+ type GenericEventHandler = EventHandler<Event>;
+
+ interface DOMAttributed {
+ // Clipboard Events
+ onCopy?:ClipboardEventHandler;
+ onCut?:ClipboardEventHandler;
+ onPaste?:ClipboardEventHandler;
+
+ // Composition Events
+ onCompositionEnd?:CompositionEventHandler;
+ onCompositionStart?:CompositionEventHandler;
+ onCompositionUpdate?:CompositionEventHandler;
+
+ // Focus Events
+ onFocus?:FocusEventHandler;
+ onBlur?:FocusEventHandler;
+
+ // Form Events
+ onChange?:GenericEventHandler;
+ onInput?:GenericEventHandler;
+ onSubmit?:GenericEventHandler;
+
+ // Keyboard Events
+ onKeyDown?:KeyboardEventHandler;
+ onKeyPress?:KeyboardEventHandler;
+ onKeyUp?:KeyboardEventHandler;
+
+ // Media Events
+ onAbort?:GenericEventHandler;
+ onCanPlay?:GenericEventHandler;
+ onCanPlayThrough?:GenericEventHandler;
+ onDurationChange?:GenericEventHandler;
+ onEmptied?:GenericEventHandler;
+ onEncrypted?:GenericEventHandler;
+ onEnded?:GenericEventHandler;
+ onLoadedData?:GenericEventHandler;
+ onLoadedMetadata?:GenericEventHandler;
+ onLoadStart?:GenericEventHandler;
+ onPause?:GenericEventHandler;
+ onPlay?:GenericEventHandler;
+ onPlaying?:GenericEventHandler;
+ onProgress?:GenericEventHandler;
+ onRateChange?:GenericEventHandler;
+ onSeeked?:GenericEventHandler;
+ onSeeking?:GenericEventHandler;
+ onStalled?:GenericEventHandler;
+ onSuspend?:GenericEventHandler;
+ onTimeUpdate?:GenericEventHandler;
+ onVolumeChange?:GenericEventHandler;
+ onWaiting?:GenericEventHandler;
+
+ // MouseEvents
+ onClick?:MouseEventHandler;
+ onContextMenu?:MouseEventHandler;
+ onDoubleClick?:MouseEventHandler;
+ onDrag?:DragEventHandler;
+ onDragEnd?:DragEventHandler;
+ onDragEnter?:DragEventHandler;
+ onDragExit?:DragEventHandler;
+ onDragLeave?:DragEventHandler;
+ onDragOver?:DragEventHandler;
+ onDragStart?:DragEventHandler;
+ onDrop?:DragEventHandler;
+ onMouseDown?:MouseEventHandler;
+ onMouseEnter?:MouseEventHandler;
+ onMouseLeave?:MouseEventHandler;
+ onMouseMove?:MouseEventHandler;
+ onMouseOut?:MouseEventHandler;
+ onMouseOver?:MouseEventHandler;
+ onMouseUp?:MouseEventHandler;
+
+ // Selection Events
+ onSelect?:GenericEventHandler;
+
+ // Touch Events
+ onTouchCancel?:TouchEventHandler;
+ onTouchEnd?:TouchEventHandler;
+ onTouchMove?:TouchEventHandler;
+ onTouchStart?:TouchEventHandler;
+
+ // UI Events
+ onScroll?:UIEventHandler;
+
+ // Wheel Events
+ onWheel?:WheelEventHandler;
+
+ // Animation Events
+ onAnimationStart?:AnimationEventHandler;
+ onAnimationEnd?:AnimationEventHandler;
+ onAnimationIteration?:AnimationEventHandler;
+
+ // Transition Events
+ onTransitionEnd?:TransitionEventHandler;
+ }
+
+ interface HTMLAttributes extends preact.PreactHTMLAttributes, DOMAttributed {
+ // Standard HTML Attributes
+ accept?:string;
+ acceptCharset?:string;
+ accessKey?:string;
+ action?:string;
+ allowFullScreen?:boolean;
+ allowTransparency?:boolean;
+ alt?:string;
+ async?:boolean;
+ autocomplete?:string;
+ autofocus?:boolean;
+ autoPlay?:boolean;
+ capture?:boolean;
+ cellPadding?:number | string;
+ cellSpacing?:number | string;
+ charSet?:string;
+ challenge?:string;
+ checked?:boolean;
+ class?:string;
+ className?:string;
+ cols?:number;
+ colSpan?:number;
+ content?:string;
+ contentEditable?:boolean;
+ contextMenu?:string;
+ controls?:boolean;
+ coords?:string;
+ crossOrigin?:string;
+ data?:string;
+ dateTime?:string;
+ default?:boolean;
+ defer?:boolean;
+ dir?:string;
+ disabled?:boolean;
+ download?:any;
+ draggable?:boolean;
+ encType?:string;
+ form?:string;
+ formAction?:string;
+ formEncType?:string;
+ formMethod?:string;
+ formNoValidate?:boolean;
+ formTarget?:string;
+ frameBorder?:number | string;
+ headers?:string;
+ height?:number | string;
+ hidden?:boolean;
+ high?:number;
+ href?:string;
+ hrefLang?:string;
+ for?:string;
+ httpEquiv?:string;
+ icon?:string;
+ id?:string;
+ inputMode?:string;
+ integrity?:string;
+ is?:string;
+ keyParams?:string;
+ keyType?:string;
+ kind?:string;
+ label?:string;
+ lang?:string;
+ list?:string;
+ loop?:boolean;
+ low?:number;
+ manifest?:string;
+ marginHeight?:number;
+ marginWidth?:number;
+ max?:number | string;
+ maxLength?:number;
+ media?:string;
+ mediaGroup?:string;
+ method?:string;
+ min?:number | string;
+ minLength?:number;
+ multiple?:boolean;
+ muted?:boolean;
+ name?:string;
+ noValidate?:boolean;
+ open?:boolean;
+ optimum?:number;
+ pattern?:string;
+ placeholder?:string;
+ poster?:string;
+ preload?:string;
+ radioGroup?:string;
+ readOnly?:boolean;
+ rel?:string;
+ required?:boolean;
+ role?:string;
+ rows?:number;
+ rowSpan?:number;
+ sandbox?:string;
+ scope?:string;
+ scoped?:boolean;
+ scrolling?:string;
+ seamless?:boolean;
+ selected?:boolean;
+ shape?:string;
+ size?:number;
+ sizes?:string;
+ span?:number;
+ spellCheck?:boolean;
+ src?:string;
+ srcset?:string;
+ srcDoc?:string;
+ srcLang?:string;
+ srcSet?:string;
+ start?:number;
+ step?:number | string;
+ style?:any;
+ summary?:string;
+ tabIndex?:number;
+ target?:string;
+ title?:string;
+ type?:string;
+ useMap?:string;
+ value?:string | string[];
+ width?:number | string;
+ wmode?:string;
+ wrap?:string;
+
+ // RDFa Attributes
+ about?:string;
+ datatype?:string;
+ inlist?:any;
+ prefix?:string;
+ property?:string;
+ resource?:string;
+ typeof?:string;
+ vocab?:string;
+ }
+
+ interface IntrinsicElements {
+ // HTML
+ a:HTMLAttributes;
+ abbr:HTMLAttributes;
+ address:HTMLAttributes;
+ area:HTMLAttributes;
+ article:HTMLAttributes;
+ aside:HTMLAttributes;
+ audio:HTMLAttributes;
+ b:HTMLAttributes;
+ base:HTMLAttributes;
+ bdi:HTMLAttributes;
+ bdo:HTMLAttributes;
+ big:HTMLAttributes;
+ blockquote:HTMLAttributes;
+ body:HTMLAttributes;
+ br:HTMLAttributes;
+ button:HTMLAttributes;
+ canvas:HTMLAttributes;
+ caption:HTMLAttributes;
+ cite:HTMLAttributes;
+ code:HTMLAttributes;
+ col:HTMLAttributes;
+ colgroup:HTMLAttributes;
+ data:HTMLAttributes;
+ datalist:HTMLAttributes;
+ dd:HTMLAttributes;
+ del:HTMLAttributes;
+ details:HTMLAttributes;
+ dfn:HTMLAttributes;
+ dialog:HTMLAttributes;
+ div:HTMLAttributes;
+ dl:HTMLAttributes;
+ dt:HTMLAttributes;
+ em:HTMLAttributes;
+ embed:HTMLAttributes;
+ fieldset:HTMLAttributes;
+ figcaption:HTMLAttributes;
+ figure:HTMLAttributes;
+ footer:HTMLAttributes;
+ form:HTMLAttributes;
+ h1:HTMLAttributes;
+ h2:HTMLAttributes;
+ h3:HTMLAttributes;
+ h4:HTMLAttributes;
+ h5:HTMLAttributes;
+ h6:HTMLAttributes;
+ head:HTMLAttributes;
+ header:HTMLAttributes;
+ hr:HTMLAttributes;
+ html:HTMLAttributes;
+ i:HTMLAttributes;
+ iframe:HTMLAttributes;
+ img:HTMLAttributes;
+ input:HTMLAttributes;
+ ins:HTMLAttributes;
+ kbd:HTMLAttributes;
+ keygen:HTMLAttributes;
+ label:HTMLAttributes;
+ legend:HTMLAttributes;
+ li:HTMLAttributes;
+ link:HTMLAttributes;
+ main:HTMLAttributes;
+ map:HTMLAttributes;
+ mark:HTMLAttributes;
+ menu:HTMLAttributes;
+ menuitem:HTMLAttributes;
+ meta:HTMLAttributes;
+ meter:HTMLAttributes;
+ nav:HTMLAttributes;
+ noscript:HTMLAttributes;
+ object:HTMLAttributes;
+ ol:HTMLAttributes;
+ optgroup:HTMLAttributes;
+ option:HTMLAttributes;
+ output:HTMLAttributes;
+ p:HTMLAttributes;
+ param:HTMLAttributes;
+ picture:HTMLAttributes;
+ pre:HTMLAttributes;
+ progress:HTMLAttributes;
+ q:HTMLAttributes;
+ rp:HTMLAttributes;
+ rt:HTMLAttributes;
+ ruby:HTMLAttributes;
+ s:HTMLAttributes;
+ samp:HTMLAttributes;
+ script:HTMLAttributes;
+ section:HTMLAttributes;
+ select:HTMLAttributes;
+ small:HTMLAttributes;
+ source:HTMLAttributes;
+ span:HTMLAttributes;
+ strong:HTMLAttributes;
+ style:HTMLAttributes;
+ sub:HTMLAttributes;
+ summary:HTMLAttributes;
+ sup:HTMLAttributes;
+ table:HTMLAttributes;
+ tbody:HTMLAttributes;
+ td:HTMLAttributes;
+ textarea:HTMLAttributes;
+ tfoot:HTMLAttributes;
+ th:HTMLAttributes;
+ thead:HTMLAttributes;
+ time:HTMLAttributes;
+ title:HTMLAttributes;
+ tr:HTMLAttributes;
+ track:HTMLAttributes;
+ u:HTMLAttributes;
+ ul:HTMLAttributes;
+ "var":HTMLAttributes;
+ video:HTMLAttributes;
+ wbr:HTMLAttributes;
+
+ //SVG
+ svg:SVGAttributes;
+
+ circle:SVGAttributes;
+ clipPath:SVGAttributes;
+ defs:SVGAttributes;
+ ellipse:SVGAttributes;
+ feBlend:SVGAttributes;
+ feColorMatrix:SVGAttributes;
+ feComponentTransfer:SVGAttributes;
+ feComposite:SVGAttributes;
+ feConvolveMatrix:SVGAttributes;
+ feDiffuseLighting:SVGAttributes;
+ feDisplacementMap:SVGAttributes;
+ feFlood:SVGAttributes;
+ feGaussianBlur:SVGAttributes;
+ feImage:SVGAttributes;
+ feMerge:SVGAttributes;
+ feMergeNode:SVGAttributes;
+ feMorphology:SVGAttributes;
+ feOffset:SVGAttributes;
+ feSpecularLighting:SVGAttributes;
+ feTile:SVGAttributes;
+ feTurbulence:SVGAttributes;
+ filter:SVGAttributes;
+ foreignObject:SVGAttributes;
+ g:SVGAttributes;
+ image:SVGAttributes;
+ line:SVGAttributes;
+ linearGradient:SVGAttributes;
+ marker:SVGAttributes;
+ mask:SVGAttributes;
+ path:SVGAttributes;
+ pattern:SVGAttributes;
+ polygon:SVGAttributes;
+ polyline:SVGAttributes;
+ radialGradient:SVGAttributes;
+ rect:SVGAttributes;
+ stop:SVGAttributes;
+ symbol:SVGAttributes;
+ text:SVGAttributes;
+ tspan:SVGAttributes;
+ use:SVGAttributes;
+ }
+}
diff --git a/lib/vendor/preact b/lib/vendor/preact
deleted file mode 120000
index 6111fdad3..000000000
--- a/lib/vendor/preact
+++ /dev/null
@@ -1 +0,0 @@
-../../thirdparty/preact/src/ \ No newline at end of file
diff --git a/lib/vendor/preact.js b/lib/vendor/preact.js
new file mode 100644
index 000000000..3b06bb6af
--- /dev/null
+++ b/lib/vendor/preact.js
@@ -0,0 +1,469 @@
+!function(global, factory) {
+ 'object' == typeof exports && 'undefined' != typeof module ? factory(exports) : 'function' == typeof define && define.amd ? define([ 'exports' ], factory) : factory(global.preact = global.preact || {});
+}(this, function(exports) {
+ function VNode(nodeName, attributes, children) {
+ this.nodeName = nodeName;
+ this.attributes = attributes;
+ this.children = children;
+ this.key = attributes && attributes.key;
+ }
+ function h(nodeName, attributes) {
+ var children, lastSimple, child, simple, i;
+ for (i = arguments.length; i-- > 2; ) stack.push(arguments[i]);
+ if (attributes && attributes.children) {
+ if (!stack.length) stack.push(attributes.children);
+ delete attributes.children;
+ }
+ while (stack.length) if ((child = stack.pop()) instanceof Array) for (i = child.length; i--; ) stack.push(child[i]); else if (null != child && child !== !1) {
+ if ('number' == typeof child || child === !0) child = String(child);
+ simple = 'string' == typeof child;
+ if (simple && lastSimple) children[children.length - 1] += child; else {
+ if (children) children.push(child); else children = [ child ];
+ lastSimple = simple;
+ }
+ }
+ var p = new VNode(nodeName, attributes || void 0, children);
+ if (options.vnode) options.vnode(p);
+ return p;
+ }
+ function extend(obj, props) {
+ if (props) for (var i in props) obj[i] = props[i];
+ return obj;
+ }
+ function clone(obj) {
+ return extend({}, obj);
+ }
+ function delve(obj, key) {
+ for (var p = key.split('.'), i = 0; i < p.length && obj; i++) obj = obj[p[i]];
+ return obj;
+ }
+ function isFunction(obj) {
+ return 'function' == typeof obj;
+ }
+ function isString(obj) {
+ return 'string' == typeof obj;
+ }
+ function hashToClassName(c) {
+ var str = '';
+ for (var prop in c) if (c[prop]) {
+ if (str) str += ' ';
+ str += prop;
+ }
+ return str;
+ }
+ function cloneElement(vnode, props) {
+ return h(vnode.nodeName, extend(clone(vnode.attributes), props), arguments.length > 2 ? [].slice.call(arguments, 2) : vnode.children);
+ }
+ function createLinkedState(component, key, eventPath) {
+ var path = key.split('.'), p0 = path[0];
+ return function(e) {
+ var _component$setState;
+ var i, t = e && e.currentTarget || this, s = component.state, obj = s, v = isString(eventPath) ? delve(e, eventPath) : t.nodeName ? (t.nodeName + t.type).match(/^input(che|rad)/i) ? t.checked : t.value : e;
+ if (path.length > 1) {
+ for (i = 0; i < path.length - 1; i++) obj = obj[path[i]] || (obj[path[i]] = {});
+ obj[path[i]] = v;
+ v = s[p0];
+ }
+ component.setState((_component$setState = {}, _component$setState[p0] = v, _component$setState));
+ };
+ }
+ function enqueueRender(component) {
+ if (!component._dirty && (component._dirty = !0) && 1 == items.push(component)) (options.debounceRendering || defer)(rerender);
+ }
+ function rerender() {
+ var p, list = items;
+ items = [];
+ while (p = list.pop()) if (p._dirty) renderComponent(p);
+ }
+ function isFunctionalComponent(vnode) {
+ var nodeName = vnode && vnode.nodeName;
+ return nodeName && isFunction(nodeName) && !(nodeName.prototype && nodeName.prototype.render);
+ }
+ function buildFunctionalComponent(vnode, context) {
+ return vnode.nodeName(getNodeProps(vnode), context || EMPTY);
+ }
+ function isSameNodeType(node, vnode) {
+ if (isString(vnode)) return node instanceof Text;
+ if (isString(vnode.nodeName)) return isNamedNode(node, vnode.nodeName);
+ if (isFunction(vnode.nodeName)) return node._componentConstructor === vnode.nodeName || isFunctionalComponent(vnode); else ;
+ }
+ function isNamedNode(node, nodeName) {
+ return node.normalizedNodeName === nodeName || toLowerCase(node.nodeName) === toLowerCase(nodeName);
+ }
+ function getNodeProps(vnode) {
+ var defaultProps = vnode.nodeName.defaultProps, props = clone(vnode.attributes);
+ if (defaultProps) for (var i in defaultProps) if (void 0 === props[i]) props[i] = defaultProps[i];
+ if (vnode.children) props.children = vnode.children;
+ return props;
+ }
+ function removeNode(node) {
+ var p = node.parentNode;
+ if (p) p.removeChild(node);
+ }
+ function setAccessor(node, name, value, old, isSvg) {
+ node[ATTR_KEY][name] = value;
+ if ('className' === name) name = 'class';
+ if ('class' === name && value && 'object' == typeof value) value = hashToClassName(value);
+ if ('key' === name || 'children' === name || 'innerHTML' === name) ; else if ('class' === name && !isSvg) node.className = value || ''; else if ('style' === name) {
+ if (!value || isString(value) || isString(old)) node.style.cssText = value || '';
+ if (value && 'object' == typeof value) {
+ if (!isString(old)) for (var i in old) if (!(i in value)) node.style[i] = '';
+ for (var i in value) node.style[i] = 'number' == typeof value[i] && !NON_DIMENSION_PROPS[i] ? value[i] + 'px' : value[i];
+ }
+ } else if ('dangerouslySetInnerHTML' === name) {
+ if (value) node.innerHTML = value.__html;
+ } else if ('o' == name[0] && 'n' == name[1]) {
+ var l = node._listeners || (node._listeners = {});
+ name = toLowerCase(name.substring(2));
+ if (value) {
+ if (!l[name]) node.addEventListener(name, eventProxy, !!NON_BUBBLING_EVENTS[name]);
+ } else if (l[name]) node.removeEventListener(name, eventProxy, !!NON_BUBBLING_EVENTS[name]);
+ l[name] = value;
+ } else if ('list' !== name && 'type' !== name && !isSvg && name in node) {
+ setProperty(node, name, null == value ? '' : value);
+ if (null == value || value === !1) node.removeAttribute(name);
+ } else {
+ var ns = isSvg && name.match(/^xlink\:?(.+)/);
+ if (null == value || value === !1) if (ns) node.removeAttributeNS('http://www.w3.org/1999/xlink', toLowerCase(ns[1])); else node.removeAttribute(name); else if ('object' != typeof value && !isFunction(value)) if (ns) node.setAttributeNS('http://www.w3.org/1999/xlink', toLowerCase(ns[1]), value); else node.setAttribute(name, value);
+ }
+ }
+ function setProperty(node, name, value) {
+ try {
+ node[name] = value;
+ } catch (e) {}
+ }
+ function eventProxy(e) {
+ return this._listeners[e.type](options.event && options.event(e) || e);
+ }
+ function collectNode(node) {
+ removeNode(node);
+ if (node instanceof Element) {
+ node._component = node._componentConstructor = null;
+ var _name = node.normalizedNodeName || toLowerCase(node.nodeName);
+ (nodes[_name] || (nodes[_name] = [])).push(node);
+ }
+ }
+ function createNode(nodeName, isSvg) {
+ var name = toLowerCase(nodeName), node = nodes[name] && nodes[name].pop() || (isSvg ? document.createElementNS('http://www.w3.org/2000/svg', nodeName) : document.createElement(nodeName));
+ node.normalizedNodeName = name;
+ return node;
+ }
+ function flushMounts() {
+ var c;
+ while (c = mounts.pop()) if (c.componentDidMount) c.componentDidMount();
+ }
+ function diff(dom, vnode, context, mountAll, parent, componentRoot) {
+ if (!diffLevel++) isSvgMode = parent instanceof SVGElement;
+ var ret = idiff(dom, vnode, context, mountAll);
+ if (parent && ret.parentNode !== parent) parent.appendChild(ret);
+ if (!--diffLevel && !componentRoot) flushMounts();
+ return ret;
+ }
+ function idiff(dom, vnode, context, mountAll) {
+ var originalAttributes = vnode && vnode.attributes;
+ while (isFunctionalComponent(vnode)) vnode = buildFunctionalComponent(vnode, context);
+ if (null == vnode) vnode = '';
+ if (isString(vnode)) {
+ if (dom) {
+ if (dom instanceof Text && dom.parentNode) {
+ dom.nodeValue = vnode;
+ return dom;
+ }
+ recollectNodeTree(dom);
+ }
+ return document.createTextNode(vnode);
+ }
+ if (isFunction(vnode.nodeName)) return buildComponentFromVNode(dom, vnode, context, mountAll);
+ var out = dom, nodeName = vnode.nodeName, prevSvgMode = isSvgMode;
+ if (!isString(nodeName)) nodeName = String(nodeName);
+ isSvgMode = 'svg' === nodeName ? !0 : 'foreignObject' === nodeName ? !1 : isSvgMode;
+ if (!dom) out = createNode(nodeName, isSvgMode); else if (!isNamedNode(dom, nodeName)) {
+ out = createNode(nodeName, isSvgMode);
+ while (dom.firstChild) out.appendChild(dom.firstChild);
+ recollectNodeTree(dom);
+ }
+ if (vnode.children && 1 === vnode.children.length && 'string' == typeof vnode.children[0] && 1 === out.childNodes.length && out.firstChild instanceof Text) out.firstChild.nodeValue = vnode.children[0]; else if (vnode.children || out.firstChild) innerDiffNode(out, vnode.children, context, mountAll);
+ var props = out[ATTR_KEY];
+ if (!props) {
+ out[ATTR_KEY] = props = {};
+ for (var a = out.attributes, i = a.length; i--; ) props[a[i].name] = a[i].value;
+ }
+ diffAttributes(out, vnode.attributes, props);
+ if (originalAttributes && 'function' == typeof originalAttributes.ref) (props.ref = originalAttributes.ref)(out);
+ isSvgMode = prevSvgMode;
+ return out;
+ }
+ function innerDiffNode(dom, vchildren, context, mountAll) {
+ var j, c, vchild, child, originalChildren = dom.childNodes, children = [], keyed = {}, keyedLen = 0, min = 0, len = originalChildren.length, childrenLen = 0, vlen = vchildren && vchildren.length;
+ if (len) for (var i = 0; i < len; i++) {
+ var _child = originalChildren[i], key = vlen ? (c = _child._component) ? c.__key : (c = _child[ATTR_KEY]) ? c.key : null : null;
+ if (key || 0 === key) {
+ keyedLen++;
+ keyed[key] = _child;
+ } else children[childrenLen++] = _child;
+ }
+ if (vlen) for (var i = 0; i < vlen; i++) {
+ vchild = vchildren[i];
+ child = null;
+ var key = vchild.key;
+ if (null != key) {
+ if (keyedLen && key in keyed) {
+ child = keyed[key];
+ keyed[key] = void 0;
+ keyedLen--;
+ }
+ } else if (!child && min < childrenLen) {
+ for (j = min; j < childrenLen; j++) {
+ c = children[j];
+ if (c && isSameNodeType(c, vchild)) {
+ child = c;
+ children[j] = void 0;
+ if (j === childrenLen - 1) childrenLen--;
+ if (j === min) min++;
+ break;
+ }
+ }
+ if (!child && min < childrenLen && isFunction(vchild.nodeName) && mountAll) {
+ child = children[min];
+ children[min++] = void 0;
+ }
+ }
+ child = idiff(child, vchild, context, mountAll);
+ if (child && child !== dom && child !== originalChildren[i]) dom.insertBefore(child, originalChildren[i] || null);
+ }
+ if (keyedLen) for (var i in keyed) if (keyed[i]) recollectNodeTree(keyed[i]);
+ if (min < childrenLen) removeOrphanedChildren(children);
+ }
+ function removeOrphanedChildren(children, unmountOnly) {
+ for (var i = children.length; i--; ) if (children[i]) recollectNodeTree(children[i], unmountOnly);
+ }
+ function recollectNodeTree(node, unmountOnly) {
+ var component = node._component;
+ if (component) unmountComponent(component, !unmountOnly); else {
+ if (node[ATTR_KEY] && node[ATTR_KEY].ref) node[ATTR_KEY].ref(null);
+ if (!unmountOnly) collectNode(node);
+ if (node.childNodes && node.childNodes.length) removeOrphanedChildren(node.childNodes, unmountOnly);
+ }
+ }
+ function diffAttributes(dom, attrs, old) {
+ for (var _name in old) if (!(attrs && _name in attrs) && null != old[_name]) setAccessor(dom, _name, null, old[_name], isSvgMode);
+ if (attrs) for (var _name2 in attrs) if (!(_name2 in old) || attrs[_name2] !== ('value' === _name2 || 'checked' === _name2 ? dom[_name2] : old[_name2])) setAccessor(dom, _name2, attrs[_name2], old[_name2], isSvgMode);
+ }
+ function collectComponent(component) {
+ var name = component.constructor.name, list = components[name];
+ if (list) list.push(component); else components[name] = [ component ];
+ }
+ function createComponent(Ctor, props, context) {
+ var inst = new Ctor(props, context), list = components[Ctor.name];
+ Component.call(inst, props, context);
+ if (list) for (var i = list.length; i--; ) if (list[i].constructor === Ctor) {
+ inst.nextBase = list[i].nextBase;
+ list.splice(i, 1);
+ break;
+ }
+ return inst;
+ }
+ function setComponentProps(component, props, opts, context, mountAll) {
+ if (!component._disable) {
+ component._disable = !0;
+ if (component.__ref = props.ref) delete props.ref;
+ if (component.__key = props.key) delete props.key;
+ if (!component.base || mountAll) {
+ if (component.componentWillMount) component.componentWillMount();
+ } else if (component.componentWillReceiveProps) component.componentWillReceiveProps(props, context);
+ if (context && context !== component.context) {
+ if (!component.prevContext) component.prevContext = component.context;
+ component.context = context;
+ }
+ if (!component.prevProps) component.prevProps = component.props;
+ component.props = props;
+ component._disable = !1;
+ if (0 !== opts) if (1 === opts || options.syncComponentUpdates !== !1 || !component.base) renderComponent(component, 1, mountAll); else enqueueRender(component);
+ if (component.__ref) component.__ref(component);
+ }
+ }
+ function renderComponent(component, opts, mountAll, isChild) {
+ if (!component._disable) {
+ var skip, rendered, inst, cbase, props = component.props, state = component.state, context = component.context, previousProps = component.prevProps || props, previousState = component.prevState || state, previousContext = component.prevContext || context, isUpdate = component.base, nextBase = component.nextBase, initialBase = isUpdate || nextBase, initialChildComponent = component._component;
+ if (isUpdate) {
+ component.props = previousProps;
+ component.state = previousState;
+ component.context = previousContext;
+ if (2 !== opts && component.shouldComponentUpdate && component.shouldComponentUpdate(props, state, context) === !1) skip = !0; else if (component.componentWillUpdate) component.componentWillUpdate(props, state, context);
+ component.props = props;
+ component.state = state;
+ component.context = context;
+ }
+ component.prevProps = component.prevState = component.prevContext = component.nextBase = null;
+ component._dirty = !1;
+ if (!skip) {
+ if (component.render) rendered = component.render(props, state, context);
+ if (component.getChildContext) context = extend(clone(context), component.getChildContext());
+ while (isFunctionalComponent(rendered)) rendered = buildFunctionalComponent(rendered, context);
+ var toUnmount, base, childComponent = rendered && rendered.nodeName;
+ if (isFunction(childComponent)) {
+ inst = initialChildComponent;
+ var childProps = getNodeProps(rendered);
+ if (inst && inst.constructor === childComponent) setComponentProps(inst, childProps, 1, context); else {
+ toUnmount = inst;
+ inst = createComponent(childComponent, childProps, context);
+ inst.nextBase = inst.nextBase || nextBase;
+ inst._parentComponent = component;
+ component._component = inst;
+ setComponentProps(inst, childProps, 0, context);
+ renderComponent(inst, 1, mountAll, !0);
+ }
+ base = inst.base;
+ } else {
+ cbase = initialBase;
+ toUnmount = initialChildComponent;
+ if (toUnmount) cbase = component._component = null;
+ if (initialBase || 1 === opts) {
+ if (cbase) cbase._component = null;
+ base = diff(cbase, rendered, context, mountAll || !isUpdate, initialBase && initialBase.parentNode, !0);
+ }
+ }
+ if (initialBase && base !== initialBase && inst !== initialChildComponent) {
+ var baseParent = initialBase.parentNode;
+ if (baseParent && base !== baseParent) baseParent.replaceChild(base, initialBase);
+ if (!cbase && !toUnmount && component._parentComponent) {
+ initialBase._component = null;
+ recollectNodeTree(initialBase);
+ }
+ }
+ if (toUnmount) unmountComponent(toUnmount, base !== initialBase);
+ component.base = base;
+ if (base && !isChild) {
+ var componentRef = component, t = component;
+ while (t = t._parentComponent) componentRef = t;
+ base._component = componentRef;
+ base._componentConstructor = componentRef.constructor;
+ }
+ }
+ if (!isUpdate || mountAll) mounts.unshift(component); else if (!skip && component.componentDidUpdate) component.componentDidUpdate(previousProps, previousState, previousContext);
+ var fn, cb = component._renderCallbacks;
+ if (cb) while (fn = cb.pop()) fn.call(component);
+ if (!diffLevel && !isChild) flushMounts();
+ }
+ }
+ function buildComponentFromVNode(dom, vnode, context, mountAll) {
+ var c = dom && dom._component, oldDom = dom, isDirectOwner = c && dom._componentConstructor === vnode.nodeName, isOwner = isDirectOwner, props = getNodeProps(vnode);
+ while (c && !isOwner && (c = c._parentComponent)) isOwner = c.constructor === vnode.nodeName;
+ if (c && isOwner && (!mountAll || c._component)) {
+ setComponentProps(c, props, 3, context, mountAll);
+ dom = c.base;
+ } else {
+ if (c && !isDirectOwner) {
+ unmountComponent(c, !0);
+ dom = oldDom = null;
+ }
+ c = createComponent(vnode.nodeName, props, context);
+ if (dom && !c.nextBase) c.nextBase = dom;
+ setComponentProps(c, props, 1, context, mountAll);
+ dom = c.base;
+ if (oldDom && dom !== oldDom) {
+ oldDom._component = null;
+ recollectNodeTree(oldDom);
+ }
+ }
+ return dom;
+ }
+ function unmountComponent(component, remove) {
+ var base = component.base;
+ component._disable = !0;
+ if (component.componentWillUnmount) component.componentWillUnmount();
+ component.base = null;
+ var inner = component._component;
+ if (inner) unmountComponent(inner, remove); else if (base) {
+ if (base[ATTR_KEY] && base[ATTR_KEY].ref) base[ATTR_KEY].ref(null);
+ component.nextBase = base;
+ if (remove) {
+ removeNode(base);
+ collectComponent(component);
+ }
+ removeOrphanedChildren(base.childNodes, !remove);
+ }
+ if (component.__ref) component.__ref(null);
+ if (component.componentDidUnmount) component.componentDidUnmount();
+ }
+ function Component(props, context) {
+ this._dirty = !0;
+ this.context = context;
+ this.props = props;
+ if (!this.state) this.state = {};
+ }
+ function render(vnode, parent, merge) {
+ return diff(merge, vnode, {}, !1, parent);
+ }
+ var options = {};
+ var stack = [];
+ var lcCache = {};
+ var toLowerCase = function(s) {
+ return lcCache[s] || (lcCache[s] = s.toLowerCase());
+ };
+ var resolved = 'undefined' != typeof Promise && Promise.resolve();
+ var defer = resolved ? function(f) {
+ resolved.then(f);
+ } : setTimeout;
+ var EMPTY = {};
+ var ATTR_KEY = 'undefined' != typeof Symbol ? Symbol.for('preactattr') : '__preactattr_';
+ var NON_DIMENSION_PROPS = {
+ boxFlex: 1,
+ boxFlexGroup: 1,
+ columnCount: 1,
+ fillOpacity: 1,
+ flex: 1,
+ flexGrow: 1,
+ flexPositive: 1,
+ flexShrink: 1,
+ flexNegative: 1,
+ fontWeight: 1,
+ lineClamp: 1,
+ lineHeight: 1,
+ opacity: 1,
+ order: 1,
+ orphans: 1,
+ strokeOpacity: 1,
+ widows: 1,
+ zIndex: 1,
+ zoom: 1
+ };
+ var NON_BUBBLING_EVENTS = {
+ blur: 1,
+ error: 1,
+ focus: 1,
+ load: 1,
+ resize: 1,
+ scroll: 1
+ };
+ var items = [];
+ var nodes = {};
+ var mounts = [];
+ var diffLevel = 0;
+ var isSvgMode = !1;
+ var components = {};
+ extend(Component.prototype, {
+ linkState: function(key, eventPath) {
+ var c = this._linkedStates || (this._linkedStates = {});
+ return c[key + eventPath] || (c[key + eventPath] = createLinkedState(this, key, eventPath));
+ },
+ setState: function(state, callback) {
+ var s = this.state;
+ if (!this.prevState) this.prevState = clone(s);
+ extend(s, isFunction(state) ? state(s, this.props) : state);
+ if (callback) (this._renderCallbacks = this._renderCallbacks || []).push(callback);
+ enqueueRender(this);
+ },
+ forceUpdate: function() {
+ renderComponent(this, 2);
+ },
+ render: function() {}
+ });
+ exports.h = h;
+ exports.cloneElement = cloneElement;
+ exports.Component = Component;
+ exports.render = render;
+ exports.rerender = rerender;
+ exports.options = options;
+});
+//# sourceMappingURL=preact.js.map \ No newline at end of file
diff --git a/lib/wallet/renderHtml.ts b/lib/wallet/renderHtml.ts
index 6d9823d71..022bce113 100644
--- a/lib/wallet/renderHtml.ts
+++ b/lib/wallet/renderHtml.ts
@@ -24,26 +24,26 @@
import {AmountJson, Contract} from "./types";
+let h = preact.h;
+
export function prettyAmount(amount: AmountJson) {
let v = amount.value + amount.fraction / 1e6;
return `${v.toFixed(2)} ${amount.currency}`;
}
-export function renderContract(contract: Contract): any {
+export function renderContract(contract: Contract): JSX.Element {
let merchantName = m("strong", contract.merchant.name);
let amount = m("strong", prettyAmount(contract.amount));
- return m("div", {}, [
- m("p",
- i18n.parts`${merchantName}
+ return h("div", {},
+ h("p", {},
+ i18n.parts`${merchantName}
wants to enter a contract over ${amount}
with you.`),
- m("p",
- i18n`You are about to purchase:`),
- m('ul',
-
- contract.products.map(
- (p: any) => m("li",
- `${p.description}: ${prettyAmount(p.price)}`)))
- ]);
+ h("p", {},
+ i18n`You are about to purchase:`),
+ h('ul', {},
+ ...contract.products.map(
+ (p: any) => h("li", {},
+ `${p.description}: ${prettyAmount(p.price)}`))));
} \ No newline at end of file
diff --git a/pages/confirm-contract.html b/pages/confirm-contract.html
index e7200910a..6e773f1b6 100644
--- a/pages/confirm-contract.html
+++ b/pages/confirm-contract.html
@@ -11,9 +11,10 @@
<script src="../lib/vendor/URI.js"></script>
<script src="../lib/vendor/mithril.js"></script>
+ <script src="../lib/vendor/preact.js"></script>
<script src="../lib/vendor/lodash.core.min.js"></script>
<script src="../lib/vendor/system-csp-production.src.js"></script>
- <script src="../lib/vendor/jed.js"></script>
+ <!-- <script src="../lib/vendor/jed.js"></script> -->
<script src="../lib/i18n.js"></script>
<script src="../i18n/strings.js"></script>
<script src="../lib/module-trampoline.js"></script>
diff --git a/pages/confirm-contract.tsx b/pages/confirm-contract.tsx
index f162dca85..8e553b05b 100644
--- a/pages/confirm-contract.tsx
+++ b/pages/confirm-contract.tsx
@@ -22,113 +22,166 @@
*/
-/// <reference path="../lib/decl/handlebars/handlebars.d.ts" />
-import MithrilComponent = _mithril.MithrilComponent;
+/// <reference path="../lib/decl/preact.d.ts" />
import {substituteFulfillmentUrl} from "../lib/wallet/helpers";
import m from "mithril";
import {Contract, AmountJson} from "../lib/wallet/types";
import {renderContract, prettyAmount} from "../lib/wallet/renderHtml";
"use strict";
-const Details = {
- controller() {
- return {collapsed: m.prop(true)};
- },
- view(ctrl: any, contract: Contract) {
- if (ctrl.collapsed()) {
- return m("div", [
- m("button.linky", {
- onclick: () => {
- ctrl.collapsed(false);
- }
- }, "show more details")
- ]);
+
+interface DetailState {
+ collapsed: boolean;
+}
+
+interface DetailProps {
+ contract: Contract;
+}
+
+let h = preact.h;
+
+
+class Details extends preact.Component<DetailProps, DetailState> {
+ constructor() {
+ super();
+ this.state = {
+ collapsed: true
+ };
+ }
+
+ render(props: DetailProps, state: DetailState) {
+ if (state.collapsed) {
+ return h("div", {},
+ h("button", {
+ className: "linky",
+ onClick: () => {
+ this.setState({collapsed: false});
+ }
+ }, "show more details"));
} else {
- return m("div", [
- m("button.linky", {
- onclick: () => {
- ctrl.collapsed(true);
- }
- }, "show less details"),
- m("div", [
- "Accepted exchanges:",
- m("ul",
- contract.exchanges.map(e => m("li", `${e.url}: ${e.master_pub}`)))
- ])
- ]);
+ return h("div", {},
+ h("button", {
+ className: "linky",
+ onClick: () => {
+ this.setState({collapsed: true});
+ }
+ }, "show less details"),
+ h("div", {},
+ "Accepted exchanges:",
+ h("ul", {},
+ ...props.contract.exchanges.map(
+ e => h("li", {}, `${e.url}: ${e.master_pub}`)))));
}
}
-};
+}
-export function main() {
- let url = URI(document.location.href);
- let query: any = URI.parseQuery(url.query());
- let offer = JSON.parse(query.offer);
- console.dir(offer);
- let contract = offer.contract;
- let error: string|null = null;
- let payDisabled = true;
-
- var Contract = {
- view(ctrl: any) {
- return [
- renderContract(contract),
- m("button.accept",
- {onclick: doPayment, disabled: payDisabled},
- i18n`Confirm Payment`),
- (error ? m("p.errorbox", error) : []),
- m(Details, contract)
- ];
+interface ContractPromptProps {
+ offer: any;
+}
+
+interface ContractPromptState {
+ error: string|null;
+ payDisabled: boolean;
+}
+
+class ContractPrompt extends preact.Component<ContractPromptProps, ContractPromptState> {
+ constructor() {
+ super();
+ this.state = {
+ error: null,
+ payDisabled: true,
}
- };
+ }
- m.mount(document.getElementById("contract")!, Contract);
+ componentWillMount() {
+ this.checkPayment();
+ }
+
+ componentWillUnmount() {
+ // FIXME: abort running ops
+ }
- function checkPayment() {
- chrome.runtime.sendMessage({type: 'check-pay', detail: {offer}}, (resp) => {
+ checkPayment() {
+ let msg = {
+ type: 'check-pay',
+ detail: {
+ offer: this.props.offer
+ }
+ };
+ chrome.runtime.sendMessage(msg, (resp) => {
if (resp.error) {
console.log("check-pay error", JSON.stringify(resp));
switch (resp.error) {
case "coins-insufficient":
- error = i18n`You have insufficient funds of the requested currency in your wallet.`;
+ this.state.error = i18n`You have insufficient funds of the requested currency in your wallet.`;
break;
default:
- error = `Error: ${resp.error}`;
+ this.state.error = `Error: ${resp.error}`;
break;
}
- payDisabled = true;
+ this.state.payDisabled = true;
} else {
- payDisabled = false;
- error = null;
+ this.state.payDisabled = false;
+ this.state.error = null;
}
- m.redraw();
- window.setTimeout(checkPayment, 300);
+ this.forceUpdate();
+ window.setTimeout(() => this.checkPayment(), 300);
});
}
- checkPayment();
-
-
- function doPayment() {
- let d = {offer};
+ doPayment() {
+ let d = {offer: this.props.offer};
chrome.runtime.sendMessage({type: 'confirm-pay', detail: d}, (resp) => {
if (resp.error) {
console.log("confirm-pay error", JSON.stringify(resp));
switch (resp.error) {
case "coins-insufficient":
- error = "You do not have enough coins of the requested currency.";
+ this.state.error = "You do not have enough coins of the" +
+ " requested currency.";
break;
default:
- error = `Error: ${resp.error}`;
+ this.state.error = `Error: ${resp.error}`;
break;
}
- m.redraw();
+ preact.rerender();
return;
}
let c = d.offer.contract;
console.log("contract", c);
document.location.href = substituteFulfillmentUrl(c.fulfillment_url,
- offer);
+ this.props.offer);
});
}
+
+
+ render(props: ContractPromptProps, state: ContractPromptState) {
+ let c = props.offer.contract;
+ return h("div", {},
+ renderContract(c),
+ h("button",
+ {
+ onClick: () => this.doPayment(),
+ disabled: state.payDisabled,
+ "className": "accept"
+ },
+ i18n`Confirm Payment`),
+ (state.error ? h("p",
+ {className: "errorbox"},
+ state.error) : h("p", "")),
+ h(Details, {contract: c})
+ );
+ }
+}
+
+
+export function main() {
+ let url = URI(document.location.href);
+ let query: any = URI.parseQuery(url.query());
+ let offer = JSON.parse(query.offer);
+ console.dir(offer);
+ let contract = offer.contract;
+
+
+ let prompt = h(ContractPrompt, {offer});
+ preact.render(prompt, document.getElementById("contract")!);
}