<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Owner: mark@famo.us
 * @license MPL 2.0
 * @copyright Famous Industries, Inc. 2014
 */

define(function(require, exports, module) {

    /**
     * Helper object used to iterate through items sequentially. Used in
     *   views that deal with layout.  A ViewSequence object conceptually points
     *   to a node in a linked list.
     *
     * @class ViewSequence
     *
     * @constructor
     * @param {Object|Array} options Options object, or content array.
     * @param {Number} [options.index] starting index.
     * @param {Number} [options.array] Array of elements to populate the ViewSequence
     * @param {Object} [options._] Optional backing store (internal
     * @param {Boolean} [options.loop] Whether to wrap when accessing elements just past the end
     *   (or beginning) of the sequence.
     */
    function ViewSequence(options) {
        if (!options) options = [];
        if (options instanceof Array) options = {array: options};

        this._ = null;
        this.index = options.index || 0;

        if (options.array) this._ = new (this.constructor.Backing)(options.array);
        else if (options._) this._ = options._;

        if (this.index === this._.firstIndex) this._.firstNode = this;
        if (this.index === this._.firstIndex + this._.array.length - 1) this._.lastNode = this;

        if (options.loop !== undefined) this._.loop = options.loop;

        if (options.trackSize !== undefined) this._.trackSize = options.trackSize;

        this._previousNode = null;
        this._nextNode = null;
    }

    // constructor for internal storage
    ViewSequence.Backing = function Backing(array) {
        this.array = array;
        this.firstIndex = 0;
        this.loop = false;
        this.firstNode = null;
        this.lastNode = null;
        this.cumulativeSizes = [[0, 0]];
        this.sizeDirty = true;
        this.trackSize = false;
    };

    // Get value "i" slots away from the first index.
    ViewSequence.Backing.prototype.getValue = function getValue(i) {
        var _i = i - this.firstIndex;
        if (_i < 0 || _i >= this.array.length) return null;
        return this.array[_i];
    };

    // Set value "i" slots away from the first index.
    ViewSequence.Backing.prototype.setValue = function setValue(i, value) {
        this.array[i - this.firstIndex] = value;
    };

    // Get sequence size from backing up to index
    // TODO: remove from viewSequence with proper abstraction
    ViewSequence.Backing.prototype.getSize = function getSize(index) {
        return this.cumulativeSizes[index];
    };

    // Calculates cumulative size
    // TODO: remove from viewSequence with proper abstraction
    ViewSequence.Backing.prototype.calculateSize = function calculateSize(index) {
        index = index || this.array.length;
        var size = [0, 0];
        for (var i = 0; i < index; i++) {
            var nodeSize = this.array[i].getSize();
            if (!nodeSize) return undefined;
            if (size[0] !== undefined) {
                if (nodeSize[0] === undefined) size[0] = undefined;
                else size[0] += nodeSize[0];
            }
            if (size[1] !== undefined) {
                if (nodeSize[1] === undefined) size[1] = undefined;
                else size[1] += nodeSize[1];
            }
            this.cumulativeSizes[i + 1] = size.slice();
        }
        this.sizeDirty = false;
        return size;
    };

    // After splicing into the backing store, restore the indexes of each node correctly.
    ViewSequence.Backing.prototype.reindex = function reindex(start, removeCount, insertCount) {
        if (!this.array[0]) return;

        var i = 0;
        var index = this.firstIndex;
        var indexShiftAmount = insertCount - removeCount;
        var node = this.firstNode;

        // find node to begin
        while (index < start - 1) {
            node = node.getNext();
            index++;
        }
        // skip removed nodes
        var spliceStartNode = node;
        for (i = 0; i < removeCount; i++) {
            node = node.getNext();
            if (node) node._previousNode = spliceStartNode;
        }
        var spliceResumeNode = node ? node.getNext() : null;
        // generate nodes for inserted items
        spliceStartNode._nextNode = null;
        node = spliceStartNode;
        for (i = 0; i < insertCount; i++) node = node.getNext();
        index += insertCount;
        // resume the chain
        if (node !== spliceResumeNode) {
            node._nextNode = spliceResumeNode;
            if (spliceResumeNode) spliceResumeNode._previousNode = node;
        }
        if (spliceResumeNode) {
            node = spliceResumeNode;
            index++;
            while (node && index < this.array.length + this.firstIndex) {
                if (node._nextNode) node.index += indexShiftAmount;
                else node.index = index;
                node = node.getNext();
                index++;
            }
        }
        if (this._.trackSize) this._.sizeDirty = true;
    };

    /**
     * Return ViewSequence node previous to this node in the list, respecting looping if applied.
     *
     * @method getPrevious
     * @return {ViewSequence} previous node.
     */
    ViewSequence.prototype.getPrevious = function getPrevious() {
        if (this.index === this._.firstIndex) {
            if (this._.loop) {
                this._previousNode = this._.lastNode || new (this.constructor)({_: this._, index: this._.firstIndex + this._.array.length - 1});
                this._previousNode._nextNode = this;
            }
            else {
                this._previousNode = null;
            }
        }
        else if (!this._previousNode) {
            this._previousNode = new (this.constructor)({_: this._, index: this.index - 1});
            this._previousNode._nextNode = this;
        }
        return this._previousNode;
    };

    /**
     * Return ViewSequence node next after this node in the list, respecting looping if applied.
     *
     * @method getNext
     * @return {ViewSequence} previous node.
     */
    ViewSequence.prototype.getNext = function getNext() {
        if (this.index === this._.firstIndex + this._.array.length - 1) {
            if (this._.loop) {
                this._nextNode = this._.firstNode || new (this.constructor)({_: this._, index: this._.firstIndex});
                this._nextNode._previousNode = this;
            }
            else {
                this._nextNode = null;
            }
        }
        else if (!this._nextNode) {
            this._nextNode = new (this.constructor)({_: this._, index: this.index + 1});
            this._nextNode._previousNode = this;
        }
        return this._nextNode;
    };

    /**
     * Return index of this ViewSequence node.
     *
     * @method getIndex
     * @return {Number} index
     */
    ViewSequence.prototype.getIndex = function getIndex() {
        return this.index;
    };

    /**
     * Return printable version of this ViewSequence node.
     *
     * @method toString
     * @return {string} this index as a string
     */
    ViewSequence.prototype.toString = function toString() {
        return '' + this.index;
    };

    /**
     * Add one or more objects to the beginning of the sequence.
     *
     * @method unshift
     * @param {...Object} value arguments array of objects
     */
    ViewSequence.prototype.unshift = function unshift(value) {
        this._.array.unshift.apply(this._.array, arguments);
        this._.firstIndex -= arguments.length;
        if (this._.trackSize) this._.sizeDirty = true;
    };

    /**
     * Add one or more objects to the end of the sequence.
     *
     * @method push
     * @param {...Object} value arguments array of objects
     */
    ViewSequence.prototype.push = function push(value) {
        this._.array.push.apply(this._.array, arguments);
        if (this._.trackSize) this._.sizeDirty = true;
    };

    /**
     * Remove objects from the sequence
     *
     * @method splice
     * @param {Number} index starting index for removal
     * @param {Number} howMany how many elements to remove
     * @param {...Object} value arguments array of objects
     */
    ViewSequence.prototype.splice = function splice(index, howMany) {
        var values = Array.prototype.slice.call(arguments, 2);
        this._.array.splice.apply(this._.array, [index - this._.firstIndex, howMany].concat(values));
        this._.reindex(index, howMany, values.length);
    };

    /**
     * Exchange this element's sequence position with another's.
     *
     * @method swap
     * @param {ViewSequence} other element to swap with.
     */
    ViewSequence.prototype.swap = function swap(other) {
        var otherValue = other.get();
        var myValue = this.get();
        this._.setValue(this.index, otherValue);
        this._.setValue(other.index, myValue);

        var myPrevious = this._previousNode;
        var myNext = this._nextNode;
        var myIndex = this.index;
        var otherPrevious = other._previousNode;
        var otherNext = other._nextNode;
        var otherIndex = other.index;

        this.index = otherIndex;
        this._previousNode = (otherPrevious === this) ? other : otherPrevious;
        if (this._previousNode) this._previousNode._nextNode = this;
        this._nextNode = (otherNext === this) ? other : otherNext;
        if (this._nextNode) this._nextNode._previousNode = this;

        other.index = myIndex;
        other._previousNode = (myPrevious === other) ? this : myPrevious;
        if (other._previousNode) other._previousNode._nextNode = other;
        other._nextNode = (myNext === other) ? this : myNext;
        if (other._nextNode) other._nextNode._previousNode = other;

        if (this.index === this._.firstIndex) this._.firstNode = this;
        else if (this.index === this._.firstIndex + this._.array.length - 1) this._.lastNode = this;
        if (other.index === this._.firstIndex) this._.firstNode = other;
        else if (other.index === this._.firstIndex + this._.array.length - 1) this._.lastNode = other;
        if (this._.trackSize) this._.sizeDirty = true;
    };

   /**
     * Return value of this ViewSequence node.
     *
     * @method get
     * @return {Object} value of thiss
     */
    ViewSequence.prototype.get = function get() {
        return this._.getValue(this.index);
    };

   /**
     * Call getSize() on the contained View.
     *
     * @method getSize
     * @return {Array.Number} [width, height]
     */
    ViewSequence.prototype.getSize = function getSize() {
        var target = this.get();
        return target ? target.getSize() : null;
    };

    /**
     * Generate a render spec from the contents of this component.
     * Specifically, this will render the value at the current index.
     * @private
     * @method render
     * @return {number} Render spec for this component
     */
    ViewSequence.prototype.render = function render() {
        if (this._.trackSize && this._.sizeDirty) this._.calculateSize();
        var target = this.get();
        return target ? target.render.apply(target, arguments) : null;
    };

    module.exports = ViewSequence;
});
<commit_msg>Added indexOf to ViewSequence<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Owner: mark@famo.us
 * @license MPL 2.0
 * @copyright Famous Industries, Inc. 2014
 */

