@@ -0,0 +1,176 @@
/**
* --------------------------------------------------------------------------
* Bootstrap (v4.0.0-alpha.6): button.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* --------------------------------------------------------------------------
*/

const Button = (($) => {


/**
* ------------------------------------------------------------------------
* Constants
* ------------------------------------------------------------------------
*/

const NAME = 'button'
const VERSION = '4.0.0-alpha.6'
const DATA_KEY = 'bs.button'
const EVENT_KEY = `.${DATA_KEY}`
const DATA_API_KEY = '.data-api'
const JQUERY_NO_CONFLICT = $.fn[NAME]

const ClassName = {
ACTIVE : 'active',
BUTTON : 'btn',
FOCUS : 'focus'
}

const Selector = {
DATA_TOGGLE_CARROT : '[data-toggle^="button"]',
DATA_TOGGLE : '[data-toggle="buttons"]',
INPUT : 'input',
ACTIVE : '.active',
BUTTON : '.btn'
}

const Event = {
CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`,
FOCUS_BLUR_DATA_API : `focus${EVENT_KEY}${DATA_API_KEY} `
+ `blur${EVENT_KEY}${DATA_API_KEY}`
}


/**
* ------------------------------------------------------------------------
* Class Definition
* ------------------------------------------------------------------------
*/

class Button {

constructor(element) {
this._element = element
}


// getters

static get VERSION() {
return VERSION
}


// public

toggle() {
let triggerChangeEvent = true
const rootElement = $(this._element).closest(
Selector.DATA_TOGGLE
)[0]

if (rootElement) {
const input = $(this._element).find(Selector.INPUT)[0]

if (input) {
if (input.type === 'radio') {
if (input.checked &&
$(this._element).hasClass(ClassName.ACTIVE)) {
triggerChangeEvent = false

} else {
const activeElement = $(rootElement).find(Selector.ACTIVE)[0]

if (activeElement) {
$(activeElement).removeClass(ClassName.ACTIVE)
}
}
}

if (triggerChangeEvent) {
input.checked = !$(this._element).hasClass(ClassName.ACTIVE)
$(input).trigger('change')
}

input.focus()
}

}

this._element.setAttribute('aria-pressed',
!$(this._element).hasClass(ClassName.ACTIVE))

if (triggerChangeEvent) {
$(this._element).toggleClass(ClassName.ACTIVE)
}
}

dispose() {
$.removeData(this._element, DATA_KEY)
this._element = null
}


// static

static _jQueryInterface(config) {
return this.each(function () {
let data = $(this).data(DATA_KEY)

if (!data) {
data = new Button(this)
$(this).data(DATA_KEY, data)
}

if (config === 'toggle') {
data[config]()
}
})
}

}


/**
* ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/

$(document)
.on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, (event) => {
event.preventDefault()

let button = event.target

if (!$(button).hasClass(ClassName.BUTTON)) {
button = $(button).closest(Selector.BUTTON)
}

Button._jQueryInterface.call($(button), 'toggle')
})
.on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, (event) => {
const button = $(event.target).closest(Selector.BUTTON)[0]
$(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type))
})


/**
* ------------------------------------------------------------------------
* jQuery
* ------------------------------------------------------------------------
*/

$.fn[NAME] = Button._jQueryInterface
$.fn[NAME].Constructor = Button
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT
return Button._jQueryInterface
}

return Button

})(jQuery)

export default Button

Large diffs are not rendered by default.

@@ -0,0 +1,387 @@
import Util from './util'


/**
* --------------------------------------------------------------------------
* Bootstrap (v4.0.0-alpha.6): collapse.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* --------------------------------------------------------------------------
*/

const Collapse = (($) => {


/**
* ------------------------------------------------------------------------
* Constants
* ------------------------------------------------------------------------
*/

const NAME = 'collapse'
const VERSION = '4.0.0-alpha.6'
const DATA_KEY = 'bs.collapse'
const EVENT_KEY = `.${DATA_KEY}`
const DATA_API_KEY = '.data-api'
const JQUERY_NO_CONFLICT = $.fn[NAME]
const TRANSITION_DURATION = 600

const Default = {
toggle : true,
parent : ''
}

const DefaultType = {
toggle : 'boolean',
parent : 'string'
}

const Event = {
SHOW : `show${EVENT_KEY}`,
SHOWN : `shown${EVENT_KEY}`,
HIDE : `hide${EVENT_KEY}`,
HIDDEN : `hidden${EVENT_KEY}`,
CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`
}

const ClassName = {
SHOW : 'show',
COLLAPSE : 'collapse',
COLLAPSING : 'collapsing',
COLLAPSED : 'collapsed'
}

const Dimension = {
WIDTH : 'width',
HEIGHT : 'height'
}

const Selector = {
ACTIVES : '.card > .show, .card > .collapsing',
DATA_TOGGLE : '[data-toggle="collapse"]'
}


/**
* ------------------------------------------------------------------------
* Class Definition
* ------------------------------------------------------------------------
*/

class Collapse {

constructor(element, config) {
this._isTransitioning = false
this._element = element
this._config = this._getConfig(config)
this._triggerArray = $.makeArray($(
`[data-toggle="collapse"][href="#${element.id}"],` +
`[data-toggle="collapse"][data-target="#${element.id}"]`
))

this._parent = this._config.parent ? this._getParent() : null

if (!this._config.parent) {
this._addAriaAndCollapsedClass(this._element, this._triggerArray)
}

if (this._config.toggle) {
this.toggle()
}
}


// getters

static get VERSION() {
return VERSION
}

static get Default() {
return Default
}


// public

toggle() {
if ($(this._element).hasClass(ClassName.SHOW)) {
this.hide()
} else {
this.show()
}
}

show() {
if (this._isTransitioning) {
throw new Error('Collapse is transitioning')
}

if ($(this._element).hasClass(ClassName.SHOW)) {
return
}

let actives
let activesData

if (this._parent) {
actives = $.makeArray($(this._parent).find(Selector.ACTIVES))
if (!actives.length) {
actives = null
}
}

if (actives) {
activesData = $(actives).data(DATA_KEY)
if (activesData && activesData._isTransitioning) {
return
}
}

const startEvent = $.Event(Event.SHOW)
$(this._element).trigger(startEvent)
if (startEvent.isDefaultPrevented()) {
return
}

if (actives) {
Collapse._jQueryInterface.call($(actives), 'hide')
if (!activesData) {
$(actives).data(DATA_KEY, null)
}
}

const dimension = this._getDimension()

$(this._element)
.removeClass(ClassName.COLLAPSE)
.addClass(ClassName.COLLAPSING)

this._element.style[dimension] = 0
this._element.setAttribute('aria-expanded', true)

if (this._triggerArray.length) {
$(this._triggerArray)
.removeClass(ClassName.COLLAPSED)
.attr('aria-expanded', true)
}

this.setTransitioning(true)

const complete = () => {
$(this._element)
.removeClass(ClassName.COLLAPSING)
.addClass(ClassName.COLLAPSE)
.addClass(ClassName.SHOW)

this._element.style[dimension] = ''

this.setTransitioning(false)

$(this._element).trigger(Event.SHOWN)
}

if (!Util.supportsTransitionEnd()) {
complete()
return
}

const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1)
const scrollSize = `scroll${capitalizedDimension}`

$(this._element)
.one(Util.TRANSITION_END, complete)
.emulateTransitionEnd(TRANSITION_DURATION)

this._element.style[dimension] = `${this._element[scrollSize]}px`
}

hide() {
if (this._isTransitioning) {
throw new Error('Collapse is transitioning')
}

if (!$(this._element).hasClass(ClassName.SHOW)) {
return
}

const startEvent = $.Event(Event.HIDE)
$(this._element).trigger(startEvent)
if (startEvent.isDefaultPrevented()) {
return
}

const dimension = this._getDimension()
const offsetDimension = dimension === Dimension.WIDTH ?
'offsetWidth' : 'offsetHeight'

this._element.style[dimension] = `${this._element[offsetDimension]}px`

Util.reflow(this._element)

$(this._element)
.addClass(ClassName.COLLAPSING)
.removeClass(ClassName.COLLAPSE)
.removeClass(ClassName.SHOW)

this._element.setAttribute('aria-expanded', false)

if (this._triggerArray.length) {
$(this._triggerArray)
.addClass(ClassName.COLLAPSED)
.attr('aria-expanded', false)
}

this.setTransitioning(true)

const complete = () => {
this.setTransitioning(false)
$(this._element)
.removeClass(ClassName.COLLAPSING)
.addClass(ClassName.COLLAPSE)
.trigger(Event.HIDDEN)
}

this._element.style[dimension] = ''

if (!Util.supportsTransitionEnd()) {
complete()
return
}

$(this._element)
.one(Util.TRANSITION_END, complete)
.emulateTransitionEnd(TRANSITION_DURATION)
}

setTransitioning(isTransitioning) {
this._isTransitioning = isTransitioning
}

dispose() {
$.removeData(this._element, DATA_KEY)

this._config = null
this._parent = null
this._element = null
this._triggerArray = null
this._isTransitioning = null
}


// private

_getConfig(config) {
config = $.extend({}, Default, config)
config.toggle = Boolean(config.toggle) // coerce string values
Util.typeCheckConfig(NAME, config, DefaultType)
return config
}

_getDimension() {
const hasWidth = $(this._element).hasClass(Dimension.WIDTH)
return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT
}

_getParent() {
const parent = $(this._config.parent)[0]
const selector =
`[data-toggle="collapse"][data-parent="${this._config.parent}"]`

$(parent).find(selector).each((i, element) => {
this._addAriaAndCollapsedClass(
Collapse._getTargetFromElement(element),
[element]
)
})

return parent
}

_addAriaAndCollapsedClass(element, triggerArray) {
if (element) {
const isOpen = $(element).hasClass(ClassName.SHOW)
element.setAttribute('aria-expanded', isOpen)

if (triggerArray.length) {
$(triggerArray)
.toggleClass(ClassName.COLLAPSED, !isOpen)
.attr('aria-expanded', isOpen)
}
}
}


// static

static _getTargetFromElement(element) {
const selector = Util.getSelectorFromElement(element)
return selector ? $(selector)[0] : null
}

static _jQueryInterface(config) {
return this.each(function () {
const $this = $(this)
let data = $this.data(DATA_KEY)
const _config = $.extend(
{},
Default,
$this.data(),
typeof config === 'object' && config
)

if (!data && _config.toggle && /show|hide/.test(config)) {
_config.toggle = false
}

if (!data) {
data = new Collapse(this, _config)
$this.data(DATA_KEY, data)
}

if (typeof config === 'string') {
if (data[config] === undefined) {
throw new Error(`No method named "${config}"`)
}
data[config]()
}
})
}

}


/**
* ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/

$(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
event.preventDefault()

const target = Collapse._getTargetFromElement(this)
const data = $(target).data(DATA_KEY)
const config = data ? 'toggle' : $(this).data()

Collapse._jQueryInterface.call($(target), config)
})


/**
* ------------------------------------------------------------------------
* jQuery
* ------------------------------------------------------------------------
*/

$.fn[NAME] = Collapse._jQueryInterface
$.fn[NAME].Constructor = Collapse
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT
return Collapse._jQueryInterface
}

