<commit_before>define(["./frame"], function (Frame) {
    "use strict";

    /**
     * Constructs a new Graph
     * @constructor
     * @alias Graph
     *
     * @param {Object} props - Object containing optional properties of the Graph
     * @param {Boolean} props.antialias - 'true' if antialiasing should be enabled on the graph. Defaults to 'false'.
     * @param {Boolean} props.sizeAttenuation - 'true' if nodes' size should change with distance. Defaults to 'false'.
     * @param {String} props.nodeImage - Path to an image to use for the graph nodes, defaults to no image.
     * @param {Boolean} props.nodeImageTransparent - 'true' if the node image has transparency, defaults to 'false'.
     * @param {Number} props.nodeSize - Number representing the size of the nodes within the graph
     * @param {Number} props.edgeWidth - Number representing the width of the edges within the graph
     * @param {Number|String} props.bgColor - Hexadecimal or CSS-style string representation the color of the background
     * @param {Number} props.bgOpacity - Number (between 0 and 1) indicating the opacity of the background
     */
    var Graph = function (props) {
        this._nodeIds = {};
        this._nodes = [];
        this._edges = [];
        this._initProps(props);
    };

    Graph.prototype._initProps = function (properties) {
        properties = properties || {};

        this._antialias = !!properties.antialias;

        this._sizeAttenuation = !!properties.sizeAttenuation;

        this._nodeImage = properties.nodeImage || undefined;

        this._nodeImageTransparent = !!properties.nodeImageTransparent;

        this._nodeSize = properties.nodeSize !== undefined ? properties.nodeSize : 10;

        this._bgColor = properties.bgColor || "white";

        this._bgOpacity = properties.bgOpacity !== undefined ? properties.bgOpacity : 1;

        this._edgeWidth = properties.edgeWidth !== undefined ? properties.edgeWidth : 1;

        return this;
    };

    Graph.prototype.addNode = function (node) {
        var id = node.getId();

        if (id) {
            this._nodeIds[id] = node;
        }

        this._nodes.push(node);

        return this;
    };

    Graph.prototype.getNode = function (id) {
        return this._nodeIds[id];
    };

    Graph.prototype.getNodes = function () {
        return this._nodes;
    };

    Graph.prototype.getEdges = function () {
        return this._edges;
    };

    /**
     * Add an Edge to the Graph. Upon adding, if the Edge contains Node string ID's, they will be looked up in the Graph and replaced with Node instances.
     */
    Graph.prototype.addEdge = function (edge) {
        this._resolveEdgeIds(edge);
        this._edges.push(edge);

        return this;
    };

    /**
     * Replace string IDs representing Nodes in Edges with Node references
     * @private
     *
     * @param {Edge} edge - Edge that
     * @returns {undefined}
     */
    Graph.prototype._resolveEdgeIds = function (edge) {
        var nodes = edge.getNodes(), type;

        type = typeof nodes[0];
        if (type === "string" || type === "number") {
            nodes[0] = this.getNode(nodes[0]);
        }

        type = typeof nodes[1];
        if (type === "string" || type === "number") {
            nodes[1] = this.getNode(nodes[1]);
        }
    };

    Graph.prototype.renderIn = function (elem) {
        return new Frame(elem, this);
    };

    return Graph;
});
<commit_msg>Clarify nodeSize, edgeWidth documentation<commit_after>define(["./frame"], function (Frame) {
    "use strict";

    /**
     * Constructs a new Graph
     * @constructor
     * @alias Graph
     *
     * @param {Object} props - Object containing optional properties of the Graph
     * @param {Boolean} props.antialias - 'true' if antialiasing should be enabled on the graph. Defaults to 'false'.
     * @param {Boolean} props.sizeAttenuation - 'true' if nodes' size should change with distance. Defaults to 'false'.
     * @param {String} props.nodeImage - Path to an image to use for the graph nodes, defaults to no image.
     * @param {Boolean} props.nodeImageTransparent - 'true' if the node image has transparency, defaults to 'false'.
     * @param {Number} props.nodeSize - Number representing the size (in pixels) of the nodes within the graph, defaults to 10
     * @param {Number} props.edgeWidth - Number representing the width (in pixels) of the edges within the graph, defaults to 1
     * @param {Number|String} props.bgColor - Hexadecimal or CSS-style string representation the color of the background
     * @param {Number} props.bgOpacity - Number (between 0 and 1) indicating the opacity of the background
     */
    var Graph = function (props) {
        this._nodeIds = {};
        this._nodes = [];
        this._edges = [];
        this._initProps(props);
    };

    Graph.prototype._initProps = function (properties) {
        properties = properties || {};

        this._antialias = !!properties.antialias;

        this._sizeAttenuation = !!properties.sizeAttenuation;

        this._nodeImage = properties.nodeImage || undefined;

        this._nodeImageTransparent = !!properties.nodeImageTransparent;

        this._nodeSize = properties.nodeSize !== undefined ? properties.nodeSize : 10;

        this._bgColor = properties.bgColor || "white";

        this._bgOpacity = properties.bgOpacity !== undefined ? properties.bgOpacity : 1;

        this._edgeWidth = properties.edgeWidth !== undefined ? properties.edgeWidth : 1;

        return this;
    };

    Graph.prototype.addNode = function (node) {
        var id = node.getId();

        if (id) {
            this._nodeIds[id] = node;
        }

        this._nodes.push(node);

        return this;
    };

    Graph.prototype.getNode = function (id) {
        return this._nodeIds[id];
    };

    Graph.prototype.getNodes = function () {
        return this._nodes;
    };

    Graph.prototype.getEdges = function () {
        return this._edges;
    };

    /**
     * Add an Edge to the Graph. Upon adding, if the Edge contains Node string ID's, they will be looked up in the Graph and replaced with Node instances.
     */
    Graph.prototype.addEdge = function (edge) {
        this._resolveEdgeIds(edge);
        this._edges.push(edge);

        return this;
    };

    /**
     * Replace string IDs representing Nodes in Edges with Node references
     * @private
     *
     * @param {Edge} edge - Edge that
     * @returns {undefined}
     */
    Graph.prototype._resolveEdgeIds = function (edge) {
        var nodes = edge.getNodes(), type;

        type = typeof nodes[0];
        if (type === "string" || type === "number") {
            nodes[0] = this.getNode(nodes[0]);
        }

        type = typeof nodes[1];
        if (type === "string" || type === "number") {
            nodes[1] = this.getNode(nodes[1]);
        }
    };

    Graph.prototype.renderIn = function (elem) {
        return new Frame(elem, this);
    };

    return Graph;
});
<|endoftext|>


<commit_before>import {Component, Template} from 'angular2/angular2';
import {If} from 'angular2/angular2';
import {bootstrap} from 'angular2/angular2';

@Component({
    selector: 'hello'  //TODO: default to camel-cased class name if not provided?
})
@Template({
    inline: `<span *if="name">Hello, {{name}}!</span>`,
    directives: [If]
})
export class Hello {
    name: string = 'World';
    constructor() {
        setTimeout(() => {
          this.name = 'NEW World'
        }, 2000);
    }
}

bootstrap(Hello);<commit_msg>refactor: simplify imports<commit_after>import {Component, Template, bootstrap, If} from 'angular2/angular2';

@Component({
    selector: 'hello'  //TODO: default to camel-cased class name if not provided?
})
@Template({
    inline: `<span *if="name">Hello, {{name}}!</span>`,
    directives: [If]
})
export class Hello {
    name: string = 'World';
    constructor() {
        setTimeout(() => {
          this.name = 'NEW World'
        }, 2000);
    }
}

bootstrap(Hello);
<|endoftext|>


<commit_before>var {EventEmitter} = require("events");
var _ = require("./_");
var util = require("./util");
var hash = require("./hash");

