@itfin/components 1.3.53 → 1.3.56

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.53",
3
+ "version": "1.3.56",
4
4
  "author": "Vitalii Savchuk <esvit666@gmail.com>",
5
5
  "scripts": {
6
6
  "serve": "vue-cli-service serve",
@@ -929,7 +929,7 @@ $rangeThumbSize: 12px;
929
929
  }
930
930
  }
931
931
 
932
- .itf-datepicker {
932
+ .itf-datepicker, .itf-monthpicker {
933
933
  &.with-addon .addon-end {
934
934
  pointer-events: all;
935
935
  padding-right: 0.25rem;
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="itf-monthpicker" :class="{'with-addon addon-start': prependIcon}">
2
+ <div class="itf-monthpicker input-group" :class="{'with-addon addon-start': prependIcon, 'with-addon addon-end': clearable}">
3
3
  <div class="addon" v-if="prependIcon">
4
4
  <slot name="addon">
5
5
  <itf-icon :name="prependIcon" />
@@ -16,6 +16,17 @@
16
16
  :value="displayValue"
17
17
  :placeholder="placeholder"
18
18
  />
19
+ <div class="addon-end" v-if="clearable && value">
20
+ <slot name="clear">
21
+ <itf-button
22
+ icon
23
+ small
24
+ @click="$emit('input', '')"
25
+ >
26
+ <itf-icon name="close" />
27
+ </itf-button>
28
+ </slot>
29
+ </div>
19
30
  <div style="display: none">
20
31
  <div ref="dropdown" class="itf-monthpicker__dropdown border rounded">
21
32
  <div>
@@ -42,10 +53,12 @@ import { DateTime } from 'luxon';
42
53
  import tippy from 'tippy.js';
43
54
  import itfIcon from '../icon/Icon';
44
55
  import itfDatePickerInline from './DatePickerInline.vue';
56
+ import itfButton from "@/components/button/Button.vue";
45
57
 
46
58
  export default @Component({
47
59
  name: 'itfMonthPicker',
48
60
  components: {
61
+ itfButton,
49
62
  itfIcon,
50
63
  itfDatePickerInline
51
64
  },
@@ -64,6 +77,8 @@ class itfMonthPicker extends Vue {
64
77
  @Prop({ type: String, default: '' }) prependIcon;
65
78
  @Prop({ type: String, default: 'bottom-start' }) placement;
66
79
 
80
+ @Prop(Boolean) clearable;
81
+
67
82
  focused = false;
68
83
 
69
84
  tooltip = null;
@@ -77,6 +77,8 @@ storiesOf('Common', module)
77
77
  <h2>Month</h2>
78
78
 
79
79
  <itf-month-picker :value="month" v-model.lazy="month"></itf-month-picker>
80
+ <br />
81
+ <itf-month-picker clearable :value="month" v-model.lazy="month"></itf-month-picker>
80
82
 
81
83
  <h2>Period</h2>
82
84
 
@@ -73,7 +73,7 @@ class itfModal extends Vue {
73
73
 
74
74
  @Watch('value')
75
75
  onVisibleChanged(newValue, oldValue) {
76
- if (!this.modalEl || this.preventEvents || (typeof oldValue === 'undefined' && !newValue)) {
76
+ if (!this.modalEl || (this.preventEvents && oldValue !== true) || (typeof oldValue === 'undefined' && !newValue)) {
77
77
  return;
78
78
  }
79
79
  if (newValue) {
@@ -114,6 +114,9 @@ interface IPanel {
114
114
  once: (eventName: string, func: (event: string, ...args: any[]) => any) => void;
115
115
  emit: (event: string, ...args: any[]) => void;
116
116
  isMultiple: () => boolean;
117
+ fullsize: () => void;
118
+ getPayload: () => any;
119
+ setPayload: (value: any) => void;
117
120
  __events: Record<string, ((event: string, ...args: any[]) => any)[]>;
118
121
  }
119
122
 
@@ -136,8 +139,9 @@ export default class PanelList extends Vue {
136
139
 
137
140
  created() {
138
141
  if (this.firstPanel) {
139
- this.openPanel(this.firstPanel.title, this.firstPanel.icon, this.firstPanel.type, this.firstPanel.payload);
142
+ this.internalOpenPanel(this.firstPanel.title, this.firstPanel.icon, this.firstPanel.type, this.firstPanel.payload);
140
143
  }
144
+ this.parsePanelHash();
141
145
  }
142
146
 
143
147
  get isOpenMultiple() {
@@ -181,8 +185,8 @@ export default class PanelList extends Vue {
181
185
  this.panelsStack = newStack;
182
186
  }
183
187
 
184
- openPanel(title: string, icon: string, type: string, payload: any, openIndex?: number) {
185
- const newPanel:IPanel = {
188
+ internalOpenPanel(title: string, icon: string, type: string, payload: any, openIndex?: number) {
189
+ const newPanel:any = {
186
190
  id: this.nextId++,
187
191
  title,
188
192
  icon,
@@ -190,7 +194,7 @@ export default class PanelList extends Vue {
190
194
  payload,
191
195
  isCollapsed: false,
192
196
  isCloseable: true,
193
- __events: {}
197
+ __events: {},
194
198
  };
195
199
  if (!this.panelsStack.length) {
196
200
  newPanel.isCloseable = false;
@@ -200,42 +204,51 @@ export default class PanelList extends Vue {
200
204
  newStack = newStack.slice(0, openIndex);
201
205
  }
202
206
  this.panelsStack = newStack;
203
- this.$nextTick(() => { // щоб панелі змінювались при редагуванні
204
- const n = newStack.length;
205
- newPanel.emit = (event, ...args) => this.emitEvent(event, ...args);
206
- newPanel.open = (type, visOptions, payload) => this.openPanel(visOptions.title, visOptions.icon, type, payload, n + 1);
207
- newPanel.close = () => this.closePanel(newPanel);
208
- newPanel.expand = () => this.expandPanel(newPanel);
209
- newPanel.on = (eventName, func: (event: string, ...args: any[]) => any) => {
210
- if (!newPanel.__events[eventName]) {
211
- newPanel.__events[eventName] = [];
212
- }
213
- newPanel.__events[eventName].push(func);
214
- };
215
- newPanel.off = (eventName, func: (event: string, ...args: any[]) => any) => {
216
- if (newPanel.__events[eventName]) {
217
- newPanel.__events[eventName] = newPanel.__events[eventName].filter(f => f !== func);
218
- }
219
- };
220
- newPanel.once = (eventName, func: (event: string, ...args: any[]) => any) => {
221
- const wrapper = (...args) => {
222
- func(...args);
223
- newPanel.off(eventName, wrapper);
207
+ return new Promise(res => {
208
+ this.$nextTick(() => { // щоб панелі змінювались при редагуванні
209
+ const n = newStack.length;
210
+ newPanel.emit = (event, ...args) => this.emitEvent(event, ...args);
211
+ newPanel.open = (type, visOptions, payload) => this.openPanel(visOptions.title, visOptions.icon, type, payload, n + 1);
212
+ newPanel.close = () => this.closePanel(newPanel);
213
+ newPanel.expand = () => this.expandPanel(newPanel);
214
+ newPanel.on = (eventName, func: (event: string, ...args: any[]) => any) => {
215
+ if (!newPanel.__events[eventName]) {
216
+ newPanel.__events[eventName] = [];
217
+ }
218
+ newPanel.__events[eventName].push(func);
224
219
  };
225
- newPanel.on(eventName, wrapper);
226
- };
227
- newPanel.isMultiple = () => this.isOpenMultiple;
228
- newPanel.getPayload = () => newPanel.payload;
229
- newPanel.setPayload = (value: any) => {
230
- console.info(value);
231
- newPanel.payload = value;
232
- }
233
- newStack.push(newPanel);
234
- this.panelsStack = newStack;
235
- this.ensureOnlyTwoOpenPanels(newPanel.id);
220
+ newPanel.off = (eventName, func: (event: string, ...args: any[]) => any) => {
221
+ if (newPanel.__events[eventName]) {
222
+ newPanel.__events[eventName] = newPanel.__events[eventName].filter(f => f !== func);
223
+ }
224
+ };
225
+ newPanel.once = (eventName, func: (event: string, ...args: any[]) => any) => {
226
+ const wrapper = (...args) => {
227
+ func(eventName, ...args);
228
+ newPanel.off(eventName, wrapper);
229
+ };
230
+ newPanel.on(eventName, wrapper);
231
+ };
232
+ newPanel.isMultiple = () => this.isOpenMultiple;
233
+ newPanel.fullsize = () => this.fullsizePanel(newPanel);
234
+ newPanel.getPayload = () => newPanel.payload;
235
+ newPanel.setPayload = (value: any) => {
236
+ newPanel.payload = value;
237
+ this.setPanelHash()
238
+ }
239
+ newStack.push(newPanel);
240
+ this.panelsStack = newStack;
241
+ this.ensureOnlyTwoOpenPanels(newPanel.id);
242
+ return res(newPanel);
243
+ })
236
244
  });
237
245
  }
238
246
 
247
+ async openPanel(title: string, icon: string, type: string, payload: any, openIndex?: number) {
248
+ await this.internalOpenPanel(title, icon, type, payload, openIndex);
249
+ this.setPanelHash()
250
+ }
251
+
239
252
  emitEvent(event: string, ...args: any[]) {
240
253
  for (const panel of this.panelsStack) {
241
254
  if (panel.__events[event]) {
@@ -258,6 +271,7 @@ export default class PanelList extends Vue {
258
271
  this.panelsStack[openPanelIndex - 1].isCollapsed = false;
259
272
  }
260
273
  this.ensureOnlyTwoOpenPanels(openPanel.id);
274
+ this.setPanelHash()
261
275
  }
262
276
 
263
277
  fullsizePanel(panel: IPanel) {
@@ -267,5 +281,28 @@ export default class PanelList extends Vue {
267
281
  }
268
282
  this.panelsStack = newStack;
269
283
  }
284
+
285
+ setPanelHash() {
286
+ const hash = this.panelsStack.map(panel => {
287
+ return `${panel.type}=${JSON.stringify(panel.payload || {})}`;
288
+ }).join('&');
289
+ this.$router.push({ hash });
290
+ }
291
+
292
+ async parsePanelHash() {
293
+ const hash = this.$route.hash;
294
+ if (hash) {
295
+ const panels = hash.slice(1).split('&').map(item => {
296
+ const [type, payload] = item.split('=');
297
+ return {
298
+ type,
299
+ payload: JSON.parse(decodeURIComponent(payload))
300
+ };
301
+ });
302
+ for (const panel of panels) {
303
+ await this.internalOpenPanel('', '', panel.type, panel.payload);
304
+ }
305
+ }
306
+ }
270
307
  }
271
308
  </script>
@@ -26,16 +26,18 @@
26
26
  <slot :name="name" v-bind="slotData || {}"/>
27
27
  </template>
28
28
  </itf-table-rows>
29
- <div v-if="!rows.length" data-test="table-no-results" class="table-view-item">
30
- <div class="table-row-template">
31
- <div accept-group="items" class="table-view-body-space"></div>
32
- <div class="shadow-area"></div>
33
- <div class="indicator sticky"></div>
34
- <div class="table-item-inner">
35
- <div class="table-view-item-value w-100 align-items-center p-3 no-results">
36
- {{$t('components.table.noResults')}}
29
+ <div v-if="!rows.length" data-test="table-no-results" class="scroller">
30
+ <div class="table-view-item">
31
+ <div class="table-row-template">
32
+ <div accept-group="items" class="table-view-body-space"></div>
33
+ <div class="shadow-area"></div>
34
+ <div class="indicator sticky"></div>
35
+ <div class="table-item-inner">
36
+ <div class="table-view-item-value w-100 align-items-center p-3 no-results">
37
+ {{$t('components.table.noResults')}}
38
+ </div>
39
+ <div class="boundary right"></div>
37
40
  </div>
38
- <div class="boundary right"></div>
39
41
  </div>
40
42
  </div>
41
43
  </div>
@@ -7,7 +7,7 @@
7
7
  </div-->
8
8
 
9
9
  <div data-test="table-group-wrapper" class="table-group-wrapper flex-grow-1 w-100 d-block"
10
- :style="`--row-count: ${isShowTable ? rows.length : 0}`" data-sticky-container>
10
+ :style="`--row-count: ${isShowTable ? rows.length : 0}`">
11
11
  <div data-test="table-group" class="position-relative">
12
12
  <div :class="stickyId" class="sticky-group">
13
13
  <div v-if="title" group="tablegroups" class="draggable-item"
@@ -22,7 +22,7 @@
22
22
  </span>
23
23
  <span class="d-flex align-items-center line-overflow group-header-value"
24
24
  data-test="group-value-group-label-value">
25
- <slot name="group-title" :rows="rows" :title="rows">{{ title }}</slot>
25
+ <slot name="group-title" :rows="rows" :title="title">{{ title }}</slot>
26
26
  </span>
27
27
  </a>
28
28
  </div>
@@ -132,13 +132,6 @@
132
132
  </template>
133
133
  <style lang="scss">
134
134
  .itf-table-group {
135
- --group-title-height: 40px;
136
- --table-row-height: 36px;
137
- --table-small-row-size: var(--table-row-height);
138
- --shadow-area-width: 12px;
139
- --indicator-area-width: 38px;
140
- --hover-bg: var(--bs-tertiary-bg);
141
-
142
135
  flex-direction: column;
143
136
  min-width: 100%;
144
137
  display: flex;
@@ -268,6 +261,11 @@
268
261
  }
269
262
  }
270
263
 
264
+ .sticky-group {
265
+ position: sticky;
266
+ top: 0;
267
+ z-index: 10;
268
+ }
271
269
  .table-summary {
272
270
  .shadow-area {
273
271
  border-right: 0;
@@ -1,4 +1,7 @@
1
- .itf-table2 {
1
+ :root {
2
+ --itf-table-border-color: #e1e1e1;
3
+ --itf-table-header-bg: #f8f8f8;
4
+ --itf-table-selected-bg: #f0f0f0;
2
5
  --itf-table-border-color: #dbddd1;
3
6
  --itf-table-header-bg: #f9faf5;
4
7
  --itf-table-hover-header-bg: var(--bs-tertiary-bg);
@@ -11,17 +14,24 @@
11
14
  --itf-table-header-subtitle-color: #aeafaa;
12
15
  --itf-table-summary-text: var(--bs-tertiary-color);
13
16
 
14
- // dark
15
- body[data-theme="dark"] & {
16
- --itf-table-hover-bg: #393b41;
17
- --itf-table-header-bg: #0f0f0f;
18
- --itf-table-hover-header-bg: #252525;
19
- --itf-table-border-color: var(--bs-card-border-color);
20
- --itf-table-input-focus-border-color: #252525;
21
- --itf-table-selected-bg: #011534;
22
- --itf-table-summary-text: #82909d80;
23
- }
24
-
17
+ --group-title-height: 40px;
18
+ --table-row-height: 36px;
19
+ --table-small-row-size: var(--table-row-height);
20
+ --shadow-area-width: 12px;
21
+ --indicator-area-width: 38px;
22
+ --hover-bg: var(--bs-tertiary-bg);
23
+ }
24
+ // dark
25
+ body[data-theme="dark"] {
26
+ --itf-table-hover-bg: #393b41;
27
+ --itf-table-header-bg: #0f0f0f;
28
+ --itf-table-hover-header-bg: #252525;
29
+ --itf-table-border-color: var(--bs-card-border-color);
30
+ --itf-table-input-focus-border-color: #252525;
31
+ --itf-table-selected-bg: #011534;
32
+ --itf-table-summary-text: #82909d80;
33
+ }
34
+ .itf-table2 {
25
35
  &.scrollable {
26
36
  -webkit-overflow-scrolling: touch;
27
37
  overflow: hidden scroll;
@@ -42,24 +42,24 @@ describe('Validators', () => {
42
42
  expect(dateBeforeValidation()(null, $t)).toEqual(true);
43
43
  expect(dateBeforeValidation()(undefined, $t)).toEqual(true);
44
44
  expect(dateBeforeValidation('2020-01-02')('2020-01-01', $t)).toEqual(true);
45
- expect(dateBeforeValidation('2020-01-01')('2020-01-02', $t)).toEqual('validators.dateBefore');
46
- expect(dateBeforeValidation('2020-01-01')('2020-01-01', $t)).toEqual('validators.dateBefore');
45
+ expect(dateBeforeValidation('2020-01-01')('2020-01-02', $t)).toEqual('components.dateBefore');
46
+ expect(dateBeforeValidation('2020-01-01')('2020-01-01', $t)).toEqual('components.dateBefore');
47
47
  });
48
48
 
49
49
  test('dateAfterValidation', () => {
50
50
  expect(dateAfterValidation()(0, $t)).toEqual(true);
51
51
  expect(dateAfterValidation()(null, $t)).toEqual(true);
52
52
  expect(dateAfterValidation()(undefined, $t)).toEqual(true);
53
- expect(dateAfterValidation('2020-01-02')('2020-01-01', $t)).toEqual('validators.dateAfter');
53
+ expect(dateAfterValidation('2020-01-02')('2020-01-01', $t)).toEqual('components.dateAfter');
54
54
  expect(dateAfterValidation('2020-01-01')('2020-01-02', $t)).toEqual(true);
55
- expect(dateAfterValidation('2020-01-01')('2020-01-01', $t)).toEqual('validators.dateAfter');
55
+ expect(dateAfterValidation('2020-01-01')('2020-01-01', $t)).toEqual('components.dateAfter');
56
56
  });
57
57
 
58
58
  test('dateSameOrAfterValidation', () => {
59
59
  expect(dateSameOrAfterValidation()(0, $t)).toEqual(true);
60
60
  expect(dateSameOrAfterValidation()(null, $t)).toEqual(true);
61
61
  expect(dateSameOrAfterValidation()(undefined, $t)).toEqual(true);
62
- expect(dateSameOrAfterValidation('2020-01-02')('2020-01-01', $t)).toEqual('validators.dateSameOrAfter');
62
+ expect(dateSameOrAfterValidation('2020-01-02')('2020-01-01', $t)).toEqual('components.dateSameOrAfter');
63
63
  expect(dateSameOrAfterValidation('2020-01-01')('2020-01-02', $t)).toEqual(true);
64
64
  expect(dateSameOrAfterValidation('2020-01-01')('2020-01-01', $t)).toEqual(true);
65
65
  });
@@ -69,7 +69,7 @@ describe('Validators', () => {
69
69
  expect(dateSameOrBeforeValidation()(null, $t)).toEqual(true);
70
70
  expect(dateSameOrBeforeValidation()(undefined, $t)).toEqual(true);
71
71
  expect(dateSameOrBeforeValidation('2020-01-02')('2020-01-01', $t)).toEqual(true);
72
- expect(dateSameOrBeforeValidation('2020-01-01')('2020-01-02', $t)).toEqual('validators.dateSameOrBefore');
72
+ expect(dateSameOrBeforeValidation('2020-01-01')('2020-01-02', $t)).toEqual('components.dateSameOrBefore');
73
73
  expect(dateSameOrBeforeValidation('2020-01-01')('2020-01-01', $t)).toEqual(true);
74
74
  });
75
75