return Collapse

})(jQuery)

export default Collapse
@@ -0,0 +1,303 @@
import Util from './util'


/**
* --------------------------------------------------------------------------
* Bootstrap (v4.0.0-alpha.6): dropdown.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* --------------------------------------------------------------------------
*/

const Dropdown = (($) => {


/**
* ------------------------------------------------------------------------
* Constants
* ------------------------------------------------------------------------
*/

const NAME = 'dropdown'
const VERSION = '4.0.0-alpha.6'
const DATA_KEY = 'bs.dropdown'
const EVENT_KEY = `.${DATA_KEY}`
const DATA_API_KEY = '.data-api'
const JQUERY_NO_CONFLICT = $.fn[NAME]
const ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key
const ARROW_UP_KEYCODE = 38 // KeyboardEvent.which value for up arrow key
const ARROW_DOWN_KEYCODE = 40 // KeyboardEvent.which value for down arrow key
const RIGHT_MOUSE_BUTTON_WHICH = 3 // MouseEvent.which value for the right button (assuming a right-handed mouse)

const Event = {
HIDE : `hide${EVENT_KEY}`,
HIDDEN : `hidden${EVENT_KEY}`,
SHOW : `show${EVENT_KEY}`,
SHOWN : `shown${EVENT_KEY}`,
CLICK : `click${EVENT_KEY}`,
CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`,
FOCUSIN_DATA_API : `focusin${EVENT_KEY}${DATA_API_KEY}`,
KEYDOWN_DATA_API : `keydown${EVENT_KEY}${DATA_API_KEY}`
}

const ClassName = {
BACKDROP : 'dropdown-backdrop',
DISABLED : 'disabled',
SHOW : 'show'
}

const Selector = {
BACKDROP : '.dropdown-backdrop',
DATA_TOGGLE : '[data-toggle="dropdown"]',
FORM_CHILD : '.dropdown form',
ROLE_MENU : '[role="menu"]',
ROLE_LISTBOX : '[role="listbox"]',
NAVBAR_NAV : '.navbar-nav',
VISIBLE_ITEMS : '[role="menu"] li:not(.disabled) a, '
+ '[role="listbox"] li:not(.disabled) a'
}


/**
* ------------------------------------------------------------------------
* Class Definition
* ------------------------------------------------------------------------
*/

class Dropdown {

constructor(element) {
this._element = element

this._addEventListeners()
}


// getters

static get VERSION() {
return VERSION
}


// public

toggle() {
if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {
return false
}

const parent = Dropdown._getParentFromElement(this)
const isActive = $(parent).hasClass(ClassName.SHOW)

Dropdown._clearMenus()

if (isActive) {
return false
}

if ('ontouchstart' in document.documentElement &&
!$(parent).closest(Selector.NAVBAR_NAV).length) {

// if mobile we use a backdrop because click events don't delegate
const dropdown = document.createElement('div')
dropdown.className = ClassName.BACKDROP
$(dropdown).insertBefore(this)
$(dropdown).on('click', Dropdown._clearMenus)
}

const relatedTarget = {
relatedTarget : this
}
const showEvent = $.Event(Event.SHOW, relatedTarget)

$(parent).trigger(showEvent)

if (showEvent.isDefaultPrevented()) {
return false
}

this.focus()
this.setAttribute('aria-expanded', true)

$(parent).toggleClass(ClassName.SHOW)
$(parent).trigger($.Event(Event.SHOWN, relatedTarget))

return false
}

dispose() {
$.removeData(this._element, DATA_KEY)
$(this._element).off(EVENT_KEY)
this._element = null
}


// private

_addEventListeners() {
$(this._element).on(Event.CLICK, this.toggle)
}


// static

static _jQueryInterface(config) {
return this.each(function () {
let data = $(this).data(DATA_KEY)

if (!data) {
data = new Dropdown(this)
$(this).data(DATA_KEY, data)
}

if (typeof config === 'string') {
if (data[config] === undefined) {
throw new Error(`No method named "${config}"`)
}
data[config].call(this)
}
})
}

static _clearMenus(event) {
if (event && event.which === RIGHT_MOUSE_BUTTON_WHICH) {
return
}

const backdrop = $(Selector.BACKDROP)[0]
if (backdrop) {
backdrop.parentNode.removeChild(backdrop)
}

const toggles = $.makeArray($(Selector.DATA_TOGGLE))

for (let i = 0; i < toggles.length; i++) {
const parent = Dropdown._getParentFromElement(toggles[i])
const relatedTarget = {
relatedTarget : toggles[i]
}

if (!$(parent).hasClass(ClassName.SHOW)) {
continue
}

if (event && (event.type === 'click' &&
/input|textarea/i.test(event.target.tagName) || event.type === 'focusin')
&& $.contains(parent, event.target)) {
continue
}

const hideEvent = $.Event(Event.HIDE, relatedTarget)
$(parent).trigger(hideEvent)
if (hideEvent.isDefaultPrevented()) {
continue
}

toggles[i].setAttribute('aria-expanded', 'false')

$(parent)
.removeClass(ClassName.SHOW)
.trigger($.Event(Event.HIDDEN, relatedTarget))
}
}

static _getParentFromElement(element) {
let parent
const selector = Util.getSelectorFromElement(element)

if (selector) {
parent = $(selector)[0]
}

return parent || element.parentNode
}

static _dataApiKeydownHandler(event) {
if (!/(38|40|27|32)/.test(event.which) ||
/input|textarea/i.test(event.target.tagName)) {
return
}

event.preventDefault()
event.stopPropagation()

if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {
return
}

const parent = Dropdown._getParentFromElement(this)
const isActive = $(parent).hasClass(ClassName.SHOW)

if (!isActive && event.which !== ESCAPE_KEYCODE ||
isActive && event.which === ESCAPE_KEYCODE) {

if (event.which === ESCAPE_KEYCODE) {
const toggle = $(parent).find(Selector.DATA_TOGGLE)[0]
$(toggle).trigger('focus')
}

$(this).trigger('click')
return
}

const items = $(parent).find(Selector.VISIBLE_ITEMS).get()

if (!items.length) {
return
}

let index = items.indexOf(event.target)

if (event.which === ARROW_UP_KEYCODE && index > 0) { // up
index--
}

if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) { // down
index++
}

if (index < 0) {
index = 0
}

items[index].focus()
}

}


/**
* ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/

$(document)
.on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler)
.on(Event.KEYDOWN_DATA_API, Selector.ROLE_MENU, Dropdown._dataApiKeydownHandler)
.on(Event.KEYDOWN_DATA_API, Selector.ROLE_LISTBOX, Dropdown._dataApiKeydownHandler)
.on(`${Event.CLICK_DATA_API} ${Event.FOCUSIN_DATA_API}`, Dropdown._clearMenus)
.on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, Dropdown.prototype.toggle)
.on(Event.CLICK_DATA_API, Selector.FORM_CHILD, (e) => {
e.stopPropagation()
})


/**
* ------------------------------------------------------------------------
* jQuery
* ------------------------------------------------------------------------
*/

$.fn[NAME] = Dropdown._jQueryInterface
$.fn[NAME].Constructor = Dropdown
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT
return Dropdown._jQueryInterface
}

return Dropdown

})(jQuery)

export default Dropdown

Large diffs are not rendered by default.

@@ -0,0 +1,179 @@
import Tooltip from './tooltip'


/**
* --------------------------------------------------------------------------
* Bootstrap (v4.0.0-alpha.6): popover.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* --------------------------------------------------------------------------
*/

const Popover = (($) => {


/**
* ------------------------------------------------------------------------
* Constants
* ------------------------------------------------------------------------
*/

const NAME = 'popover'
const VERSION = '4.0.0-alpha.6'
const DATA_KEY = 'bs.popover'
const EVENT_KEY = `.${DATA_KEY}`
const JQUERY_NO_CONFLICT = $.fn[NAME]

const Default = $.extend({}, Tooltip.Default, {
placement : 'right',
trigger : 'click',
content : '',
template : '<div class="popover" role="tooltip">'
+ '<h3 class="popover-title"></h3>'
+ '<div class="popover-content"></div></div>'
})

const DefaultType = $.extend({}, Tooltip.DefaultType, {
content : '(string|element|function)'
})

const ClassName = {
FADE : 'fade',
SHOW : 'show'
}

const Selector = {
TITLE : '.popover-title',
CONTENT : '.popover-content'
}

const Event = {
HIDE : `hide${EVENT_KEY}`,
HIDDEN : `hidden${EVENT_KEY}`,
SHOW : `show${EVENT_KEY}`,
SHOWN : `shown${EVENT_KEY}`,
INSERTED : `inserted${EVENT_KEY}`,
CLICK : `click${EVENT_KEY}`,
FOCUSIN : `focusin${EVENT_KEY}`,
FOCUSOUT : `focusout${EVENT_KEY}`,
MOUSEENTER : `mouseenter${EVENT_KEY}`,
MOUSELEAVE : `mouseleave${EVENT_KEY}`
}


/**
* ------------------------------------------------------------------------
* Class Definition
* ------------------------------------------------------------------------
*/

class Popover extends Tooltip {


// getters

static get VERSION() {
return VERSION
}

static get Default() {
return Default
}

static get NAME() {
return NAME
}

static get DATA_KEY() {
return DATA_KEY
}

static get Event() {
return Event
}

static get EVENT_KEY() {
return EVENT_KEY
}

static get DefaultType() {
return DefaultType
}


// overrides

isWithContent() {
return this.getTitle() || this._getContent()
}

getTipElement() {
return this.tip = this.tip || $(this.config.template)[0]
}

setContent() {
const $tip = $(this.getTipElement())

// we use append for html objects to maintain js events
this.setElementContent($tip.find(Selector.TITLE), this.getTitle())
this.setElementContent($tip.find(Selector.CONTENT), this._getContent())

$tip.removeClass(`${ClassName.FADE} ${ClassName.SHOW}`)

this.cleanupTether()
}

// private

_getContent() {
return this.element.getAttribute('data-content')
|| (typeof this.config.content === 'function' ?
this.config.content.call(this.element) :
this.config.content)
}


// static

static _jQueryInterface(config) {
return this.each(function () {
let data = $(this).data(DATA_KEY)
const _config = typeof config === 'object' ? config : null

if (!data && /destroy|hide/.test(config)) {
return
}

if (!data) {
data = new Popover(this, _config)
$(this).data(DATA_KEY, data)
}

if (typeof config === 'string') {
if (data[config] === undefined) {
throw new Error(`No method named "${config}"`)
}
data[config]()
}
})
}
}


/**
* ------------------------------------------------------------------------
* jQuery
* ------------------------------------------------------------------------
*/

$.fn[NAME] = Popover._jQueryInterface
$.fn[NAME].Constructor = Popover
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT
return Popover._jQueryInterface
}

return Popover

})(jQuery)

export default Popover
@@ -0,0 +1,332 @@
import Util from './util'


/**
* --------------------------------------------------------------------------
* Bootstrap (v4.0.0-alpha.6): scrollspy.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* --------------------------------------------------------------------------
*/

const ScrollSpy = (($) => {


/**
* ------------------------------------------------------------------------
* Constants
* ------------------------------------------------------------------------
*/

const NAME = 'scrollspy'
const VERSION = '4.0.0-alpha.6'
const DATA_KEY = 'bs.scrollspy'
const EVENT_KEY = `.${DATA_KEY}`
const DATA_API_KEY = '.data-api'
const JQUERY_NO_CONFLICT = $.fn[NAME]

const Default = {
offset : 10,
method : 'auto',
target : ''
}

const DefaultType = {
offset : 'number',
method : 'string',
target : '(string|element)'
}

const Event = {
ACTIVATE : `activate${EVENT_KEY}`,
SCROLL : `scroll${EVENT_KEY}`,
LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}`
}

const ClassName = {
DROPDOWN_ITEM : 'dropdown-item',
DROPDOWN_MENU : 'dropdown-menu',
NAV_LINK : 'nav-link',
NAV : 'nav',
ACTIVE : 'active'
}

const Selector = {
DATA_SPY : '[data-spy="scroll"]',
ACTIVE : '.active',
LIST_ITEM : '.list-item',
LI : 'li',
LI_DROPDOWN : 'li.dropdown',
NAV_LINKS : '.nav-link',
DROPDOWN : '.dropdown',
DROPDOWN_ITEMS : '.dropdown-item',
DROPDOWN_TOGGLE : '.dropdown-toggle'
}

const OffsetMethod = {
OFFSET : 'offset',
POSITION : 'position'
}


/**
* ------------------------------------------------------------------------
* Class Definition
* ------------------------------------------------------------------------
*/

class ScrollSpy {

constructor(element, config) {
this._element = element
this._scrollElement = element.tagName === 'BODY' ? window : element
this._config = this._getConfig(config)
this._selector = `${this._config.target} ${Selector.NAV_LINKS},`
+ `${this._config.target} ${Selector.DROPDOWN_ITEMS}`
this._offsets = []
this._targets = []
this._activeTarget = null
this._scrollHeight = 0

$(this._scrollElement).on(Event.SCROLL, (event) => this._process(event))

this.refresh()
this._process()
}


// getters

static get VERSION() {
return VERSION
}

static get Default() {
return Default
}


// public

refresh() {
const autoMethod = this._scrollElement !== this._scrollElement.window ?
OffsetMethod.POSITION : OffsetMethod.OFFSET

const offsetMethod = this._config.method === 'auto' ?
autoMethod : this._config.method

const offsetBase = offsetMethod === OffsetMethod.POSITION ?
this._getScrollTop() : 0

this._offsets = []
this._targets = []

this._scrollHeight = this._getScrollHeight()

const targets = $.makeArray($(this._selector))

targets
.map((element) => {
let target
const targetSelector = Util.getSelectorFromElement(element)

if (targetSelector) {
target = $(targetSelector)[0]
}

if (target && (target.offsetWidth || target.offsetHeight)) {
// todo (fat): remove sketch reliance on jQuery position/offset
return [
$(target)[offsetMethod]().top + offsetBase,
targetSelector
]
}
return null
})
.filter((item) => item)
.sort((a, b) => a[0] - b[0])
.forEach((item) => {
this._offsets.push(item[0])
this._targets.push(item[1])
})
}

dispose() {
$.removeData(this._element, DATA_KEY)
$(this._scrollElement).off(EVENT_KEY)

this._element = null
this._scrollElement = null
this._config = null
this._selector = null
this._offsets = null
this._targets = null
this._activeTarget = null
this._scrollHeight = null
}


// private

_getConfig(config) {
config = $.extend({}, Default, config)

if (typeof config.target !== 'string') {
let id = $(config.target).attr('id')
if (!id) {
id = Util.getUID(NAME)
$(config.target).attr('id', id)
}
config.target = `#${id}`
}

Util.typeCheckConfig(NAME, config, DefaultType)

return config
}

_getScrollTop() {
return this._scrollElement === window ?
this._scrollElement.pageYOffset : this._scrollElement.scrollTop
}

_getScrollHeight() {
return this._scrollElement.scrollHeight || Math.max(
document.body.scrollHeight,
document.documentElement.scrollHeight
)
}

_getOffsetHeight() {
return this._scrollElement === window ?
window.innerHeight : this._scrollElement.offsetHeight
}

_process() {
const scrollTop = this._getScrollTop() + this._config.offset
const scrollHeight = this._getScrollHeight()
const maxScroll = this._config.offset
+ scrollHeight
- this._getOffsetHeight()

if (this._scrollHeight !== scrollHeight) {
this.refresh()
}

if (scrollTop >= maxScroll) {
const target = this._targets[this._targets.length - 1]

if (this._activeTarget !== target) {
this._activate(target)
}
return
}

if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {
this._activeTarget = null
this._clear()
return
}

for (let i = this._offsets.length; i--;) {
const isActiveTarget = this._activeTarget !== this._targets[i]
&& scrollTop >= this._offsets[i]
&& (this._offsets[i + 1] === undefined ||
scrollTop < this._offsets[i + 1])

if (isActiveTarget) {
this._activate(this._targets[i])
}
}
}

_activate(target) {
this._activeTarget = target

this._clear()

let queries = this._selector.split(',')
queries = queries.map((selector) => {
return `${selector}[data-target="${target}"],` +
`${selector}[href="${target}"]`
})

const $link = $(queries.join(','))

if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {
$link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE)
$link.addClass(ClassName.ACTIVE)
} else {
// todo (fat) this is kinda sus...
// recursively add actives to tested nav-links
$link.parents(Selector.LI).find(`> ${Selector.NAV_LINKS}`).addClass(ClassName.ACTIVE)
}

$(this._scrollElement).trigger(Event.ACTIVATE, {
relatedTarget: target
})
}

_clear() {
$(this._selector).filter(Selector.ACTIVE).removeClass(ClassName.ACTIVE)
}


// static

static _jQueryInterface(config) {
return this.each(function () {
let data = $(this).data(DATA_KEY)
const _config = typeof config === 'object' && config

if (!data) {
data = new ScrollSpy(this, _config)
$(this).data(DATA_KEY, data)
}

if (typeof config === 'string') {
if (data[config] === undefined) {
throw new Error(`No method named "${config}"`)
}
data[config]()
}
})
}


}


/**
* ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/

$(window).on(Event.LOAD_DATA_API, () => {
const scrollSpys = $.makeArray($(Selector.DATA_SPY))

for (let i = scrollSpys.length; i--;) {
const $spy = $(scrollSpys[i])
ScrollSpy._jQueryInterface.call($spy, $spy.data())
}
})


/**
* ------------------------------------------------------------------------
* jQuery
* ------------------------------------------------------------------------
*/

$.fn[NAME] = ScrollSpy._jQueryInterface
$.fn[NAME].Constructor = ScrollSpy
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT
return ScrollSpy._jQueryInterface
}

