@itfin/components 2.0.7 → 2.0.9

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.
Files changed (36) hide show
  1. package/package.json +1 -1
  2. package/src/assets/scss/_css_variables.scss +0 -5
  3. package/src/assets/scss/_variables.scss +7 -5
  4. package/src/components/button/Button.vue +1 -1
  5. package/src/components/filter/FilterPanel.vue +15 -3
  6. package/src/components/icon/components/nomi-ai.vue +6 -0
  7. package/src/components/icon/components/nomi-expand.vue +7 -0
  8. package/src/components/icon/components/nomi-eye.vue +4 -0
  9. package/src/components/icon/components/nomi-help.vue +5 -0
  10. package/src/components/icon/components/nomi-logout.vue +5 -0
  11. package/src/components/icon/components/nomi-settings.vue +4 -0
  12. package/src/components/icon/icons.js +302 -296
  13. package/src/components/icon/new-icons/ai.svg +5 -0
  14. package/src/components/icon/new-icons/expand.svg +6 -0
  15. package/src/components/icon/new-icons/eye.svg +3 -0
  16. package/src/components/icon/new-icons/help.svg +4 -0
  17. package/src/components/icon/new-icons/logout.svg +4 -0
  18. package/src/components/icon/new-icons/settings.svg +3 -0
  19. package/src/components/pagination/Pagination2.vue +5 -1
  20. package/src/components/panels/Panel.vue +6 -5
  21. package/src/components/panels/PanelLink.vue +26 -6
  22. package/src/components/panels/PanelList.vue +15 -25
  23. package/src/components/panels/helpers.spec.ts +27 -0
  24. package/src/components/panels/helpers.ts +37 -0
  25. package/src/components/table/Table2.vue +5 -1
  26. package/src/components/table/TableBody.vue +3 -16
  27. package/src/components/table/TableGroup.vue +5 -2
  28. package/src/components/table/TableHeader.vue +20 -8
  29. package/src/components/table/TableRowToggle.vue +50 -0
  30. package/src/components/table/TableRows.vue +13 -24
  31. package/src/components/table/table2.scss +13 -4
  32. package/src/components/tree/TreeEditor.vue +2 -3
  33. package/src/components/view/View.vue +42 -4
  34. package/src/helpers/tree.js +3 -3
  35. package/src/locales/en.js +1 -0
  36. package/src/locales/uk.js +3 -0
