├── .gitattributes ├── .gitignore ├── LICENSE.md ├── README.md ├── basic-template.html └── kube ├── dist ├── addons │ ├── autocomplete │ │ ├── kube.autocomplete.css │ │ ├── kube.autocomplete.js │ │ ├── kube.autocomplete.min.css │ │ └── kube.autocomplete.min.js │ ├── check │ │ ├── kube.check.js │ │ └── kube.check.min.js │ ├── combobox │ │ ├── kube.combobox.css │ │ ├── kube.combobox.js │ │ ├── kube.combobox.min.css │ │ └── kube.combobox.min.js │ ├── datepicker │ │ ├── i18n │ │ │ ├── kube.datepicker.de.js │ │ │ ├── kube.datepicker.en.js │ │ │ ├── kube.datepicker.es.js │ │ │ ├── kube.datepicker.fi.js │ │ │ ├── kube.datepicker.fr.js │ │ │ ├── kube.datepicker.it.js │ │ │ └── kube.datepicker.ru.js │ │ ├── kube.datepicker.css │ │ ├── kube.datepicker.js │ │ ├── kube.datepicker.min.css │ │ └── kube.datepicker.min.js │ ├── editable │ │ ├── kube.editable.css │ │ ├── kube.editable.js │ │ ├── kube.editable.min.css │ │ └── kube.editable.min.js │ ├── kube-addons.css │ ├── kube-addons.js │ ├── kube-addons.min.css │ ├── kube-addons.min.js │ ├── magicquery │ │ ├── kube.magicquery.js │ │ └── kube.magicquery.min.js │ ├── number │ │ ├── kube.number.css │ │ ├── kube.number.js │ │ ├── kube.number.min.css │ │ └── kube.number.min.js │ ├── selector │ │ ├── kube.selector.js │ │ └── kube.selector.min.js │ ├── slider │ │ ├── kube.slider.css │ │ ├── kube.slider.js │ │ ├── kube.slider.min.css │ │ └── kube.slider.min.js │ ├── upload │ │ ├── kube.upload.css │ │ ├── kube.upload.js │ │ ├── kube.upload.min.css │ │ └── kube.upload.min.js │ ├── validate │ │ ├── kube.validate.js │ │ └── kube.validate.min.js │ └── visibility │ │ ├── kube.visibility.js │ │ └── kube.visibility.min.js ├── css │ ├── kube.css │ └── kube.min.css ├── js │ ├── kube.js │ └── kube.min.js ├── scss │ ├── mixins.scss │ └── vars.scss └── themes │ ├── kube.theme.css │ └── kube.theme.min.css └── src ├── js ├── addons │ ├── autocomplete │ │ └── autocomplete.js │ ├── check │ │ └── check.js │ ├── combobox │ │ └── combobox.js │ ├── datepicker │ │ ├── datepicker.box.js │ │ ├── datepicker.grid.js │ │ └── datepicker.js │ ├── editable │ │ └── editable.js │ ├── magicquery │ │ └── magicquery.js │ ├── number │ │ └── number.js │ ├── selector │ │ └── selector.js │ ├── slider │ │ └── slider.js │ ├── upload │ │ └── upload.js │ ├── validate │ │ └── validate.js │ └── visibility │ │ └── visibility.js ├── app │ ├── App.Api.js │ ├── App.Broadcast.js │ ├── App.Builder.js │ ├── App.Callback.js │ ├── App.Context.js │ ├── App.Element.js │ ├── App.Module.js │ ├── App.Starter.js │ ├── App.Target.js │ ├── App.js │ └── Kube.js ├── dom │ ├── Ajax.js │ └── Dom.js ├── extends │ └── dom.js ├── modules │ ├── alert │ │ └── alert.js │ ├── dropdown │ │ └── dropdown.js │ ├── offcanvas │ │ └── offcanvas.js │ ├── sticky │ │ └── sticky.js │ ├── tabs │ │ └── tabs.js │ └── toggle │ │ └── toggle.js ├── services │ ├── animate │ │ └── animate.js │ ├── lang │ │ └── lang.js │ ├── message │ │ └── message.js │ ├── modal │ │ ├── modal.element.js │ │ ├── modal.form.js │ │ └── modal.js │ ├── observer │ │ └── observer.js │ ├── options │ │ └── options.js │ ├── progress │ │ └── progress.js │ ├── response │ │ └── response.js │ ├── transition │ │ └── transition.js │ └── utils │ │ └── utils.js └── wrappers │ ├── intro.js │ └── outro.js └── sass ├── _mixins.scss ├── _modules.scss ├── _vars.scss ├── addons ├── autocomplete.scss ├── combobox.scss ├── datepicker.scss ├── editable.scss ├── number.scss ├── slider.scss └── upload.scss ├── kube.scss ├── mixins ├── _breakpoint.scss ├── _button.scss ├── _flex.scss ├── _label.scss ├── _layout.scss └── _utils.scss ├── modules ├── _alert.scss ├── _animation.scss ├── _breadcrumb.scss ├── _button.scss ├── _dropdown.scss ├── _form.scss ├── _grid.scss ├── _helpers.scss ├── _icons.scss ├── _label.scss ├── _message.scss ├── _modal.scss ├── _navbar.scss ├── _offcanvas.scss ├── _pager.scss ├── _print.scss ├── _progress.scss ├── _reset.scss ├── _space.scss ├── _table.scss ├── _tabs.scss └── _typo.scss └── themes ├── kube.theme.scss └── kube.theme.vars.scss /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS generated files 2 | .DS_Store 3 | .DS_Store? 4 | ._* 5 | .Spotlight-V100 6 | .Trashes 7 | ehthumbs.db 8 | Thumbs.db 9 | # Dir 10 | /_stuff 11 | /assets 12 | /docs 13 | /kube/release 14 | /tests 15 | /tmp 16 | /all-tags.html 17 | /all-typo.html 18 | /gulpfile.js 19 | /index.php -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2009-2016 Imperavi LLC. https://imperavi.com/kube 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kube UI Framework 2 | 3 | ## What is Kube 4 | 5 | Kube ("kyu:b") is a web framework for developers and designers alike. 6 | Kube is built and designed to provide the most flexible yet powerful CSS & JS framework to the community. 7 | Unlike many other web frameworks, Kube is great for both super-fast bootstrapping and for a serious cutting edge, future-proof web development. 8 | 9 | [See the documentation](https://imperavi.com/kube/docs/) on the website. 10 | 11 | ## Supported Browsers 12 | 13 | Kube supports the latest, stable releases of all major browsers: 14 | 15 | - Latest Chrome 16 | - Latest Firefox 17 | - Latest Safari 18 | - Latest Opera 19 | - Microsoft Edge 20 | 21 | ## Quick Start 22 | - [Quick Start Guide](https://imperavi.com/kube/docs/get-started/quick-start/) — Setup in under a minute 23 | - [Developing with Kube](https://imperavi.com/kube/docs/get-started/quick-start/#s-sass-development-with-kube) — Getting started with custom development 24 | 25 | ## License 26 | You have our permission to use Kube in whatever projects you wish commercial, for sale, or otherwise, in whichever way you like. Official license information can be find in [LICENSE.md](LICENSE.md) (spoiler: it's the MIT License) 27 | -------------------------------------------------------------------------------- /basic-template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Basic Template 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |

Hello, world!

15 | 16 | 17 | 18 | 21 | 22 | -------------------------------------------------------------------------------- /kube/dist/addons/autocomplete/kube.autocomplete.css: -------------------------------------------------------------------------------- 1 | .autocomplete { 2 | position: absolute; 3 | background-color: #fff; 4 | box-shadow: 0 1px 3px rgba(17, 17, 19, 0.15); 5 | padding: 0; 6 | max-height: 200px; 7 | border-bottom-left-radius: 4px; 8 | border-bottom-right-radius: 4px; 9 | border: 0 solid transparent; 10 | overflow: auto; } 11 | .autocomplete a { 12 | font-size: 0.9375em; 13 | display: block; 14 | padding: 8px; 15 | text-decoration: none; 16 | color: #111113; 17 | border-bottom: 1px solid rgba(17, 17, 19, 0.05); } 18 | .autocomplete a:last-child { 19 | border-bottom-color: transparent; } 20 | .autocomplete a:hover, .autocomplete a.is-active { 21 | background-color: rgba(17, 17, 19, 0.04); 22 | color: #111113; 23 | text-decoration: underline; } 24 | 25 | .autocomplete-labels .label { 26 | margin-right: 4px; 27 | margin-bottom: 4px; } 28 | -------------------------------------------------------------------------------- /kube/dist/addons/autocomplete/kube.autocomplete.min.css: -------------------------------------------------------------------------------- 1 | .autocomplete{position:absolute;background-color:#fff;box-shadow:0 1px 3px rgba(17,17,19,.15);padding:0;max-height:200px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;border:0 solid transparent;overflow:auto}.autocomplete a{font-size:.9375em;display:block;padding:8px;text-decoration:none;color:#111113;border-bottom:1px solid rgba(17,17,19,.05)}.autocomplete a:last-child{border-bottom-color:transparent}.autocomplete a.is-active,.autocomplete a:hover{background-color:rgba(17,17,19,.04);color:#111113;text-decoration:underline}.autocomplete-labels .label{margin-right:4px;margin-bottom:4px} -------------------------------------------------------------------------------- /kube/dist/addons/autocomplete/kube.autocomplete.min.js: -------------------------------------------------------------------------------- 1 | !function(t){t.add("module","autocomplete",{init:function(t,e){this.app=t,this.$doc=t.$doc,this.$win=t.$win,this.$body=t.$body,this.animate=t.animate;var i={url:!1,min:2,labelClass:!1,target:!1,param:!1};this.context=e,this.params=e.getParams(i),this.$element=e.getElement(),this.$target=e.getTarget()},start:function(){this._build(),this.timeout=null,this.$element.on("keyup.kube.autocomplete",this._open.bind(this))},stop:function(){this.$box.remove(),this.$element.off(".kube.autocomplete"),this.$doc.off(".kube.autocomplete"),this.$win.off(".kube.autocomplete")},_build:function(){if(this.$box=t.dom("
"),this.$box.addClass("autocomplete"),this.$box.addClass("is-hidden"),this.$body.append(this.$box),this.$target&&!this._isInputTarget()){this.$target.addClass("autocomplete-labels");var e=this.$target.find(".close");e.on("click",this._removeLabel.bind(this))}},_open:function(t){t&&t.preventDefault(),clearTimeout(this.timeout);var e=this.$element.val();e.length>=this.params.min?(this._resize(),this.$win.on("resize.kube.autocomplete",this._resize.bind(this)),this.$doc.on("click.kube.autocomplete",this._close.bind(this)),this.$box.addClass("is-open"),this._listen(t)):this._close(t)},_close:function(t){t&&t.preventDefault(),this.$box.removeClass("is-open"),this.$box.addClass("is-hidden"),this.$doc.off(".kube.autocomplete"),this.$win.off(".kube.autocomplete")},_getPlacement:function(t,e){return this.$doc.height()-(t.top+e)");s.attr("href","#"),s.attr("rel",e[i].id),s.html(e[i].name),s.on("click",this._set.bind(this)),this.$box.append(s)}var a=this.$element.offset(),n=this.$element.height(),o=this.$element.width(),h=this._getPlacement(a,n),l="top"===h?a.top-this.$box.height()-n:a.top+n;this.$box.css({width:o+"px",top:l+"px",left:a.left+"px"}),this.$box.removeClass("is-hidden")},_listen:function(t){switch(t.which){case 40:t.preventDefault(),this._select("next");break;case 38:t.preventDefault(),this._select("prev");break;case 13:t.preventDefault(),this._set();break;case 27:this._close(t);break;default:this.timeout=setTimeout(this._lookup.bind(this),300)}},_select:function(t){var e=this.$box.find("a"),i=this.$box.find(".is-active");e.removeClass("is-active");var s=this._selectItem(i,e,t);s.addClass("is-active")},_selectItem:function(t,e,i){var s,a=0!==t.length,n="next"===i?0:e.length-1;return a&&(s=t[i]()),a&&s&&0!==s.length||(s=e.eq(n)),s},_set:function(e){var i=this.$box.find(".is-active");e&&(e.preventDefault(),i=t.dom(e.target));var s=i.attr("rel"),a=i.html();if(0!==this.$target.length){if(this._isInputTarget())this.$target.val(a);else{var n=this.$target.find('[data-id="'+s+'"]');0===n.length&&this._addLabel(s,a)}this.$element.val("")}else this.$element.val(a);this.$element.focus(),this.app.broadcast("autocomplete.set",this,a),this._close()},_addLabel:function(e,i){var s=t.dom("");s.addClass("label"),s.attr("data-id",e),s.text(i+" "),this.params.labelClass&&s.addClass(this.params.labelClass);var a=t.dom("");a.addClass("close"),a.on("click",this._removeLabel.bind(this));var n=t.dom("");n.attr("type","hidden"),n.attr("name",this._getTargetName()+"[]"),n.val(i),s.append(a),s.append(n),this.$target.append(s)},_isInputTarget:function(){return"INPUT"===this.$target.get().tagName},_removeLabel:function(e){e.preventDefault();var i=t.dom(e.target),s=i.closest(".label");this.animate.run(s,"fadeOut",function(){s.remove()}.bind(this))}})}(Kube); -------------------------------------------------------------------------------- /kube/dist/addons/check/kube.check.js: -------------------------------------------------------------------------------- 1 | (function($K) 2 | { 3 | $K.add('module', 'check', { 4 | init: function(app, context) 5 | { 6 | this.app = app; 7 | 8 | // defaults 9 | var defaults = { 10 | target: false, 11 | classname: 'ch' 12 | }; 13 | 14 | // context 15 | this.context = context; 16 | this.params = context.getParams(defaults); 17 | this.$element = context.getElement(); 18 | this.$target = context.getTarget(); 19 | 20 | }, 21 | // events 22 | onclick: function(e, element, type) 23 | { 24 | if (type === 'all') 25 | { 26 | this._toggleAll(); 27 | } 28 | }, 29 | 30 | // public 31 | start: function() 32 | { 33 | this.$checkall = this.$element.find('[data-type=all]'); 34 | 35 | this.$checkboxes = this.$element.find('.' + this.params.classname); 36 | this.$checkboxes.on('click.kube.check', this._toggle.bind(this)); 37 | 38 | this._buildChecked(); 39 | }, 40 | stop: function() 41 | { 42 | this.$checkboxes.off('.kube.check'); 43 | this.$target.val(''); 44 | }, 45 | 46 | // private 47 | _buildChecked: function() 48 | { 49 | if (!this.params.target) return; 50 | 51 | var arr = this.$target.val().split(','); 52 | this.$checkboxes.each(function(node) 53 | { 54 | if (arr.indexOf(node.value) !== -1) 55 | { 56 | node.checked = true; 57 | } 58 | }); 59 | 60 | this.$checkall.attr('checked', this._isCheckedAll()); 61 | }, 62 | _setTarget: function() 63 | { 64 | if (!this.params.target) return; 65 | 66 | var arr = []; 67 | this.$checkboxes.each(function(node) 68 | { 69 | if (node.checked) 70 | { 71 | arr.push(node.value); 72 | } 73 | }); 74 | 75 | var value = (arr.length === 0) ? '' : arr.join(','); 76 | 77 | this.$target.val(value); 78 | this.app.broadcast('check.set', this, this.$target); 79 | }, 80 | _isCheckedAll: function() 81 | { 82 | var count = 0; 83 | var len = this.$checkboxes.length; 84 | 85 | this.$checkboxes.each(function(node) 86 | { 87 | if (node.checked) 88 | { 89 | count++; 90 | } 91 | }); 92 | 93 | return (len === count); 94 | }, 95 | _toggleAll: function(element) 96 | { 97 | var isChecked = this.$checkall.attr('checked'); 98 | this.$checkboxes.attr('checked', isChecked); 99 | this._setTarget(); 100 | }, 101 | _toggle: function() 102 | { 103 | this.$checkall.attr('checked', this._isCheckedAll()); 104 | this._setTarget(); 105 | } 106 | }); 107 | })(Kube); -------------------------------------------------------------------------------- /kube/dist/addons/check/kube.check.min.js: -------------------------------------------------------------------------------- 1 | !function(t){t.add("module","check",{init:function(t,e){this.app=t;var c={target:!1,classname:"ch"};this.context=e,this.params=e.getParams(c),this.$element=e.getElement(),this.$target=e.getTarget()},onclick:function(t,e,c){"all"===c&&this._toggleAll()},start:function(){this.$checkall=this.$element.find("[data-type=all]"),this.$checkboxes=this.$element.find("."+this.params.classname),this.$checkboxes.on("click.kube.check",this._toggle.bind(this)),this._buildChecked()},stop:function(){this.$checkboxes.off(".kube.check"),this.$target.val("")},_buildChecked:function(){if(this.params.target){var t=this.$target.val().split(",");this.$checkboxes.each(function(e){-1!==t.indexOf(e.value)&&(e.checked=!0)}),this.$checkall.attr("checked",this._isCheckedAll())}},_setTarget:function(){if(this.params.target){var t=[];this.$checkboxes.each(function(e){e.checked&&t.push(e.value)});var e=0===t.length?"":t.join(",");this.$target.val(e),this.app.broadcast("check.set",this,this.$target)}},_isCheckedAll:function(){var t=0,e=this.$checkboxes.length;return this.$checkboxes.each(function(e){e.checked&&t++}),e===t},_toggleAll:function(t){var e=this.$checkall.attr("checked");this.$checkboxes.attr("checked",e),this._setTarget()},_toggle:function(){this.$checkall.attr("checked",this._isCheckedAll()),this._setTarget()}})}(Kube); -------------------------------------------------------------------------------- /kube/dist/addons/combobox/kube.combobox.css: -------------------------------------------------------------------------------- 1 | .combobox { 2 | position: relative; } 3 | .combobox input { 4 | padding-right: 36px; } 5 | .combobox select { 6 | position: absolute; 7 | top: 0; 8 | right: 0; 9 | width: 32px; 10 | height: 100%; 11 | z-index: 2; 12 | opacity: 0; 13 | cursor: pointer; } 14 | .combobox .combobox-caret { 15 | position: absolute; 16 | z-index: 1; 17 | top: 0; 18 | right: 0; 19 | width: 32px; 20 | height: 100%; 21 | background-image: url('data:image/svg+xml;utf8,'); 22 | background-repeat: no-repeat; 23 | background-position-y: 50%; 24 | background-position-x: 50%; 25 | cursor: pointer; } 26 | -------------------------------------------------------------------------------- /kube/dist/addons/combobox/kube.combobox.js: -------------------------------------------------------------------------------- 1 | (function($K) 2 | { 3 | $K.add('module', 'combobox', { 4 | init: function(app, context) 5 | { 6 | this.app = app; 7 | this.$win = app.$win; 8 | 9 | // defaults 10 | var defaults = { 11 | placeholder: '' 12 | }; 13 | 14 | // context 15 | this.context = context; 16 | this.params = context.getParams(defaults); 17 | this.$element = context.getElement(); 18 | }, 19 | start: function() 20 | { 21 | this._buildSource(); 22 | this._buildCaret(); 23 | this._buildEvent(); 24 | }, 25 | stop: function() 26 | { 27 | this.$sourceBox.after(this.$element); 28 | this.$sourceBox.remove(); 29 | 30 | this.$element.off('.kube.combobox'); 31 | this.$win.off('.kube.combobox'); 32 | }, 33 | 34 | // private 35 | _buildSource: function() 36 | { 37 | this.$sourceBox = $K.dom('
'); 38 | this.$sourceBox.addClass('combobox'); 39 | 40 | this.$source = $K.dom(''); 41 | this.$source.attr('type', 'text'); 42 | this.$source.attr('placeholder', this.params.placeholder); 43 | 44 | this.$sourceBox.width(this.$element.width()); 45 | this.$sourceBox.append(this.$source); 46 | 47 | this.$element.after(this.$sourceBox); 48 | this.$element.attr('class', ''); 49 | this.$element.attr('style', ''); 50 | this.$sourceBox.append(this.$element); 51 | 52 | this.$win.on('resize.kube.combobox', this._resize.bind(this)); 53 | }, 54 | _buildCaret: function() 55 | { 56 | this.$sourceCaret = $K.dom(''); 57 | this.$sourceCaret.addClass('combobox-caret'); 58 | 59 | this.$sourceBox.append(this.$sourceCaret); 60 | }, 61 | _buildEvent: function() 62 | { 63 | this.$element.on('change.kube.combobox', this._select.bind(this)); 64 | this.$source.on('keyup.kube.combobox', this._type.bind(this)); 65 | }, 66 | _resize: function() 67 | { 68 | this.$sourceBox.width(this.$element.width()); 69 | }, 70 | _type: function(e) 71 | { 72 | var value = this.$source.val(); 73 | 74 | this.app.broadcast('combobox.set', this, value); 75 | 76 | if (this.$sourceValue) this.$sourceValue.remove(); 77 | if (value.trim() === '') return; 78 | 79 | this.$sourceValue = $K.dom('