return ScrollSpy

})(jQuery)

export default ScrollSpy
@@ -0,0 +1,278 @@
import Util from './util'


/**
* --------------------------------------------------------------------------
* Bootstrap (v4.0.0-alpha.6): tab.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* --------------------------------------------------------------------------
*/

const Tab = (($) => {


/**
* ------------------------------------------------------------------------
* Constants
* ------------------------------------------------------------------------
*/

const NAME = 'tab'
const VERSION = '4.0.0-alpha.6'
const DATA_KEY = 'bs.tab'
const EVENT_KEY = `.${DATA_KEY}`
const DATA_API_KEY = '.data-api'
const JQUERY_NO_CONFLICT = $.fn[NAME]
const TRANSITION_DURATION = 150

const Event = {
HIDE : `hide${EVENT_KEY}`,
HIDDEN : `hidden${EVENT_KEY}`,
SHOW : `show${EVENT_KEY}`,
SHOWN : `shown${EVENT_KEY}`,
CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`
}

const ClassName = {
DROPDOWN_MENU : 'dropdown-menu',
ACTIVE : 'active',
DISABLED : 'disabled',
FADE : 'fade',
SHOW : 'show'
}

const Selector = {
A : 'a',
LI : 'li',
DROPDOWN : '.dropdown',
LIST : 'ul:not(.dropdown-menu), ol:not(.dropdown-menu), nav:not(.dropdown-menu)',
FADE_CHILD : '> .nav-item .fade, > .fade',
ACTIVE : '.active',
ACTIVE_CHILD : '> .nav-item > .active, > .active',
DATA_TOGGLE : '[data-toggle="tab"], [data-toggle="pill"]',
DROPDOWN_TOGGLE : '.dropdown-toggle',
DROPDOWN_ACTIVE_CHILD : '> .dropdown-menu .active'
}


/**
* ------------------------------------------------------------------------
* Class Definition
* ------------------------------------------------------------------------
*/

class Tab {

constructor(element) {
this._element = element
}


// getters

static get VERSION() {
return VERSION
}


// public

show() {
if (this._element.parentNode &&
this._element.parentNode.nodeType === Node.ELEMENT_NODE &&
$(this._element).hasClass(ClassName.ACTIVE) ||
$(this._element).hasClass(ClassName.DISABLED)) {
return
}

let target
let previous
const listElement = $(this._element).closest(Selector.LIST)[0]
const selector = Util.getSelectorFromElement(this._element)

if (listElement) {
previous = $.makeArray($(listElement).find(Selector.ACTIVE))
previous = previous[previous.length - 1]
}

const hideEvent = $.Event(Event.HIDE, {
relatedTarget: this._element
})

const showEvent = $.Event(Event.SHOW, {
relatedTarget: previous
})

if (previous) {
$(previous).trigger(hideEvent)
}

$(this._element).trigger(showEvent)

if (showEvent.isDefaultPrevented() ||
hideEvent.isDefaultPrevented()) {
return
}

if (selector) {
target = $(selector)[0]
}

this._activate(
this._element,
listElement
)

const complete = () => {
const hiddenEvent = $.Event(Event.HIDDEN, {
relatedTarget: this._element
})

const shownEvent = $.Event(Event.SHOWN, {
relatedTarget: previous
})

$(previous).trigger(hiddenEvent)
$(this._element).trigger(shownEvent)
}

if (target) {
this._activate(target, target.parentNode, complete)
} else {
complete()
}
}

dispose() {
$.removeClass(this._element, DATA_KEY)
this._element = null
}


// private

_activate(element, container, callback) {
const active = $(container).find(Selector.ACTIVE_CHILD)[0]
const isTransitioning = callback
&& Util.supportsTransitionEnd()
&& (active && $(active).hasClass(ClassName.FADE)
|| Boolean($(container).find(Selector.FADE_CHILD)[0]))

const complete = () => this._transitionComplete(
element,
active,
isTransitioning,
callback
)

if (active && isTransitioning) {
$(active)
.one(Util.TRANSITION_END, complete)
.emulateTransitionEnd(TRANSITION_DURATION)

} else {
complete()
}

if (active) {
$(active).removeClass(ClassName.SHOW)
}
}

_transitionComplete(element, active, isTransitioning, callback) {
if (active) {
$(active).removeClass(ClassName.ACTIVE)

const dropdownChild = $(active.parentNode).find(
Selector.DROPDOWN_ACTIVE_CHILD
)[0]

if (dropdownChild) {
$(dropdownChild).removeClass(ClassName.ACTIVE)
}

active.setAttribute('aria-expanded', false)
}

$(element).addClass(ClassName.ACTIVE)
element.setAttribute('aria-expanded', true)

if (isTransitioning) {
Util.reflow(element)
$(element).addClass(ClassName.SHOW)
} else {
$(element).removeClass(ClassName.FADE)
}

if (element.parentNode &&
$(element.parentNode).hasClass(ClassName.DROPDOWN_MENU)) {

const dropdownElement = $(element).closest(Selector.DROPDOWN)[0]
if (dropdownElement) {
$(dropdownElement).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE)
}

element.setAttribute('aria-expanded', true)
}

if (callback) {
callback()
}
}


// static

static _jQueryInterface(config) {
return this.each(function () {
const $this = $(this)
let data = $this.data(DATA_KEY)

if (!data) {
data = new Tab(this)
$this.data(DATA_KEY, data)
}

if (typeof config === 'string') {
if (data[config] === undefined) {
throw new Error(`No method named "${config}"`)
}
data[config]()
}
})
}

}


/**
* ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/

$(document)
.on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
event.preventDefault()
Tab._jQueryInterface.call($(this), 'show')
})


/**
* ------------------------------------------------------------------------
* jQuery
* ------------------------------------------------------------------------
*/

$.fn[NAME] = Tab._jQueryInterface
$.fn[NAME].Constructor = Tab
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT
return Tab._jQueryInterface
}

return Tab

})(jQuery)

export default Tab

Large diffs are not rendered by default.

@@ -0,0 +1,161 @@
/**
* --------------------------------------------------------------------------
* Bootstrap (v4.0.0-alpha.6): util.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* --------------------------------------------------------------------------
*/

const Util = (($) => {


/**
* ------------------------------------------------------------------------
* Private TransitionEnd Helpers
* ------------------------------------------------------------------------
*/

let transition = false

const MAX_UID = 1000000

const TransitionEndEvent = {
WebkitTransition : 'webkitTransitionEnd',
MozTransition : 'transitionend',
OTransition : 'oTransitionEnd otransitionend',
transition : 'transitionend'
}

// shoutout AngusCroll (https://goo.gl/pxwQGp)
function toType(obj) {
return {}.toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}

function isElement(obj) {
return (obj[0] || obj).nodeType
}

function getSpecialTransitionEndEvent() {
return {
bindType: transition.end,
delegateType: transition.end,
handle(event) {
if ($(event.target).is(this)) {
return event.handleObj.handler.apply(this, arguments) // eslint-disable-line prefer-rest-params
}
return undefined
}
}
}

function transitionEndTest() {
if (window.QUnit) {
return false
}

const el = document.createElement('bootstrap')

for (const name in TransitionEndEvent) {
if (el.style[name] !== undefined) {
return {
end: TransitionEndEvent[name]
}
}
}

return false
}

function transitionEndEmulator(duration) {
let called = false

$(this).one(Util.TRANSITION_END, () => {
called = true
})

setTimeout(() => {
if (!called) {
Util.triggerTransitionEnd(this)
}
}, duration)

return this
}

function setTransitionEndSupport() {
transition = transitionEndTest()

$.fn.emulateTransitionEnd = transitionEndEmulator

if (Util.supportsTransitionEnd()) {
$.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent()
}
}


/**
* --------------------------------------------------------------------------
* Public Util Api
* --------------------------------------------------------------------------
*/

const Util = {

TRANSITION_END: 'bsTransitionEnd',

getUID(prefix) {
do {
// eslint-disable-next-line no-bitwise
prefix += ~~(Math.random() * MAX_UID) // "~~" acts like a faster Math.floor() here
} while (document.getElementById(prefix))
return prefix
},

getSelectorFromElement(element) {
let selector = element.getAttribute('data-target')

if (!selector) {
selector = element.getAttribute('href') || ''
selector = /^#[a-z]/i.test(selector) ? selector : null
}

return selector
},

reflow(element) {
return element.offsetHeight
},

triggerTransitionEnd(element) {
$(element).trigger(transition.end)
},

supportsTransitionEnd() {
return Boolean(transition)
},

typeCheckConfig(componentName, config, configTypes) {
for (const property in configTypes) {
if (configTypes.hasOwnProperty(property)) {
const expectedTypes = configTypes[property]
const value = config[property]
const valueType = value && isElement(value) ?
'element' : toType(value)

if (!new RegExp(expectedTypes).test(valueType)) {
throw new Error(
`${componentName.toUpperCase()}: ` +
`Option "${property}" provided type "${valueType}" ` +
`but expected type "${expectedTypes}".`)
}
}
}
}
}

setTransitionEndSupport()

return Util

})(jQuery)

export default Util
@@ -0,0 +1,18 @@
# set env vars usually set by MyGet (enable for local testing)
#$env:SourcesPath = '..'
#$env:NuGet = "./nuget.exe" #https://dist.nuget.org/win-x86-commandline/latest/nuget.exe

$nuget = $env:NuGet

# parse the version number out of package.json
$bsversionParts = ((Get-Content $env:SourcesPath\package.json) -join "`n" | ConvertFrom-Json).version.split('-', 2) # split the version on the '-'
$bsversion = $bsversionParts[0]

if ($bsversionParts.Length -gt 1)
{
$bsversion += '-' + $bsversionParts[1].replace('.', '').replace('-', '_') # strip out invalid chars from the PreRelease part
}

# create packages
& $nuget pack "$env:SourcesPath\nuget\bootstrap.nuspec" -Verbosity detailed -NonInteractive -NoPackageAnalysis -BasePath $env:SourcesPath -Version $bsversion
& $nuget pack "$env:SourcesPath\nuget\bootstrap.sass.nuspec" -Verbosity detailed -NonInteractive -NoPackageAnalysis -BasePath $env:SourcesPath -Version $bsversion
@@ -0,0 +1,27 @@
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>bootstrap</id>
<version>4.0.0</version>
<title>Bootstrap CSS</title>
<authors>The Bootstrap Authors, Twitter Inc.</authors>
<owners>bootstrap</owners>
<description>The most popular front-end framework for developing responsive, mobile first projects on the web.</description>
<releaseNotes>https://blog.getbootstrap.com</releaseNotes>
<summary>Bootstrap framework in CSS. Includes fonts and JavaScript</summary>
<language>en-us</language>
<projectUrl>https://getbootstrap.com</projectUrl>
<iconUrl>https://getbootstrap.com/apple-touch-icon.png</iconUrl>
<licenseUrl>https://github.com/twbs/bootstrap/blob/master/LICENSE</licenseUrl>
<copyright>Copyright 2017</copyright>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<dependencies>
<dependency id="jQuery" version="[1.9.1,4)" />
</dependencies>
<tags>css mobile-first responsive front-end framework web</tags>
</metadata>
<files>
<file src="dist\css\*.*" target="content\Content" />
<file src="dist\js\bootstrap*.js" target="content\Scripts" />
</files>
</package>
@@ -0,0 +1,27 @@
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>bootstrap.sass</id>
<version>4.0.0</version>
<title>Bootstrap Sass</title>
<authors>The Bootstrap Authors, Twitter Inc.</authors>
<owners>bootstrap</owners>
<description>The most popular front-end framework for developing responsive, mobile first projects on the web.</description>
<releaseNotes>https://blog.getbootstrap.com</releaseNotes>
<summary>Bootstrap framework in Sass. Includes fonts and JavaScript</summary>
<language>en-us</language>
<projectUrl>https://getbootstrap.com</projectUrl>
<iconUrl>https://getbootstrap.com/apple-touch-icon.png</iconUrl>
<licenseUrl>https://github.com/twbs/bootstrap/blob/master/LICENSE</licenseUrl>
<copyright>Copyright 2017</copyright>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<dependencies>
<dependency id="jQuery" version="[1.9.1,4)" />
</dependencies>
<tags>css sass mobile-first responsive front-end framework web</tags>
</metadata>
<files>
<file src="scss\**\*.scss" target="content\Content\bootstrap" />
<file src="dist\js\bootstrap*.js" target="content\Scripts" />
</files>
</package>
@@ -0,0 +1,19 @@
// package metadata file for Meteor.js

/* global Package:true */

Package.describe({
name: 'twbs:bootstrap', // https://atmospherejs.com/twbs/bootstrap
summary: 'The most popular front-end framework for developing responsive, mobile first projects on the web.',
version: '4.0.0-alpha.6',
git: 'https://github.com/twbs/bootstrap.git'
});

Package.onUse(function (api) {
api.versionsFrom('METEOR@1.0');
api.use('jquery', 'client');
api.addFiles([
'dist/css/bootstrap.css',
'dist/js/bootstrap.js'
], 'client');
});
@@ -0,0 +1,112 @@
{
"name": "bootstrap",
"description": "The most popular front-end framework for developing responsive, mobile first projects on the web.",
"version": "4.0.0-alpha.6",
"keywords": [
"css",
"sass",
"mobile-first",
"responsive",
"front-end",
"framework",
"web"
],
"homepage": "https://getbootstrap.com",
"author": "The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)",
"contributors": [
"Twitter, Inc."
],
"scripts": {
"change-version": "node grunt/change-version.js",
"clean-css": "cleancss --skip-advanced --source-map --output dist/css/bootstrap.min.css dist/css/bootstrap.css && cleancss --skip-advanced --source-map --output dist/css/bootstrap-grid.min.css dist/css/bootstrap-grid.css && cleancss --skip-advanced --source-map --output dist/css/bootstrap-reboot.min.css dist/css/bootstrap-reboot.css",
"clean-css-docs": "cleancss --skip-advanced --source-map --output docs/assets/css/docs.min.css docs/assets/css/docs.min.css",
"eslint": "eslint --ignore-path .eslintignore js && eslint --config js/tests/.eslintrc.json --env node grunt Gruntfile.js && eslint --config js/tests/.eslintrc.json docs/assets/js/src docs/assets/js/ie-emulation-modes-warning.js docs/assets/js/ie10-viewport-bug-workaround.js",
"htmlhint": "htmlhint --config docs/.htmlhintrc _gh_pages/",
"postcss": "postcss --config grunt/postcss.js --replace dist/css/*.css",
"postcss-docs": "postcss --config grunt/postcss.js --no-map --replace docs/assets/css/docs.min.css && postcss --config grunt/postcss.js --no-map --replace docs/examples/**/*.css",
"sass": "node-sass --output-style expanded --source-map true --precision 6 scss/bootstrap.scss dist/css/bootstrap.css && node-sass --output-style expanded --source-map true --precision 6 scss/bootstrap-grid.scss dist/css/bootstrap-grid.css && node-sass --output-style expanded --source-map true --precision 6 scss/bootstrap-reboot.scss dist/css/bootstrap-reboot.css",
"sass-docs": "node-sass --output-style expanded --source-map true --precision 6 docs/assets/scss/docs.scss docs/assets/css/docs.min.css",
"scss-lint": "bundle exec scss-lint --config scss/.scss-lint.yml --exclude scss/_normalize.scss scss/*.scss",
"scss-lint-docs": "bundle exec scss-lint --config scss/.scss-lint.yml --exclude docs/assets/scss/docs.scss docs/assets/scss/*.scss",
"uglify": "uglifyjs --compress warnings=false --mangle --comments '/^!/' --output dist/js/bootstrap.min.js dist/js/bootstrap.js",
"uglify-docs": "uglifyjs --compress warnings=false --mangle --comments '/^!/' --output docs/assets/js/docs.min.js docs/assets/js/vendor/*.js docs/assets/js/src/application.js",
"update-shrinkwrap": "npm shrinkwrap --dev && shx mv ./npm-shrinkwrap.json ./grunt/npm-shrinkwrap.json",
"test": "npm run eslint && grunt test"
},
"style": "dist/css/bootstrap.css",
"sass": "scss/bootstrap.scss",
"main": "dist/js/bootstrap",
"repository": {
"type": "git",
"url": "https://github.com/twbs/bootstrap.git"
},
"bugs": {
"url": "https://github.com/twbs/bootstrap/issues"
},
"license": "MIT",
"dependencies": {
"jquery": ">=1.9.1",
"tether": "^1.4.0"
},
"devDependencies": {
"autoprefixer": "^6.6.1",
"babel-eslint": "^7.1.1",
"babel-plugin-transform-es2015-modules-strip": "^0.1.0",
"babel-preset-es2015": "^6.18.0",
"clean-css": "^3.4.23",
"eslint": "^3.12.2",
"grunt": "^1.0.1",
"grunt-babel": "^6.0.0",
"grunt-build-control": "^0.7.1",
"grunt-contrib-clean": "^1.0.0",
"grunt-contrib-compress": "^1.3.0",
"grunt-contrib-concat": "^1.0.1",
"grunt-contrib-connect": "^1.0.2",
"grunt-contrib-copy": "^1.0.0",
"grunt-contrib-qunit": "^1.2.0",
"grunt-contrib-watch": "^1.0.0",
"grunt-exec": "^1.0.1",
"grunt-html": "^8.1.0",
"grunt-jekyll": "^0.4.4",
"grunt-saucelabs": "^9.0.0",
"grunt-stamp": "^0.3.0",
"htmlhint": "^0.9.13",
"is-travis": "^1.0.0",
"load-grunt-tasks": "^3.5.2",
"node-sass": "^4.1.1",
"postcss-cli": "^2.6.0",
"postcss-flexbugs-fixes": "^2.1.0",
"shelljs": "^0.7.5",
"shx": "^0.2.1",
"time-grunt": "^1.4.0",
"uglify-js": "^2.7.5"
},
"engines": {
"node": ">=4"
},
"files": [
"dist",
"grunt",
"js/**/*.js",
"scss/**/*.scss",
"Gruntfile.js",
"LICENSE"
],
"jspm": {
"main": "js/bootstrap",
"directories": {
"lib": "dist"
},
"shim": {
"js/bootstrap": {
"deps": [
"jquery"
],
"exports": "$"
}
},
"dependencies": {
"jquery": "3"
}
}
}
@@ -0,0 +1,5 @@
{
"name": "bootstrap",
"description": "The most popular HTML, CSS, and JavaScript framework for developing responsive, mobile first projects on the web.",
"tags": ["bootstrap", "grid", "typography", "buttons", "ui", "responsive-web-design"]
}

Large diffs are not rendered by default.

@@ -0,0 +1,55 @@
//
// Base styles
//

.alert {
padding: $alert-padding-y $alert-padding-x;
margin-bottom: $alert-margin-bottom;
border: $alert-border-width solid transparent;
@include border-radius($alert-border-radius);
}

// Headings for larger alerts
.alert-heading {
// Specified to prevent conflicts of changing $headings-color
color: inherit;
}

// Provide class for links that match alerts
.alert-link {
font-weight: $alert-link-font-weight;
}


// Dismissible alerts
//
// Expand the right padding and account for the close button's positioning.

.alert-dismissible {
// Adjust close link position
.close {
position: relative;
top: -$alert-padding-y;
right: -$alert-padding-x;
padding: $alert-padding-y $alert-padding-x;
color: inherit;
}
}


// Alternate styles
//
// Generate contextual modifier classes for colorizing the alert.

.alert-success {
@include alert-variant($alert-success-bg, $alert-success-border, $alert-success-text);
}
.alert-info {
@include alert-variant($alert-info-bg, $alert-info-border, $alert-info-text);
}
.alert-warning {
@include alert-variant($alert-warning-bg, $alert-warning-border, $alert-warning-text);
}
.alert-danger {
@include alert-variant($alert-danger-bg, $alert-danger-border, $alert-danger-text);
}
@@ -0,0 +1,77 @@
// Base class
//
// Requires one of the contextual, color modifier classes for `color` and
// `background-color`.

.badge {
display: inline-block;
padding: $badge-padding-y $badge-padding-x;
font-size: $badge-font-size;
font-weight: $badge-font-weight;
line-height: 1;
color: $badge-color;
text-align: center;
white-space: nowrap;
vertical-align: baseline;
@include border-radius();

// Empty badges collapse automatically
&:empty {
display: none;
}
}

// Quick fix for badges in buttons
.btn .badge {
position: relative;
top: -1px;
}

// scss-lint:disable QualifyingElement
// Add hover effects, but only for links
a.badge {
@include hover-focus {
color: $badge-link-hover-color;
text-decoration: none;
cursor: pointer;
}
}
// scss-lint:enable QualifyingElement

// Pill badges
//
// Make them extra rounded with a modifier to replace v3's badges.

.badge-pill {
padding-right: $badge-pill-padding-x;
padding-left: $badge-pill-padding-x;
@include border-radius($badge-pill-border-radius);
}

// Colors
//
// Contextual variations (linked badges get darker on :hover).

.badge-default {
@include badge-variant($badge-default-bg);
}

.badge-primary {
@include badge-variant($badge-primary-bg);
}

.badge-success {
@include badge-variant($badge-success-bg);
}

.badge-info {
@include badge-variant($badge-info-bg);
}

.badge-warning {
@include badge-variant($badge-warning-bg);
}

.badge-danger {
@include badge-variant($badge-danger-bg);
}
@@ -0,0 +1,38 @@
.breadcrumb {
padding: $breadcrumb-padding-y $breadcrumb-padding-x;
margin-bottom: $spacer-y;
list-style: none;
background-color: $breadcrumb-bg;
@include border-radius($border-radius);
@include clearfix;
}

.breadcrumb-item {
float: left;

// The separator between breadcrumbs (by default, a forward-slash: "/")
+ .breadcrumb-item::before {
display: inline-block; // Suppress underlining of the separator in modern browsers
padding-right: $breadcrumb-item-padding;
padding-left: $breadcrumb-item-padding;
color: $breadcrumb-divider-color;
content: "#{$breadcrumb-divider}";
}

// IE9-11 hack to properly handle hyperlink underlines for breadcrumbs built
// without `<ul>`s. The `::before` pseudo-element generates an element
// *within* the .breadcrumb-item and thereby inherits the `text-decoration`.
//
// To trick IE into suppressing the underline, we give the pseudo-element an
// underline and then immediately remove it.
+ .breadcrumb-item:hover::before {
text-decoration: underline;
}
+ .breadcrumb-item:hover::before {
text-decoration: none;
}

&.active {
color: $breadcrumb-active-color;
}
}
@@ -0,0 +1,202 @@
// scss-lint:disable QualifyingElement

// Make the div behave like a button
.btn-group,
.btn-group-vertical {
position: relative;
display: inline-flex;
vertical-align: middle; // match .btn alignment given font-size hack above

> .btn {
position: relative;
flex: 0 1 auto;

// Bring the hover, focused, and "active" buttons to the fron to overlay
// the borders properly
@include hover {
z-index: 2;
}
&:focus,
&:active,
&.active {
z-index: 2;
}
}

// Prevent double borders when buttons are next to each other
.btn + .btn,
.btn + .btn-group,
.btn-group + .btn,
.btn-group + .btn-group {
margin-left: -$input-btn-border-width;
}
}

// Optional: Group multiple button groups together for a toolbar
.btn-toolbar {
display: flex;
justify-content: flex-start;

.input-group {
width: auto;
}
}

.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
border-radius: 0;
}

// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match
.btn-group > .btn:first-child {
margin-left: 0;

&:not(:last-child):not(.dropdown-toggle) {
@include border-right-radius(0);
}
}
// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it
.btn-group > .btn:last-child:not(:first-child),
.btn-group > .dropdown-toggle:not(:first-child) {
@include border-left-radius(0);
}

// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)
.btn-group > .btn-group {
float: left;
}
.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
border-radius: 0;
}
.btn-group > .btn-group:first-child:not(:last-child) {
> .btn:last-child,
> .dropdown-toggle {
@include border-right-radius(0);
}
}
.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {
@include border-left-radius(0);
}

// On active and open, don't show outline
.btn-group .dropdown-toggle:active,
.btn-group.open .dropdown-toggle {
outline: 0;
}


// Sizing
//
// Remix the default button sizing classes into new ones for easier manipulation.

.btn-group-sm > .btn { @extend .btn-sm; }
.btn-group-lg > .btn { @extend .btn-lg; }


//
// Split button dropdowns
//

.btn + .dropdown-toggle-split {
padding-right: $btn-padding-x * .75;
padding-left: $btn-padding-x * .75;

&::after {
margin-left: 0;
}
}

.btn-sm + .dropdown-toggle-split {
padding-right: $btn-padding-x-sm * .75;
padding-left: $btn-padding-x-sm * .75;
}

.btn-lg + .dropdown-toggle-split {
padding-right: $btn-padding-x-lg * .75;
padding-left: $btn-padding-x-lg * .75;
}


// The clickable button for toggling the menu
// Remove the gradient and set the same inset shadow as the :active state
.btn-group.open .dropdown-toggle {
@include box-shadow($btn-active-box-shadow);

// Show no shadow for `.btn-link` since it has no other button styles.
&.btn-link {
@include box-shadow(none);
}
}


//
// Vertical button groups
//

.btn-group-vertical {
display: inline-flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;

.btn,
.btn-group {
width: 100%;
}

> .btn + .btn,
> .btn + .btn-group,
> .btn-group + .btn,
> .btn-group + .btn-group {
margin-top: -$input-btn-border-width;
margin-left: 0;
}
}

.btn-group-vertical > .btn {
&:not(:first-child):not(:last-child) {
border-radius: 0;
}
&:first-child:not(:last-child) {
@include border-bottom-radius(0);
}
&:last-child:not(:first-child) {
@include border-top-radius(0);
}
}
.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
border-radius: 0;
}
.btn-group-vertical > .btn-group:first-child:not(:last-child) {
> .btn:last-child,
> .dropdown-toggle {
@include border-bottom-radius(0);
}
}
.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {
@include border-top-radius(0);
}