define(function(require, exports, module) {

    /**
     * Helper object used to iterate through items sequentially. Used in
     *   views that deal with layout.  A ViewSequence object conceptually points
     *   to a node in a linked list.
     *
     * @class ViewSequence
     *
     * @constructor
     * @param {Object|Array} options Options object, or content array.
     * @param {Number} [options.index] starting index.
     * @param {Number} [options.array] Array of elements to populate the ViewSequence
     * @param {Object} [options._] Optional backing store (internal
     * @param {Boolean} [options.loop] Whether to wrap when accessing elements just past the end
     *   (or beginning) of the sequence.
     */
    function ViewSequence(options) {
        if (!options) options = [];
        if (options instanceof Array) options = {array: options};

        this._ = null;
        this.index = options.index || 0;

        if (options.array) this._ = new (this.constructor.Backing)(options.array);
        else if (options._) this._ = options._;

        if (this.index === this._.firstIndex) this._.firstNode = this;
        if (this.index === this._.firstIndex + this._.array.length - 1) this._.lastNode = this;

        if (options.loop !== undefined) this._.loop = options.loop;

        if (options.trackSize !== undefined) this._.trackSize = options.trackSize;

        this._previousNode = null;
        this._nextNode = null;
    }

    // constructor for internal storage
    ViewSequence.Backing = function Backing(array) {
        this.array = array;
        this.firstIndex = 0;
        this.loop = false;
        this.firstNode = null;
        this.lastNode = null;
        this.cumulativeSizes = [[0, 0]];
        this.sizeDirty = true;
        this.trackSize = false;
    };

    // Get value "i" slots away from the first index.
    ViewSequence.Backing.prototype.getValue = function getValue(i) {
        var _i = i - this.firstIndex;
        if (_i < 0 || _i >= this.array.length) return null;
        return this.array[_i];
    };

    // Set value "i" slots away from the first index.
    ViewSequence.Backing.prototype.setValue = function setValue(i, value) {
        this.array[i - this.firstIndex] = value;
    };

    // Get sequence size from backing up to index
    // TODO: remove from viewSequence with proper abstraction
    ViewSequence.Backing.prototype.getSize = function getSize(index) {
        return this.cumulativeSizes[index];
    };

    // Calculates cumulative size
    // TODO: remove from viewSequence with proper abstraction
    ViewSequence.Backing.prototype.calculateSize = function calculateSize(index) {
        index = index || this.array.length;
        var size = [0, 0];
        for (var i = 0; i < index; i++) {
            var nodeSize = this.array[i].getSize();
            if (!nodeSize) return undefined;
            if (size[0] !== undefined) {
                if (nodeSize[0] === undefined) size[0] = undefined;
                else size[0] += nodeSize[0];
            }
            if (size[1] !== undefined) {
                if (nodeSize[1] === undefined) size[1] = undefined;
                else size[1] += nodeSize[1];
            }
            this.cumulativeSizes[i + 1] = size.slice();
        }
        this.sizeDirty = false;
        return size;
    };

    // After splicing into the backing store, restore the indexes of each node correctly.
    ViewSequence.Backing.prototype.reindex = function reindex(start, removeCount, insertCount) {
        if (!this.array[0]) return;

        var i = 0;
        var index = this.firstIndex;
        var indexShiftAmount = insertCount - removeCount;
        var node = this.firstNode;

        // find node to begin
        while (index < start - 1) {
            node = node.getNext();
            index++;
        }
        // skip removed nodes
        var spliceStartNode = node;
        for (i = 0; i < removeCount; i++) {
            node = node.getNext();
            if (node) node._previousNode = spliceStartNode;
        }
        var spliceResumeNode = node ? node.getNext() : null;
        // generate nodes for inserted items
        spliceStartNode._nextNode = null;
        node = spliceStartNode;
        for (i = 0; i < insertCount; i++) node = node.getNext();
        index += insertCount;
        // resume the chain
        if (node !== spliceResumeNode) {
            node._nextNode = spliceResumeNode;
            if (spliceResumeNode) spliceResumeNode._previousNode = node;
        }
        if (spliceResumeNode) {
            node = spliceResumeNode;
            index++;
            while (node && index < this.array.length + this.firstIndex) {
                if (node._nextNode) node.index += indexShiftAmount;
                else node.index = index;
                node = node.getNext();
                index++;
            }
        }
        if (this._.trackSize) this._.sizeDirty = true;
    };

    /**
     * Return ViewSequence node previous to this node in the list, respecting looping if applied.
     *
     * @method getPrevious
     * @return {ViewSequence} previous node.
     */
    ViewSequence.prototype.getPrevious = function getPrevious() {
        if (this.index === this._.firstIndex) {
            if (this._.loop) {
                this._previousNode = this._.lastNode || new (this.constructor)({_: this._, index: this._.firstIndex + this._.array.length - 1});
                this._previousNode._nextNode = this;
            }
            else {
                this._previousNode = null;
            }
        }
        else if (!this._previousNode) {
            this._previousNode = new (this.constructor)({_: this._, index: this.index - 1});
            this._previousNode._nextNode = this;
        }
        return this._previousNode;
    };

    /**
     * Return ViewSequence node next after this node in the list, respecting looping if applied.
     *
     * @method getNext
     * @return {ViewSequence} previous node.
     */
    ViewSequence.prototype.getNext = function getNext() {
        if (this.index === this._.firstIndex + this._.array.length - 1) {
            if (this._.loop) {
                this._nextNode = this._.firstNode || new (this.constructor)({_: this._, index: this._.firstIndex});
                this._nextNode._previousNode = this;
            }
            else {
                this._nextNode = null;
            }
        }
        else if (!this._nextNode) {
            this._nextNode = new (this.constructor)({_: this._, index: this.index + 1});
            this._nextNode._previousNode = this;
        }
        return this._nextNode;
    };

    /**
     * Return index of the provided item in the backing array
     *
     * @method indexOf
     * @return {Number} index or <tt>-1</tt> if not found
     */
    ViewSequence.prototype.indexOf = function indexOf(item) {
        return this._.array.indexOf(item);
    };

    /**
     * Return index of this ViewSequence node.
     *
     * @method getIndex
     * @return {Number} index
     */
    ViewSequence.prototype.getIndex = function getIndex() {
        return this.index;
    };

    /**
     * Return printable version of this ViewSequence node.
     *
     * @method toString
     * @return {string} this index as a string
     */
    ViewSequence.prototype.toString = function toString() {
        return '' + this.index;
    };

    /**
     * Add one or more objects to the beginning of the sequence.
     *
     * @method unshift
     * @param {...Object} value arguments array of objects
     */
    ViewSequence.prototype.unshift = function unshift(value) {
        this._.array.unshift.apply(this._.array, arguments);
        this._.firstIndex -= arguments.length;
        if (this._.trackSize) this._.sizeDirty = true;
    };

    /**
     * Add one or more objects to the end of the sequence.
     *
     * @method push
     * @param {...Object} value arguments array of objects
     */
    ViewSequence.prototype.push = function push(value) {
        this._.array.push.apply(this._.array, arguments);
        if (this._.trackSize) this._.sizeDirty = true;
    };

    /**
     * Remove objects from the sequence
     *
     * @method splice
     * @param {Number} index starting index for removal
     * @param {Number} howMany how many elements to remove
     * @param {...Object} value arguments array of objects
     */
    ViewSequence.prototype.splice = function splice(index, howMany) {
        var values = Array.prototype.slice.call(arguments, 2);
        this._.array.splice.apply(this._.array, [index - this._.firstIndex, howMany].concat(values));
        this._.reindex(index, howMany, values.length);
    };

    /**
     * Exchange this element's sequence position with another's.
     *
     * @method swap
     * @param {ViewSequence} other element to swap with.
     */
    ViewSequence.prototype.swap = function swap(other) {
        var otherValue = other.get();
        var myValue = this.get();
        this._.setValue(this.index, otherValue);
        this._.setValue(other.index, myValue);

        var myPrevious = this._previousNode;
        var myNext = this._nextNode;
        var myIndex = this.index;
        var otherPrevious = other._previousNode;
        var otherNext = other._nextNode;
        var otherIndex = other.index;

        this.index = otherIndex;
        this._previousNode = (otherPrevious === this) ? other : otherPrevious;
        if (this._previousNode) this._previousNode._nextNode = this;
        this._nextNode = (otherNext === this) ? other : otherNext;
        if (this._nextNode) this._nextNode._previousNode = this;

        other.index = myIndex;
        other._previousNode = (myPrevious === other) ? this : myPrevious;
        if (other._previousNode) other._previousNode._nextNode = other;
        other._nextNode = (myNext === other) ? this : myNext;
        if (other._nextNode) other._nextNode._previousNode = other;

        if (this.index === this._.firstIndex) this._.firstNode = this;
        else if (this.index === this._.firstIndex + this._.array.length - 1) this._.lastNode = this;
        if (other.index === this._.firstIndex) this._.firstNode = other;
        else if (other.index === this._.firstIndex + this._.array.length - 1) this._.lastNode = other;
        if (this._.trackSize) this._.sizeDirty = true;
    };

   /**
     * Return value of this ViewSequence node.
     *
     * @method get
     * @return {Object} value of thiss
     */
    ViewSequence.prototype.get = function get() {
        return this._.getValue(this.index);
    };

   /**
     * Call getSize() on the contained View.
     *
     * @method getSize
     * @return {Array.Number} [width, height]
     */
    ViewSequence.prototype.getSize = function getSize() {
        var target = this.get();
        return target ? target.getSize() : null;
    };

    /**
     * Generate a render spec from the contents of this component.
     * Specifically, this will render the value at the current index.
     * @private
     * @method render
     * @return {number} Render spec for this component
     */
    ViewSequence.prototype.render = function render() {
        if (this._.trackSize && this._.sizeDirty) this._.calculateSize();
        var target = this.get();
        return target ? target.render.apply(target, arguments) : null;
    };

    module.exports = ViewSequence;
});
<|endoftext|>


