@itfin/components 1.4.35 → 1.5.0

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 (202) hide show
  1. package/package.json +17 -20
  2. package/src/ITFSettings.js +6 -0
  3. package/src/assets/scss/_css_variables.scss +2 -7
  4. package/src/assets/scss/_dark-theme.scss +2 -12
  5. package/src/assets/scss/_variables.scss +34 -9
  6. package/src/assets/scss/components/_button.scss +147 -10
  7. package/src/assets/scss/components/_checkbox.scss +9 -0
  8. package/src/assets/scss/components/_datepicker.scss +3 -3
  9. package/src/assets/scss/components/_pagination.scss +4 -1
  10. package/src/assets/scss/components/_popover.scss +22 -0
  11. package/src/assets/scss/components/_segmeneted-control.scss +19 -8
  12. package/src/assets/scss/components/_select.scss +6 -8
  13. package/src/assets/scss/components/_text-field.scss +27 -11
  14. package/src/assets/scss/components/select/_dropdown-menu.scss +1 -0
  15. package/src/assets/scss/components/select/_dropdown-toggle.scss +0 -1
  16. package/src/assets/scss/directives/tooltip.scss +10 -5
  17. package/src/assets/scss/main.scss +48 -0
  18. package/src/components/alert/AlertBanner.vue +75 -0
  19. package/src/components/app/App.vue +1 -1
  20. package/src/components/button/Button.vue +3 -1
  21. package/src/components/button/NativeButton.js +4 -0
  22. package/src/components/button/index.stories.js +2 -2
  23. package/src/components/checkbox/Checkbox.vue +2 -1
  24. package/src/components/checkbox/RadioBox.vue +1 -2
  25. package/src/components/copyToClipboard/CopyToClipboard.vue +4 -1
  26. package/src/components/customize/PropertiesList.vue +0 -2
  27. package/src/components/customize/PropertiesPopupMenu.vue +1 -1
  28. package/src/components/customize/PropertyItem.vue +6 -24
  29. package/src/components/datepicker/DatePicker.vue +3 -1
  30. package/src/components/datepicker/DatePickerInline.vue +2 -2
  31. package/src/components/datepicker/DateRangePickerInline.vue +6 -1
  32. package/src/components/dropdown/Dropdown.vue +1 -1
  33. package/src/components/dropdown/DropdownMenu.vue +1 -1
  34. package/src/components/editable/EditButton.vue +1 -1
  35. package/src/components/filter/FilterBadge.vue +20 -1
  36. package/src/components/filter/FilterFacetsList.vue +67 -13
  37. package/src/components/filter/FilterPanel.vue +39 -14
  38. package/src/components/filter/NewFilter.vue +305 -0
  39. package/src/components/form/Label.vue +5 -5
  40. package/src/components/icon/components/nomi-ai-alt.vue +5 -0
  41. package/src/components/icon/components/nomi-arrow-right.vue +4 -0
  42. package/src/components/icon/components/nomi-bell.vue +5 -0
  43. package/src/components/icon/components/nomi-calendar-payment.vue +10 -0
  44. package/src/components/icon/components/nomi-card-plus.vue +1 -0
  45. package/src/components/icon/components/nomi-cash-provider.vue +9 -0
  46. package/src/components/icon/components/nomi-cash-repeat.vue +6 -0
  47. package/src/components/icon/components/nomi-category-edit.vue +5 -0
  48. package/src/components/icon/components/nomi-chavron-up.vue +4 -0
  49. package/src/components/icon/components/nomi-chavron_down.vue +4 -0
  50. package/src/components/icon/components/nomi-chavron_up.vue +4 -0
  51. package/src/components/icon/components/nomi-chevron-up.vue +4 -0
  52. package/src/components/icon/components/nomi-exit-right.vue +4 -0
  53. package/src/components/icon/components/nomi-help.vue +2 -3
  54. package/src/components/icon/components/nomi-history.vue +7 -0
  55. package/src/components/icon/components/nomi-lock.vue +1 -1
  56. package/src/components/icon/components/nomi-pen-alt.vue +4 -0
  57. package/src/components/icon/components/nomi-project.vue +2 -2
  58. package/src/components/icon/components/nomi-refresh-off.vue +4 -0
  59. package/src/components/icon/components/nomi-refresh.vue +4 -0
  60. package/src/components/icon/components/nomi-scissors.vue +1 -1
  61. package/src/components/icon/components/nomi-start.vue +28 -0
  62. package/src/components/icon/components/nomi-table-view.vue +1 -4
  63. package/src/components/icon/components/nomi-transactions-delete.vue +5 -0
  64. package/src/components/icon/components/nomi-type-array.vue +6 -0
  65. package/src/components/icon/components/nomi-type-boolean.vue +5 -0
  66. package/src/components/icon/components/nomi-type-date.vue +4 -0
  67. package/src/components/icon/components/nomi-type-null.vue +4 -0
  68. package/src/components/icon/components/nomi-type-number.vue +4 -0
  69. package/src/components/icon/components/nomi-type-object.vue +4 -0
  70. package/src/components/icon/components/nomi-type-string.vue +4 -0
  71. package/src/components/icon/components/nomi-unarchive.vue +17 -0
  72. package/src/components/icon/components/nomi-unlink.vue +10 -0
  73. package/src/components/icon/components/nomi-user.vue +3 -3
  74. package/src/components/icon/components/nomi-warning-triangle.vue +6 -0
  75. package/src/components/icon/components/nomi-warning_triangle_filled.vue +6 -0
  76. package/src/components/icon/convert-icons.js +3 -0
  77. package/src/components/icon/icons.js +390 -312
  78. package/src/components/icon/new-icons/ai-alt.svg +4 -0
  79. package/src/components/icon/new-icons/arrow-right-alt.svg +3 -0
  80. package/src/components/icon/new-icons/arrow-right.svg +3 -0
  81. package/src/components/icon/new-icons/arrow_left.svg +3 -0
  82. package/src/components/icon/new-icons/automation.svg +4 -0
  83. package/src/components/icon/new-icons/balance.svg +3 -0
  84. package/src/components/icon/new-icons/balance_turnover.svg +4 -0
  85. package/src/components/icon/new-icons/bar-horizontal.svg +6 -0
  86. package/src/components/icon/new-icons/bell.svg +4 -0
  87. package/src/components/icon/new-icons/calendar-payment.svg +9 -0
  88. package/src/components/icon/new-icons/card-plus.svg +1 -0
  89. package/src/components/icon/new-icons/cash-provider.svg +8 -0
  90. package/src/components/icon/new-icons/cash-repeat.svg +5 -0
  91. package/src/components/icon/new-icons/cash.svg +3 -0
  92. package/src/components/icon/new-icons/cashflow.svg +3 -0
  93. package/src/components/icon/new-icons/category-edit.svg +4 -0
  94. package/src/components/icon/new-icons/category.svg +4 -0
  95. package/src/components/icon/new-icons/category_alt.svg +3 -0
  96. package/src/components/icon/new-icons/chart-bars.svg +5 -0
  97. package/src/components/icon/new-icons/chart-donut.svg +3 -0
  98. package/src/components/icon/new-icons/chart-funnel.svg +5 -0
  99. package/src/components/icon/new-icons/chart-kpi.svg +7 -0
  100. package/src/components/icon/new-icons/chart-line.svg +4 -0
  101. package/src/components/icon/new-icons/chart-lines.svg +5 -0
  102. package/src/components/icon/new-icons/check-alt.svg +3 -0
  103. package/src/components/icon/new-icons/check.svg +3 -0
  104. package/src/components/icon/new-icons/chevron-down.svg +3 -0
  105. package/src/components/icon/new-icons/chevron-left.svg +3 -0
  106. package/src/components/icon/new-icons/chevron-right.svg +3 -0
  107. package/src/components/icon/new-icons/chevron-up.svg +3 -0
  108. package/src/components/icon/new-icons/collapse.svg +6 -0
  109. package/src/components/icon/new-icons/control-panel.svg +7 -0
  110. package/src/components/icon/new-icons/credit.svg +3 -0
  111. package/src/components/icon/new-icons/currencies.svg +3 -0
  112. package/src/components/icon/new-icons/debt.svg +3 -0
  113. package/src/components/icon/new-icons/demo.svg +6 -0
  114. package/src/components/icon/new-icons/dev.svg +3 -0
  115. package/src/components/icon/new-icons/dots.svg +5 -0
  116. package/src/components/icon/new-icons/duplicate.svg +4 -0
  117. package/src/components/icon/new-icons/exit-right.svg +3 -0
  118. package/src/components/icon/new-icons/export.svg +3 -0
  119. package/src/components/icon/new-icons/file.svg +3 -0
  120. package/src/components/icon/new-icons/folder.svg +3 -0
  121. package/src/components/icon/new-icons/goods-turnover.svg +3 -0
  122. package/src/components/icon/new-icons/goods.svg +4 -0
  123. package/src/components/icon/new-icons/help-alt.svg +3 -0
  124. package/src/components/icon/new-icons/help.svg +2 -3
  125. package/src/components/icon/new-icons/history.svg +6 -0
  126. package/src/components/icon/new-icons/integration.svg +3 -0
  127. package/src/components/icon/new-icons/link.svg +5 -0
  128. package/src/components/icon/new-icons/lock.svg +1 -1
  129. package/src/components/icon/new-icons/menu.svg +5 -0
  130. package/src/components/icon/new-icons/minus.svg +3 -0
  131. package/src/components/icon/new-icons/payment_calendar.svg +3 -0
  132. package/src/components/icon/new-icons/pc.svg +3 -0
  133. package/src/components/icon/new-icons/pen-alt.svg +3 -0
  134. package/src/components/icon/new-icons/planFact.svg +4 -0
  135. package/src/components/icon/new-icons/pnl.svg +7 -0
  136. package/src/components/icon/new-icons/project.svg +2 -2
  137. package/src/components/icon/new-icons/project_alt.svg +3 -0
  138. package/src/components/icon/new-icons/project_alt2.svg +3 -0
  139. package/src/components/icon/new-icons/promo.svg +3 -0
  140. package/src/components/icon/new-icons/refresh-off.svg +3 -0
  141. package/src/components/icon/new-icons/refresh.svg +3 -0
  142. package/src/components/icon/new-icons/scissors.svg +1 -1
  143. package/src/components/icon/new-icons/segment.svg +3 -0
  144. package/src/components/icon/new-icons/start.svg +27 -0
  145. package/src/components/icon/new-icons/strongbox.svg +3 -0
  146. package/src/components/icon/new-icons/subscription.svg +3 -0
  147. package/src/components/icon/new-icons/table-view.svg +1 -4
  148. package/src/components/icon/new-icons/time.svg +3 -0
  149. package/src/components/icon/new-icons/transactions_alt.svg +6 -0
  150. package/src/components/icon/new-icons/transactions_delete.svg +4 -0
  151. package/src/components/icon/new-icons/type-array.svg +5 -0
  152. package/src/components/icon/new-icons/type-boolean.svg +4 -0
  153. package/src/components/icon/new-icons/type-date.svg +3 -0
  154. package/src/components/icon/new-icons/type-null.svg +3 -0
  155. package/src/components/icon/new-icons/type-number.svg +3 -0
  156. package/src/components/icon/new-icons/type-object.svg +3 -0
  157. package/src/components/icon/new-icons/type-string.svg +3 -0
  158. package/src/components/icon/new-icons/types.svg +6 -0
  159. package/src/components/icon/new-icons/unarchive.svg +16 -0
  160. package/src/components/icon/new-icons/unlink.svg +9 -0
  161. package/src/components/icon/new-icons/user.svg +3 -3
  162. package/src/components/icon/new-icons/user_plus.svg +10 -0
  163. package/src/components/icon/new-icons/warehouse.svg +3 -0
  164. package/src/components/icon/new-icons/warning_triangle.svg +5 -0
  165. package/src/components/icon/new-icons/warning_triangle_filled.svg +5 -0
  166. package/src/components/kanban/BoardCard.vue +1 -1
  167. package/src/components/kanban/BoardCardTimer.vue +1 -1
  168. package/src/components/modal/DeleteConfirmModal.vue +10 -6
  169. package/src/components/modal/ItemEditor.vue +1 -1
  170. package/src/components/modal/Modal.vue +1 -1
  171. package/src/components/overlay/SensitiveOverlay.vue +2 -4
  172. package/src/components/panels/Panel.vue +110 -23
  173. package/src/components/panels/PanelItemEdit.vue +1 -1
  174. package/src/components/panels/PanelList.vue +65 -11
  175. package/src/components/popover/Popover.vue +105 -22
  176. package/src/components/segmented-control/SegmentedControl.vue +9 -3
  177. package/src/components/sortable/draggable.js +1 -1
  178. package/src/components/table/Table2.vue +8 -3
  179. package/src/components/table/TableBody.vue +17 -16
  180. package/src/components/table/TableGroup.vue +38 -12
  181. package/src/components/table/TableHeader.vue +83 -73
  182. package/src/components/table/TableRows.vue +15 -9
  183. package/src/components/table/mobile.js +4 -0
  184. package/src/components/table/table2.scss +9 -0
  185. package/src/components/text-field/MoneyField.vue +10 -4
  186. package/src/components/text-field/TextField.vue +17 -8
  187. package/src/components/tree/TreeEditor.vue +3 -2
  188. package/src/components/view/View.vue +86 -214
  189. package/src/directives/appendToBody.js +1 -0
  190. package/src/helpers/validators.js +9 -35
  191. package/src/helpers/validators.spec.js +11 -48
  192. package/src/locales/en.js +4 -6
  193. package/src/locales/pl.js +158 -0
  194. package/src/locales/uk.js +6 -7
  195. package/src/components/icon/components/nomi-calendar-view.vue +0 -4
  196. package/src/components/icon/components/nomi-kanban-view.vue +0 -6
  197. package/src/components/icon/components/nomi-list-view.vue +0 -7
  198. package/src/components/icon/components/nomi-table-config.vue +0 -9
  199. package/src/components/icon/new-icons/calendar-view.svg +0 -3
  200. package/src/components/icon/new-icons/kanban-view.svg +0 -5
  201. package/src/components/icon/new-icons/list-view.svg +0 -6
  202. package/src/components/icon/new-icons/table-config.svg +0 -8