// Checkbox and radio options
//
// In order to support the browser's form validation feedback, powered by the
// `required` attribute, we have to "hide" the inputs via `clip`. We cannot use
// `display: none;` or `visibility: hidden;` as that also hides the popover.
// Simply visually hiding the inputs via `opacity` would leave them clickable in
// certain cases which is prevented by using `clip` and `pointer-events`.
// This way, we ensure a DOM element is visible to position the popover from.
//
// See https://github.com/twbs/bootstrap/pull/12794 and
// https://github.com/twbs/bootstrap/pull/14559 for more information.

[data-toggle="buttons"] {
> .btn,
> .btn-group > .btn {
input[type="radio"],
input[type="checkbox"] {
position: absolute;
clip: rect(0,0,0,0);
pointer-events: none;
}
}
}
@@ -0,0 +1,170 @@
// scss-lint:disable QualifyingElement

//
// Base styles
//

.btn {
display: inline-block;
font-weight: $btn-font-weight;
line-height: $btn-line-height;
text-align: center;
white-space: nowrap;
vertical-align: middle;
user-select: none;
border: $input-btn-border-width solid transparent;
@include button-size($btn-padding-y, $btn-padding-x, $font-size-base, $btn-border-radius);
@include transition($btn-transition);

// Share hover and focus styles
@include hover-focus {
text-decoration: none;
}
&:focus,
&.focus {
outline: 0;
box-shadow: $btn-focus-box-shadow;
}

// Disabled comes first so active can properly restyle
&.disabled,
&:disabled {
cursor: $cursor-disabled;
opacity: .65;
@include box-shadow(none);
}

&:active,
&.active {
background-image: none;
@include box-shadow($btn-focus-box-shadow, $btn-active-box-shadow);
}
}