<commit_before>import styled, {css} from 'styled-components'
import _get from 'lodash/get'
import {lighten} from 'polished'

import {
  declareFont,
  theme,
  shadeColor,
  StyledScrollbar,
  scale
} from '../'
import {StyledResizeHandle} from './ResizingController'

const borderColor = ({theme}) => shadeColor(_get(theme, 'colors.paper'), 2)
const basePadding = scale.space(-1)

export const StyledTableCell = styled.td`
  padding: ${basePadding};
  background-color: ${theme.color('paper')};
  border-bottom: 1px solid ${borderColor};
  align-content: center;
  max-height: 23px;
  box-sizing: content-box;
`

export const StyledDnD = styled.div`
  padding: ${basePadding};
  width: 100%;
  display: flex;
  opacity: ${({isDragged}) => isDragged ? 0.2 : 1};
  pointer-events: ${({isDraggedOver}) => isDraggedOver ? 'none' : 'auto'};
`

export const StyledTableHeaderCell = styled.th`
  position: sticky;
  top: 0;
  background-color: ${theme.color('paper')};
  text-align: left;
  border-bottom: 2px solid ${borderColor};
  ${declareFont({fontWeight: theme.fontWeight('bold')})};
  user-select: none;
  cursor: ${({sortable}) => sortable ? 'pointer' : 'auto'};
  overflow: hidden;
  white-space: nowrap;
  display: flex;
  border-right: ${({isDraggedOver, theme}) => isDraggedOver ? `3px solid ${theme.colors.secondary}` : 'none'};
  ${({isResizing, theme}) => isResizing && `
    background-color: ${lighten(0.25, theme.colors.secondaryLight)};

    > ${StyledResizeHandle} {
      opacity: 1;
    }
    `
  }
  ${({resizingColumn, theme}) => !resizingColumn && `
    &:hover {
      background-color: ${lighten(0.25, theme.colors.secondaryLight)};

        > ${StyledResizeHandle} {
          opacity: 1;
        }
    }
    `
  }
  ${({isResizing, sortable, fixedPosition}) => !isResizing && !sortable && !fixedPosition && `
    &:hover {
      background-color: transparent;
    }
    `
  }
`

