uniform-ui 2.3.6 → 3.0.0.beta2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/assets/javascripts/uniform.es5.js +1 -1
- data/lib/assets/javascripts/uniform.js +8 -21
- data/lib/assets/javascripts/uniform/checkbox.js +59 -16
- data/lib/assets/javascripts/uniform/component.js +20 -4
- data/lib/assets/javascripts/uniform/dropdown.js +78 -209
- data/lib/assets/javascripts/uniform/floating-label-input.js +63 -0
- data/lib/assets/javascripts/uniform/icons.js +12 -3
- data/lib/assets/javascripts/uniform/modal.js +13 -12
- data/lib/assets/javascripts/uniform/popover.js +45 -26
- data/lib/assets/javascripts/uniform/resizer.js +26 -30
- data/lib/assets/javascripts/uniform/select.js +188 -220
- data/lib/assets/javascripts/uniform/tooltip.js +11 -11
- data/lib/assets/stylesheets/uniform.scss +3 -7
- data/lib/assets/stylesheets/uniform/base.scss +20 -1
- data/lib/assets/stylesheets/uniform/components/buttons.scss +171 -184
- data/lib/assets/stylesheets/uniform/components/checkbox.scss +104 -0
- data/lib/assets/stylesheets/uniform/components/container.scss +3 -2
- data/lib/assets/stylesheets/uniform/components/dropdown.scss +8 -5
- data/lib/assets/stylesheets/uniform/components/floating-label-input.scss +29 -0
- data/lib/assets/stylesheets/uniform/components/input-group.scss +30 -0
- data/lib/assets/stylesheets/uniform/components/label.scss +21 -16
- data/lib/assets/stylesheets/uniform/components/loaders.scss +28 -51
- data/lib/assets/stylesheets/uniform/components/nav.scss +50 -87
- data/lib/assets/stylesheets/uniform/components/pointer.scss +83 -0
- data/lib/assets/stylesheets/uniform/components/select.scss +97 -107
- data/lib/assets/stylesheets/uniform/components/table.scss +31 -138
- data/lib/assets/stylesheets/uniform/components/thumb.scss +40 -25
- data/lib/assets/stylesheets/uniform/components/z-input.scss +20 -0
- data/lib/assets/stylesheets/uniform/defaults.scss +31 -7
- data/lib/assets/stylesheets/uniform/functions.scss +32 -7
- data/lib/assets/stylesheets/uniform/mixins.scss +110 -57
- data/lib/assets/stylesheets/uniform/utilities.scss +53 -0
- data/lib/assets/stylesheets/uniform/utilities/background.scss +9 -0
- data/lib/assets/stylesheets/uniform/utilities/borders.scss +85 -0
- data/lib/assets/stylesheets/uniform/utilities/effects.scss +172 -0
- data/lib/assets/stylesheets/uniform/utilities/layout.scss +174 -0
- data/lib/assets/stylesheets/uniform/utilities/position.scss +42 -0
- data/lib/assets/stylesheets/uniform/utilities/sizing.scss +54 -0
- data/lib/assets/stylesheets/uniform/utilities/spacing.scss +62 -0
- data/lib/assets/stylesheets/uniform/utilities/text.scss +158 -0
- data/lib/assets/stylesheets/uniform/variables.scss +104 -44
- data/lib/uniform/version.rb +1 -1
- metadata +24 -48
- data/lib/assets/javascripts/uniform.jquery.js +0 -152
- data/lib/assets/javascripts/uniform/dom-helpers.js +0 -158
- data/lib/assets/javascripts/uniform/floating-label.js +0 -54
- data/lib/assets/stylesheets/uniform-print.scss +0 -1
- data/lib/assets/stylesheets/uniform/components.scss +0 -11
- data/lib/assets/stylesheets/uniform/components/alert.scss +0 -72
- data/lib/assets/stylesheets/uniform/components/card.scss +0 -93
- data/lib/assets/stylesheets/uniform/components/form.scss +0 -149
- data/lib/assets/stylesheets/uniform/components/form/checkbox-collection.scss +0 -103
- data/lib/assets/stylesheets/uniform/components/form/checkbox.scss +0 -58
- data/lib/assets/stylesheets/uniform/components/form/floating-label.scss +0 -65
- data/lib/assets/stylesheets/uniform/components/form/input-group.scss +0 -56
- data/lib/assets/stylesheets/uniform/components/form/tristate.scss +0 -88
- data/lib/assets/stylesheets/uniform/components/grid.scss +0 -179
- data/lib/assets/stylesheets/uniform/components/row.scss +0 -67
- data/lib/assets/stylesheets/uniform/components/tooltip.scss +0 -41
- data/lib/assets/stylesheets/uniform/helpers.scss +0 -133
- data/lib/assets/stylesheets/uniform/helpers/border.scss +0 -28
- data/lib/assets/stylesheets/uniform/helpers/colors.scss +0 -24
- data/lib/assets/stylesheets/uniform/helpers/margin.scss +0 -27
- data/lib/assets/stylesheets/uniform/helpers/padding.scss +0 -9
- data/lib/assets/stylesheets/uniform/helpers/position.scss +0 -20
- data/lib/assets/stylesheets/uniform/helpers/sizes.scss +0 -38
- data/lib/assets/stylesheets/uniform/helpers/text.scss +0 -152
- data/lib/assets/stylesheets/uniform/print/grid.scss +0 -50
@@ -0,0 +1,63 @@
|
|
1
|
+
import Component from './component';
|
2
|
+
import { isVisible, isFocus, hasClass, addClass, removeClass, css, createElement } from 'dolla';
|
3
|
+
|
4
|
+
export default class FloatingLabel extends Component {
|
5
|
+
|
6
|
+
initialize(options){
|
7
|
+
if(options.input instanceof Element) {
|
8
|
+
this.input = options.input
|
9
|
+
} else {
|
10
|
+
this.input = createElement('input', Object.assign({}, {
|
11
|
+
type: this.constructor.type
|
12
|
+
}, options.input)) // TODO filter options to dolla.HTML_ATTRIBUTES
|
13
|
+
}
|
14
|
+
this.label = createElement('label', {
|
15
|
+
for: this.input.id,
|
16
|
+
children: [options.label]
|
17
|
+
});
|
18
|
+
this.input.setAttribute('aria-label', options.label);
|
19
|
+
|
20
|
+
addClass(this.el, 'uniformFloatingLabelInput');
|
21
|
+
|
22
|
+
this.listenTo(this.input, 'focus', this.focus);
|
23
|
+
this.listenTo(this.input, 'blur', this.blur);
|
24
|
+
this.listenTo(this.input, 'revealed', this.render);
|
25
|
+
}
|
26
|
+
|
27
|
+
render () {
|
28
|
+
if(!isVisible(this.input)) return;
|
29
|
+
|
30
|
+
let internalHeight = parseInt(css(this.input, 'height')) - parseInt(css(this.input, 'borderTopWidth')) - parseInt(css(this.input, 'borderBottomWidth'));
|
31
|
+
this.input.style.lineHeight = 1;
|
32
|
+
let lineHeight = parseInt(css(this.input, 'lineHeight'));
|
33
|
+
let fontSize = parseInt(css(this.input, 'fontSize'));
|
34
|
+
let padding = internalHeight - lineHeight;
|
35
|
+
|
36
|
+
this.label.style.setProperty('--font-size', css(this.input, 'fontSize'))
|
37
|
+
this.label.style.paddingLeft = css(this.input, 'paddingLeft');
|
38
|
+
this.label.style.lineHeight = lineHeight + "px";
|
39
|
+
this.label.style.paddingTop = (internalHeight/2 - lineHeight) + "px";
|
40
|
+
this.label.style.paddingBottom = (internalHeight/2 - lineHeight) + "px";
|
41
|
+
|
42
|
+
this.input.style.paddingTop = internalHeight/2 - (lineHeight - fontSize) + "px";
|
43
|
+
this.input.style.paddingBottom = (internalHeight/2 - lineHeight) + (lineHeight - fontSize) + "px";
|
44
|
+
|
45
|
+
this.input.parentNode.insertBefore(this.el, this.input.nextSibling);
|
46
|
+
this.el.append(this.input);
|
47
|
+
this.el.append(this.label);
|
48
|
+
|
49
|
+
if(this.input.value != ""){
|
50
|
+
this.focus()
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
focus (e) {
|
55
|
+
addClass(this.el, 'present');
|
56
|
+
}
|
57
|
+
|
58
|
+
blur (e) {
|
59
|
+
if(this.input.value == ""){
|
60
|
+
removeClass(this.el, 'present');
|
61
|
+
}
|
62
|
+
}
|
63
|
+
}
|
@@ -1,16 +1,25 @@
|
|
1
1
|
let check = `
|
2
|
-
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
2
|
+
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32">
|
3
3
|
<path d="M28.998 8.531l-2.134-2.134c-0.394-0.393-1.030-0.393-1.423 0l-12.795 12.795-6.086-6.13c-0.393-0.393-1.029-0.393-1.423 0l-2.134 2.134c-0.393 0.394-0.393 1.030 0 1.423l8.924 8.984c0.393 0.393 1.030 0.393 1.423 0l15.648-15.649c0.393-0.392 0.393-1.030 0-1.423z"></path>
|
4
4
|
</svg>
|
5
5
|
`.trim()
|
6
6
|
|
7
7
|
let arrow_down = `
|
8
|
-
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
8
|
+
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 20 20">
|
9
9
|
<path d="M13.418 7.601c0.271-0.268 0.709-0.268 0.979 0s0.271 0.701 0 0.969l-3.907 3.83c-0.271 0.268-0.709 0.268-0.979 0l-3.908-3.83c-0.27-0.268-0.27-0.701 0-0.969s0.708-0.268 0.979 0l3.418 3.14 3.418-3.14z"></path>
|
10
10
|
</svg>
|
11
11
|
`.trim()
|
12
12
|
|
13
|
+
let x = `
|
14
|
+
<svg version="1.2" baseProfile="tiny" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="64px" height="64px" viewBox="0 0 64 64" xml:space="preserve">
|
15
|
+
<g><rect x="-2.352" y="29.385" transform="matrix(0.7071 0.7071 -0.7071 0.7071 32.3545 -14.3899)" width="71.799" height="4.95"/></g>
|
16
|
+
<g><rect x="-2.374" y="29.376" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -12.7023 33.0352)" width="71.799" height="4.95"/></g>
|
17
|
+
</svg>
|
18
|
+
|
19
|
+
`.trim()
|
20
|
+
|
13
21
|
export {
|
14
22
|
check,
|
15
|
-
arrow_down
|
23
|
+
arrow_down,
|
24
|
+
x
|
16
25
|
}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import Component from './component';
|
2
|
-
import
|
2
|
+
import {addClass, hasClass, removeClass, css, trigger} from 'dolla';
|
3
3
|
|
4
4
|
/* UniformModal.initialize
|
5
5
|
Options
|
@@ -14,8 +14,9 @@ export default class Modal extends Component {
|
|
14
14
|
this.options = {};
|
15
15
|
this.options.klass = options.klass || false;
|
16
16
|
this.content = options.content;
|
17
|
+
this.el.removeAttribute('content');
|
17
18
|
|
18
|
-
|
19
|
+
addClass(this.el, 'uniformModal');
|
19
20
|
this.listenTo(document, 'keyup', this.keyup);
|
20
21
|
this.listenTo(this.el, 'click', this.checkCloseButton);
|
21
22
|
}
|
@@ -31,17 +32,17 @@ export default class Modal extends Component {
|
|
31
32
|
|
32
33
|
this.highest_z_index = 0;
|
33
34
|
this.overlay = document.createElement('div');
|
34
|
-
|
35
|
+
addClass(this.overlay, 'uniformModal-overlay');
|
35
36
|
|
36
37
|
this.blur = document.createElement('div');
|
37
|
-
|
38
|
+
addClass(this.blur, 'uniformModal-blur');
|
38
39
|
|
39
40
|
this.original_scroll = window.scrollY;
|
40
41
|
this.blur.style.top = 0 - this.original_scroll + "px";
|
41
42
|
|
42
43
|
if (document.body.querySelectorAll('.uniformModal').length > 0) {
|
43
44
|
this.highest_z_index = Math.max(Array.prototype.map.call(document.body.querySelectorAll('.uniformModal'), function(el){
|
44
|
-
return parseInt(
|
45
|
+
return parseInt(css(el, 'zIndex'));
|
45
46
|
}));
|
46
47
|
this.el.style.zIndex = this.highest_z_index + 2;
|
47
48
|
}
|
@@ -57,12 +58,12 @@ export default class Modal extends Component {
|
|
57
58
|
}
|
58
59
|
}
|
59
60
|
|
60
|
-
|
61
|
+
addClass(document.body, 'uniformModal-active');
|
61
62
|
document.body.appendChild(this.blur);
|
62
63
|
document.body.appendChild(this.el);
|
63
64
|
|
64
65
|
var container = document.createElement('div');
|
65
|
-
|
66
|
+
addClass(container, 'uniformModal-container');
|
66
67
|
if (content instanceof Node) {
|
67
68
|
container.appendChild(content);
|
68
69
|
} else {
|
@@ -70,27 +71,27 @@ export default class Modal extends Component {
|
|
70
71
|
}
|
71
72
|
|
72
73
|
var closeButton = document.createElement('div');
|
73
|
-
|
74
|
+
addClass(closeButton, 'uniformModal-close');
|
74
75
|
this.el.appendChild(closeButton);
|
75
76
|
|
76
77
|
this.el.style.top = window.scrollY;
|
77
78
|
this.listenTo(this.overlay, 'click', this.close);
|
78
79
|
this.el.appendChild(container);
|
79
80
|
|
80
|
-
if (this.options.klass)
|
81
|
-
if (content.innerHTML)
|
81
|
+
if (this.options.klass) addClass(container, this.options.klass);
|
82
|
+
if (content.innerHTML) trigger(content, 'rendered');
|
82
83
|
this.trigger('rendered');
|
83
84
|
|
84
85
|
return this;
|
85
86
|
}
|
86
87
|
|
87
88
|
checkCloseButton (e) {
|
88
|
-
if(
|
89
|
+
if(hasClass(e.target, 'uniformModal-close'))
|
89
90
|
this.close();
|
90
91
|
}
|
91
92
|
|
92
93
|
close () {
|
93
|
-
|
94
|
+
removeClass(document.querySelectorAll('uniformModal-active'), 'uniformModal-active');
|
94
95
|
var elements = this.blur.children;
|
95
96
|
var elementCount = elements.length
|
96
97
|
for(var i=0; i < elementCount; i++){
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import Component from './component';
|
2
|
-
import
|
2
|
+
import { closest, offset, outerWidth, outerHeight, removeClass, addClass } from 'dolla';
|
3
3
|
|
4
4
|
/*
|
5
5
|
Requirements
|
@@ -12,13 +12,14 @@ import * as Helpers from './dom-helpers';
|
|
12
12
|
align: [left|right|center|#px] [top|center|bottom|#px] | default: 'center bottom'
|
13
13
|
zIndex: # | default: unset
|
14
14
|
offset: {left: 0, top: 0}
|
15
|
+
container: element to append popover to. default: document
|
15
16
|
*/
|
16
17
|
export default class Popover extends Component {
|
17
18
|
initialize (options) {
|
18
19
|
this.showing = false;
|
19
20
|
options = options || {};
|
20
21
|
this.options = {
|
21
|
-
zIndex:
|
22
|
+
zIndex: 3,
|
22
23
|
container: document.body,
|
23
24
|
align: 'center bottom',
|
24
25
|
anchor: document.body,
|
@@ -26,7 +27,9 @@ export default class Popover extends Component {
|
|
26
27
|
offset: {left: 0, top: 0}
|
27
28
|
};
|
28
29
|
Object.assign(this.options, this.pick(options, Object.keys(this.options)));
|
30
|
+
this.el.removeAttribute('content');
|
29
31
|
|
32
|
+
this.options.anchor.popover = this
|
30
33
|
this.listenTo(document, 'click', this.checkFocus);
|
31
34
|
this.listenTo(document, 'focusin', this.checkFocus);
|
32
35
|
this.listenTo(document, 'keyup', this.checkEscape);
|
@@ -35,9 +38,10 @@ export default class Popover extends Component {
|
|
35
38
|
});
|
36
39
|
|
37
40
|
if(typeof this.options.container == "string"){
|
38
|
-
this.options.container =
|
39
|
-
this.options.container = this.options.container || document.body
|
41
|
+
this.options.container = closest(this.options.anchor, this.options.container)
|
40
42
|
}
|
43
|
+
this.options.container = this.options.container || document.body
|
44
|
+
|
41
45
|
}
|
42
46
|
|
43
47
|
render () {
|
@@ -59,7 +63,7 @@ export default class Popover extends Component {
|
|
59
63
|
|
60
64
|
resize () {
|
61
65
|
this.setPosition();
|
62
|
-
|
66
|
+
let bounds = this.el.getBoundingClientRect();
|
63
67
|
const body_bounds = document.body.getBoundingClientRect();
|
64
68
|
const window_bounds = {
|
65
69
|
top: 0,
|
@@ -69,10 +73,14 @@ export default class Popover extends Component {
|
|
69
73
|
};
|
70
74
|
|
71
75
|
var reposition = false;
|
72
|
-
if (bounds.bottom > body_bounds.bottom
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
+
if (bounds.bottom > Math.max(body_bounds.bottom, window_bounds.bottom)) {
|
77
|
+
var [leftAlign, topAlign] = this.options.align.split(" ");
|
78
|
+
this.setPosition(`${leftAlign} top`);
|
79
|
+
bounds = this.el.getBoundingClientRect()
|
80
|
+
if(bounds.top < 0) {
|
81
|
+
this.setPosition(`${leftAlign} bottom`);
|
82
|
+
}
|
83
|
+
bounds = this.el.getBoundingClientRect()
|
76
84
|
}
|
77
85
|
if (bounds.top < body_bounds.top) {
|
78
86
|
const difference = body_bounds.top - bounds.top
|
@@ -83,6 +91,7 @@ export default class Popover extends Component {
|
|
83
91
|
const difference = body_bounds.left - bounds.left
|
84
92
|
if(this.el.style.left != null) this.el.style.left = parseInt(this.el.style.left) + difference + "px"
|
85
93
|
if(this.el.style.right != null) this.el.style.right = parseInt(this.el.style.right) - difference + "px"
|
94
|
+
bounds = this.el.getBoundingClientRect()
|
86
95
|
}
|
87
96
|
if (bounds.right > body_bounds.right) {
|
88
97
|
const difference = body_bounds.right - bounds.right
|
@@ -96,43 +105,43 @@ export default class Popover extends Component {
|
|
96
105
|
var [leftAlign, topAlign] = align.split(" ");
|
97
106
|
leftAlign = leftAlign || "bottom";
|
98
107
|
|
99
|
-
var
|
108
|
+
var anchorOffset = offset(this.options.anchor);
|
100
109
|
var container = this.options.container;
|
101
110
|
if(getComputedStyle(container)['position'] == "static") container = container.offsetParent;
|
102
111
|
if(!container) container = document.body;
|
103
112
|
|
104
|
-
var containerOffset =
|
105
|
-
|
106
|
-
top:
|
107
|
-
left:
|
113
|
+
var containerOffset = offset(container);
|
114
|
+
anchorOffset = {
|
115
|
+
top: anchorOffset.top - containerOffset.top,
|
116
|
+
left: anchorOffset.left - containerOffset.left
|
108
117
|
}
|
109
118
|
|
110
119
|
var position = {};
|
111
120
|
if(leftAlign == 'left'){
|
112
|
-
position.right =
|
121
|
+
position.right = outerWidth(container) - anchorOffset.left;
|
113
122
|
} else if(leftAlign == 'center'){
|
114
|
-
position.left =
|
123
|
+
position.left = anchorOffset.left + outerWidth(this.options.anchor) / 2 - outerWidth(this.el) / 2;
|
115
124
|
} else if (leftAlign == 'right'){
|
116
|
-
position.left =
|
125
|
+
position.left = anchorOffset.left + outerWidth(this.options.anchor);
|
117
126
|
} else if (leftAlign.includes("px")){
|
118
|
-
position.left =
|
127
|
+
position.left = anchorOffset.left + parseInt(leftAlign);
|
119
128
|
}
|
120
129
|
|
121
130
|
if(topAlign == 'top'){
|
122
|
-
let height =
|
131
|
+
let height = outerHeight(container);
|
123
132
|
if(container == document.body && getComputedStyle(container)['position'] == "static"){
|
124
133
|
height = window.innerHeight;
|
125
134
|
} else if (container == document.body) {
|
126
135
|
height = Math.max(height, document.body.clientHeight);
|
127
136
|
}
|
128
|
-
position.bottom = height -
|
137
|
+
position.bottom = height - anchorOffset.top;
|
129
138
|
} else if(topAlign == 'center'){
|
130
|
-
position.top =
|
139
|
+
position.top = anchorOffset.top + outerHeight(this.options.anchor) / 2;
|
131
140
|
position.transform = "translateY(-50%)";
|
132
141
|
} else if (topAlign == 'bottom'){
|
133
|
-
position.top =
|
142
|
+
position.top = anchorOffset.top + outerHeight(this.options.anchor);
|
134
143
|
} else if (topAlign.includes("px")){
|
135
|
-
position.top =
|
144
|
+
position.top = anchorOffset.top + parseInt(topAlign);
|
136
145
|
}
|
137
146
|
|
138
147
|
if(this.options.offset.left) position.left += parseInt(this.options.offset.left);
|
@@ -145,9 +154,9 @@ export default class Popover extends Component {
|
|
145
154
|
this.el.style.top = null;
|
146
155
|
this.el.style.bottom = null;
|
147
156
|
this.el.style.transform = null;
|
148
|
-
|
149
|
-
|
150
|
-
|
157
|
+
removeClass(this.el, 'popover-left popover-right popover-center popover-top popover-bottom');
|
158
|
+
addClass(this.el, 'popover-' + topAlign);
|
159
|
+
addClass(this.el, 'popover-' + leftAlign);
|
151
160
|
Object.keys(position).forEach(function(key){
|
152
161
|
this.el.style[key] = position[key] + (key != "transform" ? "px" : "");
|
153
162
|
}, this);
|
@@ -160,11 +169,13 @@ export default class Popover extends Component {
|
|
160
169
|
if (e.target == this.options.anchor) return;
|
161
170
|
if (this.el.contains(e.target)) return;
|
162
171
|
if (this.options.anchor.contains(e.target)) return;
|
172
|
+
if (this.persisting) return;
|
163
173
|
this.hide();
|
164
174
|
}
|
165
175
|
|
166
176
|
checkEscape (e) {
|
167
177
|
if(e.which != 27) return;
|
178
|
+
if (this.persisting) return;
|
168
179
|
this.hide();
|
169
180
|
}
|
170
181
|
|
@@ -193,4 +204,12 @@ export default class Popover extends Component {
|
|
193
204
|
flag = flag || this.showing;
|
194
205
|
if(flag) this.hide(); else this.show();
|
195
206
|
}
|
207
|
+
|
208
|
+
persist() {
|
209
|
+
this.persisting = true;
|
210
|
+
}
|
211
|
+
|
212
|
+
unpersist() {
|
213
|
+
this.persisting = false;
|
214
|
+
}
|
196
215
|
}
|
@@ -1,43 +1,39 @@
|
|
1
1
|
import Component from './component';
|
2
|
-
import
|
2
|
+
import { trigger, toggleClass } from 'dolla';
|
3
3
|
|
4
4
|
export default class Resizer extends Component {
|
5
5
|
|
6
6
|
initialize () {
|
7
|
+
const breakpoints = getComputedStyle(window.document.body).getPropertyValue('--breakpoints')
|
8
|
+
this.breakpoints = {}
|
9
|
+
breakpoints.split(",").forEach(breakpoint => {
|
10
|
+
const [key, value] = breakpoint.split("/")
|
11
|
+
this.breakpoints[key.trim()] = value;
|
12
|
+
})
|
13
|
+
|
7
14
|
this.listenTo(window, 'resize', this.resize);
|
8
|
-
|
15
|
+
this.resize();
|
9
16
|
}
|
10
17
|
|
11
18
|
resize () {
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
if(width > 1080 && !Helpers.hasClass(this.el, 'lg-size')) {
|
23
|
-
Helpers.addClass(this.el, 'lg-size');
|
24
|
-
Helpers.trigger(window, 'resized-lg');
|
25
|
-
} else if (width < 1080 && Helpers.hasClass(this.el, 'lg-size')) {
|
26
|
-
Helpers.removeClass(this.el, 'lg-size');
|
19
|
+
const width = this.el.offsetWidth;
|
20
|
+
Object.keys(this.breakpoints).forEach(size => {
|
21
|
+
const query = this.breakpoints[size]
|
22
|
+
const css_class = size + '-container'
|
23
|
+
let [attribute, value] = query.split(":")
|
24
|
+
if(value.match("px")){
|
25
|
+
value = parseInt(value)
|
26
|
+
} else {
|
27
|
+
throw "unsupported media units"
|
27
28
|
}
|
28
|
-
|
29
|
-
if(
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
if(width < 720 && !Helpers.hasClass(this.el, 'sm-size')) {
|
37
|
-
Helpers.addClass(this.el, 'sm-size');
|
38
|
-
Helpers.trigger(window, 'resized-sm');
|
39
|
-
} else if (width > 720 && Helpers.hasClass(this.el, 'sm-size')) {
|
40
|
-
Helpers.removeClass(this.el, 'sm-size');
|
29
|
+
|
30
|
+
if(attribute == "min-width") {
|
31
|
+
toggleClass(this.el, css_class, width > value)
|
32
|
+
} else if (attribute == "max-width") {
|
33
|
+
toggleClass(this.el, css_class, width < value)
|
34
|
+
} else {
|
35
|
+
throw "unsupported media feature"
|
41
36
|
}
|
37
|
+
});
|
42
38
|
}
|
43
39
|
}
|
@@ -1,250 +1,218 @@
|
|
1
1
|
import Component from './component';
|
2
2
|
import Popover from './popover';
|
3
3
|
import Modal from './modal';
|
4
|
-
import { check as checkIcon, arrow_down as arrowIcon } from './icons';
|
5
|
-
import
|
4
|
+
import { check as checkIcon, arrow_down as arrowIcon, x as xIcon } from './icons';
|
5
|
+
import { createElement, HTML_ATTRIBUTES, filter, css, toggleClass, removeClass, isEmpty, trigger, hasClass, closest } from 'dolla';
|
6
6
|
|
7
7
|
/*
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
8
|
+
options: array of html options, each item can be string | array | object
|
9
|
+
ex. ["Employee", "Manager", "General Manager"]
|
10
|
+
ex. [
|
11
|
+
["Employee", "employee", false],
|
12
|
+
["Manager", "manager", false],
|
13
|
+
["General Manager", "general_manager", true],
|
14
|
+
]
|
15
|
+
ex. [
|
16
|
+
{value: "employee", text: 'Employee', selected: false},
|
17
|
+
{value: "manager", text: 'Manager', selected: false},
|
18
|
+
{value: "general_manager", text: 'General Manager', selected: true}
|
19
|
+
]
|
20
|
+
limit: int | false - number of options to limit to, or false to not limit
|
21
|
+
container: selector for where to render dropdown
|
22
|
+
multiple: false
|
14
23
|
*/
|
15
24
|
export default class Select extends Component {
|
16
25
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
var button = button_options.querySelector('.uniformSelect-show-all');
|
24
|
-
button.parentNode.removeChild(button);
|
25
|
-
|
26
|
-
return false;
|
27
|
-
},
|
28
|
-
limit: 8,
|
29
|
-
container: document.body
|
26
|
+
initialize (options = {}) {
|
27
|
+
this.htmlOptions = options.options.map(option => {
|
28
|
+
if(typeof option == "string") {
|
29
|
+
return {
|
30
|
+
value: option,
|
31
|
+
text: option
|
30
32
|
}
|
33
|
+
} else if (Array.isArray(option)){
|
34
|
+
return {
|
35
|
+
value: option[1],
|
36
|
+
text: option[0],
|
37
|
+
selected: option[2]
|
38
|
+
}
|
39
|
+
} else if (typeof option == "object") {
|
40
|
+
return option
|
41
|
+
} else {
|
42
|
+
throw "option of unexpected type"
|
43
|
+
}
|
44
|
+
});
|
45
|
+
this.options = {
|
46
|
+
multiple: false,
|
47
|
+
limit: 8,
|
48
|
+
container: false
|
49
|
+
}
|
50
|
+
Object.assign(this.options, this.pick(options, Object.keys(this.options)));
|
31
51
|
|
32
|
-
|
52
|
+
this.el_options = Object.assign({}, this.pick(options, HTML_ATTRIBUTES));
|
53
|
+
this.el = createElement('button', this.el_options);
|
54
|
+
this.el.classList.add('uniformSelect');
|
33
55
|
|
34
|
-
|
35
|
-
|
36
|
-
|
56
|
+
this.listenTo(this.el, 'click', this.toggleOptions);
|
57
|
+
this.listenTo(this.el, 'click', '.uniformSelect-remove', this.removeSelection);
|
58
|
+
this.listenTo(this.el, 'change', 'select', this.renderValue);
|
59
|
+
this.listenTo(this.el, 'close', 'select', this.removeOptions);
|
60
|
+
}
|
61
|
+
|
62
|
+
render () {
|
63
|
+
this.valueEl = createElement('span');
|
64
|
+
this.valueEl.classList.add('uniformSelect-value')
|
65
|
+
this.el.append(this.valueEl);
|
37
66
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
}
|
67
|
+
this.indicatorEl = createElement('span', {children: arrowIcon})
|
68
|
+
this.indicatorEl.classList.add('uniformSelect-indicator')
|
69
|
+
this.el.append(this.indicatorEl);
|
42
70
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
71
|
+
this.select = createElement('select', this.el_options);
|
72
|
+
this.htmlOptions.forEach(option => {
|
73
|
+
this.select.append(createElement('option', Object.assign({}, {children: option.text}, option)))
|
74
|
+
});
|
75
|
+
this.el.append(this.select);
|
47
76
|
|
48
|
-
this.activeIcon.parentNode.removeChild(this.activeIcon);
|
49
|
-
delete this.activeIcon;
|
50
77
|
|
51
|
-
|
52
|
-
|
78
|
+
// Append placeholder of longest option, to set width
|
79
|
+
const longestText = this.htmlOptions.map(x => x.text).sort((a, b) => a.length < b.length)[0]
|
80
|
+
const placeholder = createElement('span', {class: 'uniformSelect-placeholder', children: longestText})
|
81
|
+
this.el.append(placeholder);
|
53
82
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
}
|
58
|
-
}
|
83
|
+
this.renderValue();
|
84
|
+
return this;
|
85
|
+
}
|
59
86
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
if (this.el.name) {
|
69
|
-
Helpers.addClass(this.edit_button, this.el.name.toLowerCase().replace(/[^a-z0-9\-_]+/g, '-'));
|
70
|
-
}
|
71
|
-
this.el.style.display = "none";
|
72
|
-
this.el.insertAdjacentElement('beforebegin', this.edit_button);
|
73
|
-
|
74
|
-
// Set Min-Width for when empty
|
75
|
-
const option = this.el.querySelectorAll("option")[0];
|
76
|
-
this.edit_button.querySelector('.text-js').style.opacity = 0;
|
77
|
-
this.edit_button.querySelector('.text-js').innerHTML = option.textContent;
|
78
|
-
const min_width = this.edit_button.querySelector('.text-js').offsetWidth;
|
79
|
-
this.edit_button.style.minWidth = min_width + "px";
|
80
|
-
this.edit_button.querySelector('.text-js').innerHTML = "";
|
81
|
-
this.edit_button.querySelector('.text-js').style.opacity = null;
|
82
|
-
|
83
|
-
this.renderSelected();
|
87
|
+
renderValue () {
|
88
|
+
const selectedOptions = filter(this.select.querySelectorAll("option"), el => el.selected);
|
89
|
+
const html = selectedOptions.map(el => this.options.multiple ? `
|
90
|
+
<span class="uniformSelect-selection">
|
91
|
+
<span>${el.textContent}</span><span class="uniformSelect-remove">${xIcon}</span>
|
92
|
+
</span>
|
93
|
+
` : el.textContent).join(" ");
|
84
94
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
95
|
+
this.valueEl.innerHTML = html;
|
96
|
+
}
|
97
|
+
|
98
|
+
selectOption (e) {
|
99
|
+
const makeActive = !e.target.option.selected;
|
100
|
+
if (!this.options.multiple && makeActive) {
|
101
|
+
removeClass(e.target.offsetParent.querySelectorAll('.active'), 'active');
|
89
102
|
}
|
90
|
-
|
91
|
-
|
92
|
-
this.button_options = Helpers.createElement("<div class='uniformSelect-options'>");
|
93
|
-
if (this.el.name) {
|
94
|
-
Helpers.addClass(this.button_options, this.el.name.toLowerCase().replace(/[^a-z0-9\-_]+/g, '-'));
|
95
|
-
}
|
96
|
-
this.button_options.style.fontSize = Helpers.css(this.el, 'font-size');
|
103
|
+
toggleClass(e.target, 'active', makeActive);
|
104
|
+
e.target.option.selected = makeActive;
|
97
105
|
|
98
|
-
|
99
|
-
|
100
|
-
button.option = el;
|
101
|
-
button.textContent = el.textContent;
|
102
|
-
button.value = el.value;
|
103
|
-
if (button.textContent == "") button.innerHTML = "<span class='text-italic text-muted'>None</span>";
|
104
|
-
if(el.selected){
|
105
|
-
Helpers.addClass(button, 'active');
|
106
|
-
button.append(this.activeIcon.cloneNode(true));
|
107
|
-
} else if (this.options.limit && index > this.options.limit) {
|
108
|
-
Helpers.addClass(button, 'hide');
|
109
|
-
}
|
110
|
-
this.button_options.append(button);
|
111
|
-
}.bind(this));
|
112
|
-
|
113
|
-
this.listenTo(this.button_options, 'click', '.uniformSelect-option', this.selectOption);
|
114
|
-
|
115
|
-
const actions_el = Helpers.createElement('<div class="uniformSelect-options-actions"></div>');
|
116
|
-
if (this.options.limit && this.el.querySelectorAll('option').length > this.options.limit) {
|
117
|
-
const show_all_button = Helpers.createElement("<button type='button' class='uniformSelect-show-all outline blue' style='display: block; border: none'>Show All</button>");
|
118
|
-
this.listenTo(show_all_button, 'click', function(e){
|
119
|
-
Helpers.trigger(this.el, 'show_all');
|
120
|
-
if (this.options.showAll) this.options.showAll(this.button_options);
|
121
|
-
e.preventDefault();
|
122
|
-
e.stopPropagation();
|
123
|
-
})
|
124
|
-
actions_el.appendChild(show_all_button);
|
125
|
-
}
|
126
|
-
if (this.el.multiple) {
|
127
|
-
var done_button = Helpers.createElement("<button type='button' class='uniformSelect-done block outline blue'>Done</button>");
|
128
|
-
this.listenTo(done_button, 'click', this.hideOptions);
|
129
|
-
actions_el.appendChild(done_button);
|
130
|
-
}
|
131
|
-
if (!Helpers.is_empty(actions_el)) {
|
132
|
-
this.button_options.appendChild(actions_el);
|
133
|
-
}
|
106
|
+
if (!this.options.multiple) {
|
107
|
+
this.removeOptions();
|
134
108
|
}
|
135
|
-
|
136
|
-
renderSelected () {
|
137
|
-
const selected_options = Helpers.filter(this.el.querySelectorAll("option"), function(el){
|
138
|
-
return el.selected;
|
139
|
-
});
|
140
|
-
const html = Helpers.map(selected_options, function(el){
|
141
|
-
return this.el.multiple ? `<span class="uniformSelect-selection">${el.textContent}<span class="uniformSelect-remove"></span></span>` : el.textContent;
|
142
|
-
}.bind(this)).join(" ");
|
143
109
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
110
|
+
trigger(this.select, 'change');
|
111
|
+
}
|
112
|
+
|
113
|
+
removeSelection (e) {
|
114
|
+
e.preventDefault();
|
115
|
+
e.stopPropagation();
|
116
|
+
var option = filter(this.select.querySelectorAll("option"), function(el){
|
117
|
+
return el.innerText.trim() == closest(e.target, '.uniformSelect-selection').innerText.trim();
|
118
|
+
})[0];
|
119
|
+
if(!option) return;
|
120
|
+
option.selected = false;
|
121
|
+
option.button.classList.remove('active');
|
149
122
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
Helpers.removeClass(el, 'active');
|
157
|
-
Helpers.each(el.querySelectorAll('.uniformSelect-option-icon'), Helpers.remove);
|
158
|
-
}
|
159
|
-
}.bind(this))
|
160
|
-
}
|
123
|
+
trigger(this.select, 'change');
|
124
|
+
}
|
125
|
+
|
126
|
+
toggleOptions (e) {
|
127
|
+
if(e && (e.target.matches('.uniformSelect-remove') || closest(e.target, '.uniformSelect-remove'))){
|
128
|
+
return;
|
161
129
|
}
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
this.button_options_popover.remove();
|
168
|
-
delete this.button_options_popover;
|
169
|
-
}
|
170
|
-
Helpers.removeClass(this.edit_button, 'active');
|
130
|
+
toggleClass(this.el, 'active')
|
131
|
+
if(hasClass(this.el, 'active')){
|
132
|
+
this.renderOptions()
|
133
|
+
} else {
|
134
|
+
this.removeOptions()
|
171
135
|
}
|
136
|
+
}
|
172
137
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
} else {
|
201
|
-
this.button_options.style.minWidth = this.edit_button.offsetWidth + "px";
|
202
|
-
this.button_options_popover = new Popover({
|
203
|
-
offset: {top: 1},
|
204
|
-
anchor: this.edit_button,
|
205
|
-
align: '0px bottom',
|
206
|
-
content: this.button_options,
|
207
|
-
container: this.options.container
|
208
|
-
}).render()
|
209
|
-
this.button_options_popover.on('hidden', () => {
|
210
|
-
Helpers.removeClass(this.edit_button, 'active');
|
211
|
-
this.button_options_popover.remove();
|
212
|
-
delete this.button_options_popover;
|
213
|
-
})
|
214
|
-
}
|
215
|
-
}
|
138
|
+
renderOptions () {
|
139
|
+
const options = createElement("div", {
|
140
|
+
class: 'uniformSelect-options'
|
141
|
+
});
|
142
|
+
|
143
|
+
options.style.fontSize = css(this.el, 'font-size')
|
144
|
+
|
145
|
+
this.select.querySelectorAll('option').forEach(function(option, index){
|
146
|
+
var button = createElement("button", {
|
147
|
+
type: 'button',
|
148
|
+
class: 'uniformSelect-option'
|
149
|
+
});
|
150
|
+
button.option = option;
|
151
|
+
option.button = button;
|
152
|
+
button.textContent = option.textContent;
|
153
|
+
button.value = option.value;
|
154
|
+
if (button.textContent == "") button.innerHTML = "<span class='text-italic text-muted'>None</span>";
|
155
|
+
toggleClass(button, 'active', option.selected);
|
156
|
+
|
157
|
+
console.log(this.options.limit, index);
|
158
|
+
if (this.options.limit && (index + 1) > this.options.limit) {
|
159
|
+
button.classList.add('hide')
|
160
|
+
}
|
161
|
+
options.append(button);
|
162
|
+
}, this);
|
163
|
+
|
164
|
+
this.listenTo(options, 'click', '.uniformSelect-option', this.selectOption);
|
216
165
|
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
}), function (child) {
|
222
|
-
child.selected = false;
|
223
|
-
});
|
224
|
-
Helpers.each(this.button_options.querySelectorAll('.uniformSelect-option.active .uniformSelect-option-icon'), Helpers.remove);
|
225
|
-
Helpers.removeClass(this.button_options.querySelectorAll('.uniformSelect-option.active'), 'active');
|
226
|
-
}
|
227
|
-
Helpers.toggleClass(e.target, 'active');
|
228
|
-
e.target.option.selected = Helpers.hasClass(e.target, 'active');
|
229
|
-
Helpers.each(this.button_options.querySelectorAll("button"), function(button) {
|
230
|
-
if(!button.option) return;
|
231
|
-
Helpers.toggleClass(button, 'active', button.option.selected);
|
232
|
-
if (Helpers.hasClass(button, 'active')) {
|
233
|
-
button.append(this.activeIcon.cloneNode(true));
|
234
|
-
} else {
|
235
|
-
Helpers.each(button.querySelectorAll('.uniformSelect-option-icon'), Helpers.remove);
|
236
|
-
}
|
237
|
-
}.bind(this))
|
238
|
-
Helpers.trigger(this.el, 'change');
|
239
|
-
}
|
166
|
+
|
167
|
+
const actions = createElement('div', {
|
168
|
+
class: 'uniformSelect-actions'
|
169
|
+
});
|
240
170
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
171
|
+
if (this.options.limit && this.htmlOptions.length > this.options.limit) {
|
172
|
+
const button = createElement('button', {
|
173
|
+
type: 'button',
|
174
|
+
class: 'uniformSelect-show-all',
|
175
|
+
children: 'Show All'
|
176
|
+
});
|
177
|
+
this.listenTo(button, 'click', this.showAllOptions.bind(this))
|
178
|
+
actions.append(button);
|
179
|
+
}
|
180
|
+
if (this.options.multiple) {
|
181
|
+
const button = createElement('button', {
|
182
|
+
type: 'button',
|
183
|
+
class: 'uniformSelect-done',
|
184
|
+
children: ['Done']
|
185
|
+
});
|
186
|
+
this.listenTo(button, 'click', this.removeOptions.bind(this));
|
187
|
+
actions.append(button);
|
188
|
+
}
|
189
|
+
if (!isEmpty(actions)) {
|
190
|
+
options.append(actions);
|
249
191
|
}
|
192
|
+
|
193
|
+
this.popover = new Popover({
|
194
|
+
offset: {top: 1},
|
195
|
+
align: '0px bottom',
|
196
|
+
anchor: this.el,
|
197
|
+
content: options,
|
198
|
+
container: this.options.container
|
199
|
+
}).render()
|
200
|
+
|
201
|
+
this.listenTo(this.popover, 'hidden', this.removeOptions);
|
202
|
+
}
|
203
|
+
|
204
|
+
removeOptions () {
|
205
|
+
this.el.classList.remove('active')
|
206
|
+
if(!this.popover) return;
|
207
|
+
this.popover.remove()
|
208
|
+
}
|
209
|
+
|
210
|
+
showAllOptions (e) {
|
211
|
+
e.preventDefault();
|
212
|
+
e.stopPropagation();
|
213
|
+
if(!this.popover) return;
|
214
|
+
removeClass(this.popover.el.querySelectorAll('button.hide'), 'hide');
|
215
|
+
var button = this.popover.el.querySelector('.uniformSelect-show-all');
|
216
|
+
button.parentNode.removeChild(button);
|
217
|
+
}
|
250
218
|
}
|