// Future-proof disabling of clicks on `<a>` elements
a.btn.disabled,
fieldset[disabled] a.btn {
pointer-events: none;
}


//
// Alternate buttons
//

.btn-primary {
@include button-variant($btn-primary-color, $btn-primary-bg, $btn-primary-border);
}
.btn-secondary {
@include button-variant($btn-secondary-color, $btn-secondary-bg, $btn-secondary-border);
}
.btn-info {
@include button-variant($btn-info-color, $btn-info-bg, $btn-info-border);
}
.btn-success {
@include button-variant($btn-success-color, $btn-success-bg, $btn-success-border);
}
.btn-warning {
@include button-variant($btn-warning-color, $btn-warning-bg, $btn-warning-border);
}
.btn-danger {
@include button-variant($btn-danger-color, $btn-danger-bg, $btn-danger-border);
}

// Remove all backgrounds
.btn-outline-primary {
@include button-outline-variant($btn-primary-bg);
}
.btn-outline-secondary {
@include button-outline-variant($btn-secondary-border);
}
.btn-outline-info {
@include button-outline-variant($btn-info-bg);
}
.btn-outline-success {
@include button-outline-variant($btn-success-bg);
}
.btn-outline-warning {
@include button-outline-variant($btn-warning-bg);
}
.btn-outline-danger {
@include button-outline-variant($btn-danger-bg);
}