@@ -1,30 +1,35 @@
1
1
  @import '../variables';
2
2
  @import '../bootstrap';
3
3
 
4
- $tooltip-color: #fff9ae;
4
+ $tooltip-color: #22222B;
5
5
  $dark-tooltip-color: #7b52eb;
6
6
 
7
7
  :root {
8
8
  --itf-tooltip-shadow: 0 0 20px 4px rgba(154, 161, 177, .15), 0 4px 80px -8px rgba(36, 40, 47, .25), 0 4px 4px -2px rgba(91, 94, 105, .15);
9
- --itf-tooltip-color: #{$body-color};
9
+ --itf-tooltip-color: #FFF;
10
10
  --itf-tooltip-bg-color: #{$tooltip-color};
11
+ --itf-tooltip-font-size: 14px;
11
12
  }
12
13
 
13
14
  [data-theme="dark"] {
14
15
  --itf-tooltip-shadow: 0 0 20px 4px rgba(87, 78, 101, 0.15), 0 4px 80px -8px rgba(211, 208, 219, 0.25), 0 4px 4px -2px rgba(156, 150, 164, 0.15);
15
16
  --itf-tooltip-color: #{$dark-body-color};
16
17
  --itf-tooltip-bg-color: #{$dark-tooltip-color};
17
- --itf-tooltip-font-size: 0.875rem;
18
+ --itf-tooltip-font-size: 14px;
18
19
  }