@@ -0,0 +1,5 @@
1
+ <svg width="16" height="16" viewBox="4 4 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M10.8461 13.8066C9.51242 12.9683 7.88973 13.5198 6.33372 14.1816L5 11.0711C5.02223 11.0711 5.06669 11.0491 5.08892 11.027C6.55601 10.4093 10.3571 8.79892 13.5136 11.5785C13.6247 11.6668 13.7136 11.755 13.8248 11.8653C14.9585 11.4461 16.2255 11.3138 17.6037 11.6006C20.1155 12.108 21.8938 14.0272 22.6273 16.6083C23.3387 19.1452 23.0497 22.366 21.6048 25.9397L18.4484 24.6823C19.6932 21.5718 19.8043 19.1452 19.3375 17.5127C18.8929 15.9244 17.9593 15.1302 16.9146 14.9096C16.5367 14.8434 16.181 14.8214 15.8031 14.8655C16.5589 16.6965 16.7812 18.704 16.5811 20.4247C16.4255 21.8807 15.9365 23.3808 15.0251 24.4617C14.0248 25.6309 12.5133 26.2927 10.7572 25.8736C8.68996 25.3882 7.75636 23.7337 7.53407 22.0792C7.33401 20.4909 7.75636 18.704 8.4899 17.1156C9.02339 15.9685 9.82362 14.7772 10.8461 13.7845V13.8066ZM12.8245 16.6303C12.3577 17.1818 11.9354 17.8216 11.5797 18.5716C11.024 19.7629 10.8239 20.91 10.9128 21.6821C11.0017 22.388 11.2463 22.5425 11.513 22.6086C11.8909 22.6969 12.1354 22.6086 12.4022 22.2998C12.7356 21.9027 13.069 21.1527 13.1802 20.0717C13.3135 18.9466 13.1802 17.7333 12.8023 16.6303H12.8245Z" fill="currentColor"/>
3
+ <path d="M20.6582 5.7567C20.7911 5.4625 21.2089 5.4625 21.3418 5.7567L21.5835 6.29203C21.809 6.79121 22.2088 7.19101 22.708 7.41646L23.2433 7.65824C23.5375 7.79111 23.5375 8.20889 23.2433 8.34176L22.708 8.58354C22.2088 8.80899 21.809 9.20879 21.5835 9.70797L21.3418 10.2433C21.2089 10.5375 20.7911 10.5375 20.6582 10.2433L20.4165 9.70797C20.191 9.20879 19.7912 8.80899 19.292 8.58354L18.7567 8.34176C18.4625 8.20889 18.4625 7.79111 18.7567 7.65824L19.292 7.41646C19.7912 7.19101 20.191 6.79121 20.4165 6.29203L20.6582 5.7567Z" fill="currentColor"/>
4
+ <path d="M24.7722 11.5045C24.8607 11.3083 25.1393 11.3083 25.2278 11.5045L25.389 11.8614C25.5393 12.1941 25.8059 12.4607 26.1386 12.611L26.4955 12.7722C26.6917 12.8607 26.6917 13.1393 26.4955 13.2278L26.1386 13.389C25.8059 13.5393 25.5393 13.8059 25.389 14.1386L25.2278 14.4955C25.1393 14.6917 24.8607 14.6917 24.7722 14.4955L24.611 14.1386C24.4607 13.8059 24.1941 13.5393 23.8614 13.389L23.5045 13.2278C23.3083 13.1393 23.3083 12.8607 23.5045 12.7722L23.8614 12.611C24.1941 12.4607 24.4607 12.1941 24.611 11.8614L24.7722 11.5045Z" fill="currentColor"/>
5
+ </svg>
@@ -0,0 +1,6 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M19 10V5.3C19 5.13431 18.8657 5 18.7 5H14" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
3
+ <path d="M5 14V18.7C5 18.8657 5.13431 19 5.3 19H10" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
4
+ <path d="M5.5 18.5L9.5 14.5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
5
+ <path d="M14.5 9.5L18.5 5.5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
6
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M5.08422 11.626C4.97192 11.8628 4.97193 12.1375 5.08423 12.3743C6.303 14.9438 8.94045 16.7231 11.9977 16.7231C15.055 16.7231 17.6925 14.9437 18.9112 12.3741C19.0235 12.1373 19.0235 11.8625 18.9112 11.6258C17.6924 9.0562 15.055 7.27698 11.9978 7.27698C8.94046 7.27698 6.30294 9.05631 5.08422 11.626ZM15 12C15 13.6569 13.6569 15 12 15C10.3432 15 9.00003 13.6569 9.00003 12C9.00003 10.3432 10.3432 9.00002 12 9.00002C12.3075 9.00002 12.6042 9.04627 12.8834 9.1322C12.3625 9.36738 12 9.89137 12 10.5C12 11.3284 12.6716 12 13.5 12C14.1087 12 14.6327 11.6375 14.8678 11.1166C14.9538 11.3959 15 11.6926 15 12Z" fill="currentColor"/>
3
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-info-circle" viewBox="0 0 16 16">
2
+ <path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16"/>
3
+ <path d="m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0"/>
4
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-door-closed" viewBox="0 0 16 16">
2
+ <path d="M3 2a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v13h1.5a.5.5 0 0 1 0 1h-13a.5.5 0 0 1 0-1H3zm1 13h8V2H4z"/>
3
+ <path d="M9 9a1 1 0 1 0 2 0 1 1 0 0 0-2 0"/>
4
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
2
+ <path d="M8.932.727c-.243-.97-1.62-.97-1.864 0l-.071.286a.96.96 0 0 1-1.622.434l-.205-.211c-.695-.719-1.888-.03-1.613.931l.08.284a.96.96 0 0 1-1.186 1.187l-.284-.081c-.96-.275-1.65.918-.931 1.613l.211.205a.96.96 0 0 1-.434 1.622l-.286.071c-.97.243-.97 1.62 0 1.864l.286.071a.96.96 0 0 1 .434 1.622l-.211.205c-.719.695-.03 1.888.931 1.613l.284-.08a.96.96 0 0 1 1.187 1.187l-.081.283c-.275.96.918 1.65 1.613.931l.205-.211a.96.96 0 0 1 1.622.434l.071.286c.243.97 1.62.97 1.864 0l.071-.286a.96.96 0 0 1 1.622-.434l.205.211c.695.719 1.888.03 1.613-.931l-.08-.284a.96.96 0 0 1 1.187-1.187l.283.081c.96.275 1.65-.918.931-1.613l-.211-.205a.96.96 0 0 1 .434-1.622l.286-.071c.97-.243.97-1.62 0-1.864l-.286-.071a.96.96 0 0 1-.434-1.622l.211-.205c.719-.695.03-1.888-.931-1.613l-.284.08a.96.96 0 0 1-1.187-1.186l.081-.284c.275-.96-.918-1.65-1.613-.931l-.205.211a.96.96 0 0 1-1.622-.434zM8 12.997a4.998 4.998 0 1 1 0-9.995 4.998 4.998 0 0 1 0 9.996z"/>
3
+ </svg>
@@ -16,7 +16,7 @@
16
16
 
17
17
  <div v-if="page.type === 'page'" class="d-flex flex-nowrap text-nowrap align-items-center gap-1 text-muted">
18
18
  <itf-text-field :invalid="!isValid" type="number" small :min="1" :max="9999" :value="value" @change="onPageChange" />