//
// Link buttons
//

// Make a button look and behave like a link
.btn-link {
font-weight: $font-weight-normal;
color: $link-color;
border-radius: 0;

&,
&:active,
&.active,
&:disabled {
background-color: transparent;
@include box-shadow(none);
}
&,
&:focus,
&:active {
border-color: transparent;
}
@include hover {
border-color: transparent;
}
@include hover-focus {
color: $link-hover-color;
text-decoration: $link-hover-decoration;
background-color: transparent;
}
&:disabled {
color: $btn-link-disabled-color;

@include hover-focus {
text-decoration: none;
}
}
}


//
// Button Sizes
//

.btn-lg {
// line-height: ensure even-numbered height of button next to large input
@include button-size($btn-padding-y-lg, $btn-padding-x-lg, $font-size-lg, $btn-border-radius-lg);
}
.btn-sm {
// line-height: ensure proper height of button next to small input
@include button-size($btn-padding-y-sm, $btn-padding-x-sm, $font-size-sm, $btn-border-radius-sm);
}


//
// Block button
//

.btn-block {
display: block;
width: 100%;
}

// Vertically space out multiple block buttons
.btn-block + .btn-block {
margin-top: $btn-block-spacing-y;
}

// Specificity overrides
input[type="submit"],
input[type="reset"],
input[type="button"] {
&.btn-block {
width: 100%;
}
}
@@ -0,0 +1,276 @@
//
// Base styles
//

