@itfin/components 1.3.94 → 1.3.96

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.
@@ -0,0 +1,602 @@
1
+ <template>
2
+ <div
3
+ :style="{
4
+ '--itf-tree-editor-disabled-font-size': `${textDisabledFontSize}px`,
5
+ '--itf-tree-editor-disabled-padding-left': `${textDisabledPaddingLeft}px`,
6
+ '--itf-tree-editor-disabled-background-color': $options.filters.color2hex(textDisabledBackgroundColor),
7
+ '--itf-tree-editor-disabled-color': $options.filters.color2hex(textDisabledColor),
8
+ '--itf-tree-editor-join-block-color': $options.filters.color2hex(joinBlockColor),
9
+ '--itf-tree-editor-shift-block-color': $options.filters.color2hex(shiftBlockColor),
10
+ '--itf-tree-editor-shift-line-color': $options.filters.color2hex(shiftLineColor)
11
+ }"
12
+ >
13
+ <div style="position:relative; user-select:none;">
14
+ <template v-for="(node,knode) in nodes">
15
+ <div
16
+ :key="get(node,itemKey,knode)"
17
+ class="itf-tree-editor_node"
18
+ :class="{ 'hidden': isNodeHidden(node) }"
19
+ :style="`transition:all 0.2s linear; cursor:pointer; outline:none; padding-left:${(node.nk.length - toggleStartLevel - 1)*indent}px;`"
20
+ :dragindex="knode"
21
+ tabindex="0"
22
+ dragtag
23
+ @mouseenter="(e)=>{$emit('mouseenter',{event:e,ele:e.target,node,knode})}"
24
+ @mouseleave="(e)=>{$emit('mouseleave',{event:e,ele:e.target,node,knode})}"
25
+ @keyup.enter="(e)=>{$emit('click',{event:e,ele:e.target,node,knode})}"
26
+ @click="(e)=>{$emit('click',{event:e,ele:e.target,node,knode})}"
27
+ >
28
+ <div v-if="node.level >= toggleStartLevel" class="itf-tree-editor_node_toggle ps-2">
29
+ <itf-button
30
+ v-if="autoToggleTree && node.level >= toggleStartLevel && node.Children && node.Children.length > 0"
31
+ small
32
+ @click.stop="toggleNode($event, node, knode)"
33
+ >
34
+ <itf-icon v-if="isNodeToggled(node)" name="plus" size="24" />
35
+ <itf-icon v-if="!isNodeToggled(node)" name="minus" size="24" />
36
+ </itf-button>
37
+ </div>
38
+ <div class="itf-tree-editor_node_content" :data-node="node[itemKey]">
39
+ <slot
40
+ name="item"
41
+ :isFirstElement="knode === 0"
42
+ :isLastElement="knode === nodes.length - 1"
43
+ :item="node"
44
+ :node="node"
45
+ :knode="knode"
46
+ />
47
+ </div>
48
+ </div>
49
+ </template>
50
+ <div
51
+ :style="{
52
+ position: 'absolute',
53
+ 'z-index': 9999,
54
+ left: `${dgTipLeft}px`,
55
+ top: `${dgTipTop}px`,
56
+ '--itf-tree-editor-tip-width': `${dgTipWidth}px`,
57
+ '--itf-tree-editor-tip-height': `${dgTipHeight}px`,
58
+ }"
59
+ >
60
+ <div v-if="dgTipMode==='lineTop'" class="itf-tree-editor_border-top" />
61
+ <div v-else-if="dgTipMode==='lineBottom'" class="itf-tree-editor_border-bottom" />
62
+ <div v-else-if="dgTipMode==='block'" class="itf-tree-editor_inside" />
63
+ <div v-else-if="dgTipMode==='disabled'" class="itf-tree-editor_disabled">
64
+ <div class="itf-tree-editor_disabled-text">
65
+ <template v-if="isNestingLimited">
66
+ {{ textDisabledNested }}
67
+ </template>
68
+ <template v-else>
69
+ {{ textDisabled }}
70
+ </template>
71
+ </div>
72
+ </div>
73
+ </div>
74
+ </div>
75
+ </div>
76
+ </template>
77
+ <style lang="scss">
78
+ :root {
79
+ --itf-tree-hover-bg: rgba(0 0 0 / 5%);
80
+ }
81
+ [data-theme="dark"] {
82
+ --itf-tree-hover-bg: rgba(255 255 255 / 5%);
83
+ }
84
+
85
+ .itf-tree-editor {
86
+ &_inside:after,
87
+ &_disabled:after,
88
+ &_border-top:after,
89
+ &_border-bottom:after {
90
+ content: " ";
91
+ display: block;
92
+ position: absolute;
93
+ top: -5px;
94
+ left: -5px;
95
+ border-left: 7px solid var(--bs-primary);
96
+ border-top: 7px solid transparent;
97
+ border-bottom: 7px solid transparent;
98
+ border-right: 7px solid transparent;
99
+ }
100
+ &_border-top {
101
+ display:inline-block;
102
+ width: var(--itf-tree-editor-tip-width);
103
+ height: var(--itf-tree-editor-tip-height);
104
+ /*background-color: var(--itf-tree-editor-shift-block-color);*/
105
+ border-top: 3px solid var(--bs-primary);
106
+ }
107
+ &_border-bottom {
108
+ display:inline-block;
109
+ width: var(--itf-tree-editor-tip-width);
110
+ height: var(--itf-tree-editor-tip-height);
111
+ /*background-color: var(--itf-tree-editor-shift-block-color);*/
112
+ border-bottom: 3px solid var(--bs-primary);
113
+
114
+ &:after {
115
+ top: auto;
116
+ bottom: 1px
117
+ }
118
+ }
119
+ &_inside {
120
+ display:inline-block;
121
+ width: var(--itf-tree-editor-tip-width);
122
+ height: var(--itf-tree-editor-tip-height);
123
+ background-color: var(--itf-tree-editor-shift-block-color);
124
+
125
+ &:after {
126
+ top: 50%;
127
+ transform: translateY(-100%);
128
+ left: -7px;
129
+ }
130
+ }
131
+ &_node {
132
+ display: flex;
133
+ position: relative;
134
+ }
135
+ &_node.hidden {
136
+ display: none;
137
+ }
138
+ &_node .selected,
139
+ &_node:hover {
140
+ background-color: var(--itf-tree-hover-bg);
141
+ }
142
+ &_node_toggle {
143
+ margin-left: 0;
144
+ width: 45px;
145
+ display: flex;
146
+ align-items: center;
147
+ }
148
+ &_node_content {
149
+ flex-grow: 1;
150
+ align-items: start;
151
+ }
152
+ &_disabled {
153
+ display:inline-flex;
154
+ width: var(--itf-tree-editor-tip-width);
155
+ height: var(--itf-tree-editor-tip-height);
156
+ background-color: var(--itf-tree-editor-disabled-background-color);
157
+ color: var(--itf-tree-editor-disabled-color);
158
+ line-height: var(--itf-tree-editor-tip-height);
159
+ vertical-align: middle;
160
+
161
+ &-text {
162
+ font-size: var(--itf-tree-editor-disabled-font-size);
163
+ padding-left: var(--itf-tree-editor-disabled-padding-left);
164
+ }
165
+
166
+ &:after {
167
+ content: '';
168
+ display: none;
169
+ }
170
+ }
171
+ }
172
+ </style>
173
+ <script>
174
+ import Vue from 'vue';
175
+ import pullAt from 'lodash/pullAt';
176
+ import size from 'lodash/size';
177
+ import dropRight from 'lodash/dropRight';
178
+ import takeRight from 'lodash/takeRight';
179
+ import cloneDeep from 'lodash/cloneDeep';
180
+ import get from 'lodash/get';
181
+ import set from 'lodash/set';
182
+ import min from 'lodash/min';
183
+ import take from 'lodash/take';
184
+ import isEqual from 'lodash/isEqual';
185
+ import domDrag from '../../helpers/tree/domDrag';
186
+ import cint from '../../helpers/tree/cint';
187
+ import itfButton from '../button/Button';
188
+ import itfIcon from '../icon/Icon';
189
+ import color2hex from '../../helpers/vuetifyColor';
190
+ import {buildTree, flattenTree} from '../../helpers/tree';
191
+
192
+ export default {
193
+ components: {
194
+ itfIcon,
195
+ itfButton
196
+ },
197
+ filters: {
198
+ color2hex
199
+ },
200
+ props: {
201
+ items: {
202
+ type: Array,
203
+ default: () => []
204
+ },
205
+ selectedItem: {
206
+ type: Object,
207
+ default: () => null
208
+ },
209
+ itemKey: {
210
+ type: String,
211
+ default: 'Id'
212
+ },
213
+ itemChildren: {
214
+ type: String,
215
+ default: 'Children'
216
+ },
217
+ indent: {
218
+ type: Number,
219
+ default: 10
220
+ },
221
+ textDisabled: {
222
+ type: String,
223
+ default: 'Can not drop here'
224
+ },
225
+ textDisabledNested: {
226
+ type: String,
227
+ default: 'Tree has a limitation in nesting, can not drop here'
228
+ },
229
+ textDisabledColor: {
230
+ type: String,
231
+ default: '#812'
232
+ },
233
+ textDisabledPaddingLeft: {
234
+ type: Number,
235
+ default: 15
236
+ },
237
+ textDisabledFontSize: {
238
+ type: String,
239
+ default: '0.9rem'
240
+ },
241
+ textDisabledBackgroundColor: {
242
+ type: String,
243
+ default: 'rgba(255,220,240,0.6)'
244
+ },
245
+ shiftLineColor: {
246
+ type: String,
247
+ default: '#29f'
248
+ },
249
+ shiftBlockColor: {
250
+ type: String,
251
+ default: 'rgba(80,150,255,0.15)'
252
+ },
253
+ joinBlockColor: {
254
+ type: String,
255
+ default: 'rgba(80,150,255,0.3)'
256
+ },
257
+ maxNestingLevels: {
258
+ type: Number,
259
+ default: null
260
+ },
261
+ allowDrop: {
262
+ type: Function,
263
+ default: null
264
+ },
265
+ handle: {
266
+ type: String,
267
+ default: null
268
+ },
269
+ readOnly: {
270
+ type: Boolean,
271
+ default: false
272
+ },
273
+ flat: {
274
+ type: Boolean,
275
+ default: false
276
+ },
277
+ autoToggleTree: {
278
+ type: Boolean,
279
+ default: false
280
+ },
281
+ toggleStartLevel: {
282
+ type: Number,
283
+ default: 1
284
+ },
285
+ parentKey: {
286
+ type: String,
287
+ default: 'ParentId'
288
+ }
289
+ },
290
+ data () {
291
+ return {
292
+ get,
293
+ dd: null,
294
+ dgTipMode: '',
295
+ dgTipLeft: 0,
296
+ dgTipTop: 0,
297
+ dgTipWidth: 0,
298
+ dgTipHeight: 0,
299
+ isNestingLimited: false,
300
+ toggledItems: this.toggledItems || {},
301
+ hiddenItems: this.hiddenItems || {}
302
+ };
303
+ },
304
+ computed: {
305
+ itemsTrans () {
306
+ return cloneDeep(this.items);
307
+ },
308
+ nodes () {
309
+ let items = this.itemsTrans;
310
+ if (this.flat) {
311
+ items = buildTree(items, this.itemKey, this.parentKey, this.itemChildren);
312
+ }
313
+ const list = flattenTree(items, 4, 0, null, [], this.itemChildren).map((item) => {
314
+ const [, ...nk] = item.path;
315
+ return { ...item, nk };
316
+ });
317
+ return list;
318
+ }
319
+ },
320
+ watch: {
321
+ selectedItem () {
322
+ if (this.selectedItem && this.firstInited && this.items.length) {
323
+ const node = this.nodes.find(nd => nd[this.itemKey] === this.selectedItem[this.itemKey]);
324
+ if (node) {
325
+ this.firstInited = false;
326
+ this.toggleParentHidden(node, false);
327
+ }
328
+ }
329
+ },
330
+ items () {
331
+ const draggable = get(this, 'dd.draggable');
332
+ if (draggable) {
333
+ draggable.destroy();
334
+ }
335
+ this.$nextTick(() => this.init());
336
+ }
337
+ },
338
+ mounted () {
339
+ this.init();
340
+ },
341
+ beforeDestroy () {
342
+ const draggable = get(this, 'dd.draggable');
343
+ if (draggable) {
344
+ draggable.destroy();
345
+ }
346
+ },
347
+ methods: {
348
+ init () {
349
+ this.firstInited = true;
350
+ // domDrag
351
+ const dd = domDrag(this.$el, {
352
+ attIndex: 'dragindex',
353
+ attGroup: 'draggroup',
354
+ selectors: '[dragtag]',
355
+ handle: this.handle,
356
+ previewBackground: 'rgba(255,255,255,.75)',
357
+ previewBorderColor: color2hex('blue-grey')
358
+ });
359
+ // change
360
+ dd.on('change', (msg) => {
361
+ // console.log('change', msg)
362
+ });
363
+ dd.on('start', (msg) => {
364
+ // console.log('start', msg)
365
+ });
366
+ dd.on('move', (msg) => {
367
+ // console.info('move');
368
+ // belong
369
+ const nodeSelf = this.nodes[msg.startInd];
370
+ const nodeEnter = this.nodes[msg.endInd];
371
+ const belong = this.isNkBelong(nodeEnter.nk, nodeSelf.nk);
372
+ // location
373
+ this.dgTipTop = msg.endEle.offsetTop;
374
+ this.dgTipLeft = msg.endEle.offsetLeft;
375
+ this.dgTipWidth = msg.endEle.offsetWidth;
376
+ this.dgTipHeight = msg.endEle.offsetHeight;
377
+ // dgTipMode
378
+ if (belong) {
379
+ this.dgTipMode = 'disabled';
380
+ } else if (msg.ry <= 0.3) {
381
+ this.dgTipMode = 'lineTop';
382
+ } else if (msg.ry >= 0.7) {
383
+ this.dgTipMode = 'lineBottom';
384
+ } else if (msg.ry > 0.3 && msg.ry < 0.7) {
385
+ this.dgTipMode = 'block';
386
+ } else {
387
+ // 不會有此狀況
388
+ this.dgTipMode = '';
389
+ }
390
+
391
+ this.isNestingLimited = false;
392
+ // limit nesting level
393
+ const level = Math.floor(nodeEnter.nk.length / 2);
394
+ if (typeof this.maxNestingLevels !== 'undefined' && ((level > this.maxNestingLevels) || (level >= this.maxNestingLevels && this.dgTipMode === 'block'))) {
395
+ this.dgTipMode = 'disabled';
396
+ this.isNestingLimited = true;
397
+ }
398
+ if (this.dgTipMode !== 'disabled' && this.allowDrop && !this.allowDrop(nodeSelf, nodeEnter, this.dgTipMode)) {
399
+ this.dgTipMode = 'disabled';
400
+ }
401
+ });
402
+ dd.on('enter', (msg) => {
403
+ // console.log('enter', msg)
404
+ });
405
+ dd.on('leave', (msg) => {
406
+ // console.log('leave', msg)
407
+ this.dgTipMode = '';
408
+ });
409
+ dd.on('drop', (msg) => {
410
+ // console.log('drop', msg)
411
+ // check
412
+ if (this.dgTipMode === '') {
413
+ // console.log('純點擊時無move故無有效拖曳模式')
414
+ return;
415
+ }
416
+ // modeDir
417
+ let modeDir = '';
418
+ if (cint(msg.startInd) < cint(msg.endInd)) {
419
+ modeDir = 'backward';
420
+ } else if (cint(msg.startInd) > cint(msg.endInd)) {
421
+ modeDir = 'forward';
422
+ }
423
+ // check
424
+ if (modeDir === '') {
425
+ this.dgTipMode = '';
426
+ return;
427
+ }
428
+ // modeInsert
429
+ let modeInsert;
430
+ if (this.dgTipMode === 'disabled') {
431
+ this.dgTipMode = '';
432
+ return;
433
+ } else if (this.dgTipMode === 'lineTop') {
434
+ modeInsert = 'before';
435
+ } else if (this.dgTipMode === 'lineBottom') {
436
+ modeInsert = 'after';
437
+ } else if (this.dgTipMode === 'block') {
438
+ modeInsert = 'belongto';
439
+ } else {
440
+ // console.log('invalid dgTipMode', this.dgTipMode)
441
+ }
442
+ // nkFrom
443
+ const nodeFrom = this.nodes[msg.startInd];
444
+ const nkFrom = cloneDeep(nodeFrom.nk);
445
+ // nkTo
446
+ const nodeTo = this.nodes[msg.endInd];
447
+ const nkTo = cloneDeep(nodeTo.nk);
448
+
449
+ // clear
450
+ this.dgTipMode = '';
451
+
452
+ this.$emit('update:items', this.moveItem(this.itemsTrans, nkFrom, nkTo, modeDir, modeInsert));
453
+ });
454
+ // save
455
+ this.dd = dd;
456
+ },
457
+ isNodeHidden (node) {
458
+ if (!this.autoToggleTree) {
459
+ return false;
460
+ }
461
+ if (node.parentNode && this.toggledItems[node.parentNode[this.itemKey]] !== undefined) {
462
+ return this.toggledItems[node.parentNode[this.itemKey]];
463
+ }
464
+ // if (this.hiddenItems[node.Id] !== undefined) {
465
+ // return this.hiddenItems[node.Id];
466
+ // }
467
+ return node.level > 1;
468
+ },
469
+ isNodeToggled (node) {
470
+ if (this.toggledItems[node[this.itemKey]] !== undefined) {
471
+ return this.toggledItems[node[this.itemKey]];
472
+ }
473
+ return node.level > 0;
474
+ },
475
+ toggleNode ($event, node, knode) {
476
+ if (this.toggledItems[node[this.itemKey]] === undefined) {
477
+ Vue.set(this.toggledItems, node[this.itemKey], true);
478
+ }
479
+ Vue.set(this.toggledItems, node[this.itemKey], !this.toggledItems[node[this.itemKey]]);
480
+ if (this.toggledItems[node[this.itemKey]]) { // show only 1st level
481
+ this.toggleChildrenHidden(node[this.itemKey], true);
482
+ } else if (node.Children) {
483
+ for (const subNode of node.Children) {
484
+ this.$set(this.hiddenItems, subNode[this.itemKey], this.toggledItems[node[this.itemKey]]);
485
+ }
486
+ }
487
+ },
488
+ toggleChildrenHidden (id, hide) {
489
+ const subNodes = this.nodes.filter(nd => nd[this.parentKey] === id);
490
+ if (subNodes) {
491
+ for (const subNode of subNodes) {
492
+ this.$set(this.hiddenItems, subNode[this.itemKey], hide);
493
+ this.$set(this.toggledItems, subNode[this.itemKey], hide);
494
+ this.toggleChildrenHidden(subNode[this.itemKey], hide);
495
+ }
496
+ }
497
+ },
498
+ toggleParentHidden (node, hide) {
499
+ this.$set(this.hiddenItems, node[this.itemKey], hide);
500
+ this.$set(this.toggledItems, node[this.itemKey], hide);
501
+ if (node.Children) {
502
+ for (const subNode of node.Children) {
503
+ this.$set(this.hiddenItems, subNode[this.itemKey], hide);
504
+ }
505
+ }
506
+ if (node[this.parentKey]) {
507
+ const parent = this.nodes.find(nd => nd[this.itemKey] === node[this.parentKey]);
508
+ if (parent) {
509
+ this.toggleParentHidden(parent, hide);
510
+ }
511
+ }
512
+ },
513
+ isNkBelong (arEnter, arSelf) {
514
+ function isArrayOverlap (ar1, ar2) {
515
+ // n
516
+ const n = min([size(ar1), size(ar2)]);
517
+ const tr1 = take(ar1, n);
518
+ const tr2 = take(ar2, n);
519
+ // isEqual
520
+ return isEqual(tr1, tr2);
521
+ }
522
+ if (size(arEnter) >= size(arSelf)) {
523
+ return isArrayOverlap(arEnter, arSelf);
524
+ }
525
+ return false;
526
+ },
527
+ deleteItem (items, nkFrom) {
528
+ // console.log('methods deleteItem', items, nkFrom)
529
+ // cloneDeep
530
+ items = cloneDeep(items);
531
+ let ks;
532
+ let ind = null;
533
+ // eslint-disable-next-line no-empty
534
+ if (size(nkFrom) === 0) {
535
+ } else if (size(nkFrom) === 1) {
536
+ ks = nkFrom;
537
+ } else {
538
+ ks = dropRight(nkFrom);
539
+ ind = takeRight(nkFrom);
540
+ }
541
+ if (!ind) {
542
+ // pullAt
543
+ pullAt(items, nkFrom);
544
+ } else {
545
+ const src = get(items, ks, []);
546
+ // pullAt
547
+ pullAt(src, [ind]);
548
+ }
549
+ return items;
550
+ },
551
+ moveItem (items, nkFrom, nkTo, modeDir, modeInsert) {
552
+ // console.log('methods moveItem', items, nkFrom, nkTo, modeDir, modeInsert)
553
+ // check
554
+ if (modeDir !== 'forward' && modeDir !== 'backward') {
555
+ // console.log('invalid modeDir', modeDir);
556
+ }
557
+ if (size(nkFrom) === 0) {
558
+ // console.log('invalid nkFrom', nkTo);
559
+ }
560
+ if (size(nkTo) === 0) {
561
+ // console.log('invalid nkTo', nkTo);
562
+ }
563
+ // cloneDeep
564
+ items = cloneDeep(items);
565
+ const src = get(items, nkFrom);
566
+ // modeDir
567
+ if (modeDir === 'forward') {
568
+ items = this.deleteItem(items, nkFrom);
569
+ }
570
+ let ind = takeRight(nkTo)[0];
571
+ if (modeInsert === 'before' || modeInsert === 'after') {
572
+ let tar;
573
+ if (size(nkTo) === 1) {
574
+ tar = items;
575
+ } else {
576
+ const ks = dropRight(nkTo);
577
+ tar = get(items, ks, []);
578
+ }
579
+ if (modeInsert === 'before') {
580
+ // ind = ind
581
+ } else if (modeInsert === 'after') {
582
+ ind += 1;
583
+ }
584
+ tar.splice(ind, 0, src);
585
+ } else if (modeInsert === 'belongto') {
586
+ const tar = get(items, [...nkTo, this.itemChildren], []);
587
+ // push
588
+ tar.push(src);
589
+ // set
590
+ set(items, [...nkTo, this.itemChildren], tar);
591
+ } else {
592
+ // console.log('invalid modeInsert', modeInsert);
593
+ }
594
+ // modeDir
595
+ if (modeDir === 'backward') {
596
+ items = this.deleteItem(items, nkFrom);
597
+ }
598
+ return items;
599
+ }
600
+ }
601
+ };
602
+ </script>
@@ -0,0 +1,32 @@
1
+ import toFinite from 'lodash/toFinite'
2
+ import isnum from './isnum.js'
3
+
4
+
5
+ /**
6
+ * 數字或字串轉浮點數
7
+ * 若輸入非數字則回傳0
8
+ *
9
+ * Unit Test: {@link https://github.com/yuda-lyu/wsemi/blob/master/test/cdbl.test.js Github}
10
+ * @memberOf wsemi
11
+ * @param {Number|String} v 輸入數字或字串
12
+ * @returns {Number} 回傳數字
13
+ * @example
14
+ *
15
+ * console.log(cdbl('25'))
16
+ * // => 25
17
+ *
18
+ */
19
+ function cdbl(v) {
20
+
21
+ //check
22
+ if (!isnum(v)) {
23
+ return 0
24
+ }
25
+
26
+ let r = toFinite(v)
27
+
28
+ return r
29
+ }
30
+
31
+
32
+ export default cdbl
@@ -0,0 +1,43 @@
1
+ import round from 'lodash/round'
2
+ import isnum from './isnum.js'
3
+ import cdbl from './cdbl.js'
4
+
5
+
6
+ /**
7
+ * 數字或字串四捨五入轉整數
8
+ * 若輸入非數字則回傳0
9
+ *
10
+ * Unit Test: {@link https://github.com/yuda-lyu/wsemi/blob/master/test/cint.test.js Github}
11
+ * @memberOf wsemi
12
+ * @param {Number|String} v 輸入數字或字串
13
+ * @returns {Integer} 回傳四捨五入後整數
14
+ * @example
15
+ *
16
+ * console.log(cint('1.5'))
17
+ * // => 2
18
+ *
19
+ * console.log(cint('-1.5'))
20
+ * // => -1
21
+ *
22
+ */
23
+ function cint(v) {
24
+
25
+ //check
26
+ if (!isnum(v)) {
27
+ return 0
28
+ }
29
+
30
+ v = cdbl(v)
31
+
32
+ let r = round(v)
33
+
34
+ //check -0
35
+ if (String(r) === '0') {
36
+ return 0
37
+ }
38
+
39
+ return r
40
+ }
41
+
42
+
43
+ export default cint