export const PaginationContainer = styled.div`
  grid-row-start: pagination-start;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  border-top: 1px solid ${borderColor};
`

const selectionStyles = css`
  display: contents;
  ${({clickable}) => clickable && 'cursor: pointer;'}

  &.selected {
    > ${StyledTableCell} {
      background-color: ${({theme}) => lighten(0.1, theme.colors.secondaryLight)};
    }
  }

  &.selectableRow:not(.selected):hover {
    > ${StyledTableCell} {
      background-color: ${({theme}) => lighten(0.25, theme.colors.secondaryLight)};
    }
  }
`

export const StyledSortingSpan = styled.span`
  height: 100%;
  margin-right: 2px;
`

export const StyledFullRowProgress = styled.td`
  grid-column: 1 / -1;
  padding-top: ${basePadding};
  height: 50px;
  text-align: center;
  border: 0;
`

export const StyledFullRow = styled.td`
  grid-column: 1 / -1;
  padding-top: ${basePadding};
  height: 50px;
  text-align: center;
  border: 0;
  ${declareFont()};
`

export const StyledTableHead = styled.thead`
  ${selectionStyles}
`

export const StyledTableRow = styled.tr`
  ${selectionStyles}
`

export const StyledTableBody = styled.tbody`
  ${selectionStyles}
`

