uniform-ui 2.3.8 → 3.0.0.beta5
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.js +19 -19
- 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 +15 -18
- data/lib/assets/javascripts/uniform/popover.js +42 -25
- data/lib/assets/javascripts/uniform/resizer.js +26 -30
- data/lib/assets/javascripts/uniform/select.js +188 -222
- 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 -54
- 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 -10
- 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 +55 -0
- data/lib/assets/stylesheets/uniform/utilities/background.scss +9 -0
- data/lib/assets/stylesheets/uniform/utilities/borders.scss +84 -0
- data/lib/assets/stylesheets/uniform/utilities/effects.scss +172 -0
- data/lib/assets/stylesheets/uniform/utilities/layout.scss +177 -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/svg.scss +5 -0
- data/lib/assets/stylesheets/uniform/utilities/text.scss +158 -0
- data/lib/assets/stylesheets/uniform/variables.scss +111 -42
- data/lib/uniform/version.rb +1 -1
- metadata +25 -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, 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
|
+
this.el.classList.add('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
|
+
this.el.classList.add('present');
|
56
|
+
}
|
57
|
+
|
58
|
+
blur (e) {
|
59
|
+
if(this.input.value == ""){
|
60
|
+
this.el.classList.remove('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 {css, trigger, append} 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
|
+
this.el.classList.add('uniformModal');
|
19
20
|
this.listenTo(document, 'keyup', this.keyup);
|
20
21
|
this.listenTo(this.el, 'click', this.checkCloseButton);
|
21
22
|
}
|
@@ -27,21 +28,20 @@ export default class Modal extends Component {
|
|
27
28
|
|
28
29
|
render () {
|
29
30
|
var that = this;
|
30
|
-
var content = typeof this.content == 'function' ? this.content() : this.content;
|
31
31
|
|
32
32
|
this.highest_z_index = 0;
|
33
33
|
this.overlay = document.createElement('div');
|
34
|
-
|
34
|
+
this.overlay.classList.add('uniformModal-overlay');
|
35
35
|
|
36
36
|
this.blur = document.createElement('div');
|
37
|
-
|
37
|
+
this.blur.classList.add('uniformModal-blur');
|
38
38
|
|
39
39
|
this.original_scroll = window.scrollY;
|
40
40
|
this.blur.style.top = 0 - this.original_scroll + "px";
|
41
41
|
|
42
42
|
if (document.body.querySelectorAll('.uniformModal').length > 0) {
|
43
43
|
this.highest_z_index = Math.max(Array.prototype.map.call(document.body.querySelectorAll('.uniformModal'), function(el){
|
44
|
-
return parseInt(
|
44
|
+
return parseInt(css(el, 'zIndex'));
|
45
45
|
}));
|
46
46
|
this.el.style.zIndex = this.highest_z_index + 2;
|
47
47
|
}
|
@@ -57,40 +57,37 @@ export default class Modal extends Component {
|
|
57
57
|
}
|
58
58
|
}
|
59
59
|
|
60
|
-
|
60
|
+
document.body.classList.add('uniformModal-active');
|
61
61
|
document.body.appendChild(this.blur);
|
62
62
|
document.body.appendChild(this.el);
|
63
63
|
|
64
64
|
var container = document.createElement('div');
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
} else {
|
69
|
-
container.innerHTML = content;
|
70
|
-
}
|
65
|
+
container.classList.add('uniformModal-container');
|
66
|
+
|
67
|
+
append(container, this.content);
|
71
68
|
|
72
69
|
var closeButton = document.createElement('div');
|
73
|
-
|
70
|
+
closeButton.classList.add('uniformModal-close');
|
74
71
|
this.el.appendChild(closeButton);
|
75
72
|
|
76
73
|
this.el.style.top = window.scrollY;
|
77
74
|
this.listenTo(this.overlay, 'click', this.close);
|
78
75
|
this.el.appendChild(container);
|
79
76
|
|
80
|
-
if (this.options.klass)
|
81
|
-
if (content.innerHTML)
|
77
|
+
if (this.options.klass) container.classList.add(this.options.klass);
|
78
|
+
if (this.content.innerHTML) trigger(this.content, 'rendered');
|
82
79
|
this.trigger('rendered');
|
83
80
|
|
84
81
|
return this;
|
85
82
|
}
|
86
83
|
|
87
84
|
checkCloseButton (e) {
|
88
|
-
if(
|
85
|
+
if(e.target.classList.contains('uniformModal-close'))
|
89
86
|
this.close();
|
90
87
|
}
|
91
88
|
|
92
89
|
close () {
|
93
|
-
|
90
|
+
document.querySelectorAll('uniformModal-active').forEach(el => el.classList.remove('uniformModal-active'));
|
94
91
|
var elements = this.blur.children;
|
95
92
|
var elementCount = elements.length
|
96
93
|
for(var i=0; i < elementCount; i++){
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import Component from './component';
|
2
|
-
import
|
2
|
+
import { offset, outerWidth, outerHeight, append } from 'dolla';
|
3
3
|
|
4
4
|
/*
|
5
5
|
Requirements
|
@@ -12,6 +12,7 @@ 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) {
|
@@ -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 = this.options.anchor.closest(this.options.container)
|
40
42
|
}
|
43
|
+
this.options.container = this.options.container || document.body
|
44
|
+
|
41
45
|
}
|
42
46
|
|
43
47
|
render () {
|
@@ -45,10 +49,7 @@ export default class Popover extends Component {
|
|
45
49
|
this.el.style.position = 'absolute';
|
46
50
|
this.el.style.zIndex = this.options.zIndex;
|
47
51
|
|
48
|
-
|
49
|
-
this.el.appendChild(this.options.content);
|
50
|
-
else
|
51
|
-
this.el.innerHTML = this.options.content;
|
52
|
+
append(this.el, this.options.content)
|
52
53
|
|
53
54
|
this.options.container.appendChild(this.el);
|
54
55
|
this.resize();
|
@@ -59,7 +60,7 @@ export default class Popover extends Component {
|
|
59
60
|
|
60
61
|
resize () {
|
61
62
|
this.setPosition();
|
62
|
-
|
63
|
+
let bounds = this.el.getBoundingClientRect();
|
63
64
|
const body_bounds = document.body.getBoundingClientRect();
|
64
65
|
const window_bounds = {
|
65
66
|
top: 0,
|
@@ -72,6 +73,11 @@ export default class Popover extends Component {
|
|
72
73
|
if (bounds.bottom > Math.max(body_bounds.bottom, window_bounds.bottom)) {
|
73
74
|
var [leftAlign, topAlign] = this.options.align.split(" ");
|
74
75
|
this.setPosition(`${leftAlign} top`);
|
76
|
+
bounds = this.el.getBoundingClientRect()
|
77
|
+
if(bounds.top < 0) {
|
78
|
+
this.setPosition(`${leftAlign} bottom`);
|
79
|
+
}
|
80
|
+
bounds = this.el.getBoundingClientRect()
|
75
81
|
}
|
76
82
|
if (bounds.top < body_bounds.top) {
|
77
83
|
const difference = body_bounds.top - bounds.top
|
@@ -82,6 +88,7 @@ export default class Popover extends Component {
|
|
82
88
|
const difference = body_bounds.left - bounds.left
|
83
89
|
if(this.el.style.left != null) this.el.style.left = parseInt(this.el.style.left) + difference + "px"
|
84
90
|
if(this.el.style.right != null) this.el.style.right = parseInt(this.el.style.right) - difference + "px"
|
91
|
+
bounds = this.el.getBoundingClientRect()
|
85
92
|
}
|
86
93
|
if (bounds.right > body_bounds.right) {
|
87
94
|
const difference = body_bounds.right - bounds.right
|
@@ -95,43 +102,43 @@ export default class Popover extends Component {
|
|
95
102
|
var [leftAlign, topAlign] = align.split(" ");
|
96
103
|
leftAlign = leftAlign || "bottom";
|
97
104
|
|
98
|
-
var
|
105
|
+
var anchorOffset = offset(this.options.anchor);
|
99
106
|
var container = this.options.container;
|
100
107
|
if(getComputedStyle(container)['position'] == "static") container = container.offsetParent;
|
101
108
|
if(!container) container = document.body;
|
102
109
|
|
103
|
-
var containerOffset =
|
104
|
-
|
105
|
-
top:
|
106
|
-
left:
|
110
|
+
var containerOffset = offset(container);
|
111
|
+
anchorOffset = {
|
112
|
+
top: anchorOffset.top - containerOffset.top,
|
113
|
+
left: anchorOffset.left - containerOffset.left
|
107
114
|
}
|
108
115
|
|
109
116
|
var position = {};
|
110
117
|
if(leftAlign == 'left'){
|
111
|
-
position.right =
|
118
|
+
position.right = outerWidth(container) - anchorOffset.left;
|
112
119
|
} else if(leftAlign == 'center'){
|
113
|
-
position.left =
|
120
|
+
position.left = anchorOffset.left + outerWidth(this.options.anchor) / 2 - outerWidth(this.el) / 2;
|
114
121
|
} else if (leftAlign == 'right'){
|
115
|
-
position.left =
|
122
|
+
position.left = anchorOffset.left + outerWidth(this.options.anchor);
|
116
123
|
} else if (leftAlign.includes("px")){
|
117
|
-
position.left =
|
124
|
+
position.left = anchorOffset.left + parseInt(leftAlign);
|
118
125
|
}
|
119
126
|
|
120
127
|
if(topAlign == 'top'){
|
121
|
-
let height =
|
128
|
+
let height = outerHeight(container);
|
122
129
|
if(container == document.body && getComputedStyle(container)['position'] == "static"){
|
123
130
|
height = window.innerHeight;
|
124
131
|
} else if (container == document.body) {
|
125
132
|
height = Math.max(height, document.body.clientHeight);
|
126
133
|
}
|
127
|
-
position.bottom = height -
|
134
|
+
position.bottom = height - anchorOffset.top;
|
128
135
|
} else if(topAlign == 'center'){
|
129
|
-
position.top =
|
136
|
+
position.top = anchorOffset.top + outerHeight(this.options.anchor) / 2;
|
130
137
|
position.transform = "translateY(-50%)";
|
131
138
|
} else if (topAlign == 'bottom'){
|
132
|
-
position.top =
|
139
|
+
position.top = anchorOffset.top + outerHeight(this.options.anchor);
|
133
140
|
} else if (topAlign.includes("px")){
|
134
|
-
position.top =
|
141
|
+
position.top = anchorOffset.top + parseInt(topAlign);
|
135
142
|
}
|
136
143
|
|
137
144
|
if(this.options.offset.left) position.left += parseInt(this.options.offset.left);
|
@@ -144,9 +151,9 @@ export default class Popover extends Component {
|
|
144
151
|
this.el.style.top = null;
|
145
152
|
this.el.style.bottom = null;
|
146
153
|
this.el.style.transform = null;
|
147
|
-
|
148
|
-
|
149
|
-
|
154
|
+
this.el.classList.remove('popover-left', 'popover-right', 'popover-center', 'popover-top', 'popover-bottom');
|
155
|
+
this.el.classList.add('popover-' + topAlign);
|
156
|
+
this.el.classList.add('popover-' + leftAlign);
|
150
157
|
Object.keys(position).forEach(function(key){
|
151
158
|
this.el.style[key] = position[key] + (key != "transform" ? "px" : "");
|
152
159
|
}, this);
|
@@ -159,11 +166,13 @@ export default class Popover extends Component {
|
|
159
166
|
if (e.target == this.options.anchor) return;
|
160
167
|
if (this.el.contains(e.target)) return;
|
161
168
|
if (this.options.anchor.contains(e.target)) return;
|
169
|
+
if (this.persisting) return;
|
162
170
|
this.hide();
|
163
171
|
}
|
164
172
|
|
165
173
|
checkEscape (e) {
|
166
174
|
if(e.which != 27) return;
|
175
|
+
if (this.persisting) return;
|
167
176
|
this.hide();
|
168
177
|
}
|
169
178
|
|
@@ -192,4 +201,12 @@ export default class Popover extends Component {
|
|
192
201
|
flag = flag || this.showing;
|
193
202
|
if(flag) this.hide(); else this.show();
|
194
203
|
}
|
204
|
+
|
205
|
+
persist() {
|
206
|
+
this.persisting = true;
|
207
|
+
}
|
208
|
+
|
209
|
+
unpersist() {
|
210
|
+
this.persisting = false;
|
211
|
+
}
|
195
212
|
}
|
@@ -1,43 +1,39 @@
|
|
1
1
|
import Component from './component';
|
2
|
-
import
|
2
|
+
import { trigger } 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
|
+
this.el.classList.toggle(css_class, width > value)
|
32
|
+
} else if (attribute == "max-width") {
|
33
|
+
this.el.classList.toggle(css_class, width < value)
|
34
|
+
} else {
|
35
|
+
throw "unsupported media feature"
|
41
36
|
}
|
37
|
+
});
|
42
38
|
}
|
43
39
|
}
|
@@ -1,252 +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, isEmpty, trigger } 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: false
|
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
|
-
if(!this.options.container) {
|
75
|
-
this.options.container = this.edit_button.parentElement
|
76
|
-
}
|
77
|
-
|
78
|
-
// Set Min-Width for when empty
|
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(" ");
|
79
94
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
this.edit_button.querySelector('.text-js').innerHTML = "";
|
88
|
-
this.edit_button.querySelector('.text-js').style.opacity = null;
|
89
|
-
|
90
|
-
this.renderSelected();
|
91
|
-
|
92
|
-
this.listenTo(this.edit_button, 'click', this.showOptions);
|
93
|
-
this.listenTo(this.edit_button, 'click', '.uniformSelect-remove', this.removeSelection);
|
94
|
-
|
95
|
-
return this;
|
95
|
+
this.valueEl.innerHTML = html;
|
96
|
+
}
|
97
|
+
|
98
|
+
selectOption (e) {
|
99
|
+
const makeActive = !e.target.option.selected;
|
100
|
+
if (!this.options.multiple && makeActive) {
|
101
|
+
e.target.offsetParent.querySelectorAll('.active').forEach(el => el.classList.remove('active'));
|
96
102
|
}
|
97
|
-
|
98
|
-
|
99
|
-
this.button_options = Helpers.createElement("<div class='uniformSelect-options'>");
|
100
|
-
if (this.el.name) {
|
101
|
-
Helpers.addClass(this.button_options, this.el.name.toLowerCase().replace(/[^a-z0-9\-_]+/g, '-'));
|
102
|
-
}
|
103
|
-
this.button_options.style.fontSize = Helpers.css(this.el, 'font-size');
|
103
|
+
e.target.classList.toggle('active', makeActive);
|
104
|
+
e.target.option.selected = makeActive;
|
104
105
|
|
105
|
-
|
106
|
-
|
107
|
-
button.option = el;
|
108
|
-
button.textContent = el.textContent;
|
109
|
-
button.value = el.value;
|
110
|
-
if (button.textContent == "") button.innerHTML = "<span class='text-italic text-muted'>None</span>";
|
111
|
-
if(el.selected){
|
112
|
-
Helpers.addClass(button, 'active');
|
113
|
-
button.append(this.activeIcon.cloneNode(true));
|
114
|
-
} else if (this.options.limit && index > this.options.limit) {
|
115
|
-
Helpers.addClass(button, 'hide');
|
116
|
-
}
|
117
|
-
this.button_options.append(button);
|
118
|
-
}.bind(this));
|
119
|
-
|
120
|
-
this.listenTo(this.button_options, 'click', '.uniformSelect-option', this.selectOption);
|
121
|
-
|
122
|
-
const actions_el = Helpers.createElement('<div class="uniformSelect-options-actions"></div>');
|
123
|
-
if (this.options.limit && this.el.querySelectorAll('option').length > this.options.limit) {
|
124
|
-
const show_all_button = Helpers.createElement("<button type='button' class='uniformSelect-show-all outline blue' style='display: block; border: none'>Show All</button>");
|
125
|
-
this.listenTo(show_all_button, 'click', function(e){
|
126
|
-
Helpers.trigger(this.el, 'show_all');
|
127
|
-
if (this.options.showAll) this.options.showAll(this.button_options);
|
128
|
-
e.preventDefault();
|
129
|
-
e.stopPropagation();
|
130
|
-
})
|
131
|
-
actions_el.appendChild(show_all_button);
|
132
|
-
}
|
133
|
-
if (this.el.multiple) {
|
134
|
-
var done_button = Helpers.createElement("<button type='button' class='uniformSelect-done block outline blue'>Done</button>");
|
135
|
-
this.listenTo(done_button, 'click', this.hideOptions);
|
136
|
-
actions_el.appendChild(done_button);
|
137
|
-
}
|
138
|
-
if (!Helpers.is_empty(actions_el)) {
|
139
|
-
this.button_options.appendChild(actions_el);
|
140
|
-
}
|
106
|
+
if (!this.options.multiple) {
|
107
|
+
this.removeOptions();
|
141
108
|
}
|
142
|
-
|
143
|
-
renderSelected () {
|
144
|
-
const selected_options = Helpers.filter(this.el.querySelectorAll("option"), function(el){
|
145
|
-
return el.selected;
|
146
|
-
});
|
147
|
-
const html = Helpers.map(selected_options, function(el){
|
148
|
-
return this.el.multiple ? `<span class="uniformSelect-selection">${el.textContent}<span class="uniformSelect-remove"></span></span>` : el.textContent;
|
149
|
-
}.bind(this)).join(" ");
|
150
109
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
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() == e.target.closest('.uniformSelect-selection').innerText.trim();
|
118
|
+
})[0];
|
119
|
+
if(!option) return;
|
120
|
+
option.selected = false;
|
121
|
+
option.button.classList.remove('active');
|
156
122
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
Helpers.removeClass(el, 'active');
|
164
|
-
Helpers.each(el.querySelectorAll('.uniformSelect-option-icon'), Helpers.remove);
|
165
|
-
}
|
166
|
-
}.bind(this))
|
167
|
-
}
|
123
|
+
trigger(this.select, 'change');
|
124
|
+
}
|
125
|
+
|
126
|
+
toggleOptions (e) {
|
127
|
+
if(e && (e.target.matches('.uniformSelect-remove') || e.target.closest('.uniformSelect-remove'))){
|
128
|
+
return;
|
168
129
|
}
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
this.button_options_popover.remove();
|
175
|
-
delete this.button_options_popover;
|
176
|
-
}
|
177
|
-
Helpers.removeClass(this.edit_button, 'active');
|
130
|
+
this.el.classList.toggle('active')
|
131
|
+
if(this.el.contains('active')){
|
132
|
+
this.renderOptions()
|
133
|
+
} else {
|
134
|
+
this.removeOptions()
|
178
135
|
}
|
136
|
+
}
|
179
137
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
} else {
|
208
|
-
this.button_options.style.minWidth = this.edit_button.offsetWidth + "px";
|
209
|
-
this.button_options_popover = new Popover({
|
210
|
-
offset: {top: 1},
|
211
|
-
anchor: this.edit_button,
|
212
|
-
align: '0px bottom',
|
213
|
-
content: this.button_options,
|
214
|
-
container: this.options.container
|
215
|
-
}).render()
|
216
|
-
this.button_options_popover.on('hidden', () => {
|
217
|
-
Helpers.removeClass(this.edit_button, 'active');
|
218
|
-
this.button_options_popover.remove();
|
219
|
-
delete this.button_options_popover;
|
220
|
-
})
|
221
|
-
}
|
222
|
-
}
|
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
|
+
button.classList.toggle('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);
|
223
165
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
Helpers.removeClass(this.button_options.querySelectorAll('.uniformSelect-option.active'), 'active');
|
229
|
-
}
|
230
|
-
Helpers.toggleClass(e.target, 'active');
|
231
|
-
e.target.option.selected = Helpers.hasClass(e.target, 'active');
|
232
|
-
if (Helpers.hasClass(e.target, 'active')) {
|
233
|
-
e.target.append(this.activeIcon.cloneNode(true));
|
234
|
-
} else {
|
235
|
-
Helpers.each(e.target.querySelectorAll('.uniformSelect-option-icon'), Helpers.remove);
|
236
|
-
}
|
237
|
-
if (!this.el.multiple) {
|
238
|
-
this.hideOptions();
|
239
|
-
}
|
240
|
-
Helpers.trigger(this.el, 'change');
|
241
|
-
}
|
166
|
+
|
167
|
+
const actions = createElement('div', {
|
168
|
+
class: 'uniformSelect-actions'
|
169
|
+
});
|
242
170
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
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);
|
251
188
|
}
|
189
|
+
if (!isEmpty(actions)) {
|
190
|
+
options.append(actions);
|
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
|
+
this.popover.el.querySelectorAll('button.hide').forEach(el => el.classList.remove('hide'));
|
215
|
+
var button = this.popover.el.querySelector('.uniformSelect-show-all');
|
216
|
+
button.parentNode.removeChild(button);
|
217
|
+
}
|
252
218
|
}
|