@kizmann/nano-ui 0.7.17 → 0.7.18

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kizmann/nano-ui",
3
- "version": "0.7.17",
3
+ "version": "0.7.18",
4
4
  "license": "MIT",
5
5
  "private": false,
6
6
  "author": "Eduard Kizmann <kizmann@protonmail.ch>",
package/src/index.js CHANGED
@@ -73,6 +73,7 @@ export function Install(App, Icons = {}, Styles = {})
73
73
  require('./select/index').default(App);
74
74
  require('./checkbox/index').default(App);
75
75
  require('./radio/index').default(App);
76
+ require('./slider/index').default(App);
76
77
  require('./switch/index').default(App);
77
78
  require('./confirm/index').default(App);
78
79
  require('./cascader/index').default(App);
package/src/index.scss CHANGED
@@ -11,6 +11,7 @@
11
11
  @import "./input/index";
12
12
  @import "./input-number/index";
13
13
  @import "./textarea/index";
14
+ @import "./slider/index";
14
15
  @import "./switch/index";
15
16
  @import "./checkbox/index";
16
17
  @import "./radio/index";
@@ -0,0 +1,7 @@
1
+ import Vue from "vue";
2
+
3
+ import Slider from './src/slider/slider';
4
+
5
+ export default function (App) {
6
+ App.component(Slider.name, Slider);
7
+ }
@@ -0,0 +1 @@
1
+ @import "./src/slider/slider";
@@ -0,0 +1,377 @@
1
+ import { Obj, Arr, Any, Num, Dom, Event } from "@kizmann/pico-js";
2
+
3
+ export default {
4
+
5
+ name: 'NSlider',
6
+
7
+ props: {
8
+
9
+ modelValue: {
10
+ default()
11
+ {
12
+ return null;
13
+ }
14
+ },
15
+
16
+ range: {
17
+ default()
18
+ {
19
+ return false;
20
+ },
21
+ type: [Boolean]
22
+ },
23
+
24
+ steps: {
25
+ default()
26
+ {
27
+ return 1;
28
+ }
29
+ },
30
+
31
+ labels: {
32
+ default()
33
+ {
34
+ return [];
35
+ },
36
+ type: [Array]
37
+ },
38
+
39
+ min: {
40
+ default()
41
+ {
42
+ return 0;
43
+ },
44
+ type: [Number]
45
+ },
46
+
47
+ max: {
48
+ default()
49
+ {
50
+ return 100;
51
+ },
52
+ type: [Number]
53
+ },
54
+
55
+ type: {
56
+ default()
57
+ {
58
+ return 'primary';
59
+ },
60
+ type: [String]
61
+ },
62
+
63
+ size: {
64
+ default()
65
+ {
66
+ return 'md';
67
+ },
68
+ type: [String]
69
+ },
70
+
71
+ disabled: {
72
+ default()
73
+ {
74
+ return false;
75
+ },
76
+ type: [Boolean]
77
+ },
78
+
79
+ },
80
+
81
+ data()
82
+ {
83
+ return {
84
+ index: 0, width: null, tempValue: [null, null]
85
+ };
86
+ },
87
+
88
+ computed: {
89
+
90
+ selector()
91
+ {
92
+ return `[data-index="${this.index}"]`;
93
+ },
94
+
95
+ fixmin()
96
+ {
97
+ return Any.isArray(this.steps) ? Arr.first(this.steps) : this.min;
98
+ },
99
+
100
+ fixmax()
101
+ {
102
+ return Any.isArray(this.steps) ? Arr.last(this.steps) : this.max;
103
+ },
104
+
105
+ minmax()
106
+ {
107
+ return this.fixmax - this.fixmin;
108
+ },
109
+
110
+ touch() {
111
+ return !! ('ontouchstart' in window ||
112
+ navigator.msMaxTouchPoints);
113
+ },
114
+
115
+ mousedown() {
116
+ return this.touch ? 'touchstart' :
117
+ 'mousedown';
118
+ },
119
+
120
+ mousemove() {
121
+ return this.touch ? 'touchmove' :
122
+ 'mousemove';
123
+ },
124
+
125
+ mouseup() {
126
+ return this.touch ? 'touchend' :
127
+ 'mouseup';
128
+ }
129
+ },
130
+
131
+ watch: {
132
+
133
+ modelValue()
134
+ {
135
+ this.getPseudoValue();
136
+ }
137
+
138
+ },
139
+
140
+ mounted()
141
+ {
142
+ Dom.find(window).on('resize',
143
+ Any.debounce(this.onResize, 500), this._.uid);
144
+
145
+ this.onResize();
146
+ this.getPseudoValue();
147
+ },
148
+
149
+ unmounted()
150
+ {
151
+ Dom.find(window).off('resize',
152
+ null, this._.uid);
153
+ },
154
+
155
+ methods: {
156
+
157
+ onResize()
158
+ {
159
+ this.width = Dom.find(this.$el).width();
160
+ },
161
+
162
+ getPseudoValue()
163
+ {
164
+ let value = this.modelValue;
165
+
166
+ if ( Any.isNull(value) ) {
167
+ value = this.fixmax;
168
+ }
169
+ if ( ! Any.isArray(value) ) {
170
+ value = [this.fixmin, value];
171
+ }
172
+
173
+ return this.tempValue = value;
174
+ },
175
+
176
+ setModelValue()
177
+ {
178
+ let value = this.tempValue;
179
+
180
+ if ( ! this.range ) {
181
+ value = this.tempValue[1];
182
+ }
183
+
184
+ this.$emit('update:modelValue', value);
185
+ },
186
+
187
+ getValPos(value)
188
+ {
189
+ return Num.fixed(this.width / this.minmax * value, 2) + 'px';
190
+ },
191
+
192
+ getValStyle(value)
193
+ {
194
+ return 'transform: translateX(' + this.getValPos(value) + ');';
195
+ },
196
+
197
+ getBarPos()
198
+ {
199
+ return Num.fixed(this.width / this.minmax * this.tempValue[0], 2) + 'px';
200
+ },
201
+
202
+ getBarWidth()
203
+ {
204
+ return Num.fixed(this.width / this.minmax * (this.tempValue[1] - this.tempValue[0]), 2) + 'px';
205
+ },
206
+
207
+ getBarStyle()
208
+ {
209
+ return 'max-width: ' + this.getBarWidth() + '; ' +
210
+ 'transform: translateX(' + this.getBarPos() + ');';
211
+ },
212
+
213
+ getClosestValue(width)
214
+ {
215
+ if ( Any.isNumber(this.steps) ) {
216
+ return Num.round(width / this.steps) * this.steps;
217
+ }
218
+
219
+ let range = Arr.last(this.steps) -
220
+ Arr.first(this.steps);
221
+
222
+ let diff = Arr.each(this.steps, (step) => {
223
+ return Math.abs((range / 100 * width) - step);
224
+ });
225
+
226
+ let index = Arr.findIndex(diff, Math.min(...diff));
227
+
228
+ return this.steps[index];
229
+ },
230
+
231
+ getTouchEvent(event)
232
+ {
233
+ if ( ! this.touch ) {
234
+ return event;
235
+ }
236
+
237
+ return event.touches[0] || event.changedTouches[0];
238
+ },
239
+
240
+ onMousedown(event)
241
+ {
242
+ if ( ! Arr.has([0, 1], event.which) ) {
243
+ return;
244
+ }
245
+
246
+ event.preventDefault();
247
+ event.stopPropagation();
248
+
249
+ Dom.find(this.$el).find(this.selector).addClass('n-move');
250
+ Dom.find(document.body).addClass('n-move');
251
+
252
+ Dom.find(document).on(this.mouseup,
253
+ Any.framerate(this.onMouseup, 60), this._.uid);
254
+
255
+ Dom.find(document).on(this.mousemove,
256
+ Any.framerate(this.onMousemove, 60), this._.uid);
257
+ },
258
+
259
+ onMousemove(event)
260
+ {
261
+ this.clientX = this.getTouchEvent(event).clientX;
262
+
263
+ let offsetX = Dom.find(this.$el)
264
+ .offset('left');
265
+
266
+ let relativeWidth = (this.clientX - offsetX) / this.width * 100;
267
+
268
+ let closestValue = this.getClosestValue(relativeWidth);
269
+
270
+ if ( closestValue < this.fixmin ) {
271
+ closestValue = this.fixmin;
272
+ }
273
+
274
+ if ( closestValue > this.fixmax ) {
275
+ closestValue = this.fixmax;
276
+ }
277
+
278
+ let stepMin = this.tempValue[0] + this.steps;
279
+
280
+ if ( this.index === 1 && closestValue < stepMin ) {
281
+ closestValue = stepMin;
282
+ }
283
+
284
+ let stepMax = this.tempValue[1] - this.steps;
285
+
286
+ if ( this.index === 0 && closestValue > stepMax ) {
287
+ closestValue = stepMax;
288
+ }
289
+
290
+ this.tempValue[this.index] = closestValue;
291
+ },
292
+
293
+ onMouseup(event)
294
+ {
295
+ event.preventDefault();
296
+ event.stopPropagation();
297
+
298
+ Dom.find(document).off(this.mouseup, null, this._.uid);
299
+ Dom.find(document).off(this.mousemove, null, this._.uid);
300
+
301
+ Dom.find(this.$el).find(this.selector).removeClass('n-move');
302
+ Dom.find(document.body).removeClass('n-move');
303
+
304
+ this.setModelValue();
305
+ },
306
+
307
+ },
308
+
309
+ renderHandle(value, index)
310
+ {
311
+ let handleProps = {
312
+ 'data-value': value,
313
+ 'data-index': index,
314
+ style: this.getValStyle(value)
315
+ };
316
+
317
+ handleProps['onMousedown'] = (event) => {
318
+ this.onMousedown(event, this.index = index);
319
+ };
320
+
321
+ return (
322
+ <div class="n-slider__handle" {...handleProps}>
323
+ <span>{ Obj.get(this.labels, value, value) }</span>
324
+ </div>
325
+ );
326
+ },
327
+
328
+ renderHandles()
329
+ {
330
+ let values = Arr.clone(this.tempValue);
331
+
332
+ if ( ! this.range ) {
333
+ delete values[0];
334
+ }
335
+
336
+ return Arr.each(values, (value, index) => {
337
+ return this.ctor('renderHandle')(value, index);
338
+ });
339
+ },
340
+
341
+ renderBar()
342
+ {
343
+ let barProps = {
344
+ style: this.getBarStyle()
345
+ };
346
+
347
+ return (
348
+ <div class="n-slider__bar">
349
+ <div class="n-slider__range" {...barProps}></div>
350
+ </div>
351
+ );
352
+ },
353
+
354
+ render()
355
+ {
356
+ let classList = [
357
+ 'n-slider',
358
+ 'n-slider--' + this.size
359
+ ];
360
+
361
+ if ( this.range ) {
362
+ classList.push('n-range');
363
+ }
364
+
365
+ if ( this.disabled ) {
366
+ classList.push('n-disabled');
367
+ }
368
+
369
+ return (
370
+ <div class={classList}>
371
+ { this.ctor('renderBar')() }
372
+ { this.ctor('renderHandles')() }
373
+ </div>
374
+ );
375
+ }
376
+
377
+ }
@@ -0,0 +1,93 @@
1
+ @import "../../../root/vars";
2
+
3
+ .n-slider {
4
+ position: relative;
5
+ width: 100%;
6
+ }
7
+
8
+ .n-slider__bar {
9
+ z-index: 1;
10
+ position: absolute;
11
+ overflow: hidden;
12
+ top: 50%;
13
+ left: 0;
14
+ right: 0;
15
+ margin-top: -3px;
16
+ height: 6px;
17
+ background: $color-gray-10;
18
+ border-radius: 500px;
19
+ }
20
+
21
+ .n-slider__range {
22
+ position: absolute;
23
+ top: 0;
24
+ left: 0;
25
+ right: 0;
26
+ bottom: 0;
27
+ background: $color-primary;
28
+ }
29
+
30
+ .n-slider__handle {
31
+ cursor: grab;
32
+ z-index: 2;
33
+ position: absolute;
34
+ left: 0;
35
+ top: 50%;
36
+ width: 20px;
37
+ height: 20px;
38
+ margin: -10px 0 0 -10px;
39
+ background: $color-white;
40
+ border: 2px solid $color-primary;
41
+ border-radius: 500px;
42
+ }
43
+
44
+ .n-slider__handle span {
45
+ pointer-events: none;
46
+ position: absolute;
47
+ bottom: 100%;
48
+ left: 50%;
49
+ padding: 4px 8px;
50
+ border-radius: 3px;
51
+ font-size: 13px;
52
+ display: inline-block;
53
+ opacity: 0;
54
+ color: $color-white;
55
+ transform: translate(-50%, -25%);
56
+ background: rgba($color-black, 0.8);
57
+ transition: opacity 0.3s;
58
+ }
59
+
60
+ .n-slider__handle:hover span,
61
+ .n-slider__handle.n-move span {
62
+ opacity: 1;
63
+ }
64
+
65
+ @each $suffix, $values in $form {
66
+
67
+ $-slider-font: map-get($values, 'font');
68
+ $-slider-size: map-get($values, 'size');
69
+ $-slider-radius: map-get($values, 'radius');
70
+ $-slider-ratio: map-get($values, 'ratio');
71
+
72
+ .n-slider--#{$suffix} {
73
+ height: 32px;
74
+ }
75
+
76
+ .n-slider--#{$suffix} .n-slider__bar {
77
+ margin-top: -#{$-slider-size * 0.1};
78
+ height: $-slider-size * 0.2;
79
+ }
80
+
81
+ .n-slider--#{$suffix} .n-slider__handle {
82
+ width: $-slider-size * 0.6;
83
+ height: $-slider-size * 0.6;
84
+ margin: -#{$-slider-size * 0.3} 0 0 -#{$-slider-size * 0.3};
85
+ }
86
+
87
+ .n-slider--#{$suffix} .n-slider__handle span {
88
+ padding: $-slider-size * 0.15 $-slider-size * 0.3;
89
+ border-radius: $-slider-radius;
90
+ font-size: $-slider-font - 2;
91
+ }
92
+
93
+ }
@@ -54,18 +54,18 @@ export default {
54
54
 
55
55
  data()
56
56
  {
57
- return { init: true };
57
+ return { init: false };
58
58
  },
59
59
 
60
- // mounted()
61
- // {
62
- // this.timer = setTimeout(() => this.init = true, 5);
63
- // },
64
- //
65
- // beforeUnmount()
66
- // {
67
- // clearTimeout(this.timer);
68
- // },
60
+ mounted()
61
+ {
62
+ this.timer = setTimeout(() => this.init = true, 20);
63
+ },
64
+
65
+ beforeUnmount()
66
+ {
67
+ clearTimeout(this.timer);
68
+ },
69
69
 
70
70
  methods: {
71
71
 
@@ -99,7 +99,7 @@ export default {
99
99
  framerate: {
100
100
  default()
101
101
  {
102
- return 60;
102
+ return 65;
103
103
  },
104
104
  type: [Number]
105
105
  },