const StyledTable = styled.table`
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  overflow: auto;
  display: grid;
  border-collapse: collapse;
  grid-template-columns: ${({columns}) =>
  columns.map(column => column.width ? column.width + 'px' : 'minmax(50px, auto)').join(' ')};
  grid-auto-rows: min-content;
  min-width: 100%;
  ${StyledScrollbar}
`

export const StretchingTableContainer = styled.div`
  grid-row-start: table-start;
  position: relative;
`

export const StyledTableWrapper = styled.div`
  display: grid;
  padding-left: ${scale.space(-0.5)};
  background-color: ${theme.color('paper')};
  grid-template-rows: [table-start] minmax(300px, 1fr) [pagination-start] auto auto;
  height: 100%;

  @media screen and (max-height: 650px) {
    grid-template-rows: [table-start] 1fr [pagination-start] auto auto;
  }
`

export const StyledDraggable = styled.div`
  width: 100%;
  height: 100%;
  display: flex;
`

export default StyledTable
<commit_msg>refactor(tocco-ui): refactor StyledTable.js<commit_after>import styled, {css} from 'styled-components'
import _get from 'lodash/get'
import {lighten} from 'polished'

import {
  declareFont,
  theme,
  shadeColor,
  StyledScrollbar,
  scale
} from '../'
import {StyledResizeHandle} from './ResizingController'

const borderColor = ({theme}) => shadeColor(_get(theme, 'colors.paper'), 2)
const basePadding = scale.space(-1)

export const StyledTableCell = styled.td`
  padding: ${basePadding};
  background-color: ${theme.color('paper')};
  border-bottom: 1px solid ${borderColor};
  align-content: center;
  max-height: 23px;
  box-sizing: content-box;
`

export const StyledDnD = styled.div`
  padding: ${basePadding};
  width: 100%;
  display: flex;
  opacity: ${({isDragged}) => isDragged ? 0.2 : 1};
`

export const StyledTableHeaderCell = styled.th`
  position: sticky;
  top: 0;
  background-color: ${theme.color('paper')};
  text-align: left;
  border-bottom: 2px solid ${borderColor};
  ${declareFont({fontWeight: theme.fontWeight('bold')})};
  user-select: none;
  cursor: ${({sortable}) => sortable ? 'pointer' : 'auto'};
  overflow: hidden;
  white-space: nowrap;
  display: flex;
  border-right: ${({isDraggedOver, theme}) => isDraggedOver ? `3px solid ${theme.colors.secondary}` : 'none'};
  ${({isResizing, theme}) => isResizing && `
    background-color: ${lighten(0.25, theme.colors.secondaryLight)};

    > ${StyledResizeHandle} {
      opacity: 1;
    }
    `
  }
  ${({resizingColumn, theme}) => !resizingColumn && `
    &:hover {
      background-color: ${lighten(0.25, theme.colors.secondaryLight)};

        > ${StyledResizeHandle} {
          opacity: 1;
        }
    }
    `
  }
  ${({isResizing, sortable, fixedPosition}) => !isResizing && !sortable && !fixedPosition && `
    &:hover {
      background-color: transparent;
    }
    `
  }
`

export const PaginationContainer = styled.div`
  grid-row-start: pagination-start;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  border-top: 1px solid ${borderColor};
`

const selectionStyles = css`
  display: contents;
  ${({clickable}) => clickable && 'cursor: pointer;'}

  &.selected {
    > ${StyledTableCell} {
      background-color: ${({theme}) => lighten(0.1, theme.colors.secondaryLight)};
    }
  }

  &.selectableRow:not(.selected):hover {
    > ${StyledTableCell} {
      background-color: ${({theme}) => lighten(0.25, theme.colors.secondaryLight)};
    }
  }
`

export const StyledSortingSpan = styled.span`
  height: 100%;
  margin-right: 2px;
`

export const StyledFullRowProgress = styled.td`
  grid-column: 1 / -1;
  padding-top: ${basePadding};
  height: 50px;
  text-align: center;
  border: 0;
`

export const StyledFullRow = styled.td`
  grid-column: 1 / -1;
  padding-top: ${basePadding};
  height: 50px;
  text-align: center;
  border: 0;
  ${declareFont()};
`

export const StyledTableHead = styled.thead`
  ${selectionStyles}
`

export const StyledTableRow = styled.tr`
  ${selectionStyles}
`

export const StyledTableBody = styled.tbody`
  ${selectionStyles}
`