.card {
position: relative;
display: flex;
flex-direction: column;
background-color: $card-bg;
border: $card-border-width solid $card-border-color;
@include border-radius($card-border-radius);
}

.card-block {
// Enable `flex-grow: 1` for decks and groups so that card blocks take up
// as much space as possible, ensuring footers are aligned to the bottom.
flex: 1 1 auto;
padding: $card-spacer-x;
}

.card-title {
margin-bottom: $card-spacer-y;
}

.card-subtitle {
margin-top: -($card-spacer-y / 2);
margin-bottom: 0;
}

.card-text:last-child {
margin-bottom: 0;
}

.card-link {
@include hover {
text-decoration: none;
}

+ .card-link {
margin-left: $card-spacer-x;
}
}

.card {
> .list-group:first-child {
.list-group-item:first-child {
@include border-top-radius($card-border-radius);
}
}

> .list-group:last-child {
.list-group-item:last-child {
@include border-bottom-radius($card-border-radius);
}
}
}


//
// Optional textual caps
//

.card-header {
padding: $card-spacer-y $card-spacer-x;
margin-bottom: 0; // Removes the default margin-bottom of <hN>
background-color: $card-cap-bg;
border-bottom: $card-border-width solid $card-border-color;

&:first-child {
@include border-radius($card-border-radius-inner $card-border-radius-inner 0 0);
}
}