19
- / {{pages}}
19
+ / {{pagesCount}}
20
20
  </div>
21
21
  <a v-if="page.type === 'next'" href="" class="page-link" :aria-label="$t('components.pagination.previous')" @click.prevent="onPage(page.number)">
22
22
  <span class="visually-hidden">{{$t('components.pagination.next')}}</span>
@@ -93,6 +93,10 @@ class itfPagination extends Vue {
93
93
 
94
94
  isValid = true;
95
95
 
96
+ get pagesCount() {
97
+ return this.pages || 1;
98
+ }
99
+
96
100
  onPage(page) {
97
101
  this.$emit('input', page);
98
102
  }
@@ -14,16 +14,16 @@
14
14
  <slot name="header">
15
15
  <div>
16
16
  <slot name="title">
17
- <div class="b-panel__title ps-1 fw-bold h2" v-text="title"></div>
17
+ <div class="b-panel__title fw-bold h2" v-text="title"></div>
18
18
  </slot>
19
19
  </div>
20
20
  <div class="d-flex gap-1">
21
21
  <slot name="buttons"></slot>
22
- <itf-button v-if="expandable" icon small class="b-panel__expand_button" @click="fullsizePanel">
23
- <itf-icon name="expand" />
22
+ <itf-button v-if="expandable" icon default class="b-panel__expand_button" @click="fullsizePanel">
23
+ <itf-icon new name="expand" />
24
24
  </itf-button>
25
- <itf-button v-if="closeable" icon small class="b-panel__expand_button" @click="closePanel">
26
- <itf-icon name="cross" />
25
+ <itf-button v-if="closeable" icon default class="b-panel__expand_button" @click="closePanel">
26
+ <itf-icon new name="close" />
27
27
  </itf-button>
28
28
  </div>
29
29
  </slot>
@@ -140,6 +140,7 @@ class Panel extends Vue {
140
140
  @Prop() title;
141
141
  @Prop() icon;
142
142
  @Prop() payload;
143
+ @Prop() panel;
143
144
  @Prop(Boolean) collapsed;
144
145
  @Prop(Boolean) closeable;
145
146
  @Prop(Boolean) expandable;
@@ -1,9 +1,10 @@
1
1
  <template>
2
- <a :href="link" :target="target" v-on="on"><slot></slot></a>
2
+ <a :href="link" :target="target" v-on="on" :class="{[activeClass]: isActive}"><slot></slot></a>
3
3
  </template>
4
4
  <script lang="ts">
5
5
  import { Vue, Component, Inject, Prop } from 'vue-property-decorator';
6
6
  import { IPanel } from './PanelList.vue';
7
+ import {stackToHash} from "@itfin/components/src/components/panels/helpers";
7
8
 
8
9
  @Component({
9
10
  components: {
@@ -17,9 +18,12 @@ export default class PanelLink extends Vue {
17
18
  @Inject({ default: null }) panelList;
18
19
  @Inject({ default: null }) currentPanel;
19
20
 
21
+ @Prop(Boolean) global: boolean;
20
22
  @Prop(String) panel: string;
21
23
  @Prop() payload: payload;
22
24
  @Prop() target: string;
25
+ @Prop() list;
26
+ @Prop({ type: String, default: 'active' }) activeClass: string;
23
27
  @Prop(Boolean) append: boolean;
24
28
 
25
29
  get on() {
@@ -30,25 +34,41 @@ export default class PanelLink extends Vue {
30
34
  return handlers;
31
35
  }
32
36
 
37
+ get activeList() {
38
+ return this.list ?? this.panelList;
39
+ }
40
+
41
+ get isActive() {
42
+ if (!this.activeList) {
43
+ return false;
44
+ }
45
+ let stack = this.activeList.getCurrentStack();
46
+ return stack.find(s => s.type === this.panel);
47
+ }
48
+
33
49
  get link() {
34
- let stack = this.panelList.getCurrentStack();
50
+ let stack = this.activeList?.getCurrentStack() ?? [];
35
51
  if (!this.append) {
36
- stack = stack.splice(0, this.currentPanel.index + 1);
52
+ stack = stack.splice(0, this.currentPanel?.index + 1);
37
53
  }
38
- const hash = this.panelList.getLink([
54
+ const hash = stackToHash([
39
55
  ...stack,
40
56
  {
41
57
  type: this.panel,
42
58
  payload: this.payload || {}
43
59
  }
44
60
  ]);
45
- return `#${hash}`;
61
+ return hash;
46
62
  }
47
63
 
48
64
  onClick(e) {
65
+ console.info(this.activeList);
66
+ if (!this.activeList) {
67
+ return;
68
+ }
49
69
  e.preventDefault();
50
70
  e.stopPropagation();
51
- this.panelList.openPanel(this.panel, this.payload || {}, this.append ? undefined : this.currentPanel.index + 1);
71
+ this.activeList.openPanel(this.panel, this.payload || {}, this.append ? undefined : this.currentPanel?.index + 1);
52
72
  }
53
73
  }
54
74
  </script>
@@ -11,6 +11,7 @@
11
11
  <panel
12
12
  :key="n"
13
13
  :index="n"
14
+ :panel="panel"
14
15
  :title="panel.title"
15
16
  :nocard="panel.nocard"
16
17
  :icon="panel.icon"
@@ -133,21 +134,22 @@ $double-an-time: $an-time * 2;
133
134
  transition: min-width $an-time linear, flex-grow $an-time linear;
134
135
 
135
136
  > div {
136
- transition: opacity $an-time linear;
137
+ //transition: opacity $an-time linear;
137
138
  }
138
139
  }
139
140
 
140
- .slide-enter-active > div {
141
- opacity: 0;
142
- }
143
-
144
- .opacity-null > div {
145
- opacity: 0 !important;
146
- }
141
+ //.slide-enter-active > div {
142
+ // opacity: 0;
143
+ //}
144
+ //
145
+ //.opacity-null > div {
146
+ // opacity: 0 !important;
147
+ //}
147
148
  </style>
148
149
  <script lang="ts">
149
150
  import { Vue, Component, Prop } from 'vue-property-decorator';
150
151
  import Panel from './Panel.vue';
152
+ import {hashToStack, stackToHash} from "@itfin/components/src/components/panels/helpers";
151
153
 
152
154
  interface VisualOptions {
153
155
  title: string;
@@ -199,7 +201,6 @@ export default class PanelList extends Vue {
199
201
 
200
202
  nextId:number = 0;
201
203
 
202
-
203
204
  created() {
204
205
  if (this.firstPanel) {
205
206
  this.internalOpenPanel(this.firstPanel.type, this.firstPanel.payload);
@@ -275,6 +276,8 @@ export default class PanelList extends Vue {
275
276
  if (!this.panelsStack.length || openIndex === 0) {
276
277
  newPanel.isCloseable = false;
277
278
  }
279
+ console.info(newPanel, this.panelsStack)
280
+ console.trace();
278
281
  let newStack = [...this.panelsStack];
279
282
  if (this.panels[type].permanentExpanded && newStack.length) {
280
283
  for (const panel of newStack) {
@@ -388,30 +391,17 @@ export default class PanelList extends Vue {
388
391
  return [...this.panelsStack];
389
392
  }
390
393
 
391
- getLink(stack: IPanel[]) {
392
- return stack.map(panel => {
393
- return `${panel.type}${panel.isCollapsed ? '' : '!'}=${JSON.stringify(panel.payload || {})}`;
394
- }).join('&');
395
- }
396
-
397
394
  setPanelHash() {
398
- const hash = this.getLink(this.panelsStack);
395
+ const hash = stackToHash(this.panelsStack).replace(/^#/, '');
399
396
  this.$router.push({ hash });
400
397
  }
401
398
 
402
399
  async parsePanelHash() {
403
400
  const {hash} = location;
404
401
  if (hash) {
405
- const panels = hash.slice(1).split('&').map(item => {
406
- const [type, payload] = item.split('=');
407
- const isCollapsed = !item.includes('!');
408
- return {
409
- type: type.replace('!', ''),
410
- isCollapsed,
411
- payload: JSON.parse(decodeURIComponent(payload))
412
- };
413
- });
402
+ const panels = hashToStack(hash);
414
403
  const newStack = [];
404
+ this.panelsStack = [];
415
405
  for (const panelIndex in panels) {
416
406
  const panel = panels[panelIndex];
417
407
  if (this.panelsStack[panelIndex] && this.panelsStack[panelIndex].type === panel.type) {
@@ -0,0 +1,27 @@
1
+ import {stackToHash, hashToStack} from "./helpers";
2
+
3
+ describe('panel helpers', () => {
4
+ test('stackToHash', () => {
5
+ const stack = [
6
+ { type: 'a', payload: { a: 1 }, isCollapsed: false },
7
+ { type: 'b', payload: { b: 2 }, isCollapsed: true },
8
+ { type: 'c', payload: { c: 3 }, isCollapsed: false }
9
+ ];
10
+ expect(stackToHash(stack)).toBe('a!={"a":1}&b={"b":2}&c!={"c":3}');
11
+ });
12
+ test('hashToStack', () => {
13
+ const stack = [
14
+ { type: 'a', payload: { a: 1 }, isCollapsed: false },
15
+ { type: 'b', payload: { b: 2 }, isCollapsed: true },
16
+ { type: 'c', payload: { c: 3 }, isCollapsed: false }
17
+ ];
18
+ expect(hashToStack('a!={"a":1}&b={"b":2}&c!={"c":3}')).toEqual(stack);
19
+ expect(hashToStack('a!={"a')).toEqual([
20
+ {
21
+ "isCollapsed": false,
22
+ "payload": {},
23
+ "type": "a"
24
+ }
25
+ ]);
26
+ });
27
+ });
@@ -0,0 +1,37 @@
1
+ export interface IPanel {
2
+ type: string;
3
+ payload?: any;
4
+ isCollapsed?: boolean;
5
+ }
6
+
7
+ export function stackToHash(stack: IPanel[]) {
8
+ const hash = stack.map(panel => {
9
+ return `${panel.type}${panel.isCollapsed ? '' : '!'}=${JSON.stringify(panel.payload || {})}`;
10
+ }).join('&');
11
+ return `#${hash}`;
12
+ }
13
+
14
+
15
+ export function hashToStack(hash: string|undefined): IPanel[] {
16
+ let stack:IPanel[] = [];
17
+ if (hash) {
18
+ const str = hash.replace(/^#/, '');
19
+
20
+ stack = str.split('&').map(item => {
21
+ const [type, payload] = item.split('=');
22
+ const isCollapsed = !type.includes('!');
23
+ let payloadObj:any = {};
24
+ try {
25
+ payloadObj = JSON.parse(decodeURIComponent(payload));
26
+ } catch (e) {
27
+ // ignore
28
+ }
29
+ return {
30
+ type: type.replace('!', ''),
31
+ isCollapsed,
32
+ payload: payloadObj
33
+ };
34
+ });
35
+ }
36
+ return stack;
37
+ }
@@ -5,7 +5,7 @@
5
5
  'table-absolute': absolute,
6
6
  'table-clickable': clickable,
7
7
  'permanent-checkboxes': selectedIds.length
8
- }" :style="{ '--indicator-area-width': `${indicatorType === 'none' ? 1 : indicatorWidth}px` }">
8
+ }" :style="{ '--indicator-area-width': `${indicatorType === 'none' ? 1 : indicatorWidth}px`, '--shadow-area-width': `${shadowWidth}px` }">
9
9
  <itf-notice-popout :visible="showGroupOperations" class="rounded-pill bg-dark text-light">
10
10
  <div class="d-flex gap-3 px-3 align-items-center">
11
11
  <div><strong>{{selectedIds.length}}</strong> selected</div>
@@ -29,6 +29,7 @@
29
29
  :title="group.name"
30
30
  :selected-ids.sync="selectedIds"
31
31
  :add-new-rows="addNewRows"
32
+ :shadow-width="shadowWidth"
32
33
  :column-sorting="columnSorting"
33
34
  :column-resizing="columnResizing"
34
35
  :show-grouping="showGrouping"
@@ -43,6 +44,7 @@
43
44
  :currencies="currencies"
44
45
  :currency="currency"
45
46
  :subrows-property="subrowsProperty"
47
+ :divider-property="dividerProperty"
46
48
  :indicator-type="indicatorType"
47
49
  :expanded-all="expandedAll"
48
50
  :indicatorWidth="indicatorWidth"
@@ -103,9 +105,11 @@ class itfTable2 extends Vue {
103
105
  @Prop({ type: String, default: null }) idProperty;
104
106
  @Prop({ type: String, default: null }) cssProperty;
105
107
  @Prop({ type: String, default: null }) subrowsProperty;
108
+ @Prop({ type: String, default: null }) dividerProperty;
106
109
  @Prop({ type: String, default: null }) editableProperty;
107
110
  @Prop({ default: null }) active;
108
111
  @Prop({ default: 45 }) indicatorWidth;
112
+ @Prop({ default: 0 }) shadowWidth;
109
113
  @Prop({ type: String, default: null, validator: (val) => ['order', 'checkbox', 'toggle', 'property', 'none'].includes(val) }) indicatorType;
110
114
  @Prop({ type: String, default: null }) stateName; // save state to storage
111
115
  @Prop({ type: Object, default: () => ({}) }) schema;
@@ -7,6 +7,7 @@
7
7
  :columns="columns"
8
8
  :id-property="idProperty"
9
9
  :subrows-property="subrowsProperty"
10
+ :divider-property="dividerProperty"
10
11
  :show-add-column="showAddColumn"
11
12
  :show-actions="showActions"
12
13
  :no-select-all="noSelectAll"
@@ -91,7 +92,7 @@
91
92
  display: flex;
92
93
  align-items: center;
93
94
  justify-content: center;
94
- min-width: var(--itf-table-min-width);
95
+ min-width: 1rem;//var(--itf-table-min-width);
95
96
  }
96
97
 
97
98
  .table-row-template, .table-view-header-value {
@@ -109,21 +110,6 @@
109
110
  }
110
111
  }
111
112
  }
112
- .table-row-template {
113
- .on-hover {
114
- display: none;
115
- }
116
- &:hover, .permanent-checkboxes & {
117
- .on-rest {
118
- display: none;
119
- }
120
-
121
- .on-hover {
122
- opacity: 1;
123
- display: block;
124
- }
125
- }
126
- }
127
113
 
128
114
  .table-small-row .table-view-item {
129
115
  // height: var(--table-row-height);
@@ -158,6 +144,7 @@ class itfTableBody extends Vue {
158
144
  @Prop() rows;
159
145
  @Prop() idProperty;
160
146
  @Prop() subrowsProperty;
147
+ @Prop() dividerProperty;
161
148
  @Prop() active;
162
149
  @Prop(Boolean) showAddColumn;
163
150
  @Prop(Boolean) showActions;
@@ -61,6 +61,7 @@
61
61
  @row-click="$emit('row-click', $event)"
62
62
  :id-property="idProperty"
63
63
  :subrows-property="subrowsProperty"
64
+ :divider-property="dividerProperty"
64
65
  :rows="rows"
65
66
  :editable="editable"
66
67
  :currency="currency"
@@ -112,7 +113,7 @@
112
113
  :key="n"
113
114
  :data-column="n"
114
115
  class="position-relative line-overflow px-1"
115
- :style="column.grow ? `min-width: ${column.minWidth}px; flex-grow: 1;` : `width: ${column.width}px; max-width: ${column.width}px;`">
116
+ :style="`width: ${column.width}px; max-width: ${column.width}px;`">
116
117
  <itf-dropdown append-to-context text right @open="persistSummary = true" @close="persistSummary = false" autoclose="outside">
117
118
  <template #button>
118
119
  <span data-test="summary-column" class="invisible-summary d-flex align-items-center justify-content-end flex-auto">
@@ -358,6 +359,7 @@ class itfTableGroup extends Vue {
358
359
  @Prop() title;
359
360
  @Prop() idProperty;
360
361
  @Prop() subrowsProperty;
362
+ @Prop() dividerProperty;
361
363
  @Prop() currency;
362
364
  @Prop() currencies;
363
365
  @Prop() active;
@@ -377,6 +379,7 @@ class itfTableGroup extends Vue {
377
379
  @Prop(Boolean) striped;
378
380
  @Prop(Boolean) stickyHeader;
379
381
  @Prop() indicatorWidth;
382
+ @Prop() shadowWidth;
380
383
  @Prop() cssProperty;
381
384
  @PropSync('sorting') _sorting;
382
385
  @Prop({ type: String, default: null }) indicatorType;
@@ -390,7 +393,7 @@ class itfTableGroup extends Vue {
390
393
  get visibleColumns() {
391
394
  let list = this.columns;
392
395
  list = sortBy(list, (column) => column.index);
393
- let left = 12 + (this.indicatorType === 'none' ? 1 : Number(this.indicatorWidth)); // sum of first 2 cells
396
+ let left = Number(this.shadowWidth) + (this.indicatorType === 'none' ? 1 : Math.max(Number(this.indicatorWidth), 16)); // sum of first 2 cells
394
397
  const pinned = list.filter((column) => column.pinned && column.visible !== false);
395
398
  list = list.map((column, index) => {
396
399
  const item = {...column};
@@ -15,9 +15,9 @@
15
15
  data-test="table-header-column"
16
16
  :data-column="n"
17
17
  :data-id="column.Id"
18
- :class="{'sticky': column.pinned, 'active': sortColumnParams[column.property], 'last-sticky-column': n === lastPinnedIndex, 'flex-grow-1': column.grow, [`justify-content-${column.align || 'start'}`]: true}"
18
+ :class="{'sticky': column.pinned, 'active': sortColumnParams[column.property], 'last-sticky-column': n === lastPinnedIndex, [`justify-content-${column.align || 'start'}`]: true}"
19
19
  class="table-view-header-value"
20
- :style="column.grow ? `left: ${column.left}px; flex-grow: 1` : `width: ${column.width}px; max-width: ${column.width}px; left: ${column.left}px;`">
20
+ :style="`width: ${column.width}px; max-width: ${column.width}px; left: ${column.left}px;`">
21
21
  <!-- Не треба видаляти колонки, бо вони потрібні для збереження ширини -->
22
22
  <div v-if="visibleHeader" accept-group="tablecolumns"
23
23
  class="table-view-header-space"
@@ -32,9 +32,9 @@
32
32
  v-draggable="{ handle: true, payload: { index: n, item: column }, mirror: {yAxis:false} }">
33
33
  <itf-dropdown text append-to-body shadow ref="dropdown" class="w-100" :disabled="noColumnMenu">
34
34
  <template #button>
35
- <div class="itf-table2__header-title d-flex w-100 align-items-start" :title="getTitle(column.title)" :class="{'ms-auto': column.align === 'end'}">
35
+ <div class="itf-table2__header-title d-flex w-100 align-items-center" :title="getTitle(column.title)">
36
36
  <itf-icon class="itf-table2__header-icon" new v-if="column.icon" :name="column.icon"></itf-icon>
37
- <div class="flex-grow-1 w-100 itf-table2__title-container">
37
+ <div class="flex-grow-1 w-100 itf-table2__title-container d-flex align-items-center" :class="{'justify-content-end': column.align === 'end'}">
38
38
  <div class="itf-table2__title text-truncate">{{getTitle(column.title)}}</div>
39
39
  <div v-if="column.prefix" class="itf-table2__subtitle text-truncate" v-text="column.prefix" />
40
40
  </div>
@@ -139,7 +139,7 @@
139
139
  v-dropzone="{payload:{ last: true }}">
140
140
  <div class="table-view-header-dropzone"></div>
141
141
  </div>
142
- <div v-if="visibleHeader && columnResizing && !column.grow" ref="resizeHandle" class="resize-handle"></div>
142
+ <div v-if="visibleHeader && columnResizing" ref="resizeHandle" class="resize-handle"></div>
143
143
  </div>
144
144
  </template>
145
145
  <div class="table-view-item-value extra flex-grow-1"></div>
@@ -341,15 +341,27 @@ class itfTableHeader extends Vue {
341
341
  const delta = event.pageX - startX;
342
342
  newWidth = Math.max(columnWidth + delta, 50);
343
343
  columns.forEach((column) => {
344
- if (!this.sortedColumns[index].grow) {
345
- column.style.width = `${newWidth}px`;
346
- column.style['max-width'] = `${newWidth}px`;
344
+ const { maxWidth, minWidth } = this.sortedColumns[index];
345
+ if (minWidth && newWidth < minWidth) {
346
+ newWidth = minWidth;
347
347
  }
348
+ if (maxWidth && newWidth > maxWidth) {
349
+ newWidth = maxWidth;
350
+ }
351
+ column.style.width = `${newWidth}px`;
352
+ column.style['max-width'] = `${newWidth}px`;
348
353
  });
349
354
  };
350
355
  const mouseUpHandler = () => {
351
356
  document.removeEventListener('mousemove', mouseMoveHandler);
352
357
  document.removeEventListener('mouseup', mouseUpHandler);
358
+ const { minWidth, maxWidth } = this.sortedColumns[index];
359
+ if (minWidth && newWidth < minWidth) {
360
+ newWidth = minWidth;
361
+ }
362
+ if (maxWidth && newWidth > maxWidth) {
363
+ newWidth = maxWidth;
364
+ }
353
365
  this.changeColumn(index, { width: newWidth });
354
366
  };
355
367
  document.addEventListener('mousemove', mouseMoveHandler);
@@ -0,0 +1,50 @@
1
+ <template>
2
+ <div>
3
+ <div @click.prevent.stop="toggle" class="d-flex align-items-center flex-nowrap" :class="{'active-toggle': visible}">
4
+ <div class="item-toggle text-muted">
5
+ <template v-if="visible && expanded">
6
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
7
+ width="16" height="16" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
8
+ <path d="M184.7,413.1l2.1-1.8l156.5-136c5.3-4.6,8.6-11.5,8.6-19.2c0-7.7-3.4-14.6-8.6-19.2L187.1,101l-2.6-2.3
9
+ C182,97,179,96,175.8,96c-8.7,0-15.8,7.4-15.8,16.6h0v286.8h0c0,9.2,7.1,16.6,15.8,16.6C179.1,416,182.2,414.9,184.7,413.1z" fill="currentColor" />
10
+ </svg>
11
+ </template>
12
+ <template v-else-if="visible">
13
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
14
+ width="16" height="16" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
15
+ <path d="M98.9,184.7l1.8,2.1l136,156.5c4.6,5.3,11.5,8.6,19.2,8.6c7.7,0,14.6-3.4,19.2-8.6L411,187.1l2.3-2.6
16
+ c1.7-2.5,2.7-5.5,2.7-8.7c0-8.7-7.4-15.8-16.6-15.8v0H112.6v0c-9.2,0-16.6,7.1-16.6,15.8C96,179.1,97.1,182.2,98.9,184.7z" fill="currentColor" />
17
+ </svg>
18
+ </template>
19
+ </div>
20
+
21
+ <slot></slot>
22
+ </div>
23
+ </div>
24
+ </template>
25
+ <style lang="scss" scoped>
26
+ .active-toggle {
27
+ cursor: pointer;
28
+ }
29
+ .item-toggle {
30
+ width: 1.5rem;
31
+ display: flex;
32
+ align-items: center;
33
+ }
34
+ </style>
35
+ <script>
36
+ import { Vue, Component, Prop } from 'vue-property-decorator';
37
+
38
+ export default @Component({
39
+ components: {
40
+ }
41
+ })
42
+ class itfTableRowToggle extends Vue {
43
+ @Prop(Boolean) expanded;
44
+ @Prop(Boolean) visible;
45
+
46
+ toggle() {
47
+ this.$emit('toggle');
48
+ }
49
+ }
50
+ </script>
@@ -20,29 +20,11 @@
20
20
  </a>
21
21
  </div>
22
22
  </div>
23
- <div v-if="indicatorType !== 'none'" class="indicator sticky">
24
- <div class="fill table-view-row-count" :class="{'on-rest': indicatorType !== 'checkbox' && indicatorType !== 'toggle'}">
23
+ <div class="indicator sticky">
24
+ <div v-if="indicatorType !== 'none'" class="table-view-row-count">
25
25
  <span v-if="indicatorType === 'order'">{{ (n + 1) }}</span>
26
26
  <span v-else-if="indicatorType === 'property'">{{ item[idProperty] }}</span>
27
- <a href="" @click.prevent.stop="$emit('toggle', item)" v-else-if="indicatorType === 'toggle'">
28
- <template v-if="subrowsProperty && item[subrowsProperty] && item[subrowsProperty].length">
29
- <template v-if="item[subrowsProperty] && item[subrowsProperty].length && !isExpanded(item)">
30
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-plus-square" viewBox="0 0 16 16">
31
- <path d="M14 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1zM2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2z"/>
32
- <path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4"/>
33
- </svg>
34
- </template>
35
- <template v-else>
36
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-dash-square" viewBox="0 0 16 16">
37
- <path d="M14 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1zM2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2z"/>
38
- <path d="M4 8a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 4 8"/>
39
- </svg>
40
- </template>
41
- </template>
42
- </a>
43
- </div>
44
- <div v-if="indicatorType !== 'toggle'" class="fill" :class="{'on-hover': indicatorType !== 'checkbox'}">
45
- <itf-checkbox :value="item[idProperty]" />
27
+ <span v-else-if="indicatorType === 'checkbox'"><itf-checkbox :value="item[idProperty]" /></span>
46
28
  </div>
47
29
  </div>
48
30
  <div accept-group="items" class="table-item-inner" @click="$emit('row-click', item)">
@@ -50,11 +32,16 @@
50
32
  <div
51
33
  v-if="column.visible !== false"
52
34
  :data-column="k"
53
- :style="column.grow ? `left: ${column.left}px; flex-grow: 1` : `width: ${column.width}px; max-width: ${column.width}px; left: ${column.left}px;`"
54
- :class="{'justify-content-end': column.align === 'end', 'sticky': column.pinned, 'last-sticky-column': k === lastPinnedIndex, 'flex-grow-1': column.grow, 'editable': column.editable && editable}"
35
+ :style="`width: ${column.width}px; max-width: ${column.width}px; left: ${column.left}px;`"
36
+ :class="{'justify-content-end': column.align === 'end', 'sticky': column.pinned, 'last-sticky-column': k === lastPinnedIndex, 'editable': column.editable && editable}"
55
37
  class="table-view-item-value d-flex h-100">
56
38
  <div class="table-view-item-value-content" :class="{'px-2': !(column.editable && editable)}">
57
- <slot :name="`column.${column.property}`" :toggle="() => $emit('toggle', item)" :level="level" :editable="column.editable && editable" :item="item" :column="column" :update="(val) => updateValue(item, val, n, column)" :value="getValue(item, column)">
39
+ <slot
40
+ :name="`column.${column.property}`"
41
+ :toggle="() => $emit('toggle', item)"
42
+ :hasSubitems="!!(subrowsProperty && item[subrowsProperty] && item[subrowsProperty].length)"
43
+ :isExpanded="!!(item[subrowsProperty] && item[subrowsProperty].length && !isExpanded(item))"
44
+ :level="level" :editable="column.editable && editable" :item="item" :column="column" :update="(val) => updateValue(item, val, n, column)" :value="getValue(item, column)">
58
45
  <template v-if="column.editable && editable && (!editableProperty || item[editableProperty])">
59
46
  <slot :name="`edit.${column.type}`" :level="level" :toggle="() => $emit('toggle', item)" :update="(val) => updateValue(item, val, n, column)" :value="getValue(item, column)" :item="item" :column="column">
60
47
  <itf-text-field class="w-100 h-100" v-if="column.type === 'text'" :value="getValue(item, column)" @input="updateValue(item, $event, n, column)" />
@@ -122,6 +109,7 @@
122
109
  </template>
123
110
  </itf-table-rows>
124
111
  </template>
112
+ <div v-if="dividerProperty && item[dividerProperty]" :key="`divider-${n}`" class="itf-table2__row-divider"></div>
125
113
  </template>
126
114
  </div>
127
115
  </template>
@@ -157,6 +145,7 @@ class itfTableRows extends Vue {
157
145
  @Prop() rows;
158
146
  @Prop() idProperty;
159
147
  @Prop() subrowsProperty;
148
+ @Prop() dividerProperty;
160
149
  @Prop() active;
161
150
  @Prop(Boolean) showAddColumn;
162
151
  @Prop(Boolean) noSelectAll;