const StyledTable = styled.table`
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  overflow: auto;
  display: grid;
  border-collapse: collapse;
  grid-template-columns: ${({columns}) =>
  columns.map(column => column.width ? column.width + 'px' : 'minmax(50px, auto)').join(' ')};
  grid-auto-rows: min-content;
  min-width: 100%;
  ${StyledScrollbar}
`

export const StretchingTableContainer = styled.div`
  grid-row-start: table-start;
  position: relative;
`

export const StyledTableWrapper = styled.div`
  display: grid;
  padding-left: ${scale.space(-0.5)};
  background-color: ${theme.color('paper')};
  grid-template-rows: [table-start] minmax(300px, 1fr) [pagination-start] auto auto;
  height: 100%;

  @media screen and (max-height: 650px) {
    grid-template-rows: [table-start] 1fr [pagination-start] auto auto;
  }
`

export const StyledDraggable = styled.div`
  width: 100%;
  height: 100%;
  display: flex;
`

export default StyledTable
<|endoftext|>


<commit_before>'use strict';
var util = require('util');
var path = require('path');
var fs = require('fs');
var yeoman = require('yeoman-generator');

var AngularWithRequireGenerator = module.exports = function AngularWithRequireGenerator(args, options, config) {
  yeoman.generators.Base.apply(this, arguments);

  // setup the test-framework property, Gruntfile template will need this
  this.testFramework = options['test-framework'] || 'mocha';
  this.coffee = options.coffee;

  // for hooks to resolve on mocha by default
  options['test-framework'] = this.testFramework;

  // resolved to mocha by default (could be switched to jasmine for instance)
  this.hookFor('test-framework', {
    as: 'app',
    options: {
      options: {
        'skip-install': options['skip-install-message'],
        'skip-message': options['skip-install']
      }
    }
  });

  this.options = options;

  this.pkg = JSON.parse(this.readFileAsString(path.join(__dirname, '../package.json')));
};

util.inherits(AngularWithRequireGenerator, yeoman.generators.Base);

AngularWithRequireGenerator.prototype.askForCSSFramework = function askForCSSFramework() {
  var cb = this.async();

  // have Yeoman greet the user.
  console.log(this.yeoman);

  var prompts = [{
    type: 'list',
    name: 'cssFramework',
    message: 'What CSS framework would you like to include?',
    choices: [
        { name: 'SASS Bootstrap'         , value: 'SASSBootstrap' },
        { name: 'SASS Compass framework' , value: 'CompassFramework' }
    ]
  }];

  this.prompt(prompts, function (props) {
    this.cssFramework = props.cssFramework;
    cb();
  }.bind(this));
};

AngularWithRequireGenerator.prototype.askForCSSFile = function askForCSSFile() {
  var cb = this.async();

  var prompts = [{
    type: 'checkbox',
    name: 'cssFile',
    message: 'What css library would you like to include?',
    choices: [
      { name: 'SASS Button by Alexwolfe' , value: 'includeButtonCss'   , checked: false },
      { name: 'Animate SCSS'             , value: 'includeAnimateCss'  , checked: false },
      { name: 'Bootstrap font-awesome'   , value: 'includeFontAwesome' , checked: true }
    ]
  }];

  this.prompt(prompts, function (props) {
    function includeCSS(css) { return props.cssFile.indexOf(css) !== -1; }

    // CSS
    this.includeButtonCss   = includeCSS('includeButtonCss');
    this.includeAnimateCss  = includeCSS('includeAnimateCss');
    this.includeFontAwesome = includeCSS('includeFontAwesome');

    cb();
  }.bind(this));
};

AngularWithRequireGenerator.prototype.askForJSFile = function askForJSFile() {
  var cb = this.async();

  var prompts = [{
    type: 'checkbox',
    name: 'jsFile',
    message: 'What js library would you like to include?',
    choices: [
      { name: 'Lodash.js'                 , value: 'includeLodash'         , checked: false } ,
      { name: 'Angular UI-Bootstrap'      , value: 'includeUIBootstrap'    , checked: false } ,
      { name: 'Angular animate'           , value: 'includeAngularAnimate' , checked: false } ,
      { name: 'Bindonce by Pasvaz'        , value: 'includeBindonce'       , checked: false } ,
      { name: 'Jasmine Testing framework' , value: 'includeJasmine'        , checked: true }  ,
      { name: 'Modernizr'                 , value: 'includeModernizr'      , checked: true }
    ]
  }];

  this.prompt(prompts, function (props) {
    function includeJS(js) { return props.jsFile.indexOf(js) !== -1; }

    // JS
    this.includeLodash         = includeJS('includeLodash');
    this.includeUIBootstrap    = includeJS('includeUIBootstrap');
    this.includeAngularAnimate = includeJS('includeAngularAnimate');
    this.includeBindonce       = includeJS('includeBindonce');
    this.includeJasmine        = includeJS('includeJasmine');
    this.includeModernizr      = includeJS('includeModernizr');

    if (this.includeJasmine) { this.testFramework = 'jasmine'; }

    cb();
  }.bind(this));
};

AngularWithRequireGenerator.prototype.gruntfile = function gruntfile() {
  this.template('Gruntfile.js');
};

AngularWithRequireGenerator.prototype.packageJSON= function packageJSON() {
  this.template('_package.json', 'package.json');
};

AngularWithRequireGenerator.prototype.bower = function bower() {
  this.copy('bowerrc', '.bowerrc');
  this.template('_bower.json', 'bower.json');
};

AngularWithRequireGenerator.prototype.jshint = function jshint() {
  this.copy('editorconfig', '.editorconfig');
  this.copy('jshintrc', '.jshintrc');
};