19
20
 
20
21
  .tippy-box[data-theme~=itfin] {
21
22
  color: var(--itf-tooltip-color);
22
23
  background-color: var(--itf-tooltip-bg-color);
23
24
  font-size: var(--itf-tooltip-font-size);
24
- border-radius: 5px;
25
+ border-radius: 0.5rem;
25
26
  box-shadow: var(--itf-tooltip-shadow);
26
- padding: 5px;
27
+ padding: .25rem .5rem;
27
28
  cursor: default;
29
+ a {
30
+ color: var(--itf-tooltip-color);
31
+ text-decoration: underline;
32
+ }
28
33
 
29
34
  &[data-placement^=top] > .tippy-arrow:before {
30
35
  border-top-color: var(--itf-tooltip-bg-color);
@@ -60,3 +60,51 @@ kbd {
60
60
  color: var(--bs-primary-color) !important
61
61
  }
62
62
  }
63
+
64
+ // згідно з дизайном
65
+ .dropdown-header {
66
+ font-size: .75rem;
67
+ padding: .75rem .5rem .25rem;
68
+
69
+ &:first-child {
70
+ padding-top: .25rem;
71
+ }
72
+ }
73
+ //.dropdown-item {
74
+ // --bs-dropdown-link-active-bg: #F1F2F4;
75
+ // --bs-dropdown-link-active-color: var(--bs-body-color);
76
+ // &:not(:last-child) {
77
+ // margin-bottom: 1px;
78
+ // }
79
+ //
80
+ // svg {
81
+ // color: #8E97A5;
82
+ // }
83
+ // &:hover svg {
84
+ // color: var(--bs-body-color);
85
+ // }
86
+ //}
87
+ body .form-check-input:checked[type=checkbox] {
88
+ --bs-form-check-bg-image: url("data:image/svg+xml,%3Csvg width='8' height='5' viewBox='0 0 10 8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M9 1L3.5 6.5L1 4' stroke='white' stroke-width='1.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E%0A");
89
+ box-shadow: 0px 2px 3px 0px #00000026;
90
+ }
91
+ body .form-check-input:indeterminate[type=checkbox] {
92
+ box-shadow: 0px 2px 3px 0px #00000026;
93
+ }
94
+ body .text-muted {
95
+ color: #7A818E !important;
96
+ }
97
+ body .form-control {
98
+ &:focus {
99
+ box-shadow: none !important;
100
+ }
101
+ }
102
+
103
+ @keyframes pulse-shadow {
104
+ 0% { box-shadow: 0 0 0 0 rgba(26, 74, 151, 0) }
105
+ 50% { box-shadow: 0 0 0 4px rgba(26, 74, 151, 0.15) }
106
+ 100% { box-shadow: 0 0 0 0 rgba(26, 74, 151, 0) }
107
+ }
108
+ .pulsing {
109
+ animation: pulse-shadow 3s ease-in-out infinite;
110
+ }
@@ -0,0 +1,75 @@
1
+ <template>
2
+ <div class="itf-alert-banner">
3
+ <div v-if="count" class="itf-alert-banner__counter px-2 bg-danger text-white fw-bold text-smaller text-decoration-none d-block rounded-pill">
4
+ {{ count > 99 ? '99+' : count }}
5
+ </div>
6
+ <div v-if="multiple" class="itf-alert-banner__panel itf-alert-banner__multiple rounded-3 border bg-muted-2"></div>
7
+ <div class="itf-alert-banner__panel px-3 rounded-3 border bg-muted-2 d-flex gap-3 align-items-start align-items-sm-center flex-sm-row flex-column">
8
+ <slot name="icon">
9
+ <div v-if="icon" class="itf-alert-banner__icon rounded-2 bg-danger flex-shrink-0 d-flex align-items-center justify-content-center">
10
+ <itf-icon new :name="icon" :size="24" class="text-white" />
11
+ </div>
12
+ </slot>
13
+ <div class="flex-grow-1">
14
+ <div class="fw-bold"><slot name="title">{{title}}</slot></div>
15
+ <div class="small text-muted"><slot></slot></div>
16
+ </div>
17
+ </div>
18
+ </div>
19
+ </template>
20
+ <style lang="scss" scoped>
21
+ .itf-alert-banner {
22
+ width: 100%;
23
+ position: relative;
24
+ max-width: 420px;
25
+
26
+ &__counter {
27
+ top: 0;
28
+ right: -4px;
29
+ position: absolute;
30
+ z-index: 3;
31
+ padding-top: 0.375rem;
32
+ padding-bottom: 0.375rem;
33
+ min-width: 1.75rem;
34
+ text-align: center;
35
+ }
36
+ &__panel {
37
+ position: relative;
38
+ padding-top: 0.75rem;
39
+ padding-bottom: 0.75rem;
40
+ top: 4px;
41
+ z-index: 2;
42
+ }
43
+ &__icon {
44
+ width: 48px;
45
+ height: 48px;
46
+ }
47
+ &__multiple {
48
+ position: absolute;
49
+ top: 0;
50
+ right: -4px;
51
+ z-index: 1;
52
+ height: 100%;
53
+ width: 100%;
54
+ }
55
+ }
56
+ </style>
57
+ <script>
58
+ import { Vue, Component, Prop } from 'vue-property-decorator';
59
+ import itfIcon from '@itfin/components/src/components/icon/Icon';
60
+ import itfPanelLink from '@itfin/components/src/components/panels/PanelLink.vue';
61
+
62
+ export default @Component({
63
+ name: 'itfAlertBanner',
64
+ components: {
65
+ itfIcon,
66
+ itfPanelLink,
67
+ },
68
+ })
69
+ class AlertBanner extends Vue {
70
+ @Prop(String) title;
71
+ @Prop(String) icon;
72
+ @Prop() count;
73
+ @Prop(Boolean) multiple;
74
+ }
75
+ </script>
@@ -76,7 +76,7 @@ class itfApp extends Vue {
76
76
  } catch (err) {
77
77
  if (err.code !== 'ERR_CANCELED') {
78
78
  console.error(err);
79
- this.showError(err.message);
79
+ if (!err.noMessage) this.showError(err.message);
80
80
  if (errFunc) {
81
81
  errFunc(err);
82
82
  }
@@ -17,6 +17,7 @@ class itfButton extends Vue {
17
17
  @Prop(Boolean) large;
18
18
  @Prop(Boolean) icon;
19
19
  @Prop(Boolean) block;
20
+ @Prop(Boolean) squircle;
20
21
  @Prop(String) loadingText;
21
22
  @Prop(String) color;
22
23
  @Prop(Boolean) disabled;
@@ -27,7 +28,7 @@ class itfButton extends Vue {
27
28
 
28
29
  render (createElement, { data, slots, children, props }) {
29
30
  const {
30
- to, href, target, disabled, color, block, loading, labeled, secondary, primary, small, large, icon, loadingText, default: defaultStyle,
31
+ to, href, target, disabled, color, block, loading, labeled, secondary, primary, small, large, icon, loadingText, squircle, default: defaultStyle,
31
32
  class: classNames
32
33
  } = props;
33
34
  const component = to ? 'nuxt-link' : (props.href ? 'a' : 'button');
@@ -47,6 +48,7 @@ class itfButton extends Vue {
47
48
  'btn-default': defaultStyle,
48
49
  'btn-basic': !primary && !secondary && !color && !defaultStyle,
49
50
  'btn-secondary': secondary,
51
+ // 'btn-squircle': squircle,
50
52
  'btn-sm': small,
51
53
  'btn-lg': large,
52
54
  // 'px-3': small && !icon,
@@ -7,6 +7,7 @@ const CSS_CLASSES = {
7
7
  small: ['btn-sm'],
8
8
  block: ['itf-button__block'],
9
9
  labeled: ['labeled'],
10
+ squircle: ['btn-squircle'],
10
11
  icon: ['btn-icon'],
11
12
  loading: ['loading'],
12
13
  spinner: ['itf-spinner'],
@@ -35,6 +36,9 @@ class Button extends HTMLElement {
35
36
  if (this.hasAttribute('labeled')) {
36
37
  styles.push(CSS_CLASSES.labeled);
37
38
  }
39
+ if (this.hasAttribute('squircle')) {
40
+ styles.push(CSS_CLASSES.squircle);
41
+ }
38
42
  if (this.hasAttribute('icon')) {
39
43
  styles.push(CSS_CLASSES.icon);
40
44
  }
@@ -66,7 +66,7 @@ storiesOf('Common', module)
66
66
 
67
67
  <h3>Standart button</h3>
68
68
 
69
- <itf-button primary>Primary button</itf-button>
69
+ <itf-button squircle primary>Primary button</itf-button>
70
70
  <itf-button secondary>Secondary button</itf-button>
71
71
  <itf-button>Basic button</itf-button>
72
72
  <itf-button icon>
@@ -92,7 +92,7 @@ storiesOf('Common', module)
92
92
 
93
93
  <h3>Large button</h3>
94
94
 
95
- <itf-button large primary>Primary button</itf-button>
95
+ <itf-button squircle large primary>Primary button</itf-button>
96
96
  <itf-button large secondary>Secondary button</itf-button>
97
97
  <itf-button large>Basic button</itf-button>
98
98
  <itf-button large icon>
@@ -2,12 +2,13 @@
2
2
 
3
3
  <div class="itf-checkbox form-check" :class="{ 'form-switch': this.switch, 'itf-checkbox__large': large, 'itf-checkbox__medium': medium }">
4
4
  <input class="form-check-input" ref="input" :id="id" type="checkbox" name="checkbox" v-model="isChecked" :disabled="isDisabled" />
5
- <label :for="id" class="form-check-label w-100" :class="{ 'disabled': isDisabled }">
5
+ <label :for="id" class="form-check-label" :class="{ 'disabled': isDisabled }">
6
6
  <slot name="label">
7
7
  {{label}}
8
8
  <slot name="icon"></slot>
9
9
  </slot>
10
10
  </label>
11
+ <slot name="after-label"></slot>
11
12
  </div>
12
13
 
13
14
  </template>
@@ -16,8 +16,6 @@
16
16
  padding: 0;
17
17
  margin-bottom: .5rem;
18
18
  position: relative;
19
- cursor: pointer;
20
-
21
19
  &:not(.disabled) {
22
20
  cursor: pointer;
23
21
 
@@ -29,6 +27,7 @@
29
27
  .form-check-label {
30
28
  cursor: not-allowed;
31
29
  }
30
+
32
31
  &.left {
33
32
  padding: 0 0 0 2.5rem;
34
33
 
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <itf-button icon small @click.stop="copy">
2
+ <itf-button :icon="icon" :small="small" @click.stop="copy" :disabled="disabled">
3
3
  <slot>
4
4
  <itf-icon name="clipboard_copy" />
5
5
  </slot>
@@ -18,6 +18,9 @@ export default @Component({
18
18
  })
19
19
  class CopyToClipboard extends Vue {
20
20
  @Prop(String) value;
21
+ @Prop({ type: Boolean, default: true }) small;
22
+ @Prop({ type: Boolean, default: true }) icon;
23
+ @Prop({ type: Boolean, default: false }) disabled;
21
24
 
22
25
  async copy () {
23
26
  const showSuccess = this.$showSuccess;
@@ -15,7 +15,6 @@
15
15
  :field="field"
16
16
  :editable="editable"
17
17
  :lock-fields="lockFields"
18
- :full-name="fullName"
19
18
  :value="value[field.Id]"
20
19
  @input="$emit('input', { ...value, [field.Id]: $event })"
21
20
  @delete="onDelete(field)"
@@ -105,7 +104,6 @@ class itfPropertiesList extends Vue {
105
104
  @Prop({ type: Boolean, default: false }) loading;
106
105
  @Prop({ type: Boolean, default: false }) editable;
107
106
  @Prop({ type: Boolean, default: false }) lockFields;
108
- @Prop({ type: Boolean, default: false }) fullName;
109
107
 
110
108
  isShowAll = false;
111
109
 
@@ -27,7 +27,7 @@
27
27
  </div>
28
28
  </template>
29
29
  <script>
30
- import { Vue, Component, Prop } from 'vue-property-decorator';
30
+ import { Vue, Component, Prop, Watch } from 'vue-property-decorator';
31
31
  import itfTextField from '../text-field/TextField.vue';
32
32
  import itfIcon from '../icon/Icon';
33
33
  import itfButton from '../button/Button';
@@ -9,10 +9,10 @@
9
9
 
10
10
  <itf-dropdown text :disabled="!editable || lockFields" ref="editDd" autoclose="outside" class="flex-grow-1 mw-100 editable-field" shadow @close="onClose">
11
11
  <div slot="button">
12
- <div class="d-flex align-items-center" :class="{ 'b-properties-list__title-text': lockFields }">
12
+ <div class="d-flex align-items-center">
13
13
  <!-- <itf-icon :name="field.Icon" :size="16" class="me-1" />-->
14
14
 
15
- <div :class="`b-properties-list__title-text-${fullName ? 'full' : 'short'}`" v-text="field.Name" />
15
+ <div style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis;" v-text="field.Name" />
16
16
  </div>
17
17
  </div>
18
18
  <properties-edit-menu
@@ -35,11 +35,11 @@
35
35
  />
36
36
  </itf-dropdown>
37
37
  </div>
38
- <div class="bg-light b-properties-list__value rounded-2" :class="{'editable': editable, 'active shadow rounded-2 bg-body': focusId === field.Id}" sortable-skip>
38
+ <div class="b-properties-list__value rounded-2" :class="{'editable': editable, 'active shadow rounded-2 bg-body': focusId === field.Id}" sortable-skip>
39
39
  <property-inline-edit
40
40
  @focus="onFocus(field.Id)"
41
41
  @blur="onBlur(field.Id)"
42
- class="flex-grow-1 b-properties-list__inline-editor editable-field rounded-2"
42
+ class="flex-grow-1 b-properties-list__inline-editor editable-field"
43
43
  :field="field"
44
44
  :value="value"
45
45
  :editable="editable"
@@ -62,11 +62,6 @@
62
62
  background: rgba(0, 0, 0, 0.05);
63
63
  }
64
64
  }
65
- &__inline-editor {
66
- min-height: 44px;
67
- padding-right: 10px;
68
- padding-left: 10px;
69
- }
70
65
  &__draghandler {
71
66
  user-select: none;
72
67
  transition: opacity 150ms ease-in 0s;
@@ -85,7 +80,7 @@
85
80
  }
86
81
  &__inner {
87
82
  display: flex;
88
- padding-bottom: 8px;
83
+ padding-bottom: 4px;
89
84
  width: 100%;
90
85
  }
91
86
  &__name, &__value {
@@ -103,7 +98,7 @@
103
98
  &__name {
104
99
  display: flex;
105
100
  align-items: center;
106
- min-height: 44px;
101
+ height: 34px;
107
102
  width: 250px;
108
103
  flex: 0 0 auto;
109
104
  }
@@ -124,18 +119,6 @@
124
119
  background-color: rgba(55, 53, 47, 0.08);
125
120
  }
126
121
  }
127
- &__title-text {
128
- min-height: 44px;
129
- }
130
- &__title-text-short {
131
- white-space: nowrap;
132
- overflow: hidden;
133
- text-overflow: ellipsis;
134
- }
135
- &__title-text-full {
136
- white-space: normal;
137
- word-break: break-word;
138
- }
139
122
  }
140
123
  </style>
141
124
  <script>
@@ -171,7 +154,6 @@ class itfPropertyItem extends Vue {
171
154
  @Prop({ type: Boolean, default: false }) loading;
172
155
  @Prop({ type: Boolean, default: false }) editable;
173
156
  @Prop({ type: Boolean, default: false }) lockFields;
174
- @Prop({ type: Boolean, default: false }) fullName;
175
157
 
176
158
  isEditMode = false;
177
159
  focusId = null;
@@ -24,7 +24,7 @@
24
24
  :disabled="disabled"
25
25
  />
26
26
 
27
- <div class="addon-end" v-if="clearable && value && !isInvalid()">
27
+ <div class="addon-end" v-if="clearable && value">
28
28
  <slot name="clear">
29
29
  <itf-button
30
30
  icon
@@ -44,6 +44,7 @@
44
44
  :display-format="dateFormat"
45
45
  :value-format="valueFormat"
46
46
  :min-date="minDate"
47
+ :max-date="maxDate"
47
48
  :days-list="daysList"
48
49
  @input="selectInlineDate"
49
50
  ></itf-date-picker-inline>
@@ -87,6 +88,7 @@ class itfDatePicker extends Vue {
87
88
  @Prop({ type: String, default: '' }) prependIcon;
88
89
  @Prop({ type: String, default: 'bottom-start' }) placement;
89
90
  @Prop({ type: [String, Date], default: '' }) minDate;
91
+ @Prop({ type: [String, Date], default: '' }) maxDate;
90
92
  @Prop(Boolean) clearable;
91
93
  @Prop(Boolean) disabled;
92
94
 
@@ -90,8 +90,8 @@ class itfDatePickerInline extends Vue {
90
90
  range: this.range,
91
91
  view: (this.valueAsLuxon && !this.minView) ? 'days' : this.startView,
92
92
  minView: this.minView,
93
- minDate: this.minDate,
94
- maxDate: this.maxDate,
93
+ minDate: this.minDate === 'today' ? new Date() : this.minDate,
94
+ maxDate: this.maxDate === 'today' ? new Date() : this.maxDate,
95
95
  selectedDates: this.valueAsLuxon ? [this.valueAsLuxon.toJSDate()] : [],
96
96
  onSelect: ({ date }) => {
97
97
  if (this.range && !this.calendar.rangeDateTo) {
@@ -101,7 +101,12 @@ class itfDatePickerInline extends Vue {
101
101
  range: true,
102
102
  compareRange: true,
103
103
  dynamicRange: true,
104
- toggleSelected: false,
104
+ toggleSelected: function({ date, datepicker }) {
105
+ if (datepicker.selectedDates.length > 1) {
106
+ datepicker.selectDate(date);
107
+ }
108
+ return false;
109
+ },
105
110
  selectedDates: this.valueAsLuxon
106
111
  ? [this.valueAsLuxon[0].toJSDate(), this.valueAsLuxon[1].toJSDate()]
107
112
  : [],
@@ -1,5 +1,5 @@
1
1
  <script>
2
- import { Vue, Component, Prop, PropSync } from 'vue-property-decorator';
2
+ import { Vue, Component, Prop, Watch, PropSync } from 'vue-property-decorator';
3
3
  import itfButton from '../button/Button';
4
4
  import itfDropdownMenu from './DropdownMenu';
5
5
 
@@ -4,7 +4,7 @@
4
4
  </div>
5
5
  </template>
6
6
  <script>
7
- import { Vue, Component, Prop, PropSync } from 'vue-property-decorator';
7
+ import { Vue, Component, Prop, Watch, PropSync } from 'vue-property-decorator';
8
8
 
9
9
  let globalModalIndex = 0; // base modal z-index
10
10
 
@@ -24,7 +24,7 @@
24
24
  }
25
25
  </style>
26
26
  <script>
27
- import { Component, Prop, Vue } from 'vue-property-decorator';
27
+ import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
28
28
  import itfIcon from '../icon/Icon';
29
29
  import itfButton from '../button/Button';
30
30
 
@@ -12,7 +12,7 @@
12
12
  </div>
13
13
  </template>
14
14
 
15
- <div class="px-2">
15
+ <div>
16
16
  <template v-if="type === 'list'">
17
17
  <a
18
18
  v-for="(item, n) in options.items"
@@ -36,16 +36,31 @@
36
36
  @input="onFilterChange({ value: $event })"
37
37
  />
38
38
  </template>
39
+ <template v-else-if="type === 'month'">
40
+ <itf-date-picker-inline
41
+ style="margin: -.5rem"
42
+ start-view="months"
43
+ min-view="months"
44
+ :value="value.value"
45
+ only-calendar
46
+ @input="onFilterChange({ value: $event })"
47
+ />
48
+ </template>
39
49
  <template v-else-if="type === 'date'">
40
50
  <itf-date-picker-inline
41
51
  style="margin: -.5rem"
42
52
  :value="value.value"
53
+ :only-calendar="options.calendarOptions && options.calendarOptions.onlyCalendar"
54
+ :max-date="options.calendarOptions && options.calendarOptions.maxDate"
55
+ :min-date="options.calendarOptions && options.calendarOptions.minDate"
56
+ value-format="yyyy-MM-dd"
43
57
  @input="onFilterChange({ value: $event })"
44
58
  />
45
59
  </template>
46
60
  <div v-else-if="type === 'facets-list'" style="width: 300px;">
47
61
  <filter-facets-list
48
62
  :title="options.title"
63
+ :options="options"
49
64
  :value="value.value"
50
65
  :items="options.items"
51
66
  :total="options.total"
@@ -108,9 +123,13 @@ body[data-theme="dark"] {
108
123
  &.filter-not-default-pill {
109
124
  background-color: var(--filter-badge__selected-bg-color);
110
125
  outline: 1px solid var(--filter-badge__selected-color);
126
+
127
+ .icon { color: var(--filter-badge__selected-color) }
111
128
  }
112
129
  &.filter-invalid-pill {
113
130
  background-color: var(--filter-badge__invalid-bg-color);
131
+
132
+ .icon { color: var(--filter-badge__invalid-color) }
114
133
  }
115
134
  &.filter-pill__default-value {
116
135
  padding: var(--filter-badge__padding-y) var(--filter-badge__padding-x);
@@ -20,16 +20,26 @@
20
20
  </div>
21
21
  </div>
22
22
  <div class="facets-list">
23
- <div v-for="(val, n) of mappedValues" :key="n" class="dropdown-item px-2" :class="{'active': val.isSelected}" @click="onFilterClick(val)">
24
- <span class="facet-name text-dark d-flex align-items-center">
25
- <itf-checkbox ungrouped :value="val.isSelected" class="m-0" />
26
- <div class="w-100 text-truncate">{{ val.label }} <span v-if="val.description" class="small"><br/>{{ val.description }}</span></div>
27
- </span>
28
- <span v-if="val.count" class="facet-stat">
29
- {{ val.count }}
30
- <span class="facet-bar"><span :style="{'--bar-width': `${getPercent(val)}%`}" class="facet-bar-progress" /></span>
31
- </span>
32
- </div>
23
+ <div v-for="(group, g) of groupedList">
24
+ <div v-if="group.group" class="dropdown-item ps-1 d-flex align-items-center"
25
+ :class="{'active': isGroupSelected(group.items)}" @click="groupSelected(!isGroupSelected(group.items), group.items)">
26
+ <span class="facet-name text-dark d-flex align-items-center">
27
+ <itf-checkbox ungrouped :value="isGroupSelected(group.items)" @input="groupSelected($event, group.items)" class="m-0" />
28
+ <div class="w-100 text-truncate">{{ group.group }}</div>
29
+ </span>
30
+ </div>
31
+
32
+ <div v-for="(val, n) of group.items" :key="n" class="dropdown-item ps-1" :class="{'active': val.isSelected, 'ps-4': group.group}" @click="onFilterClick(val)">
33
+ <span class="facet-name text-dark d-flex align-items-center">
34
+ <itf-checkbox ungrouped :value="val.isSelected" class="m-0" />
35
+ <div class="w-100 text-truncate">{{ val.label }} <span v-if="val.description" class="small"><br/>{{ val.description }}</span></div>
36
+ </span>
37
+ <span v-if="val.count" class="facet-stat">
38
+ {{ val.count }}
39
+ <span class="facet-bar"><span :style="{'--bar-width': `${getPercent(val)}%`}" class="facet-bar-progress" /></span>
40
+ </span>
41
+ </div>
42
+ </div>
33
43
  </div>
34
44
 
35
45
  <itf-button default class="mt-1" v-if="hasMore" small block @click="toggleMore">
@@ -76,7 +86,7 @@
76
86
  margin: 1px 0;
77
87
  &.active {
78
88
  .facet-bar-progress {
79
- background-color: var(--bs-primary);
89
+ background-color: var(--bs-blue);
80
90
  }
81
91
  }
82
92
  .facet-name {
@@ -105,12 +115,14 @@
105
115
  width: var(--bar-width);
106
116
  min-width: 5px;
107
117
  height: 10px;
108
- background-color: rgba(var(--bs-primary-rgb), 50%);
118
+ background-color: rgba(var(--bs-blue-rgb), 50%);
109
119
  transition: width 0.3s ease 0s;
110
120
  }
111
121
  }
112
122
  </style>
113
123
  <script>
124
+ import uniq from 'lodash/uniq';
125
+ import sortBy from 'lodash/sortBy';
114
126
  import { Vue, Prop, Model, Component } from 'vue-property-decorator';
115
127
  import itfTextField from '../text-field/TextField.vue';
116
128
  import itfButton from '../button/Button';
@@ -149,6 +161,33 @@ class FilterFacetsList extends Vue {
149
161
  return this.visibleList.length > this.limit;
150
162
  }
151
163
 
164
+ get hasGroups() {
165
+ const groups = uniq(this.items && this.items.map(item => item.group).filter(Boolean));
166
+ return groups.length > 1
167
+ }
168
+
169
+ isGroupSelected(items) {
170
+ return items.every(item => item.isSelected);
171
+ }
172
+
173
+ groupSelected(value, items) {
174
+ let newVal = this.value ? [...Array.isArray(this.value) ? this.value : [this.value]] : [];
175
+ if (value) {
176
+ items.forEach((item) => {
177
+ const itemValue = `${item.value}`;
178
+ if (!newVal.includes(itemValue)) {
179
+ newVal.push(itemValue);
180
+ }
181
+ });
182
+ } else {
183
+ items.forEach((item) => {
184
+ const itemValue = `${item.value}`;
185
+ newVal = newVal.filter(val => val !== itemValue);
186
+ });
187
+ }
188
+ this.$emit('input', this.multiple ? newVal : (newVal.length > 0 ? newVal[0] : null));
189
+ }
190
+
152
191
  get visibleList() {
153
192
  let list = this.items.map(val => {
154
193
  const isSelected = this.multiple
@@ -163,7 +202,22 @@ class FilterFacetsList extends Vue {
163
202
  if (this.isShowSelected) {
164
203
  return list.filter((val) => val.isSelected);
165
204
  }
166
- return list;
205
+ return sortBy(list, (item) => this.hasGroups ? item.group || item.label : item.label);
206
+ }
207
+
208
+ get groupedList() {
209
+ if (!this.hasGroups) {
210
+ return [{ items: this.mappedValues }];
211
+ }
212
+ const groups = {};
213
+ this.mappedValues.forEach((item) => {
214
+ const group = item.group || '';
215
+ if (!groups[group]) {
216
+ groups[group] = [];
217
+ }
218
+ groups[group].push(item);
219
+ });
220
+ return Object.entries(groups).map(([group, items]) => ({ group, items }));
167
221
  }
168
222
 
169
223
  get mappedValues() {