diff --git a/app/App.js b/app/App.js new file mode 100644 index 0000000000..bb71e66781 --- /dev/null +++ b/app/App.js @@ -0,0 +1,55 @@ +/** @jsx React.DOM */ +var React = require('react'); +var Store = require('./Store.js'); +var actions = require('./actions.js'); + +var App = React.createClass({ + getInitialState: function () { + return { + messages: Store.getMessages(), + newMessage: '' + }; + }, + componentWillMount: function () { + Store.addChangeListener(this.changeState); + }, + componentWillUnmount: function () { + Store.removeChangeListener(this.changeState); + }, + changeState: function () { + this.setState({ + messages: Store.getMessages() + }); + }, + addMessage: function (event) { + event.preventDefault(); + var input = this.refs.newMessage.getDOMNode(); + actions.addMessage(input.value); + this.setState({ + newMessage: '' + }); + }, + updateNewMessage: function (event) { + this.setState({ + newMessage: event.target.value + }); + }, + renderMessages: function (message) { + return ( +
{message}
+ ); + }, + render: function() { + return ( +
+ {this.state.messages.map(this.renderMessages)} +
+ +
+
+ ); + } + +}); + +module.exports = App; diff --git a/app/Store.js b/app/Store.js new file mode 100644 index 0000000000..7a7c0dbc62 --- /dev/null +++ b/app/Store.js @@ -0,0 +1,18 @@ +var flux = require('flux-react'); +var actions = require('./actions.js'); + +module.exports = flux.createStore({ + messages: [], + actions: [ + actions.addMessage + ], + addMessage: function (message) { + this.messages.push(message); + this.emitChange(); + }, + exports: { + getMessages: function () { + return this.messages; + } + } +}); \ No newline at end of file diff --git a/app/__tests__/sum-test.js b/app/__tests__/sum-test.js new file mode 100644 index 0000000000..ead8bcd786 --- /dev/null +++ b/app/__tests__/sum-test.js @@ -0,0 +1,8 @@ +jest.dontMock('../sum'); + +describe('sum', function() { + it('adds 1 + 2 to equal 3', function() { + var sum = require('../sum'); + expect(sum(1, 2)).toBe(3); + }); +}); diff --git a/app/actions.js b/app/actions.js new file mode 100644 index 0000000000..1b984841b3 --- /dev/null +++ b/app/actions.js @@ -0,0 +1,5 @@ +var flux = require('flux-react'); + +module.exports = flux.createActions([ + 'addMessage' +]); \ No newline at end of file diff --git a/app/index.html b/app/index.html new file mode 100644 index 0000000000..1914cbaadc --- /dev/null +++ b/app/index.html @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/app/main.js b/app/main.js new file mode 100644 index 0000000000..2d7e7a24ba --- /dev/null +++ b/app/main.js @@ -0,0 +1,4 @@ +/** @jsx React.DOM */ +var React = require('react'); +var App = require('./App.js'); +React.render(, document.body); diff --git a/meteor/client/stylesheets/bootstrap/alerts.import.less b/app/styles/bootstrap/alerts.less similarity index 100% rename from meteor/client/stylesheets/bootstrap/alerts.import.less rename to app/styles/bootstrap/alerts.less diff --git a/meteor/client/stylesheets/bootstrap/badges.import.less b/app/styles/bootstrap/badges.less similarity index 88% rename from meteor/client/stylesheets/bootstrap/badges.import.less rename to app/styles/bootstrap/badges.less index 20624f30db..b27c405a30 100755 --- a/meteor/client/stylesheets/bootstrap/badges.import.less +++ b/app/styles/bootstrap/badges.less @@ -44,11 +44,17 @@ } // Account for badges in navs - a.list-group-item.active > &, + .list-group-item.active > &, .nav-pills > .active > a > & { color: @badge-active-color; background-color: @badge-active-bg; } + .list-group-item > & { + float: right; + } + .list-group-item > & + & { + margin-right: 5px; + } .nav-pills > li > a > & { margin-left: 3px; } diff --git a/app/styles/bootstrap/bootstrap.less b/app/styles/bootstrap/bootstrap.less new file mode 100755 index 0000000000..61b77474f9 --- /dev/null +++ b/app/styles/bootstrap/bootstrap.less @@ -0,0 +1,50 @@ +// Core variables and mixins +@import "variables.less"; +@import "mixins.less"; + +// Reset and dependencies +@import "normalize.less"; +@import "print.less"; +@import "glyphicons.less"; + +// Core CSS +@import "scaffolding.less"; +@import "type.less"; +@import "code.less"; +@import "grid.less"; +@import "tables.less"; +@import "forms.less"; +@import "buttons.less"; + +// Components +@import "component-animations.less"; +@import "dropdowns.less"; +@import "button-groups.less"; +@import "input-groups.less"; +@import "navs.less"; +@import "navbar.less"; +@import "breadcrumbs.less"; +@import "pagination.less"; +@import "pager.less"; +@import "labels.less"; +@import "badges.less"; +@import "jumbotron.less"; +@import "thumbnails.less"; +@import "alerts.less"; +@import "progress-bars.less"; +@import "media.less"; +@import "list-group.less"; +@import "panels.less"; +@import "responsive-embed.less"; +@import "wells.less"; +@import "close.less"; + +// Components w/ JavaScript +@import "modals.less"; +@import "tooltip.less"; +@import "popovers.less"; +@import "carousel.less"; + +// Utility classes +@import "utilities.less"; +@import "responsive-utilities.less"; diff --git a/meteor/client/stylesheets/bootstrap/breadcrumbs.import.less b/app/styles/bootstrap/breadcrumbs.less similarity index 100% rename from meteor/client/stylesheets/bootstrap/breadcrumbs.import.less rename to app/styles/bootstrap/breadcrumbs.less diff --git a/meteor/client/stylesheets/bootstrap/button-groups.import.less b/app/styles/bootstrap/button-groups.less similarity index 88% rename from meteor/client/stylesheets/bootstrap/button-groups.import.less rename to app/styles/bootstrap/button-groups.less index 7021ecd171..f84febbd56 100755 --- a/meteor/client/stylesheets/bootstrap/button-groups.import.less +++ b/app/styles/bootstrap/button-groups.less @@ -18,10 +18,6 @@ &.active { z-index: 2; } - &:focus { - // Remove focus outline when dropdown JS adds it after closing the menu - outline: 0; - } } } @@ -198,7 +194,6 @@ } - // Justified button groups // ---------------------- @@ -226,15 +221,23 @@ // 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 `opacity`. We cannot -// use `display: none;` or `visibility: hidden;` as that also hides the popover. +// `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 for more. +// See https://github.com/twbs/bootstrap/pull/12794 and +// https://github.com/twbs/bootstrap/pull/14559 for more information. -[data-toggle="buttons"] > .btn > input[type="radio"], -[data-toggle="buttons"] > .btn > input[type="checkbox"] { - position: absolute; - z-index: -1; - .opacity(0); +[data-toggle="buttons"] { + > .btn, + > .btn-group > .btn { + input[type="radio"], + input[type="checkbox"] { + position: absolute; + clip: rect(0,0,0,0); + pointer-events: none; + } + } } diff --git a/meteor/client/stylesheets/bootstrap/buttons.import.less b/app/styles/bootstrap/buttons.less similarity index 96% rename from meteor/client/stylesheets/bootstrap/buttons.import.less rename to app/styles/bootstrap/buttons.less index 492bdc65ae..40553c6386 100755 --- a/meteor/client/stylesheets/bootstrap/buttons.import.less +++ b/app/styles/bootstrap/buttons.less @@ -12,6 +12,7 @@ font-weight: @btn-font-weight; text-align: center; vertical-align: middle; + touch-action: manipulation; cursor: pointer; background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 border: 1px solid transparent; @@ -22,13 +23,15 @@ &, &:active, &.active { - &:focus { + &:focus, + &.focus { .tab-focus(); } } &:hover, - &:focus { + &:focus, + &.focus { color: @btn-default-color; text-decoration: none; } @@ -43,7 +46,7 @@ &.disabled, &[disabled], fieldset[disabled] & { - cursor: not-allowed; + cursor: @cursor-disabled; pointer-events: none; // Future-proof disabling of clicks .opacity(.65); .box-shadow(none); @@ -85,11 +88,11 @@ .btn-link { color: @link-color; font-weight: normal; - cursor: pointer; border-radius: 0; &, &:active, + &.active, &[disabled], fieldset[disabled] & { background-color: transparent; diff --git a/meteor/client/stylesheets/bootstrap/carousel.import.less b/app/styles/bootstrap/carousel.less similarity index 89% rename from meteor/client/stylesheets/bootstrap/carousel.import.less rename to app/styles/bootstrap/carousel.less index 1644ddf7f5..5724d8a56e 100755 --- a/meteor/client/stylesheets/bootstrap/carousel.import.less +++ b/app/styles/bootstrap/carousel.less @@ -24,6 +24,30 @@ &:extend(.img-responsive); line-height: 1; } + + // WebKit CSS3 transforms for supported devices + @media all and (transform-3d), (-webkit-transform-3d) { + transition: transform .6s ease-in-out; + backface-visibility: hidden; + perspective: 1000; + + &.next, + &.active.right { + transform: translate3d(100%, 0, 0); + left: 0; + } + &.prev, + &.active.left { + transform: translate3d(-100%, 0, 0); + left: 0; + } + &.next.left, + &.prev.right, + &.active { + transform: translate3d(0, 0, 0); + left: 0; + } + } } > .active, diff --git a/meteor/client/stylesheets/bootstrap/close.import.less b/app/styles/bootstrap/close.less similarity index 100% rename from meteor/client/stylesheets/bootstrap/close.import.less rename to app/styles/bootstrap/close.less diff --git a/meteor/client/stylesheets/bootstrap/code.import.less b/app/styles/bootstrap/code.less similarity index 98% rename from meteor/client/stylesheets/bootstrap/code.import.less rename to app/styles/bootstrap/code.less index baa13df613..a08b4d48c4 100755 --- a/meteor/client/stylesheets/bootstrap/code.import.less +++ b/app/styles/bootstrap/code.less @@ -32,6 +32,7 @@ kbd { kbd { padding: 0; font-size: 100%; + font-weight: bold; box-shadow: none; } } diff --git a/meteor/client/stylesheets/bootstrap/component-animations.import.less b/app/styles/bootstrap/component-animations.less similarity index 73% rename from meteor/client/stylesheets/bootstrap/component-animations.import.less rename to app/styles/bootstrap/component-animations.less index 9400a0d32f..967715d98b 100755 --- a/meteor/client/stylesheets/bootstrap/component-animations.import.less +++ b/app/styles/bootstrap/component-animations.less @@ -17,8 +17,9 @@ .collapse { display: none; + visibility: hidden; - &.in { display: block; } + &.in { display: block; visibility: visible; } tr&.in { display: table-row; } tbody&.in { display: table-row-group; } } @@ -27,5 +28,7 @@ position: relative; height: 0; overflow: hidden; - .transition(height .35s ease); + .transition-property(~"height, visibility"); + .transition-duration(.35s); + .transition-timing-function(ease); } diff --git a/meteor/client/stylesheets/bootstrap/dropdowns.import.less b/app/styles/bootstrap/dropdowns.less similarity index 96% rename from meteor/client/stylesheets/bootstrap/dropdowns.import.less rename to app/styles/bootstrap/dropdowns.less index 0881908631..84a48c1413 100755 --- a/meteor/client/stylesheets/bootstrap/dropdowns.import.less +++ b/app/styles/bootstrap/dropdowns.less @@ -103,16 +103,15 @@ &:focus { color: @dropdown-link-disabled-color; } -} -// Nuke hover/focus effects -.dropdown-menu > .disabled > a { + + // Nuke hover/focus effects &:hover, &:focus { text-decoration: none; background-color: transparent; background-image: none; // Remove CSS gradient .reset-filter(); - cursor: not-allowed; + cursor: @cursor-disabled; } } @@ -198,7 +197,7 @@ // Component alignment // -// Reiterate per navbar.import.less and the modified component alignment there. +// Reiterate per navbar.less and the modified component alignment there. @media (min-width: @grid-float-breakpoint) { .navbar-right { @@ -212,4 +211,3 @@ } } } - diff --git a/meteor/client/stylesheets/bootstrap/forms.import.less b/app/styles/bootstrap/forms.less similarity index 88% rename from meteor/client/stylesheets/bootstrap/forms.import.less rename to app/styles/bootstrap/forms.less index 9b7631e770..1bcc2b6b97 100755 --- a/meteor/client/stylesheets/bootstrap/forms.import.less +++ b/app/styles/bootstrap/forms.less @@ -141,7 +141,7 @@ output { &[disabled], &[readonly], fieldset[disabled] & { - cursor: not-allowed; + cursor: @cursor-disabled; background-color: @input-bg-disabled; opacity: 1; // iOS fix for unreadable disabled content } @@ -168,23 +168,27 @@ input[type="search"] { // Special styles for iOS temporal inputs // // In Mobile Safari, setting `display: block` on temporal inputs causes the -// text within the input to become vertically misaligned. -// As a workaround, we set a pixel line-height that matches the -// given height of the input. Since this fucks up everything else, we have to -// appropriately reset it for Internet Explorer and the size variations. +// text within the input to become vertically misaligned. As a workaround, we +// set a pixel line-height that matches the given height of the input, but only +// for Safari. -input[type="date"], -input[type="time"], -input[type="datetime-local"], -input[type="month"] { - line-height: @input-height-base; - // IE8+ misaligns the text within date inputs, so we reset - line-height: @line-height-base ~"\0"; - - &.input-sm { +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type="date"], + input[type="time"], + input[type="datetime-local"], + input[type="month"] { + line-height: @input-height-base; + } + input[type="date"].input-sm, + input[type="time"].input-sm, + input[type="datetime-local"].input-sm, + input[type="month"].input-sm { line-height: @input-height-small; } - &.input-lg { + input[type="date"].input-lg, + input[type="time"].input-lg, + input[type="datetime-local"].input-lg, + input[type="month"].input-lg { line-height: @input-height-large; } } @@ -208,11 +212,11 @@ input[type="month"] { .checkbox { position: relative; display: block; - min-height: @line-height-computed; // clear the floating input if there is no label text margin-top: 10px; margin-bottom: 10px; label { + min-height: @line-height-computed; // Ensure the input doesn't jump when there is no text padding-left: 20px; margin-bottom: 0; font-weight: normal; @@ -258,7 +262,7 @@ input[type="checkbox"] { &[disabled], &.disabled, fieldset[disabled] & { - cursor: not-allowed; + cursor: @cursor-disabled; } } // These classes are used directly on