AngularWithRequireGenerator.prototype.h5bp = function h5bp() {
  this.copy('favicon.ico', 'app/favicon.ico');
  this.copy('404.html', 'app/404.html');
  this.copy('robots.txt', 'app/robots.txt');
  this.copy('htaccess', 'app/.htaccess');
  this.template('index.html', 'app/index.html');
};

AngularWithRequireGenerator.prototype.mainStylesheet = function mainStylesheet() {
  var cssFile = 'style.scss';
  var header = '';
  var content = this.readFileAsString(path.join(this.sourceRoot(), 'main.scss'));

  if (this.cssFramework === 'SASSBootstrap') {
      content += this.readFileAsString(path.join(this.sourceRoot(), 'bootstrap.css'));
  }

  if (this.includeFontAwesome) {
      header += "$fa-font-path: '../bower_components/font-awesome/fonts';\n" +
                "@import '../bower_components/font-awesome/scss/font-awesome';\n";
  }
  if (this.includeButtonCss) {
      header += "@import '../bower_components/Buttons/scss/buttons';\n"
  }
  if (this.includeAnimateCss) {
      header += "@import '../bower_components/animate-sass/animate';\n"
  }

  switch(this.cssFramework) {
    case 'CompassFramework':
      header += "@import 'compass';\n" + "@import 'compass/reset';\n";
      break;
    case 'SASSBootstrap':
      header += "$icon-font-path: '../bower_components/sass-bootstrap/fonts/';\n" +
                "@import '../bower_components/sass-bootstrap/lib/bootstrap';\n";
      break;
  }

  header += "@import 'custom_mixins.scss';\n";
  this.copy('_custom_mixins.scss', 'app/styles/_custom_mixins.scss');
  this.write('app/styles/' + cssFile, header + content);
};

AngularWithRequireGenerator.prototype.jsFile = function jsFile() {
  var prefix = 'app/src';
  this.mkdir(prefix);
  this.copy('src/config.js', prefix + '/config.js');
  this.copy('src/main.js', prefix + '/main.js');
};

AngularWithRequireGenerator.prototype.moduleCopy = function moduleCopy() {
  this.directory('src/home', 'app/src/home')
};

AngularWithRequireGenerator.prototype.app = function app() {
  this.mkdir('app/images');
  this.mkdir('app/src/vendor');
  this.mkdir('config');
};

AngularWithRequireGenerator.prototype.testFile = function testFile() {
  this.copy('karma.conf.js', 'config/karma.conf.js');
  this.copy('e2e.conf.js', 'config/e2e.conf.js');
  this.directory('test', 'test');
  this.template('test/e2eSpecs/angularE2Espec.js', 'test/e2eSpecs/angularE2Espec.js');
};

AngularWithRequireGenerator.prototype.install = function install() {
  if (this.options['skip-install']) { return; }

  var done = this.async();
  this.installDependencies({
    skipMessage: this.options['skip-install-message'],
    skipInstall: this.options['skip-install'],
    callback: function() {
      var projectDir = process.cwd() + '/app';
      fs.exists(projectDir + '/src/vendor/require.js', function(exists) {
        if (!exists) {
          fs.createReadStream(projectDir + '/bower_components/requirejs/require.js')
          .pipe(fs.createWriteStream(projectDir + '/src/vendor/require.js'));
        }
      });
    }
  });
};

<commit_msg>update template<commit_after>'use strict';
var util = require('util');
var path = require('path');
var fs = require('fs');
var yeoman = require('yeoman-generator');

var AngularWithRequireGenerator = module.exports = function AngularWithRequireGenerator(args, options, config) {
  yeoman.generators.Base.apply(this, arguments);

  // setup the test-framework property, Gruntfile template will need this
  this.testFramework = options['test-framework'] || 'mocha';
  this.coffee = options.coffee;

  // for hooks to resolve on mocha by default
  options['test-framework'] = this.testFramework;

  // resolved to mocha by default (could be switched to jasmine for instance)
  this.hookFor('test-framework', {
    as: 'app',
    options: {
      options: {
        'skip-install': options['skip-install-message'],
        'skip-message': options['skip-install']
      }
    }
  });

  this.options = options;

  this.pkg = JSON.parse(this.readFileAsString(path.join(__dirname, '../package.json')));
};

util.inherits(AngularWithRequireGenerator, yeoman.generators.Base);

AngularWithRequireGenerator.prototype.askForCSSFramework = function askForCSSFramework() {
  var cb = this.async();

  // have Yeoman greet the user.
  console.log(this.yeoman);

  var prompts = [{
    type: 'list',
    name: 'cssFramework',
    message: 'What CSS framework would you like to include?',
    choices: [
        { name: 'SASS Bootstrap'         , value: 'SASSBootstrap' },
        { name: 'SASS Compass framework' , value: 'CompassFramework' }
    ]
  }];

  this.prompt(prompts, function (props) {
    this.cssFramework = props.cssFramework;
    cb();
  }.bind(this));
};

AngularWithRequireGenerator.prototype.askForCSSFile = function askForCSSFile() {
  var cb = this.async();

  var prompts = [{
    type: 'checkbox',
    name: 'cssFile',
    message: 'What css library would you like to include?',
    choices: [
      { name: 'SASS Button by Alexwolfe' , value: 'includeButtonCss'   , checked: false },
      { name: 'Animate SCSS'             , value: 'includeAnimateCss'  , checked: false },
      { name: 'Bootstrap font-awesome'   , value: 'includeFontAwesome' , checked: true }
    ]
  }];

  this.prompt(prompts, function (props) {
    function includeCSS(css) { return props.cssFile.indexOf(css) !== -1; }

    // CSS
    this.includeButtonCss   = includeCSS('includeButtonCss');
    this.includeAnimateCss  = includeCSS('includeAnimateCss');
    this.includeFontAwesome = includeCSS('includeFontAwesome');

    cb();
  }.bind(this));
};

