@itfin/components 1.3.86 → 1.3.87

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itfin/components",
3
- "version": "1.3.86",
3
+ "version": "1.3.87",
4
4
  "author": "Vitalii Savchuk <esvit666@gmail.com>",
5
5
  "scripts": {
6
6
  "serve": "vue-cli-service serve",
@@ -72,7 +72,6 @@
72
72
  -webkit-mask-image: none!important;
73
73
  }
74
74
  &.btn-squircle:focus:after {
75
- background: rgb(103, 146, 244);
76
75
  border-color: rgb(103, 146, 244);
77
76
  }
78
77
  &:not(.dropdown-toggle):focus:after {
@@ -0,0 +1,276 @@
1
+ .vue-range-slider.slider-component {
2
+ position: relative;
3
+ -webkit-box-sizing: border-box;
4
+ box-sizing: border-box;
5
+ -webkit-user-select: none;
6
+ -moz-user-select: none;
7
+ -ms-user-select: none;
8
+ user-select: none;
9
+ }
10
+ .vue-range-slider.slider-component .slider {
11
+ position: relative;
12
+ display: block;
13
+ border-radius: 15px;
14
+ background-color: #ccc;
15
+ }
16
+ .vue-range-slider.slider-component .slider::after {
17
+ content: '';
18
+ position: absolute;
19
+ left: 0;
20
+ top: 0;
21
+ width: 100%;
22
+ height: 100%;
23
+ z-index: 2;
24
+ }
25
+ .vue-range-slider.slider-component .slider .slider-dot {
26
+ position: absolute;
27
+ border-radius: 50%;
28
+ background-color: #fff;
29
+ -webkit-box-shadow: 0.5px 0.5px 2px 1px rgba(0,0,0,0.32);
30
+ box-shadow: 0.5px 0.5px 2px 1px rgba(0,0,0,0.32);
31
+ -webkit-transition: all 0s;
32
+ transition: all 0s;
33
+ will-change: transform;
34
+ cursor: pointer;
35
+ z-index: 5;
36
+ }
37
+ .vue-range-slider.slider-component .slider .slider-dot.slider-dot-focus {
38
+ -webkit-box-shadow: 0 0 2px 1px #3498db;
39
+ box-shadow: 0 0 2px 1px #3498db;
40
+ }
41
+ .vue-range-slider.slider-component .slider .slider-dot.slider-dot-dragging {
42
+ z-index: 5;
43
+ }
44
+ .vue-range-slider.slider-component .slider .slider-dot.slider-dot-disabled {
45
+ z-index: 4;
46
+ }
47
+ .vue-range-slider.slider-component .slider .slider-dot.slider-hover:hover .slider-tooltip-wrap {
48
+ display: block;
49
+ }
50
+ .vue-range-slider.slider-component .slider .slider-dot.slider-always .slider-tooltip-wrap {
51
+ display: block !important;
52
+ }
53
+ .vue-range-slider.slider-component .slider .slider-process {
54
+ position: absolute;
55
+ border-radius: 15px;
56
+ background-color: var(--bs-primary);
57
+ z-index: 1;
58
+ }
59
+ .vue-range-slider.slider-component .slider .slider-process.slider-process-draggable {
60
+ cursor: pointer;
61
+ z-index: 3;
62
+ }
63
+ .vue-range-slider.slider-component .slider .slider-input {
64
+ position: absolute;
65
+ overflow: hidden;
66
+ height: 1px;
67
+ width: 1px;
68
+ clip: rect(1px, 1px, 1px, 1px);
69
+ }
70
+ .vue-range-slider.slider-component .slider .slider-piecewise {
71
+ position: absolute;
72
+ width: 100%;
73
+ padding: 0;
74
+ margin: 0;
75
+ left: 0;
76
+ top: 0;
77
+ height: 100%;
78
+ list-style: none;
79
+ }
80
+ .vue-range-slider.slider-component .slider .slider-piecewise .piecewise-item {
81
+ position: absolute;
82
+ width: 8px;
83
+ height: 8px;
84
+ }
85
+ .vue-range-slider.slider-component .slider .slider-piecewise .piecewise-item:first-child .piecewise-dot,
86
+ .vue-range-slider.slider-component .slider .slider-piecewise .piecewise-item:last-child .piecewise-dot {
87
+ visibility: hidden;
88
+ }
89
+ .vue-range-slider.slider-component .slider .slider-piecewise .piecewise-item .piecewise-dot {
90
+ position: absolute;
91
+ left: 50%;
92
+ top: 50%;
93
+ width: 100%;
94
+ height: 100%;
95
+ display: inline-block;
96
+ background-color: rgba(0,0,0,0.16);
97
+ border-radius: 50%;
98
+ -webkit-transform: translate(-50%, -50%);
99
+ transform: translate(-50%, -50%);
100
+ z-index: 2;
101
+ -webkit-transition: all 0.3s;
102
+ transition: all 0.3s;
103
+ }
104
+ .vue-range-slider.slider-component.slider-horizontal .slider-dot {
105
+ left: 0;
106
+ }
107
+ .vue-range-slider.slider-component.slider-horizontal .slider-process {
108
+ width: 0;
109
+ height: 100%;
110
+ top: 0;
111
+ left: 0;
112
+ will-change: width;
113
+ }
114
+ .vue-range-slider.slider-component.slider-vertical .slider-dot {
115
+ bottom: 0;
116
+ }
117
+ .vue-range-slider.slider-component.slider-vertical .slider-process {
118
+ width: 100%;
119
+ height: 0;
120
+ bottom: 0;
121
+ left: 0;
122
+ will-change: height;
123
+ }
124
+ .vue-range-slider.slider-component.slider-horizontal-reverse .slider-dot {
125
+ right: 0;
126
+ }
127
+ .vue-range-slider.slider-component.slider-horizontal-reverse .slider-process {
128
+ width: 0;
129
+ height: 100%;
130
+ top: 0;
131
+ right: 0;
132
+ }
133
+ .vue-range-slider.slider-component.slider-vertical-reverse .slider-dot {
134
+ top: 0;
135
+ }
136
+ .vue-range-slider.slider-component.slider-vertical-reverse .slider-process {
137
+ width: 100%;
138
+ height: 0;
139
+ top: 0;
140
+ left: 0;
141
+ }
142
+ .vue-range-slider.slider-component.slider-horizontal .slider-piecewise .piecewise-item .piecewise-label,
143
+ .vue-range-slider.slider-component.slider-horizontal-reverse .slider-piecewise .piecewise-item .piecewise-label {
144
+ position: absolute;
145
+ display: inline-block;
146
+ top: 100%;
147
+ left: 50%;
148
+ white-space: nowrap;
149
+ font-size: 12px;
150
+ color: #333;
151
+ -webkit-transform: translate(-50%, 8px);
152
+ transform: translate(-50%, 8px);
153
+ visibility: visible;
154
+ }
155
+ .vue-range-slider.slider-component.slider-vertical .slider-piecewise .piecewise-item .piecewise-label,
156
+ .vue-range-slider.slider-component.slider-vertical-reverse .slider-piecewise .piecewise-item .piecewise-label {
157
+ position: absolute;
158
+ display: inline-block;
159
+ top: 50%;
160
+ left: 100%;
161
+ white-space: nowrap;
162
+ font-size: 12px;
163
+ color: #333;
164
+ -webkit-transform: translate(8px, -50%);
165
+ transform: translate(8px, -50%);
166
+ visibility: visible;
167
+ }
168
+ .vue-range-slider.slider-component .slider-tooltip-wrap {
169
+ display: none;
170
+ position: absolute;
171
+ z-index: 9;
172
+ }
173
+ .vue-range-slider.slider-component .slider-tooltip-wrap.merged-tooltip {
174
+ display: block;
175
+ visibility: hidden;
176
+ }
177
+ .vue-range-slider.slider-component .slider-tooltip-wrap.slider-tooltip-top {
178
+ top: -9px;
179
+ left: 50%;
180
+ -webkit-transform: translate(-50%, -100%);
181
+ transform: translate(-50%, -100%);
182
+ }
183
+ .vue-range-slider.slider-component .slider-tooltip-wrap.slider-tooltip-top .slider-tooltip::before {
184
+ content: '';
185
+ position: absolute;
186
+ bottom: -10px;
187
+ left: 50%;
188
+ width: 0;
189
+ height: 0;
190
+ border: 5px solid transparent;
191
+ border-top-color: inherit;
192
+ -webkit-transform: translate(-50%, 0);
193
+ transform: translate(-50%, 0);
194
+ }
195
+ .vue-range-slider.slider-component .slider-tooltip-wrap.slider-tooltip-bottom {
196
+ bottom: -9px;
197
+ left: 50%;
198
+ -webkit-transform: translate(-50%, 100%);
199
+ transform: translate(-50%, 100%);
200
+ }
201
+ .vue-range-slider.slider-component .slider-tooltip-wrap.slider-tooltip-bottom .slider-tooltip::before {
202
+ content: '';
203
+ position: absolute;
204
+ top: -10px;
205
+ left: 50%;
206
+ width: 0;
207
+ height: 0;
208
+ border: 5px solid transparent;
209
+ border-bottom-color: inherit;
210
+ -webkit-transform: translate(-50%, 0);
211
+ transform: translate(-50%, 0);
212
+ }
213
+ .vue-range-slider.slider-component .slider-tooltip-wrap.slider-tooltip-left {
214
+ top: 50%;
215
+ left: -9px;
216
+ -webkit-transform: translate(-100%, -50%);
217
+ transform: translate(-100%, -50%);
218
+ }
219
+ .vue-range-slider.slider-component .slider-tooltip-wrap.slider-tooltip-left .slider-tooltip::before {
220
+ content: '';
221
+ position: absolute;
222
+ top: 50%;
223
+ right: -10px;
224
+ width: 0;
225
+ height: 0;
226
+ border: 5px solid transparent;
227
+ border-left-color: inherit;
228
+ -webkit-transform: translate(0, -50%);
229
+ transform: translate(0, -50%);
230
+ }
231
+ .vue-range-slider.slider-component .slider-tooltip-wrap.slider-tooltip-right {
232
+ top: 50%;
233
+ right: -9px;
234
+ -webkit-transform: translate(100%, -50%);
235
+ transform: translate(100%, -50%);
236
+ }
237
+ .vue-range-slider.slider-component .slider-tooltip-wrap.slider-tooltip-right .slider-tooltip::before {
238
+ content: '';
239
+ position: absolute;
240
+ top: 50%;
241
+ left: -10px;
242
+ width: 0;
243
+ height: 0;
244
+ border: 5px solid transparent;
245
+ border-right-color: inherit;
246
+ -webkit-transform: translate(0, -50%);
247
+ transform: translate(0, -50%);
248
+ }
249
+ .vue-range-slider.slider-component .slider-tooltip-wrap.merged-tooltip {
250
+ display: block;
251
+ visibility: hidden;
252
+ }
253
+ .vue-range-slider.slider-component .slider-tooltip-wrap .slider-tooltip {
254
+ display: block;
255
+ font-size: 14px;
256
+ white-space: nowrap;
257
+ padding: 2px 5px;
258
+ min-width: 20px;
259
+ text-align: center;
260
+ color: #fff;
261
+ border-radius: 5px;
262
+ border: 1px solid var(--bs-primary);
263
+ background-color: var(--bs-primary);
264
+ }
265
+ .vue-range-slider.slider-component.slider-disabled {
266
+ opacity: 0.5;
267
+ cursor: not-allowed;
268
+ }
269
+ .vue-range-slider.slider-component.slider-disabled .slider-dot {
270
+ cursor: not-allowed;
271
+ }
272
+ .vue-range-slider.slider-component.slider-has-label {
273
+ margin-bottom: 15px;
274
+ }
275
+
276
+ /*# sourceMappingURL=vue-range-slider.css.map */
@@ -22,6 +22,7 @@
22
22
  @import './components/tabs';
23
23
  @import './components/text-field';
24
24
  @import './components/tree-view';
25
+ @import './components/range';
25
26
  @import './components/wizard';
26
27
  @import './directives/loading';
27
28
  @import './directives/tooltip';
@@ -0,0 +1,93 @@
1
+ <template>
2
+ <div class="py-2" @mousemove="onRefresh" @mouseup="onUpdateValue">
3
+ <div class="px-1">
4
+ <div v-if="histogram" class="histogram px-3">
5
+ <div v-for="(item, n) in histogramPerc" :key="n" :style="`--bar-height: ${item}px`"></div>
6
+ </div>
7
+
8
+ <itf-range
9
+ ref="range"
10
+ :value="value"
11
+ :width="260"
12
+ @input="onChange"
13
+ :min="min"
14
+ :max="max"
15
+ :stop-propagation="false"
16
+ :use-keyboard="false"
17
+ :tooltip="false"
18
+ :tooltip-merge="false"
19
+ />
20
+
21
+ <div v-if="internalValue" class="d-flex justify-content-between gap-5">
22
+ <itf-text-field small type="number" :value="internalValue[0]" @input="onChange([$event, internalValue[1]], true)" />
23
+ <itf-text-field small type="number" :value="internalValue[1]" @input="onChange([internalValue[0], $event], true)" />
24
+ </div>
25
+ </div>
26
+ </div>
27
+ </template>
28
+ <style lang="scss" scoped>
29
+ .histogram {
30
+ display: flex;
31
+ justify-content: space-between;
32
+ align-items: end;
33
+ gap: .25rem;
34
+
35
+ & > div {
36
+ background: var(--bs-primary);
37
+ flex-grow: 1;
38
+ height: var(--bar-height);
39
+ }
40
+ }
41
+ </style>
42
+ <script>
43
+ import throttle from 'lodash/throttle';
44
+ import { Vue, Prop, Model, Component } from 'vue-property-decorator';
45
+ import itfTextField from '@itfin/components/src/components/text-field/TextField.vue';
46
+ import itfRange from '@itfin/components/src/components/range/Range.vue';
47
+
48
+ export default @Component({
49
+ name: 'FilterAmountRange',
50
+ components: {
51
+ itfTextField,
52
+ itfRange
53
+ }
54
+ })
55
+ class FilterAmountRange extends Vue {
56
+ @Model('input') value;
57
+ @Prop() min;
58
+ @Prop() max;
59
+ @Prop() histogram;
60
+
61
+ isRefreshed = false;
62
+ internalValue = null;
63
+
64
+ mounted() {
65
+ this.internalValue = this.value;
66
+ }
67
+
68
+ get histogramPerc() {
69
+ const max = Math.max(...this.histogram);
70
+ return this.histogram.map(item => Math.round(item / max * 100));
71
+ }
72
+
73
+ onRefresh() {
74
+ if (this.isRefreshed) {
75
+ return;
76
+ }
77
+ this.isRefreshed = true;
78
+ this.$refs.range.refresh();
79
+ }
80
+
81
+ onChange(val, isSet = false) {
82
+ this.isRefreshed = false;
83
+ this.internalValue = val;
84
+ if (isSet) {
85
+ this.onUpdateValue();
86
+ }
87
+ }
88
+
89
+ onUpdateValue() {
90
+ this.$emit('input', this.internalValue);
91
+ }
92
+ }
93
+ </script>
@@ -0,0 +1,182 @@
1
+ <template>
2
+ <itf-dropdown text ref="dropdown" autoclose="outside">
3
+ <template #button>
4
+ <div class="filter-pill" :class="{'filter-not-default-pill': !isDefault && !isInvalid, 'filter-invalid-pill': isInvalid}">
5
+ <div class="filter-pill__label" :class="{'filter-pill__not-default-value': !isDefault && !isInvalid, 'filter-pill__default-value': isDefault, 'filter-pill__label-invalid': isInvalid}">
6
+ <itf-icon v-if="icon" :size="18" :name="icon" />
7
+ {{ text }}
8
+ </div>
9
+ <div @click.stop.prevent="resetValue" v-if="!isDefault" class="filter-pill__icon" :class="{'filter-pill__icon-not-default-value': !isDefault && !isInvalid, 'filter-pill__icon-invalid': isInvalid}">
10
+ <svg width="8" height="8" viewBox="0 0 8 8" fill="#788195" xmlns="http://www.w3.org/2000/svg"><path d="M8 0.94L7.06 0L4 3.06L0.94 0L0 0.94L3.06 4L0 7.06L0.94 8L4 4.94L7.06 8L8 7.06L4.94 4L8 0.94Z" fill="inherit"></path></svg>
11
+ </div>
12
+ </div>
13
+ </template>
14
+
15
+ <div>
16
+ <template v-if="type === 'list'">
17
+ <a
18
+ v-for="(item, n) in options.items"
19
+ href=""
20
+ @click.prevent="onFilterChange(item)"
21
+ class="dropdown-item"
22
+ :class="{'active': item.value === (value && value.value)}"
23
+ :key="n">{{item.text}}</a>
24
+ </template>
25
+ <template v-else-if="type === 'period'">
26
+ <itf-date-range-picker-inline
27
+ :value="value.value"
28
+ @input="onFilterChange({ value: $event })"
29
+ />
30
+ </template>
31
+ <template v-else-if="type === 'date'">
32
+ <itf-date-picker-inline
33
+ :value="value.value"
34
+ @input="onFilterChange({ value: $event })"
35
+ />
36
+ </template>
37
+ <div class="px-2" v-else-if="type === 'facets-list'" style="width: 300px;">
38
+ <filter-facets-list
39
+ :title="options.title"
40
+ :value="value.value"
41
+ :items="options.items"
42
+ :total="options.total"
43
+ :multiple="options.multiple"
44
+ @input="onFilterChange({ value: $event })"
45
+ />
46
+ </div>
47
+ <div class="px-2" v-else-if="type === 'amount'" style="width: 300px;">
48
+ <filter-amount-range
49
+ :value="value.value"
50
+ :histogram="options.histogram"
51
+ :min="options.min"
52
+ :max="options.max"
53
+ @input="onFilterChange({ value: $event })"
54
+ />
55
+ </div>
56
+ </div>
57
+ </itf-dropdown>
58
+ </template>
59
+ <style lang="scss">
60
+ :root {
61
+ --filter-badge__default-color: #475266;
62
+ --filter-badge__default-bg-color: #4752661A;
63
+ --filter-badge__default-bg-color-hover: #47526642;
64
+
65
+ --filter-badge__invalid-color: #D83C31;
66
+ --filter-badge__invalid-bg-color: #D83C311A;
67
+ --filter-badge__invalid-bg-color-hover: #D83C3142;
68
+
69
+ --filter-badge__selected-color: #2f51fe; // #0d935b;
70
+ --filter-badge__selected-bg-color: #2f51fe1a; // #0d935b1A;
71
+ --filter-badge__selected-bg-color-hover: #2f51fe42; // #0d935b42;
72
+ --filter-badge__padding-x: 6px; // 10px;
73
+ --filter-badge__padding-y: 12px;// 18px;
74
+ }
75
+ .filter-pill {
76
+ align-items: center;
77
+ border-radius: 21px;
78
+ font-size: 14px;
79
+ line-height: 100%;
80
+ background-color: var(--filter-badge__default-bg-color);
81
+ display: flex;
82
+ min-height: 2rem;
83
+ transition: 0.1s;
84
+
85
+ &:hover {
86
+ background-color: var(--filter-badge__default-bg-color-hover);
87
+ cursor: pointer;
88
+ }
89
+ &.filter-not-default-pill {
90
+ background-color: var(--filter-badge__selected-bg-color);
91
+ outline: 1px solid var(--filter-badge__selected-color);
92
+ }
93
+ &.filter-invalid-pill {
94
+ background-color: var(--filter-badge__invalid-bg-color);
95
+ }
96
+ &.filter-pill__default-value {
97
+ padding: var(--filter-badge__padding-x) var(--filter-badge__padding-y);
98
+ }
99
+ }
100
+ .filter-pill__label {
101
+ color: var(--filter-badge__default-color);
102
+ padding: var(--filter-badge__padding-x) 0 var(--filter-badge__padding-x) var(--filter-badge__padding-y);
103
+ max-width: 330px;
104
+ text-overflow: ellipsis;
105
+ white-space: nowrap;
106
+ overflow: hidden;
107
+ display: flex;
108
+ gap: .25rem;
109
+ align-items: center;
110
+
111
+ &.filter-pill__default-value {
112
+ padding: var(--filter-badge__padding-x) var(--filter-badge__padding-y);
113
+ }
114
+ &.filter-pill__not-default-value {
115
+ color: var(--filter-badge__selected-color);
116
+ }
117
+ &.filter-pill__label-invalid {
118
+ color: var(--filter-badge__invalid-color);
119
+ }
120
+ }
121
+
122
+ .filter-pill__icon {
123
+ padding: var(--filter-badge__padding-x) calc(var(--filter-badge__padding-x) * 2) var(--filter-badge__padding-x) var(--filter-badge__padding-x);
124
+ margin-top: -2px;
125
+
126
+ svg {
127
+ fill: var(--filter-badge__default-color);
128
+ }
129
+ &.filter-pill__icon-invalid svg {
130
+ fill: var(--filter-badge__invalid-color);
131
+ }
132
+ &.filter-pill__icon-not-default-value svg {
133
+ fill: var(--filter-badge__selected-color);
134
+ }
135
+ }
136
+ </style>
137
+ <script>
138
+ import { Vue, Model, Prop, Component } from 'vue-property-decorator';
139
+ import itfIcon from '@itfin/components/src/components/icon/Icon';
140
+ import itfButton from '@itfin/components/src/components/button/Button';
141
+ import itfDropdown from '@itfin/components/src/components/dropdown/Dropdown.vue';
142
+ import itfDatePickerInline from '@itfin/components/src/components/datepicker/DatePickerInline.vue';
143
+ import itfDateRangePickerInline from '@itfin/components/src/components/datepicker/DateRangePickerInline.vue';
144
+ import itfTextField from '@itfin/components/src/components/text-field/TextField.vue';
145
+ import FilterFacetsList from './FilterFacetsList';
146
+ import FilterAmountRange from './FilterAmountRange.vue';
147
+
148
+ export default @Component({
149
+ components: {
150
+ itfIcon,
151
+ itfButton,
152
+ itfDropdown,
153
+ itfDatePickerInline,
154
+ itfDateRangePickerInline,
155
+ itfTextField,
156
+ FilterFacetsList,
157
+ FilterAmountRange
158
+ }
159
+ })
160
+ class FilterBadge extends Vue {
161
+ @Model('input') value;
162
+ @Prop(Boolean) isDefault;
163
+ @Prop(Boolean) isInvalid;
164
+ @Prop() text;
165
+ @Prop() type;
166
+ @Prop() icon;
167
+ @Prop() options;
168
+
169
+ resetValue() {
170
+ this.onFilterChange({ ...this.options.defaultValue });
171
+ this.$refs.dropdown.hide();
172
+ }
173
+
174
+ onFilterChange(value) {
175
+ this.$emit('input', value);
176
+ this.$emit('change', value);
177
+ if (!['facets-list', 'amount'].includes(this.type)) {
178
+ this.$refs.dropdown.hide();
179
+ }
180
+ }
181
+ }
182
+ </script>