.card-footer {
padding: $card-spacer-y $card-spacer-x;
background-color: $card-cap-bg;
border-top: $card-border-width solid $card-border-color;

&:last-child {
@include border-radius(0 0 $card-border-radius-inner $card-border-radius-inner);
}
}


//
// Header navs
//

.card-header-tabs {
margin-right: -($card-spacer-x / 2);
margin-bottom: -$card-spacer-y;
margin-left: -($card-spacer-x / 2);
border-bottom: 0;
}

.card-header-pills {
margin-right: -($card-spacer-x / 2);
margin-left: -($card-spacer-x / 2);
}


//
// Background variations
//

.card-primary {
@include card-variant($brand-primary, $brand-primary);
}
.card-success {
@include card-variant($brand-success, $brand-success);
}
.card-info {
@include card-variant($brand-info, $brand-info);
}
.card-warning {
@include card-variant($brand-warning, $brand-warning);
}
.card-danger {
@include card-variant($brand-danger, $brand-danger);
}

// Remove all backgrounds
.card-outline-primary {
@include card-outline-variant($btn-primary-bg);
}
.card-outline-secondary {
@include card-outline-variant($btn-secondary-border);
}
.card-outline-info {
@include card-outline-variant($btn-info-bg);
}
.card-outline-success {
@include card-outline-variant($btn-success-bg);
}
.card-outline-warning {
@include card-outline-variant($btn-warning-bg);
}
.card-outline-danger {
@include card-outline-variant($btn-danger-bg);
}

//
// Inverse text within a card for use with dark backgrounds
//

.card-inverse {
@include card-inverse;
}

//
// Blockquote
//

.card-blockquote {
padding: 0;
margin-bottom: 0;
border-left: 0;
}

// Card image
.card-img {
// margin: -1.325rem;
@include border-radius($card-border-radius-inner);
}
.card-img-overlay {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
padding: $card-img-overlay-padding;
}



// Card image caps
.card-img-top {
@include border-top-radius($card-border-radius-inner);
}
.card-img-bottom {
@include border-bottom-radius($card-border-radius-inner);
}


// Card deck

@include media-breakpoint-up(sm) {
.card-deck {
display: flex;
flex-flow: row wrap;

.card {
display: flex;
flex: 1 0 0;
flex-direction: column;

// Selectively apply horizontal margins to cards to avoid doing the
// negative margin dance like our grid. This differs from the grid
// due to the use of margins as gutters instead of padding.
&:not(:first-child) { margin-left: $card-deck-margin; }
&:not(:last-child) { margin-right: $card-deck-margin; }
}
}
}


//
// Card groups
//

@include media-breakpoint-up(sm) {
.card-group {
display: flex;
flex-flow: row wrap;

.card {
flex: 1 0 0;

+ .card {
margin-left: 0;
border-left: 0;
}

// Handle rounded corners
@if $enable-rounded {
&:first-child {
@include border-right-radius(0);

.card-img-top {
border-top-right-radius: 0;
}
.card-img-bottom {
border-bottom-right-radius: 0;
}
}
&:last-child {
@include border-left-radius(0);

.card-img-top {
border-top-left-radius: 0;
}
.card-img-bottom {
border-bottom-left-radius: 0;
}
}

&:not(:first-child):not(:last-child) {
border-radius: 0;

.card-img-top,
.card-img-bottom {
border-radius: 0;
}
}
}
}
}
}


//
// Columns
//

@include media-breakpoint-up(sm) {
.card-columns {
column-count: $card-columns-count;
column-gap: $card-columns-gap;

.card {
display: inline-block; // Don't let them vertically span multiple columns
width: 100%; // Don't let their width change
margin-bottom: $card-columns-margin;
}
}
}