AngularWithRequireGenerator.prototype.askForJSFile = function askForJSFile() {
  var cb = this.async();

  var prompts = [{
    type: 'checkbox',
    name: 'jsFile',
    message: 'What js library would you like to include?',
    choices: [
      { name: 'Lodash.js'                 , value: 'includeLodash'         , checked: false } ,
      { name: 'Angular UI-Bootstrap'      , value: 'includeUIBootstrap'    , checked: false } ,
      { name: 'Angular animate'           , value: 'includeAngularAnimate' , checked: false } ,
      { name: 'Bindonce by Pasvaz'        , value: 'includeBindonce'       , checked: false } ,
      { name: 'Jasmine Testing framework' , value: 'includeJasmine'        , checked: true }  ,
      { name: 'Modernizr'                 , value: 'includeModernizr'      , checked: true }
    ]
  }];

  this.prompt(prompts, function (props) {
    function includeJS(js) { return props.jsFile.indexOf(js) !== -1; }

    // JS
    this.includeLodash         = includeJS('includeLodash');
    this.includeUIBootstrap    = includeJS('includeUIBootstrap');
    this.includeAngularAnimate = includeJS('includeAngularAnimate');
    this.includeBindonce       = includeJS('includeBindonce');
    this.includeJasmine        = includeJS('includeJasmine');
    this.includeModernizr      = includeJS('includeModernizr');

    if (this.includeJasmine) { this.testFramework = 'jasmine'; }

    cb();
  }.bind(this));
};

AngularWithRequireGenerator.prototype.gruntfile = function gruntfile() {
  this.template('Gruntfile.js');
};

AngularWithRequireGenerator.prototype.packageJSON= function packageJSON() {
  this.template('_package.json', 'package.json');
};

AngularWithRequireGenerator.prototype.bower = function bower() {
  this.copy('bowerrc', '.bowerrc');
  this.template('_bower.json', 'bower.json');
};

AngularWithRequireGenerator.prototype.jshint = function jshint() {
  this.copy('editorconfig', '.editorconfig');
  this.copy('jshintrc', '.jshintrc');
};

AngularWithRequireGenerator.prototype.h5bp = function h5bp() {
  this.copy('favicon.ico', 'app/favicon.ico');
  this.copy('404.html', 'app/404.html');
  this.copy('robots.txt', 'app/robots.txt');
  this.copy('htaccess', 'app/.htaccess');
  this.template('index.html', 'app/index.html');
};

AngularWithRequireGenerator.prototype.mainStylesheet = function mainStylesheet() {
  var cssFile = 'style.scss';
  var header = '';
  var content = this.readFileAsString(path.join(this.sourceRoot(), 'main.scss'));

  if (this.cssFramework === 'SASSBootstrap') {
      content += this.readFileAsString(path.join(this.sourceRoot(), 'bootstrap.css'));
  }

  if (this.includeFontAwesome) {
      header += "$fa-font-path: '../bower_components/font-awesome/fonts';\n" +
                "@import '../bower_components/font-awesome/scss/font-awesome';\n";
  }
  if (this.includeButtonCss) {
      header += "@import '../bower_components/Buttons/scss/buttons';\n"
  }
  if (this.includeAnimateCss) {
      header += "@import '../bower_components/animate-sass/animate';\n"
  }

  switch(this.cssFramework) {
    case 'CompassFramework':
      header += "@import 'compass';\n" + "@import 'compass/reset';\n";
      break;
    case 'SASSBootstrap':
      header += "$icon-font-path: '../bower_components/sass-bootstrap/fonts/';\n" +
                "@import '../bower_components/sass-bootstrap/lib/bootstrap';\n";
      break;
  }

  header += "@import 'custom_mixins.scss';\n";
  this.copy('_custom_mixins.scss', 'app/styles/_custom_mixins.scss');
  this.write('app/styles/' + cssFile, header + content);
};

AngularWithRequireGenerator.prototype.jsFile = function jsFile() {
  var prefix = 'app/src';
  this.mkdir(prefix);
  this.copy('src/config.js', prefix + '/config.js');
  this.copy('src/main.js', prefix + '/main.js');
};

AngularWithRequireGenerator.prototype.moduleCopy = function moduleCopy() {
  this.directory('src/home', 'app/src/home')
};

AngularWithRequireGenerator.prototype.app = function app() {
  this.mkdir('app/images');
  this.mkdir('app/src/vendor');
  this.mkdir('config');
};

AngularWithRequireGenerator.prototype.testFile = function testFile() {
  this.copy('karma.conf.js', 'config/karma.conf.js');
  this.copy('e2e.conf.js', 'config/e2e.conf.js');
  this.copy('test/test-main.js.template', 'test/test-main.js.template');
  this.template('test/e2eSpecs/angularE2Espec.js', 'test/e2eSpecs/angularE2Espec.js');
};

AngularWithRequireGenerator.prototype.install = function install() {
  if (this.options['skip-install']) { return; }

  var done = this.async();
  this.installDependencies({
    skipMessage: this.options['skip-install-message'],
    skipInstall: this.options['skip-install'],
    callback: function() {
      var projectDir = process.cwd() + '/app';
      fs.exists(projectDir + '/src/vendor/require.js', function(exists) {
        if (!exists) {
          fs.createReadStream(projectDir + '/bower_components/requirejs/require.js')
          .pipe(fs.createWriteStream(projectDir + '/src/vendor/require.js'));
        }
      });
    }
  });
};

<|endoftext|>