module.exports = class extends EventEmitter {
  constructor(sock) {
    super();
    Object.assign(this, {
      isBot: false,
      isConnected: false,
      id: sock.id,
      ip: sock.ip,
      name: sock.name,
      time: 0,
      packs: [],
      autopick_index: -1,
      pool: [],
      cap: {
        packs: {}
      },
      picks: [],
      draftLog: {
        round : {},
        pack: []
      },
      draftStats: [],
      pickNumber: 0
    });
    this.attach(sock);
  }
  get isActive() {
    // Note that a player can be transmuted into a bot when they are kicked.
    return this.isConnected && !this.isBot;
  }
  attach(sock) {
    if (this.sock && this.sock !== sock)
      this.sock.ws.close();

    sock.mixin(this);
    sock.removeAllListeners("autopick");
    sock.on("autopick", this._autopick.bind(this));
    sock.removeAllListeners("pick");
    sock.on("pick", this._pick.bind(this));
    sock.removeAllListeners("hash");
    sock.on("hash", this._hash.bind(this));
    sock.once("exit", this._farewell.bind(this));

    var [pack] = this.packs;
    if (pack)
      this.send("pack", pack);
    this.send("pool", this.pool);
  }
  err(message) {
    this.send("error", message);
  }
  _hash(deck) {
    if (!util.deck(deck, this.pool))
      return;

    this.hash = hash(deck);
    this.emit("meta");
  }
  _farewell() {
    this.isConnected = false;
    this.send = () => {};
    this.emit("meta");
  }
  _autopick(index) {
    var [pack] = this.packs;
    if (pack && index < pack.length)
      this.autopick_index = index;
  }
  _pick(index) {
    var [pack] = this.packs;
    if (pack && index < pack.length)
      this.pick(index);
  }
  getPack(pack) {
    if (this.packs.push(pack) === 1)
      this.sendPack(pack);
  }
  sendPack(pack) {
    if (pack.length === 1)
      return this.pick(0);

    if (this.useTimer) {
      var timer = [];
      // http://www.wizards.com/contentresources/wizards/wpn/main/documents/magic_the_gathering_tournament_rules_pdf1.pdf pp43
      // official WOTC timings are
      // pick #, time in seconds)
      // (1,40)(2,40)(3,35)(4,30)(5,25)(6,25)(7,20)(8,20)(9,15)(10,10)(11,10)(12,5)(13,5)(14,5)(15,0)
      var MTRTimes = [40,40,35,30,25,25,20,20,15,10,10,5,5,5,5];
      // whereas MTGO starts @ 75s and decrements by 5s per pick
      var MTGOTimes = [75,70,65,60,55,50,45,40,35,30,25,20,15,12,10];
      // and here's a happy medium
      var AVGTimes = [55,51,47,43,38,34,30,26,22,18,14,13,11,9];
      timer = AVGTimes;
      if (this.timerLength == "Fast") {
        timer = MTRTimes;
      }
      if (this.timerLength == "Slow") {
        timer = MTGOTimes;
      }
      if (this.timerLength == "Leisurely") {
        timer = [90,85,80,75,70,65,60,55,50,45,40,35,30,25];
      }
      // if a pack has more than 15 cards in it, add the average decrement on to the first picks
      if (pack.length + this.picks.length > 15) {
        for (var x = 15; x < (pack.length + this.picks.length); x++) {
          timer.splice(0, 0, ((timer[0] + ((timer[0] + timer[timer.length - 1]) / timer.length))) | 0);
        }
      }
      this.time = timer[this.picks.length];
    }
    else {
      this.time = 0;
    }

    this.send("pickNumber", ++this.pickNumber);
    this.send("pack", pack);
  }
  updateDraftStats(pack, pool) {
    var picked;
    var notPicked = [];
    for (var card in pack) {
      pack[card].charAt(0) === "-" ?
        picked = pack[card].slice(4) :
        notPicked.push( pack[card].slice(4) );
    }
    let namePool = pool.map(card => card.name);
    this.draftStats.push( { picked, notPicked, pool: namePool } );
  }
  pick(index) {
    var pack = this.packs.shift();
    var card = pack.splice(index, 1)[0];

    this.draftLog.pack.push( [`--> ${card.name}`].concat(pack.map(x => `    ${x.name}`)) );
    this.updateDraftStats(this.draftLog.pack[ this.draftLog.pack.length-1 ], this.pool);

    var pickcard = card.name;
    if (card.foil == true)
      pickcard = "*" + pickcard + "*";

    this.pool.push(card);
    this.picks.push(pickcard);
    this.send("add", card.name);

    var [next] = this.packs;
    if (!next)
      this.time = 0;
    else
      this.sendPack(next);

    this.autopick_index = -1;
    this.emit("pass", pack);
  }
  pickOnTimeout() {
    let index = this.autopick_index;
    if (index === -1)
      index = _.rand(this.packs[0].length);
    this.pick(index);
  }
  kick() {
    this.send = ()=>{};
    while(this.packs.length)
      this.pickOnTimeout();
    this.sendPack = this.pickOnTimeout;
    this.isBot = true;
  }
};
<commit_msg>disable autopick for last pick (#359)<commit_after>var {EventEmitter} = require("events");
var _ = require("./_");
var util = require("./util");
var hash = require("./hash");

module.exports = class extends EventEmitter {
  constructor(sock) {
    super();
    Object.assign(this, {
      isBot: false,
      isConnected: false,
      id: sock.id,
      ip: sock.ip,
      name: sock.name,
      time: 0,
      packs: [],
      autopick_index: -1,
      pool: [],
      cap: {
        packs: {}
      },
      picks: [],
      draftLog: {
        round : {},
        pack: []
      },
      draftStats: [],
      pickNumber: 0
    });
    this.attach(sock);
  }
  get isActive() {
    // Note that a player can be transmuted into a bot when they are kicked.
    return this.isConnected && !this.isBot;
  }
  attach(sock) {
    if (this.sock && this.sock !== sock)
      this.sock.ws.close();

    sock.mixin(this);
    sock.removeAllListeners("autopick");
    sock.on("autopick", this._autopick.bind(this));
    sock.removeAllListeners("pick");
    sock.on("pick", this._pick.bind(this));
    sock.removeAllListeners("hash");
    sock.on("hash", this._hash.bind(this));
    sock.once("exit", this._farewell.bind(this));

    var [pack] = this.packs;
    if (pack)
      this.send("pack", pack);
    this.send("pool", this.pool);
  }
  err(message) {
    this.send("error", message);
  }
  _hash(deck) {
    if (!util.deck(deck, this.pool))
      return;

    this.hash = hash(deck);
    this.emit("meta");
  }
  _farewell() {
    this.isConnected = false;
    this.send = () => {};
    this.emit("meta");
  }
  _autopick(index) {
    var [pack] = this.packs;
    if (pack && index < pack.length)
      this.autopick_index = index;
  }
  _pick(index) {
    var [pack] = this.packs;
    if (pack && index < pack.length)
      this.pick(index);
  }
  getPack(pack) {
    if (this.packs.push(pack) === 1)
      this.sendPack(pack);
  }
  sendPack(pack) {
    if (this.useTimer) {
      var timer = [];
      // http://www.wizards.com/contentresources/wizards/wpn/main/documents/magic_the_gathering_tournament_rules_pdf1.pdf pp43
      // official WOTC timings are
      // pick #, time in seconds)
      // (1,40)(2,40)(3,35)(4,30)(5,25)(6,25)(7,20)(8,20)(9,15)(10,10)(11,10)(12,5)(13,5)(14,5)(15,0)
      var MTRTimes = [40,40,35,30,25,25,20,20,15,10,10,5,5,5,5];
      // whereas MTGO starts @ 75s and decrements by 5s per pick
      var MTGOTimes = [75,70,65,60,55,50,45,40,35,30,25,20,15,12,10];
      // and here's a happy medium
      var AVGTimes = [55,51,47,43,38,34,30,26,22,18,14,13,11,9];
      timer = AVGTimes;
      if (this.timerLength == "Fast") {
        timer = MTRTimes;
      }
      if (this.timerLength == "Slow") {
        timer = MTGOTimes;
      }
      if (this.timerLength == "Leisurely") {
        timer = [90,85,80,75,70,65,60,55,50,45,40,35,30,25];
      }
      // if a pack has more than 15 cards in it, add the average decrement on to the first picks
      if (pack.length + this.picks.length > 15) {
        for (var x = 15; x < (pack.length + this.picks.length); x++) {
          timer.splice(0, 0, ((timer[0] + ((timer[0] + timer[timer.length - 1]) / timer.length))) | 0);
        }
      }
      this.time = timer[this.picks.length];
    }
    else {
      this.time = 0;
    }

    this.send("pickNumber", ++this.pickNumber);
    this.send("pack", pack);
  }
  updateDraftStats(pack, pool) {
    var picked;
    var notPicked = [];
    for (var card in pack) {
      pack[card].charAt(0) === "-" ?
        picked = pack[card].slice(4) :
        notPicked.push( pack[card].slice(4) );
    }
    let namePool = pool.map(card => card.name);
    this.draftStats.push( { picked, notPicked, pool: namePool } );
  }
  pick(index) {
    var pack = this.packs.shift();
    var card = pack.splice(index, 1)[0];

    this.draftLog.pack.push( [`--> ${card.name}`].concat(pack.map(x => `    ${x.name}`)) );
    this.updateDraftStats(this.draftLog.pack[ this.draftLog.pack.length-1 ], this.pool);

    var pickcard = card.name;
    if (card.foil == true)
      pickcard = "*" + pickcard + "*";

    this.pool.push(card);
    this.picks.push(pickcard);
    this.send("add", card.name);

    var [next] = this.packs;
    if (!next)
      this.time = 0;
    else
      this.sendPack(next);

    this.autopick_index = -1;
    this.emit("pass", pack);
  }
  pickOnTimeout() {
    let index = this.autopick_index;
    if (index === -1)
      index = _.rand(this.packs[0].length);
    this.pick(index);
  }
  kick() {
    this.send = ()=>{};
    while(this.packs.length)
      this.pickOnTimeout();
    this.sendPack = this.pickOnTimeout;
    this.isBot = true;
  }
};
<|endoftext|>


<commit_before>import React from 'react';
import { storiesOf } from '@storybook/react';
import { boolean, number, select } from '@storybook/addon-knobs/react';
import {
  InputBase,
  Button,
  Checkbox,
  Counter,
  Icon,
  Input,
  Label,
  LoadingSpinner,
  NumericInput,
  TextBody,
  TextSmall,
  Tooltip,
  SingleLineInputBase,
} from '../components';
import { IconCalendarSmallOutline, IconInfoBadgedSmallFilled } from '@teamleader/ui-icons';

const colors = ['aqua', 'gold', 'mint', 'neutral', 'ruby', 'teal', 'violet'];
const sizes = ['small', 'medium', 'large'];
const tints = ['lightest', 'light', 'normal', 'dark', 'darkest'];

const prefix = [
  <Icon color="neutral" tint="darkest">
    <IconCalendarSmallOutline />
  </Icon>,
  <TextBody color="neutral">€</TextBody>,
];

const suffix = [<TextSmall color="neutral">incl. BTW</TextSmall>, <Counter count={99} />, <LoadingSpinner />];

const props = {
  helpText: 'This is the fields help text',
  placeholder: 'Placeholder',
  onChange: (event, value) => console.log('Changing to ', value),
};

const TooltippedIcon = Tooltip(Icon);

storiesOf('Inputs', module)
  .add('Input base', () => <InputBase />)
  .add('Single line input base', () => <SingleLineInputBase />)
  .add('Input only', () => (
    <Input
      id="input1"
      bold={boolean('Bold', false)}
      disabled={boolean('Disabled', false)}
      readOnly={boolean('Read only', false)}
      {...props}
    />
  ))
  .add('text', () => (
    <Label htmlFor="input1" inverse={boolean('Inverse', false)} size={select('Size', sizes, 'medium')}>
      Input label
      <Input
        id="input1"
        bold={boolean('Bold', false)}
        disabled={boolean('Disabled', false)}
        readOnly={boolean('Read only', false)}
        {...props}
      />
    </Label>
  ))
  .add('password', () => (
    <Label htmlFor="input1" inverse={boolean('Inverse', false)} size={select('Size', sizes, 'medium')}>
      Input label
      <Input
        id="input1"
        type="password"
        bold={boolean('Bold', false)}
        disabled={boolean('Disabled', false)}
        readOnly={boolean('Read only', false)}
        {...props}
      />
    </Label>
  ))
  .add('Numeric', () => (
    <Label htmlFor="input1" inverse={boolean('Inverse', false)} size={select('Size', sizes, 'medium')}>
      Input label
      <NumericInput
        id="input1"
        bold={boolean('Bold', false)}
        disabled={boolean('Disabled', false)}
        readOnly={boolean('Read only', false)}
        min={number('Minimum', 0)}
        max={number('Maximum', 10)}
        spinner={boolean('Render spinner', true)}
        step={number('Step', 1)}
        {...props}
      />
    </Label>
  ))
  .add('with error', () => (
    <Label htmlFor="input1" inverse={boolean('Inverse', false)} size={select('Size', sizes, 'medium')}>
      Input label
      <Input
        error="This is an error message"
        id="input1"
        size="small"
        value="wrong value"
        bold={boolean('Bold', false)}
        disabled={boolean('Disabled', false)}
        readOnly={boolean('Read only', false)}
        {...props}
      />
    </Label>
  ))
  .add('with label tooltip', () => (
    <Label
      connectedRight={
        <TooltippedIcon
          color={select('Icon color', colors, 'teal')}
          tint={select('Icon tint', tints, 'dark')}
          tooltip={<TextSmall>This is the label tooltip text</TextSmall>}
          tooltipSize="small"
        >
          <IconInfoBadgedSmallFilled />
        </TooltippedIcon>
      }
      htmlFor="input1"
      inverse={boolean('Inverse', false)}
      size={select('Size', sizes, 'medium')}
    >
      Input label
      <Input
        id="input1"
        size="small"
        value="wrong value"
        bold={boolean('Bold', false)}
        disabled={boolean('Disabled', false)}
        readOnly={boolean('Read only', false)}
        {...props}
      />
    </Label>
  ))
  .add('with prefix or suffix', () => (
    <Label htmlFor="input1" inverse={boolean('Inverse', false)} size={select('Size', sizes, 'medium')}>
      Input label
      <Input
        id="input1"
        bold={boolean('Bold', false)}
        disabled={boolean('Disabled', false)}
        readOnly={boolean('Read only', false)}
        prefix={prefix}
        suffix={suffix}
        {...props}
      />
    </Label>
  ))
  .add('with connected elements', () => (
    <Label htmlFor="input1" inverse={boolean('Inverse', false)} size={select('Size', sizes, 'medium')}>
      Input label
      <Input
        id="input1"
        bold={boolean('Bold', false)}
        connectedLeft={<Button size={select('Size', sizes, 'medium')} label="€" />}
        connectedRight={
          <Button size={select('Size', sizes, 'medium')}>
            <Checkbox size="small">Discount</Checkbox>
          </Button>
        }
        disabled={boolean('Disabled', false)}
        type="number"
        min={number('Minimum', 0)}
        max={number('Maximum', 10)}
        step={number('Step', 1)}
        readOnly={boolean('Read only', false)}
        {...props}
      />
    </Label>
  ));
<commit_msg>Add knobs on the components added/adapted in this PR se we can test the components better<commit_after>import React from 'react';
import { storiesOf } from '@storybook/react';
import { boolean, number, select, text } from '@storybook/addon-knobs/react';
import {
  InputBase,
  Button,
  Checkbox,
  Counter,
  Icon,
  Input,
  Label,
  LoadingSpinner,
  NumericInput,
  TextBody,
  TextSmall,
  Tooltip,
  SingleLineInputBase,
} from '../components';
import { IconCalendarSmallOutline, IconInfoBadgedSmallFilled } from '@teamleader/ui-icons';

const colors = ['aqua', 'gold', 'mint', 'neutral', 'ruby', 'teal', 'violet'];
const elements = [null, 'input', 'textarea'];
const sizes = [null, 'small', 'medium', 'large'];
const tints = ['lightest', 'light', 'normal', 'dark', 'darkest'];
const types = [
  null,
  'text',
  'button',
  'checkbox',
  'color',
  'date',
  'datetime-local',
  'email',
  'file',
  'hidden',
  'image',
  'month',
  'number',
  'password',
  'radio',
  'range',
  'reset',
  'search',
  'submit',
  'tel',
  'time',
  'url',
  'week',
];

const prefix = [
  <Icon color="neutral" tint="darkest">
    <IconCalendarSmallOutline />
  </Icon>,
  <TextBody color="neutral">€</TextBody>,
];

const suffix = [<TextSmall color="neutral">incl. BTW</TextSmall>, <Counter count={99} />, <LoadingSpinner />];

const connectedLeft = <Button label="€" />;
const connectedRight = (
  <Button>
    <Checkbox size="small">Discount</Checkbox>
  </Button>
);

const props = {
  helpText: 'This is the fields help text',
  placeholder: 'Placeholder',
  onChange: (event, value) => console.log('Changing to ', value),
};

const TooltippedIcon = Tooltip(Icon);

storiesOf('Inputs', module)
  .add('Input base', () => (
    <InputBase
      bold={boolean('bold', false)}
      disabled={boolean('disabled', false)}
      element={select('element', elements) || undefined}
      inverse={boolean('inverse', false)}
      readOnly={boolean('readOnly', false)}
      size={select('size', sizes) || undefined}
      type={select('type', types) || undefined}
      value={text('value', undefined)}
    />
  ))
  .add('Single line input base', () => {
    const hasPrefix = boolean('render a prefix', false);
    const hasSuffix = boolean('render a suffix', false);
    const hasConnectedLeft = boolean('render a connectedLeft', false);
    const hasConnectedRight = boolean('render a connectedRight', false);

    return (
      <SingleLineInputBase
        bold={boolean('bold', false)}
        disabled={boolean('disabled', false)}
        element={select('element', elements) || undefined}
        error={text('error', undefined)}
        helpText={text('helpText', undefined)}
        inverse={boolean('inverse', false)}
        readOnly={boolean('readOnly', false)}
        size={select('size', sizes) || undefined}
        type={select('type', types) || undefined}
        value={text('value', undefined)}
        prefix={hasPrefix ? prefix : undefined}
        suffix={hasSuffix ? suffix : undefined}
        connectedLeft={hasConnectedLeft ? connectedLeft : undefined}
        connectedRight={hasConnectedRight ? connectedRight : undefined}
      />
    );
  })
  .add('Input only', () => (
    <Input
      id="input1"
      bold={boolean('Bold', false)}
      disabled={boolean('Disabled', false)}
      readOnly={boolean('Read only', false)}
      {...props}
    />
  ))
  .add('text', () => (
    <Label htmlFor="input1" inverse={boolean('Inverse', false)} size={select('Size', sizes, 'medium')}>
      Input label
      <Input
        id="input1"
        bold={boolean('Bold', false)}
        disabled={boolean('Disabled', false)}
        readOnly={boolean('Read only', false)}
        {...props}
      />
    </Label>
  ))
  .add('password', () => (
    <Label htmlFor="input1" inverse={boolean('Inverse', false)} size={select('Size', sizes, 'medium')}>
      Input label
      <Input
        id="input1"
        type="password"
        bold={boolean('Bold', false)}
        disabled={boolean('Disabled', false)}
        readOnly={boolean('Read only', false)}
        {...props}
      />
    </Label>
  ))
  .add('Numeric', () => (
    <Label htmlFor="input1" inverse={boolean('Inverse', false)} size={select('Size', sizes, 'medium')}>
      Input label
      <NumericInput
        id="input1"
        bold={boolean('Bold', false)}
        disabled={boolean('Disabled', false)}
        readOnly={boolean('Read only', false)}
        min={number('Minimum', 0)}
        max={number('Maximum', 10)}
        spinner={boolean('Render spinner', true)}
        step={number('Step', 1)}
        {...props}
      />
    </Label>
  ))
  .add('with error', () => (
    <Label htmlFor="input1" inverse={boolean('Inverse', false)} size={select('Size', sizes, 'medium')}>
      Input label
      <Input
        error="This is an error message"
        id="input1"
        size="small"
        value="wrong value"
        bold={boolean('Bold', false)}
        disabled={boolean('Disabled', false)}
        readOnly={boolean('Read only', false)}
        {...props}
      />
    </Label>
  ))
  .add('with label tooltip', () => (
    <Label
      connectedRight={
        <TooltippedIcon
          color={select('Icon color', colors, 'teal')}
          tint={select('Icon tint', tints, 'dark')}
          tooltip={<TextSmall>This is the label tooltip text</TextSmall>}
          tooltipSize="small"
        >
          <IconInfoBadgedSmallFilled />
        </TooltippedIcon>
      }
      htmlFor="input1"
      inverse={boolean('Inverse', false)}
      size={select('Size', sizes, 'medium')}
    >
      Input label
      <Input
        id="input1"
        size="small"
        value="wrong value"
        bold={boolean('Bold', false)}
        disabled={boolean('Disabled', false)}
        readOnly={boolean('Read only', false)}
        {...props}
      />
    </Label>
  ))
  .add('with prefix or suffix', () => (
    <Label htmlFor="input1" inverse={boolean('Inverse', false)} size={select('Size', sizes, 'medium')}>
      Input label
      <Input
        id="input1"
        bold={boolean('Bold', false)}
        disabled={boolean('Disabled', false)}
        readOnly={boolean('Read only', false)}
        prefix={prefix}
        suffix={suffix}
        {...props}
      />
    </Label>
  ))
  .add('with connected elements', () => (
    <Label htmlFor="input1" inverse={boolean('Inverse', false)} size={select('Size', sizes, 'medium')}>
      Input label
      <Input
        id="input1"
        bold={boolean('Bold', false)}
        connectedLeft={<Button size={select('Size', sizes, 'medium')} label="€" />}
        connectedRight={
          <Button size={select('Size', sizes, 'medium')}>
            <Checkbox size="small">Discount</Checkbox>
          </Button>
        }
        disabled={boolean('Disabled', false)}
        type="number"
        min={number('Minimum', 0)}
        max={number('Maximum', 10)}
        step={number('Step', 1)}
        readOnly={boolean('Read only', false)}
        {...props}
      />
    </Label>
  ));
<|endoftext|>


<commit_before>
var stressDisplayLightBulb_Characteristic = null;
var stressDisplayHeartRate_Characteristic = null;

var stressDisplay_specs = {
    uuid: 0x7777,
    service: '00007777-0000-1000-8000-00805f9b34fb',
    characteristic: ['00008877-0000-1000-8000-00805f9b34fb']
};

function stressDisplay_lightBulb_connect() {
    var serviceUuid = stressDisplay_specs.service;
    var characteristicUuid = stressDisplay_specs.characteristic[0]

    navigator.bluetooth.requestDevice
        ({
            acceptAllDevices: true,
            optionalServices: [
                stressDisplay_specs.uuid,
                // stressDisplay_specs.service,
            ]
        })
        .then(device => { return device.gatt.connect(); })
        .then(server => { return server.getPrimaryService(serviceUuid); })
        .then(service => { return service.getCharacteristic(characteristicUuid); })

        .then(characteristic => {   // Save characteristic
            stressDisplayLightBulb_Characteristic = characteristic;
            return characteristic;
        })
        .then(characteristic => {   // Set to blue when starting
            var send = getPayload(0x00, 0x00, 0xff);
            characteristic.writeValue(send);

            return characteristic;
        })
        .catch(error => {   // Handle Errors
            log('Error! ' + error);
        });
}

function stressDisplay_heartRate_connect() {
    let serviceUuid = "heart_rate";
    let characteristicUuid = "heart_rate_measurement"

    navigator.bluetooth.requestDevice
        ({
            filters: [{ services: [serviceUuid] }]
        })
        .then(device => { return device.gatt.connect(); })
        .then(server => { return server.getPrimaryService(serviceUuid); })
        .then(service => { return service.getCharacteristic(characteristicUuid); })
        .then(characteristic => {   // Save characteristic
            stressDisplayHeartRate_Characteristic = characteristic;
            return characteristic;
        })
        .then(characteristic => {   // Start notification
            return characteristic.startNotifications()
                .then(_ => {
                    characteristic.addEventListener(
                        'characteristicvaluechanged',
                        stressDisplay_read);
                });
        })
        .catch(error => {   // Handle Errors
            log('Error! ' + error);
        });
}

function stressDisplay_read(event) {
    let value = event.target.value;

    var bpm = value.getUint8(1);
    setHeartRateValue(bpm);

    var minStress = parseInt(document.getElementById("minStress").value);
    var maxStress = parseInt(document.getElementById("maxStress").value);

    var lut =  // determine a color based on the bpm value
        (bpm < minStress) ?
            { r: 0x00, g: 0xef * (bpm - 50) / (minStress - 50) + 0x10, b: 0x00 } : // green
            (bpm > maxStress) ?
                { r: 0xef * (bpm - maxStress) / (100 - maxStress) + 0x10, g: 0x00, b: 0x00 } :  // red
                {
                    r: 0xef * (bpm - minStress) / (maxStress - minStress) + 0x10,
                    g: 0xef * (bpm - minStress) / (maxStress - minStress) + 0x10,
                    b: 0x00
                }; // yellow

    setColorValue(lut.r, lut.g, lut.b);

    log('{'
        + '0x' + ('0' + (lut.r & 0xFF).toString(16)).slice(-2) + ', '
        + '0x' + ('0' + (lut.g & 0xFF).toString(16)).slice(-2) + ', '
        + '0x' + ('0' + (lut.b & 0xFF).toString(16)).slice(-2)
        + '}, '
        + bpm.toString().padStart(3) + '|' + '-'.repeat(bpm-40) + '>'
    );

    var send = getPayload(lut.r, lut.g, lut.b);
    stressDisplayLightBulb_Characteristic.writeValue(send);
    sleep(50);
}

function getPayload(r, g, b) {   // Create the payload
    var data = [
        0x01, 0xfe, 0x00, 0x00, 0x53, 0x83, 0x10, 0x00,
        g, // Green
        b, // Blue
        r, // Red
        0x00, 0x50, 0x00, 0x00, 0x00
    ];
    return Uint8Array.from(data); Í
}

function stressDisplay_disconnect() {   // Disconnect
    if (stressDisplayLightBulb_Characteristic) {
        stressDisplayLightBulb_Characteristic.stopNotifications()
            .then(_ => { })
            .catch(error => {
                log('Error! ' + error);
            });
    }
    if (stressDisplayHeartRate_Characteristic) {
        stressDisplayHeartRate_Characteristic.stopNotifications()
            .then(_ => {
                stressDisplayHeartRate_Characteristic.removeEventListener(
                    'characteristicvaluechanged',
                    stressDisplay_read);
            })
            .catch(error => {
                log('Error! ' + error);
            });
    }
}<commit_msg>Remove RGB values in Results area.<commit_after>
var stressDisplayLightBulb_Characteristic = null;
var stressDisplayHeartRate_Characteristic = null;

var stressDisplay_specs = {
    uuid: 0x7777,
    service: '00007777-0000-1000-8000-00805f9b34fb',
    characteristic: ['00008877-0000-1000-8000-00805f9b34fb']
};

function stressDisplay_lightBulb_connect() {
    var serviceUuid = stressDisplay_specs.service;
    var characteristicUuid = stressDisplay_specs.characteristic[0]

    navigator.bluetooth.requestDevice
        ({
            acceptAllDevices: true,
            optionalServices: [
                stressDisplay_specs.uuid,
                // stressDisplay_specs.service,
            ]
        })
        .then(device => { return device.gatt.connect(); })
        .then(server => { return server.getPrimaryService(serviceUuid); })
        .then(service => { return service.getCharacteristic(characteristicUuid); })

        .then(characteristic => {   // Save characteristic
            stressDisplayLightBulb_Characteristic = characteristic;
            return characteristic;
        })
        .then(characteristic => {   // Set to blue when starting
            var send = getPayload(0x00, 0x00, 0xff);
            characteristic.writeValue(send);

            return characteristic;
        })
        .catch(error => {   // Handle Errors
            log('Error! ' + error);
        });
}

function stressDisplay_heartRate_connect() {
    let serviceUuid = "heart_rate";
    let characteristicUuid = "heart_rate_measurement"

    navigator.bluetooth.requestDevice
        ({
            filters: [{ services: [serviceUuid] }]
        })
        .then(device => { return device.gatt.connect(); })
        .then(server => { return server.getPrimaryService(serviceUuid); })
        .then(service => { return service.getCharacteristic(characteristicUuid); })
        .then(characteristic => {   // Save characteristic
            stressDisplayHeartRate_Characteristic = characteristic;
            return characteristic;
        })
        .then(characteristic => {   // Start notification
            return characteristic.startNotifications()
                .then(_ => {
                    characteristic.addEventListener(
                        'characteristicvaluechanged',
                        stressDisplay_read);
                });
        })
        .catch(error => {   // Handle Errors
            log('Error! ' + error);
        });
}

function stressDisplay_read(event) {
    let value = event.target.value;

    var bpm = value.getUint8(1);
    setHeartRateValue(bpm);

    var minStress = parseInt(document.getElementById("minStress").value);
    var maxStress = parseInt(document.getElementById("maxStress").value);

    var lut =  // determine a color based on the bpm value
        (bpm < minStress) ?
            { r: 0x00, g: 0xef * (bpm - 50) / (minStress - 50) + 0x10, b: 0x00 } : // green
            (bpm > maxStress) ?
                { r: 0xef * (bpm - maxStress) / (100 - maxStress) + 0x10, g: 0x00, b: 0x00 } :  // red
                {
                    r: 0xef * (bpm - minStress) / (maxStress - minStress) + 0x10,
                    g: 0xef * (bpm - minStress) / (maxStress - minStress) + 0x10,
                    b: 0x00
                }; // yellow

    setColorValue(lut.r, lut.g, lut.b);

    // log('{'
    //     + '0x' + ('0' + (lut.r & 0xFF).toString(16)).slice(-2) + ', '
    //     + '0x' + ('0' + (lut.g & 0xFF).toString(16)).slice(-2) + ', '
    //     + '0x' + ('0' + (lut.b & 0xFF).toString(16)).slice(-2)
    //     + '}, '
    //     + bpm.toString().padStart(3) + '|' + '-'.repeat(bpm - 40) + '>'
    // );
    log(bpm.toString().padStart(3) + '|' + '-'.repeat(bpm-40) + '>');

    var send = getPayload(lut.r, lut.g, lut.b);
    stressDisplayLightBulb_Characteristic.writeValue(send);
    sleep(50);
}

function getPayload(r, g, b) {   // Create the payload
    var data = [
        0x01, 0xfe, 0x00, 0x00, 0x53, 0x83, 0x10, 0x00,
        g, // Green
        b, // Blue
        r, // Red
        0x00, 0x50, 0x00, 0x00, 0x00
    ];
    return Uint8Array.from(data); Í
}

function stressDisplay_disconnect() {   // Disconnect
    if (stressDisplayLightBulb_Characteristic) {
        stressDisplayLightBulb_Characteristic.stopNotifications()
            .then(_ => { })
            .catch(error => {
                log('Error! ' + error);
            });
    }
    if (stressDisplayHeartRate_Characteristic) {
        stressDisplayHeartRate_Characteristic.stopNotifications()
            .then(_ => {
                stressDisplayHeartRate_Characteristic.removeEventListener(
                    'characteristicvaluechanged',
                    stressDisplay_read);
            })
            .catch(error => {
                log('Error! ' + error);
            });
    }
}<|endoftext|>


<commit_before>SVG.Image = SVG.invent({
  // Initialize node
  create: 'image'

  // Inherit from
, inherit: SVG.Shape

  // Add class methods
, extend: {
    // (re)load image
    load: function(url) {
      if (!url) return this

      var self = this
        , img  = document.createElement('img')

      // preload image
      img.onload = function() {
        var p = self.parent(SVG.Pattern)

        if(p === null) return

        // ensure image size
        if (self.width() == 0 && self.height() == 0)
          self.size(img.width, img.height)

        // ensure pattern size if not set
        if (p && p.width() == 0 && p.height() == 0)
          p.size(self.width(), self.height())

        // callback
        if (typeof self._loaded === 'function')
          self._loaded.call(self, {
            width:  img.width
          , height: img.height
          , ratio:  img.width / img.height
          , url:    url
          })
      }

      return this.attr('href', (img.src = this.src = url), SVG.xlink)
    }
    // Add loaded callback
  , loaded: function(loaded) {
      this._loaded = loaded
      return this
    }
  }

  // Add parent method
, construct: {
    // create image element, load image and set its size
    image: function(source, width, height) {
      return this.put(new SVG.Image).load(source).size(width || 0, height || width || 0)
    }
  }

})<commit_msg>add error callback on image loading<commit_after>SVG.Image = SVG.invent({
  // Initialize node
  create: 'image'

  // Inherit from
, inherit: SVG.Shape

  // Add class methods
, extend: {
    // (re)load image
    load: function(url) {
      if (!url) return this

      var self = this
        , img  = document.createElement('img')

      // preload image
      img.onload = function() {
        var p = self.parent(SVG.Pattern)

        if(p === null) return

        // ensure image size
        if (self.width() == 0 && self.height() == 0)
          self.size(img.width, img.height)

        // ensure pattern size if not set
        if (p && p.width() == 0 && p.height() == 0)
          p.size(self.width(), self.height())

        // callback
        if (typeof self._loaded === 'function')
          self._loaded.call(self, {
            width:  img.width
          , height: img.height
          , ratio:  img.width / img.height
          , url:    url
          })
      }

      img.onerror = function(e){
        if (typeof self._error === 'function'){
            self._error.call(self, e)
        }
      }

      return this.attr('href', (img.src = this.src = url), SVG.xlink)
    }
    // Add loaded callback
  , loaded: function(loaded) {
      this._loaded = loaded
      return this
    }

  , error: function(error) {
      this._error = error
      return this
    }
  }

  // Add parent method
, construct: {
    // create image element, load image and set its size
    image: function(source, width, height) {
      return this.put(new SVG.Image).load(source).size(width || 0, height || width || 0)
    }
  }

})<|endoftext|>


<commit_before>import * as directives from './directives'
import * as components from './components'
import { each } from './utils'
import { version } from '../package.json'

export { ErrorBag } from './utils'

export const plugin = {
  version,
  install (Vue, options = {}) {
    if (options.custom === true) {
      components.Modal.props.custom.default = true
      components.InputBox.props.custom.default = true
    }

    each(components, (component, name) => {
      if (options.all || name.startsWith('Input') || name === 'CheckboxWrapper') {
        Vue.component(name, component)
      }
    })
    each(directives, (directive, name) => Vue.directive(name, directive))
  }
}

// Install by default if using the script tag
if (typeof window !== 'undefined' && 'Vue' in window) {
  Vue.use(plugin, window.bootstrapForVueConfig || {}) // eslint-disable-line no-undef
}

<commit_msg>Export formHelper<commit_after>import * as directives from './directives'
import * as components from './components'
import { each } from './utils'
import { version } from '../package.json'

export { formHelper } from './mixins'
export { ErrorBag } from './utils'

export const plugin = {
  version,
  install (Vue, options = {}) {
    if (options.custom === true) {
      components.Modal.props.custom.default = true
      components.InputBox.props.custom.default = true
    }

    each(components, (component, name) => {
      if (options.all || name.startsWith('Input') || name === 'CheckboxWrapper') {
        Vue.component(name, component)
      }
    })
    each(directives, (directive, name) => Vue.directive(name, directive))
  }
}

// Install by default if using the script tag
if (typeof window !== 'undefined' && 'Vue' in window) {
  Vue.use(plugin, window.bootstrapForVueConfig || {}) // eslint-disable-line no-undef
}
<|endoftext|>


<commit_before>var nativeCreate = Object.create;

module.exports = nativeCreate || (function() {
    function F() {}
    return function create(object) {
        F.prototype = object;
        return new F();
    };
}());
<commit_msg>clean up<commit_after>module.exports = Object.create || (function() {
    function F() {}
    return function create(object) {
        F.prototype = object;
        return new F();
    };
}());
<|endoftext|>


<commit_before>var assert = require('assert')

var bitcoin = require('bitcoinjs-lib')
var bip32utils = require('bip32-utils')
var networks = bitcoin.networks
var typeForce = require('typeforce')
var selectInputs = require('./selection')

function Wallet (external, internal) {
  this.account = new bip32utils.Account(external, internal)
  this.external = external
  this.internal = internal
  this.unspents = []
}

Wallet.fromJSON = function (json) {
  var external = bitcoin.HDNode.fromBase58(json.external.node)
  var internal = bitcoin.HDNode.fromBase58(json.internal.node)
  var wallet = new Wallet(external, internal)
  wallet.account.external.addresses = json.external.addresses
  wallet.account.internal.addresses = json.internal.addresses
  wallet.account.external.map = json.external.map
  wallet.account.internal.map = json.internal.map
  wallet.account.external.k = json.external.k
  wallet.account.internal.k = json.internal.k
  wallet.unspents = json.unspents

  return wallet
}

Wallet.fromSeedBuffer = function (seed, network) {
  network = network || networks.bitcoin

  // HD first-level child derivation method should be hardened
  // See https://bitcointalk.org/index.php?topic=405179.msg4415254#msg4415254
  var m = bitcoin.HDNode.fromSeedBuffer(seed, network)
  var i = m.deriveHardened(0)
  var external = i.derive(0)
  var internal = i.derive(1)

  return new Wallet(external, internal)
}

Wallet.prototype.createTransaction = function (outputs, external, internal) {
  external = external || this.external
  internal = internal || this.internal
  var network = this.getNetwork()

  // filter un-confirmed
  var unspents = this.unspents.filter(function (unspent) {
    return unspent.confirmations > 0
  })

  var selection = selectInputs(unspents, outputs, network.feePerKb)
  var inputs = selection.inputs

  // sanity check (until things are battle tested)
  var totalInputValue = inputs.reduce(function (a, x) { return a + x.value }, 0)
  var totalOutputValue = outputs.reduce(function (a, x) { return a + x.value }, 0)
  assert.equal(totalInputValue - totalOutputValue, selection.change + selection.fee)

  // ensure fee isn't crazy (max 0.1 BTC)
  assert(selection.fee < 0.1 * 1e8, 'Very high fee: ' + selection.fee)

  // is the change worth it?
  var change, fee

  if (selection.change > network.dustThreshold) {
    // add the change address w/o mutating
    change = selection.change
    fee = selection.fee
    outputs = outputs.concat({
      address: this.getChangeAddress(),
      value: selection.change
    })

  } else {
    change = 0
    fee = selection.change + selection.fee
  }

  // build transaction
  var txb = new bitcoin.TransactionBuilder()

  // add each input
  inputs.forEach(function (input) {
    txb.addInput(input.txId, input.vout)
  })

  // add each output
  outputs.forEach(function (output) {
    txb.addOutput(output.address, output.value)
  })

  // sign and return
  var addresses = inputs.map(function (input) { return input.address })
  var transaction = this.signWith(txb, addresses, external, internal).build()

  return {
    fee: fee,
    change: change,
    transaction: transaction
  }
}

Wallet.prototype.containsAddress = function (address) { return this.account.containsAddress(address) }
Wallet.prototype.discover = function (gapLimit, queryCallback, done) {
  function discoverChain (iterator, callback) {
    bip32utils.discovery(iterator, gapLimit, queryCallback, function (err, used, checked) {
      if (err) return callback(err)

      // throw away ALL unused addresses AFTER the last unused address
      var unused = checked - used
      for (var i = 1; i < unused; ++i) iterator.pop()

      return callback()
    })
  }

  var external = this.account.external
  var internal = this.account.internal

  discoverChain(external, function (err) {
    if (err) return done(err)

    discoverChain(internal, done)
  })
}
Wallet.prototype.getAllAddresses = function () { return this.account.getAllAddresses() }
Wallet.prototype.getBalance = function () {
  return this.unspents.reduce(function (accum, unspent) {
    return accum + unspent.value
  }, 0)
}
Wallet.prototype.getChangeAddress = function () { return this.account.getInternalAddress() }
Wallet.prototype.getConfirmedBalance = function () {
  return this.unspents.filter(function (unspent) {
    return unspent.confirmations > 0

  }).reduce(function (accum, unspent) {
    return accum + unspent.value
  }, 0)
}
Wallet.prototype.getNetwork = function () { return this.account.getNetwork() }
Wallet.prototype.getReceiveAddress = function () { return this.account.getExternalAddress() }
Wallet.prototype.isChangeAddress = function (address) { return this.account.isInternalAddress(address) }
Wallet.prototype.isReceiveAddress = function (address) { return this.account.isExternalAddress(address) }
Wallet.prototype.nextChangeAddress = function () { return this.account.nextInternalAddress() }
Wallet.prototype.nextReceiveAddress = function () { return this.account.nextExternalAddress() }

Wallet.prototype.setUnspentOutputs = function (unspents) {
  var seen = {}

  unspents.forEach(function (unspent) {
    var txId = unspent.txId

    typeForce({
      txId: 'String',
      confirmations: 'Number',
      address: 'String',
      value: 'Number',
      vout: 'Number'
    }, unspent)

    assert.equal(txId.length, 64, 'Expected valid txId, got ' + txId)

    var shortId = txId + ':' + unspent.vout
    assert(!(shortId in seen), 'Duplicate unspent ' + shortId)
    seen[shortId] = true

    try {
      bitcoin.Address.fromBase58Check(unspent.address)
    } catch (e) {
      throw ('Expected valid base58 Address, got ' + unspent.address)
    }
  })

  this.unspents = unspents
}

Wallet.prototype.signWith = function (tx, addresses, external, internal) {
  external = external || this.external
  internal = internal || this.internal

  var nodes = this.account.getNodes(addresses, external, internal)

  nodes.forEach(function (node, i) {
    tx.sign(i, node.privKey)
  })

  return tx
}

Wallet.prototype.toJSON = function () {
  return {
    external: {
      addresses: this.account.external.addresses,
      map: this.account.external.map,
      k: this.account.external.k,
      node: this.external.toBase58()
    },
    internal: {
      addresses: this.account.internal.addresses,
      map: this.account.internal.map,
      k: this.account.internal.k,
      node: this.internal.toBase58()
    },
    unspents: this.unspents
  }
}

module.exports = Wallet
<commit_msg>index: sort by addresses to preserve privacy<commit_after>var assert = require('assert')

var bitcoin = require('bitcoinjs-lib')
var bip32utils = require('bip32-utils')
var networks = bitcoin.networks
var typeForce = require('typeforce')
var selectInputs = require('./selection')

function Wallet (external, internal) {
  this.account = new bip32utils.Account(external, internal)
  this.external = external
  this.internal = internal
  this.unspents = []
}

Wallet.fromJSON = function (json) {
  var external = bitcoin.HDNode.fromBase58(json.external.node)
  var internal = bitcoin.HDNode.fromBase58(json.internal.node)
  var wallet = new Wallet(external, internal)
  wallet.account.external.addresses = json.external.addresses
  wallet.account.internal.addresses = json.internal.addresses
  wallet.account.external.map = json.external.map
  wallet.account.internal.map = json.internal.map
  wallet.account.external.k = json.external.k
  wallet.account.internal.k = json.internal.k
  wallet.unspents = json.unspents

  return wallet
}

Wallet.fromSeedBuffer = function (seed, network) {
  network = network || networks.bitcoin

  // HD first-level child derivation method should be hardened
  // See https://bitcointalk.org/index.php?topic=405179.msg4415254#msg4415254
  var m = bitcoin.HDNode.fromSeedBuffer(seed, network)
  var i = m.deriveHardened(0)
  var external = i.derive(0)
  var internal = i.derive(1)

  return new Wallet(external, internal)
}

Wallet.prototype.createTransaction = function (outputs, external, internal) {
  external = external || this.external
  internal = internal || this.internal
  var network = this.getNetwork()

  // filter un-confirmed
  var unspents = this.unspents.filter(function (unspent) {
    return unspent.confirmations > 0
  })

  var selection = selectInputs(unspents, outputs, network.feePerKb)
  var inputs = selection.inputs

  // sanity check (until things are battle tested)
  var totalInputValue = inputs.reduce(function (a, x) { return a + x.value }, 0)
  var totalOutputValue = outputs.reduce(function (a, x) { return a + x.value }, 0)
  assert.equal(totalInputValue - totalOutputValue, selection.change + selection.fee)

  // ensure fee isn't crazy (max 0.1 BTC)
  assert(selection.fee < 0.1 * 1e8, 'Very high fee: ' + selection.fee)

  // is the change worth it?
  var change, fee

  if (selection.change > network.dustThreshold) {
    // add the change address w/o mutating
    change = selection.change
    fee = selection.fee
    outputs = outputs.concat({
      address: this.getChangeAddress(),
      value: selection.change
    })

  } else {
    change = 0
    fee = selection.change + selection.fee
  }

  // build transaction
  var txb = new bitcoin.TransactionBuilder()

  // add each input
  inputs.forEach(function (input) {
    txb.addInput(input.txId, input.vout)
  })

  // sort [a copy of the] outputs uniformly, to preserve privacy
  outputs.concat().sort(function (a, b) {
    return a.address.localeCompare(b.address)

  // then add each output
  }).forEach(function (output) {
    txb.addOutput(output.address, output.value)
  })

  // sign and return
  var addresses = inputs.map(function (input) { return input.address })
  var transaction = this.signWith(txb, addresses, external, internal).build()

  return {
    fee: fee,
    change: change,
    transaction: transaction
  }
}

Wallet.prototype.containsAddress = function (address) { return this.account.containsAddress(address) }
Wallet.prototype.discover = function (gapLimit, queryCallback, done) {
  function discoverChain (iterator, callback) {
    bip32utils.discovery(iterator, gapLimit, queryCallback, function (err, used, checked) {
      if (err) return callback(err)

      // throw away ALL unused addresses AFTER the last unused address
      var unused = checked - used
      for (var i = 1; i < unused; ++i) iterator.pop()

      return callback()
    })
  }

  var external = this.account.external
  var internal = this.account.internal

  discoverChain(external, function (err) {
    if (err) return done(err)

    discoverChain(internal, done)
  })
}
Wallet.prototype.getAllAddresses = function () { return this.account.getAllAddresses() }
Wallet.prototype.getBalance = function () {
  return this.unspents.reduce(function (accum, unspent) {
    return accum + unspent.value
  }, 0)
}
Wallet.prototype.getChangeAddress = function () { return this.account.getInternalAddress() }
Wallet.prototype.getConfirmedBalance = function () {
  return this.unspents.filter(function (unspent) {
    return unspent.confirmations > 0

  }).reduce(function (accum, unspent) {
    return accum + unspent.value
  }, 0)
}
Wallet.prototype.getNetwork = function () { return this.account.getNetwork() }
Wallet.prototype.getReceiveAddress = function () { return this.account.getExternalAddress() }
Wallet.prototype.isChangeAddress = function (address) { return this.account.isInternalAddress(address) }
Wallet.prototype.isReceiveAddress = function (address) { return this.account.isExternalAddress(address) }
Wallet.prototype.nextChangeAddress = function () { return this.account.nextInternalAddress() }
Wallet.prototype.nextReceiveAddress = function () { return this.account.nextExternalAddress() }

Wallet.prototype.setUnspentOutputs = function (unspents) {
  var seen = {}

  unspents.forEach(function (unspent) {
    var txId = unspent.txId

    typeForce({
      txId: 'String',
      confirmations: 'Number',
      address: 'String',
      value: 'Number',
      vout: 'Number'
    }, unspent)

    assert.equal(txId.length, 64, 'Expected valid txId, got ' + txId)

    var shortId = txId + ':' + unspent.vout
    assert(!(shortId in seen), 'Duplicate unspent ' + shortId)
    seen[shortId] = true

    try {
      bitcoin.Address.fromBase58Check(unspent.address)
    } catch (e) {
      throw ('Expected valid base58 Address, got ' + unspent.address)
    }
  })

  this.unspents = unspents
}

Wallet.prototype.signWith = function (tx, addresses, external, internal) {
  external = external || this.external
  internal = internal || this.internal

  var nodes = this.account.getNodes(addresses, external, internal)

  nodes.forEach(function (node, i) {
    tx.sign(i, node.privKey)
  })

  return tx
}

Wallet.prototype.toJSON = function () {
  return {
    external: {
      addresses: this.account.external.addresses,
      map: this.account.external.map,
      k: this.account.external.k,
      node: this.external.toBase58()
    },
    internal: {
      addresses: this.account.internal.addresses,
      map: this.account.internal.map,
      k: this.account.internal.k,
      node: this.internal.toBase58()
    },
    unspents: this.unspents
  }
}

module.exports = Wallet
<|endoftext|>


<commit_before>/* @flow */

/** Only real dependency atm is backbone radio. **/
import Radio from "backbone.radio";
import Marionette from "backbone.marionette";

/**
 * Event decorator
 *
 * Event listeners for components.
 *
 * @param eventName {String} The event you want to bind (EG/ "click div")
 * @returns {Function} The "on" decorator (@on)
 */
export function on(eventName: string) {
    /**
     * Return a decorator function
     */
    return function(target: Object, name: string, descriptor: Object){

        /** Guard conditions **/
        if(!target.events) target.events = {};
        if(typeof target.events === "function") throw new Error("The on decorator is only compatible with an events object");
        if(!eventName) throw new Error("The on decorator requires an eventName argument");

        target.addEvent(eventName, name, target);

        return descriptor;
    };
}

// Provide context from one class to another
var GlobalElement: Object;

/**
 * Marionette Components.
 *
 * Re-usable components for Marionette JS.
 *
 * @param elementName {String} The name of the element (We register the radio channel with it here)
 * @param localRegistrationName {String} The unique identifier for this component
 * @param options {Object} Optional settings
 */
export class Component {

    /**
     * Setup types for variables.
     */
    radioChannel: Object;
    elementChannel: Object;
    state: Object;
    events: Object;
    __disableShadowDOM: boolean = false;

    /**
     * Construct your component, Only requires elementName & localRegistration name (Which is usually handled by your component registrar)
     *
     * @param elementName {String} The name of the element (We register the radio channel with it here)
     * @param localRegistrationName {String} The unique identifier for this component
     * @param options {Object} Optional settings
     */
    constructor(elementName: string, localRegistrationName: string, options: Object) {
        this.radioChannel = Radio.channel(`components:${localRegistrationName}`);
        this.elementChannel = Radio.channel(`elements:${elementName}`);
        const optionsPresent = undefined !== options;

        if(optionsPresent && options.disableShadowDOM) {
            this.__disableShadowDOM = true;
        }

        this.initialize();
    }

    /**
     * Render the component.
     *
     * @param elementName {string} The name for your custom element (Web Component).
     * @param element {Object} The pass through object for constructing the Component View.
     * @param stylesheet {Object} The stylesheet for your encapsulated component.
     * @param state {Object} The state object
     */
    renderComponent (elementName: string, element: Object, stylesheet: Object, state: Object) {
        /** Setup Component **/
        let that: Object = this;

        if (undefined !== state) this.state = state;
        if (undefined === this.events) this.events = {};

        GlobalElement = {
            elementName: elementName,
            element: element,
            stylesheet: stylesheet,
            disableShadowDOM: that.__disableShadowDOM
        };

        this.radioChannel.on("attached", element => {
            /** If events object isn't empty **/
            if(Object.keys(that.events).length !== 0 && that.events.constructor === Object) {

                for (let event in that.events) {
                    const eventArray = event.split(" ");

                    /** Now that the element is attached to the dom, add in the event listeners **/
                    element.addEventListener(eventArray[0], function (e) {
                        if (eventArray.length <= 2 && eventArray[1] !== undefined) {
                            let elem = element;

                            if(!that.__disableShadowDOM) {
                                elem = element.shadowRoot;
                            }

                            if(elem.querySelector(eventArray[1]).length <= 1) {

                                // Only run if we've matched the same element.
                                if(e.path && e.path[0] === elem.querySelector(eventArray[1])) {
                                    that.radioChannel.trigger("eventListenerTriggered", that.events[event], e);
                                }
                            } else {
                                elem.querySelectorAll(eventArray[1]).forEach(element => {
                                    // Only run if we've matched the same element.
                                    if(e.path && e.path[0] === element) {
                                        that.radioChannel.trigger("eventListenerTriggered", that.events[event], e);
                                    }
                                });
                            }
                        } else {
                            that.radioChannel.trigger("eventListenerTriggered", that.events[event], e);
                        }
                    });
                }

            }
        });
    }

    /**
     * Initialize the events
     */
    initialize () {
        let that = this;
        // $FlowIgnore: This is registered dynamically, so static typing can't detect this.
        this.radioChannel.on("eventListenerTriggered", (event, passthroughEvent) => that[event](passthroughEvent));
    }

    /**
     * Add an event listener.
     *
     * @param event {String} The event you're listening to
     * @param method {String} The method that will be called
     */
    addEvent(event: String, method: string) {
        this.events[event] = method;
    }

    /**
     * Remove an event listener
     *
     * @param event {String} The event that the method is listening to (EG/ click)
     * @param method {String} The method you want to remove
     */
    removeEvent (event: string, method: string) {
        if(undefined !== event && typeof method === "function") {
            this.element.removeEventListener(event, method);
            delete this.events[event];
        }
    }

    /**
     * Returns the element that is registered to the component
     *
     * @returns {Element}
     */
    // $FlowIgnore: We don't want to pre-initialize the element!
    get element () : Element {
        return Element;
    }

    /**
     * Change the component at run time.
     *
     * @param elem {Element|HTMLElement} The element you're setting it to.
     */
    // $FlowIgnore: We don't want to pre-initialize the element!
    set element (elem: HTMLElement) {
        Element = elem;
    }
}

/**
 * Custom elements with optional shadow dom support.
 *
 * @extends HTMLElement
 */
class Element extends HTMLElement {

    _previousElement: HTMLElement;
    _element: HTMLElement;
    _elementName: string;
    _previousStylesheet: Object;
    _stylesheet: Object;
    _updated: boolean;
    _hasShadowRoot: boolean;
    createShadowRoot: Function;

    /**
     * Set the element
     *
     * @param updatedElement {HTMLElement} The new element you're setting
     */
    set element (updatedElement: HTMLElement) {
        this.hasUpdated = true;
        this._previousElement = this._element;

        this._element = updatedElement;
    }

    /**
     * Get the element.
     *
     * @returns {HTMLElement}
     */
    get element () {
        return this._element;
    }

    /**
     * Returns the registered name for this component.
     *
     * @returns {String}
     */
    get elementName () {
        return this._elementName;
    }

    /**
     * Returns the previous element (Only set after update).
     *
     * @returns {HTMLElement}
     */
    get previousElement () {
        return this._previousElement;
    }

    /**
     * Set the stylesheet
     *
     * @param stylesheet {Object}
     */
    set stylesheet (stylesheet: Object) {
        this.hasUpdated = true;
        this._previousStylesheet = this._stylesheet;

        this._stylesheet = stylesheet;
    }

    /**
     * Get the stylesheet
     *
     * @returns {Object}
     */
    get stylesheet () {
        return this._stylesheet;
    }

    /**
     * Sets the updated attribute
     *
     * @param updated {boolean}
     */
    set hasUpdated (updated: boolean) {
        if(typeof updated  !== "boolean") throw new TypeError("Updated can only be a boolean type");

        this._updated = updated;

        if (updated) Radio.channel(`components:${this._elementName}`).trigger("updated");
    }

    /**
     * Returns the boolean value of the updated attribute.
     *
     * @returns {boolean} True if it has updated
     */
    get hasUpdated () {
        return this._updated;
    }

    /**
     * Get the instance of the radio channel that's used to communicate events.
     *
     * @returns {Backbone.Radio} An instance of Backbone radio.
     */
    get radio () {
        return Radio.channel(`components:${this._elementName}`);
    }

    /**
     * When the element is initialized, we'll create the element
     */
    createdCallback () {
        this._element = GlobalElement.element;
        this._stylesheet = GlobalElement.stylesheet;
        this._elementName = GlobalElement.elementName;
        this._hasShadowRoot = !GlobalElement.disableShadowDOM;

        let element = this;

        /** Add the styles directly into the shadow root & then append the rendered template **/
        if(this._hasShadowRoot) {
            element = this.createShadowRoot();
        }

        element.innerHTML = `<style>${this.stylesheet.toString()}</style>${this.element.toString()}`;
    }

    /**
     * When the component has been painted to the DOM
     */
    attachedCallback () {
        Radio.channel(`components:${this._elementName}`).trigger("attached", this);
    }

    /**
     * When attributes have changed
     *
     * @param attrName {String} Name of the attribute that changed
     * @param oldValue {String} Old value of the attribute
     * @param newValue {String} New value of the attribute
     */
    attributeChangedCallback (attrName: string, oldValue: string, newValue: string) {
        Radio.channel(`components:${this._elementName}`).trigger("attributeChanged", {
            attributeName: attrName,
            previousAttribute: oldValue,
            newAttribute: newValue
        });
    }

    /**
     * When the component has been removed from the DOM
     */
    detachedCallback () {
        Radio.channel(`components:${this._elementName}`).trigger("detached");
    }

    /**
     * Provide a method to update the element
     *
     * @param updatedElement {HTMLElement} The new contents of the HTML
     * @param updatedStylesheet {Object} The new stylesheet
     * @public
     */
    updateElement (updatedElement: HTMLElement, updatedStylesheet: Object) {
        let hasShadowDom = this._hasShadowRoot;
        let element = this;

        if(hasShadowDom) {
            /* $FlowIgnore: shadowRoot is spec compliant */
            element = this.shadowRoot;
        }

        /** Only update if we were passed data **/
        if(undefined !== updatedElement) this.element = updatedElement;
        if(undefined !== updatedElement) this.stylesheet = updatedStylesheet;

        /** If we've triggered a hasUpdated method **/
        // $FlowIgnore: Not part of Flow type yet
        if (this.hasUpdated) element.innerHTML = `<style>${this.stylesheet.toString()}</style>${this.element}`;

    }

}

/**
 * Export an abstracted Marionette View to provide helpers for registering & maintaining components.
 *
 * @extends Marionette.View
 */
export class View extends Marionette.View {

    _components: Object = {};
    _componentChannels: Object = {};
    _count: Object = {};

    /**
     * Lookup a component by its name & get an object containing its radioChannel & the component.
     *
     * @param componentName {String} The name of the component you registered
     * @returns {Object} References to the radio channel & itself.
     */
    getComponent (componentName: String) {
        return {
            component: this._components[componentName],
            radioChannel: this._componentChannels[componentName]
        };
    }

    /**
     * Conflict detection
     *
     * @param componentName {string} The component name
     * @returns {string} Conflict free name, (EG/ property-01)
     */
    noConflict (componentName) {
        let localCompName = componentName;
        const isPredefined = undefined !== this._components[componentName];

        if(isPredefined) {
            this._count[componentName] = this._count[componentName] || 0;

            localCompName = `${componentName}-${this._count[componentName]}`;
            this._count[componentName]++;

        }

        return localCompName;
    }

    /**
     * Register the component.
     *
     * @param componentRegistrar {Object} The singleton component registrar that holds components (outside of the view preferably)
     * @param componentName {String} Name the component will be registered under.
     * @param component {HTMLElement} The component you're registering.
     * @param el {HTMLElement|jQuery} Container/Element you're putting the component into.
     * @param properties {Object} Properties you wish to apply to the component.
     */
    registerComponent (componentRegistrar: Object, componentName: string, component: HTMLElement, el: HTMLElement, properties: Object) {

        let localCompName = this.noConflict(componentName);

        /** Store a reference to the returned element **/
        const local = componentRegistrar.register(componentName, component, properties, localCompName);
        const componentObject = componentRegistrar.getComponent(localCompName);

        /** Store references to the component & radio channels **/
        this._components[localCompName] = {
            element: componentObject.component,
            module: componentObject.componentModule
        };

        this._componentChannels[localCompName] = componentObject.radioChannel || {};

        /** Append the returned element to the DOM **/
        if(undefined !== el.jquery) {
            /* $FlowIgnore: Support jQuery */
            el.append(local);
        } else {
            el.appendChild(local);
        }

        return localCompName;
    }

    /**
     * Delete a component
     *
     * @param componentName {String} Name of the component
     */
    deleteComponent (componentName: String) {
        delete this._components[componentName];
        delete this._componentChannels[componentName];
    }

    /**
     * Remove all the components.
     *
     * Dangerous function!!
     */
    clearComponents () {
        for(let key in this._components) {
            /** Loop through and delete all props **/
            if(this._components.hasOwnProperty(key)) {
                delete this._components[key];
                delete this._componentChannels[key];
            }
        }

        for (let key in this._count) {
            if(this._count.hasOwnProperty(key)) {
                delete this._count[key];
            }
        }
    }

}
<commit_msg>Add spec compliancy error (Unused so far)<commit_after>/* @flow */

/** Only real dependency atm is backbone radio. **/
import Radio from "backbone.radio";
import Marionette from "backbone.marionette";

/**
 * Event decorator
 *
 * Event listeners for components.
 *
 * @param eventName {String} The event you want to bind (EG/ "click div")
 * @returns {Function} The "on" decorator (@on)
 */
export function on(eventName: string) {
    /**
     * Return a decorator function
     */
    return function(target: Object, name: string, descriptor: Object){

        /** Guard conditions **/
        if(!target.events) target.events = {};
        if(typeof target.events === "function") throw new Error("The on decorator is only compatible with an events object");
        if(!eventName) throw new Error("The on decorator requires an eventName argument");

        target.addEvent(eventName, name, target);

        return descriptor;
    };
}

/**
 *
 * @param message
 * @constructor
 */
function SpecificationCompliantError(message) {
    this.name = "SpecificationCompliantError";
    this.message = message || "The given custom element is not spec compliant";
    this.stack = (new Error()).stack;
}
SpecificationCompliantError.prototype = Object.create(Error.prototype);
SpecificationCompliantError.prototype.constructor = SpecificationCompliantError;

// Provide context from one class to another
var GlobalElement: Object;

/**
 * Marionette Components.
 *
 * Re-usable components for Marionette JS.
 *
 * @param elementName {String} The name of the element (We register the radio channel with it here)
 * @param localRegistrationName {String} The unique identifier for this component
 * @param options {Object} Optional settings
 */
export class Component {

    /**
     * Setup types for variables.
     */
    radioChannel: Object;
    elementChannel: Object;
    state: Object;
    events: Object;
    __disableShadowDOM: boolean = false;

    /**
     * Construct your component, Only requires elementName & localRegistration name (Which is usually handled by your component registrar)
     *
     * @param elementName {String} The name of the element (We register the radio channel with it here)
     * @param localRegistrationName {String} The unique identifier for this component
     * @param options {Object} Optional settings
     */
    constructor(elementName: string, localRegistrationName: string, options: Object) {
        this.radioChannel = Radio.channel(`components:${localRegistrationName}`);
        this.elementChannel = Radio.channel(`elements:${elementName}`);
        const optionsPresent = undefined !== options;

        if(optionsPresent && options.disableShadowDOM) {
            this.__disableShadowDOM = true;
        }

        this.initialize();
    }

    /**
     * Render the component.
     *
     * @param elementName {string} The name for your custom element (Web Component).
     * @param element {Object} The pass through object for constructing the Component View.
     * @param stylesheet {Object} The stylesheet for your encapsulated component.
     * @param state {Object} The state object
     */
    renderComponent (elementName: string, element: Object, stylesheet: Object, state: Object) {
        /** Setup Component **/
        let that: Object = this;

        if (undefined !== state) this.state = state;
        if (undefined === this.events) this.events = {};

        GlobalElement = {
            elementName: elementName,
            element: element,
            stylesheet: stylesheet,
            disableShadowDOM: that.__disableShadowDOM
        };

        this.radioChannel.on("attached", element => {
            /** If events object isn't empty **/
            if(Object.keys(that.events).length !== 0 && that.events.constructor === Object) {

                for (let event in that.events) {
                    const eventArray = event.split(" ");

                    /** Now that the element is attached to the dom, add in the event listeners **/
                    element.addEventListener(eventArray[0], function (e) {
                        if (eventArray.length <= 2 && eventArray[1] !== undefined) {
                            let elem = element;

                            if(!that.__disableShadowDOM) {
                                elem = element.shadowRoot;
                            }

                            if(elem.querySelector(eventArray[1]).length <= 1) {

                                // Only run if we've matched the same element.
                                if(e.path && e.path[0] === elem.querySelector(eventArray[1])) {
                                    that.radioChannel.trigger("eventListenerTriggered", that.events[event], e);
                                }
                            } else {
                                elem.querySelectorAll(eventArray[1]).forEach(element => {
                                    // Only run if we've matched the same element.
                                    if(e.path && e.path[0] === element) {
                                        that.radioChannel.trigger("eventListenerTriggered", that.events[event], e);
                                    }
                                });
                            }
                        } else {
                            that.radioChannel.trigger("eventListenerTriggered", that.events[event], e);
                        }
                    });
                }

            }
        });
    }

    /**
     * Initialize the events
     */
    initialize () {
        let that = this;
        // $FlowIgnore: This is registered dynamically, so static typing can't detect this.
        this.radioChannel.on("eventListenerTriggered", (event, passthroughEvent) => that[event](passthroughEvent));
    }

    /**
     * Add an event listener.
     *
     * @param event {String} The event you're listening to
     * @param method {String} The method that will be called
     */
    addEvent(event: String, method: string) {
        this.events[event] = method;
    }

    /**
     * Remove an event listener
     *
     * @param event {String} The event that the method is listening to (EG/ click)
     * @param method {String} The method you want to remove
     */
    removeEvent (event: string, method: string) {
        if(undefined !== event && typeof method === "function") {
            this.element.removeEventListener(event, method);
            delete this.events[event];
        }
    }

    /**
     * Returns the element that is registered to the component
     *
     * @returns {Element}
     */
    // $FlowIgnore: We don't want to pre-initialize the element!
    get element () : Element {
        return Element;
    }

    /**
     * Change the component at run time.
     *
     * @param elem {Element|HTMLElement} The element you're setting it to.
     */
    // $FlowIgnore: We don't want to pre-initialize the element!
    set element (elem: HTMLElement) {
        Element = elem;
    }
}

/**
 * Custom elements with optional shadow dom support.
 *
 * @extends HTMLElement
 */
class Element extends HTMLElement {

    _previousElement: HTMLElement;
    _element: HTMLElement;
    _elementName: string;
    _previousStylesheet: Object;
    _stylesheet: Object;
    _updated: boolean;
    _hasShadowRoot: boolean;
    createShadowRoot: Function;

    /**
     * Set the element
     *
     * @param updatedElement {HTMLElement} The new element you're setting
     */
    set element (updatedElement: HTMLElement) {
        this.hasUpdated = true;
        this._previousElement = this._element;

        this._element = updatedElement;
    }

    /**
     * Get the element.
     *
     * @returns {HTMLElement}
     */
    get element () {
        return this._element;
    }

    /**
     * Returns the registered name for this component.
     *
     * @returns {String}
     */
    get elementName () {
        return this._elementName;
    }

    /**
     * Returns the previous element (Only set after update).
     *
     * @returns {HTMLElement}
     */
    get previousElement () {
        return this._previousElement;
    }

    /**
     * Set the stylesheet
     *
     * @param stylesheet {Object}
     */
    set stylesheet (stylesheet: Object) {
        this.hasUpdated = true;
        this._previousStylesheet = this._stylesheet;

        this._stylesheet = stylesheet;
    }

    /**
     * Get the stylesheet
     *
     * @returns {Object}
     */
    get stylesheet () {
        return this._stylesheet;
    }

    /**
     * Sets the updated attribute
     *
     * @param updated {boolean}
     */
    set hasUpdated (updated: boolean) {
        if(typeof updated  !== "boolean") throw new TypeError("Updated can only be a boolean type");

        this._updated = updated;

        if (updated) Radio.channel(`components:${this._elementName}`).trigger("updated");
    }

    /**
     * Returns the boolean value of the updated attribute.
     *
     * @returns {boolean} True if it has updated
     */
    get hasUpdated () {
        return this._updated;
    }

    /**
     * Get the instance of the radio channel that's used to communicate events.
     *
     * @returns {Backbone.Radio} An instance of Backbone radio.
     */
    get radio () {
        return Radio.channel(`components:${this._elementName}`);
    }

    /**
     * When the element is initialized, we'll create the element
     */
    createdCallback () {
        this._element = GlobalElement.element;
        this._stylesheet = GlobalElement.stylesheet;
        this._elementName = GlobalElement.elementName;
        this._hasShadowRoot = !GlobalElement.disableShadowDOM;

        let element = this;

        /** Add the styles directly into the shadow root & then append the rendered template **/
        if(this._hasShadowRoot) {
            element = this.createShadowRoot();
        }

        element.innerHTML = `<style>${this.stylesheet.toString()}</style>${this.element.toString()}`;
    }

    /**
     * When the component has been painted to the DOM
     */
    attachedCallback () {
        Radio.channel(`components:${this._elementName}`).trigger("attached", this);
    }

    /**
     * When attributes have changed
     *
     * @param attrName {String} Name of the attribute that changed
     * @param oldValue {String} Old value of the attribute
     * @param newValue {String} New value of the attribute
     */
    attributeChangedCallback (attrName: string, oldValue: string, newValue: string) {
        Radio.channel(`components:${this._elementName}`).trigger("attributeChanged", {
            attributeName: attrName,
            previousAttribute: oldValue,
            newAttribute: newValue
        });
    }

    /**
     * When the component has been removed from the DOM
     */
    detachedCallback () {
        Radio.channel(`components:${this._elementName}`).trigger("detached");
    }

    /**
     * Provide a method to update the element
     *
     * @param updatedElement {HTMLElement} The new contents of the HTML
     * @param updatedStylesheet {Object} The new stylesheet
     * @public
     */
    updateElement (updatedElement: HTMLElement, updatedStylesheet: Object) {
        let hasShadowDom = this._hasShadowRoot;
        let element = this;

        if(hasShadowDom) {
            /* $FlowIgnore: shadowRoot is spec compliant */
            element = this.shadowRoot;
        }

        /** Only update if we were passed data **/
        if(undefined !== updatedElement) this.element = updatedElement;
        if(undefined !== updatedElement) this.stylesheet = updatedStylesheet;

        /** If we've triggered a hasUpdated method **/
        // $FlowIgnore: Not part of Flow type yet
        if (this.hasUpdated) element.innerHTML = `<style>${this.stylesheet.toString()}</style>${this.element}`;

    }

}

/**
 * Export an abstracted Marionette View to provide helpers for registering & maintaining components.
 *
 * @extends Marionette.View
 */
export class View extends Marionette.View {

    _components: Object = {};
    _componentChannels: Object = {};
    _count: Object = {};

    /**
     * Lookup a component by its name & get an object containing its radioChannel & the component.
     *
     * @param componentName {String} The name of the component you registered
     * @returns {Object} References to the radio channel & itself.
     */
    getComponent (componentName: String) {
        return {
            component: this._components[componentName],
            radioChannel: this._componentChannels[componentName]
        };
    }

    /**
     * Conflict detection
     *
     * @param componentName {string} The component name
     * @returns {string} Conflict free name, (EG/ property-01)
     */
    noConflict (componentName) {
        let localCompName = componentName;
        const isPredefined = undefined !== this._components[componentName];

        if(isPredefined) {
            this._count[componentName] = this._count[componentName] || 0;

            localCompName = `${componentName}-${this._count[componentName]}`;
            this._count[componentName]++;

        }

        return localCompName;
    }

    /**
     * Register the component.
     *
     * @param componentRegistrar {Object} The singleton component registrar that holds components (outside of the view preferably)
     * @param componentName {String} Name the component will be registered under.
     * @param component {HTMLElement} The component you're registering.
     * @param el {HTMLElement|jQuery} Container/Element you're putting the component into.
     * @param properties {Object} Properties you wish to apply to the component.
     */
    registerComponent (componentRegistrar: Object, componentName: string, component: HTMLElement, el: HTMLElement, properties: Object) {

        let localCompName = this.noConflict(componentName);

        /** Store a reference to the returned element **/
        const local = componentRegistrar.register(componentName, component, properties, localCompName);
        const componentObject = componentRegistrar.getComponent(localCompName);

        /** Store references to the component & radio channels **/
        this._components[localCompName] = {
            element: componentObject.component,
            module: componentObject.componentModule
        };

        this._componentChannels[localCompName] = componentObject.radioChannel || {};

        /** Append the returned element to the DOM **/
        if(undefined !== el.jquery) {
            /* $FlowIgnore: Support jQuery */
            el.append(local);
        } else {
            el.appendChild(local);
        }

        return localCompName;
    }

    /**
     * Delete a component
     *
     * @param componentName {String} Name of the component
     */
    deleteComponent (componentName: String) {
        delete this._components[componentName];
        delete this._componentChannels[componentName];
    }

    /**
     * Remove all the components.
     *
     * Dangerous function!!
     */
    clearComponents () {
        for(let key in this._components) {
            /** Loop through and delete all props **/
            if(this._components.hasOwnProperty(key)) {
                delete this._components[key];
                delete this._componentChannels[key];
            }
        }

        for (let key in this._count) {
            if(this._count.hasOwnProperty(key)) {
                delete this._count[key];
            }
        }
    }

}
<|endoftext|>


<commit_before>const Promise = require('bluebird');

const fs = require('fs');
const path = require('path');
const gutil = require('gulp-util');
const through = require('through2');
const html2pug = require('html2pug');

const PluginError = gutil.PluginError;

// consts
const PLUGIN_NAME = 'gulp-html2pug';

fs.readFileAsync = Promise.promisify(fs.readFile);

// plugin level function (dealing with files)
function gulpHtml2pug({ encoding = 'utf8' } = {}) {
  // creating a stream through which each file will pass
  return through.obj(function (file, enc, cb) {
    const newFile = file.clone();

    fs.readFileAsync(file.path, encoding)
    .then(html => {
      const pug = html2pug(html);

      if (file.isBuffer()) {
        newFile.contents = new Buffer(pug);
      } else if (file.isStream()) {
        // start the transformation
        newFile.contents.write(pug);
        newFile.contents.end();
      } else {
        throw new PluginError(PLUGIN_NAME, 'Invalid file');
      }

      const dirname = path.dirname(file.path);
      const basename = path.basename(file.path);
      newFile.path = path.join(dirname, basename.replace(path.extname(basename), '.pug'));
      // make sure the file goes through the next gulp plugin
      this.push(newFile);
    })
    .asCallback(cb);
  });
}

// exporting the plugin main function
module.exports = gulpHtml2pug;
<commit_msg>Improve extension conversion<commit_after>const Promise = require('bluebird');

const fs = require('fs');
const path = require('path');
const gutil = require('gulp-util');
const through = require('through2');
const html2pug = require('html2pug');

const PluginError = gutil.PluginError;

// consts
const PLUGIN_NAME = 'gulp-html2pug';

fs.readFileAsync = Promise.promisify(fs.readFile);

// plugin level function (dealing with files)
function gulpHtml2pug({ encoding = 'utf8' } = {}) {
  // creating a stream through which each file will pass
  return through.obj(function (file, enc, cb) {
    const newFile = file.clone();

    fs.readFileAsync(file.path, encoding)
    .then(html => {
      const pug = html2pug(html);

      if (file.isBuffer()) {
        newFile.contents = new Buffer(pug);
      } else if (file.isStream()) {
        // start the transformation
        newFile.contents.write(pug);
        newFile.contents.end();
      } else {
        throw new PluginError(PLUGIN_NAME, 'Invalid file');
      }

      const dirname = path.dirname(file.path);
      const basename = path.basename(file.path, path.extname(file.path));
      newFile.path = path.join(dirname, `${basename}.pug`);
      // make sure the file goes through the next gulp plugin
      this.push(newFile);
    })
    .asCallback(cb);
  });
}

// exporting the plugin main function
module.exports = gulpHtml2pug;
<|endoftext|>


<commit_before>import { createFilter } from 'rollup-pluginutils';
import { writeFile } from 'fs';

import vueTransform from './vueTransform';

export default function vue(options = {}) {
    const filter = createFilter(options.include, options.exclude);
    const cssContent = {};
    const cssLang = {};
    let dest = 'bundle.js';

    return {
        name: 'vue',
        transform(source, id) {
            if (!filter(id) || !id.endsWith('.vue')) {
                return null;
            }

            const ref = vueTransform(source, id);

            // Map of every stylesheet content
            cssContent[id] = ref.css || '';

            // Map of every stylesheet lang
            cssLang[id] = ref.cssLang || 'css';

            // Component javascript with inlined html template
            return ref.js;
        },
        ongenerate(opts) {
            if (options.css === false) {
                return;
            }

            // Combine all stylesheets
            let css = '';
            Object.keys(cssContent).forEach((key) => {
                css += cssContent[key];
            });

            // Emit styles through callback or file
            if (typeof options.css === 'function') {
                options.css(css);

                return;
            }

            // Guess destination filename
            if (typeof options.css !== 'string') {
                dest = opts.dest || 'bundle.js';
                if (dest.endsWith('.js')) {
                    dest = dest.slice(0, -3);
                }
                /* eslint-disable */
                options.css = `${dest}.css`;
                /* eslint-enable */
            }

            writeFile(options.css, css, (err) => {
                if (err) {
                    throw err;
                }
                emitted(options.css, css.length);
            });
        },
    };
}

function emitted(text, bytes) {
    console.log(green(text), getSize(bytes));
}

function green(text) {
    return `\u001b[1m\u001b[32m${text}\u001b[39m\u001b[22m`;
}

function getSize(size) {
    const bytes = size / 1024;
    return bytes < 1000 ? `${bytes.toPrecision(3)} kB` : `${(bytes / 1024).toPrecision(3)} MB`;
}
<commit_msg>Don't write empty stylesheets when using default config<commit_after>import { createFilter } from 'rollup-pluginutils';
import { writeFile } from 'fs';

import vueTransform from './vueTransform';

export default function vue(options = {}) {
    const filter = createFilter(options.include, options.exclude);
    const cssContent = {};
    const cssLang = {};

    return {
        name: 'vue',
        transform(source, id) {
            if (!filter(id) || !id.endsWith('.vue')) {
                return null;
            }

            const ref = vueTransform(source, id);

            // Map of every stylesheet content
            cssContent[id] = ref.css || '';

            // Map of every stylesheet lang
            cssLang[id] = ref.cssLang || 'css';

            // Component javascript with inlined html template
            return ref.js;
        },
        ongenerate(opts) {
            if (options.css === false) {
                return;
            }

            // Combine all stylesheets
            let css = '';
            Object.keys(cssContent).forEach((key) => {
                css += cssContent[key];
            });

            // Emit styles through callback or file
            if (typeof options.css === 'function') {
                options.css(css);

                return;
            }

            if (typeof options.css !== 'string') {
                // Don't create unwanted empty stylesheets
                if (!css.length) {
                    return;
                }

                // Guess destination filename
                let dest = opts.dest || 'bundle.js';
                if (dest.endsWith('.js')) {
                    dest = dest.slice(0, -3);
                }
                /* eslint-disable */
                options.css = `${dest}.css`;
                /* eslint-enable */
            }

            writeFile(options.css, css, (err) => {
                if (err) {
                    throw err;
                }
                emitted(options.css, css.length);
            });
        },
    };
}

function emitted(text, bytes) {
    console.log(green(text), getSize(bytes));
}

function green(text) {
    return `\u001b[1m\u001b[32m${text}\u001b[39m\u001b[22m`;
}

function getSize(size) {
    const bytes = size / 1024;
    return bytes < 1000 ? `${bytes.toPrecision(3)} kB` : `${(bytes / 1024).toPrecision(3)} MB`;
}
<|endoftext|>