@eturnity/eturnity_reusable_components 7.24.3-EPDM-11320.3 → 7.24.3-qa-elisee-7.32.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 (83) hide show
  1. package/.prettierrc +6 -8
  2. package/package.json +21 -9
  3. package/public/favicon.ico +0 -0
  4. package/public/index.html +17 -0
  5. package/src/App.vue +78 -79
  6. package/src/assets/svgIcons/adjust_roof.svg +6 -0
  7. package/src/assets/svgIcons/copy.svg +10 -0
  8. package/src/assets/theme.js +3 -3
  9. package/src/components/addNewButton/AddNewButton.stories.js +2 -2
  10. package/src/components/addNewButton/index.vue +51 -48
  11. package/src/components/banner/actionBanner/index.vue +55 -54
  12. package/src/components/banner/banner/banner.stories.js +5 -5
  13. package/src/components/banner/banner/index.vue +159 -159
  14. package/src/components/banner/infoBanner/index.vue +53 -41
  15. package/src/components/buttons/buttonIcon/index.vue +122 -125
  16. package/src/components/buttons/closeButton/CloseButton.stories.js +3 -3
  17. package/src/components/buttons/closeButton/index.vue +49 -49
  18. package/src/components/buttons/mainButton/index.vue +119 -119
  19. package/src/components/card/index.vue +70 -70
  20. package/src/components/collapsableInfoText/index.vue +94 -96
  21. package/src/components/deleteIcon/DeleteIcon.stories.js +4 -4
  22. package/src/components/deleteIcon/index.vue +54 -54
  23. package/src/components/draggableInputHandle/index.vue +37 -37
  24. package/src/components/dropdown/Dropdown.stories.js +10 -9
  25. package/src/components/dropdown/index.vue +106 -106
  26. package/src/components/errorMessage/index.vue +52 -52
  27. package/src/components/filter/filterSettings.vue +433 -439
  28. package/src/components/filter/index.vue +135 -135
  29. package/src/components/filter/parentDropdown.vue +73 -73
  30. package/src/components/icon/Icons.stories.js +7 -7
  31. package/src/components/icon/iconCollection.vue +53 -53
  32. package/src/components/icon/index.vue +121 -121
  33. package/src/components/iconWrapper/index.vue +156 -156
  34. package/src/components/infoCard/index.vue +26 -26
  35. package/src/components/infoText/index.vue +132 -133
  36. package/src/components/inputs/checkbox/Checkbox.stories.js +8 -8
  37. package/src/components/inputs/checkbox/index.vue +180 -190
  38. package/src/components/inputs/inputNumber/InputNumber.stories.js +41 -41
  39. package/src/components/inputs/inputNumber/index.vue +644 -647
  40. package/src/components/inputs/inputNumberQuestion/index.vue +182 -185
  41. package/src/components/inputs/inputText/InputText.stories.js +22 -22
  42. package/src/components/inputs/inputText/index.vue +336 -337
  43. package/src/components/inputs/radioButton/RadioButton.stories.js +16 -16
  44. package/src/components/inputs/radioButton/index.vue +219 -221
  45. package/src/components/inputs/searchInput/SearchInput.stories.js +8 -8
  46. package/src/components/inputs/searchInput/index.vue +126 -127
  47. package/src/components/inputs/select/index.vue +776 -778
  48. package/src/components/inputs/select/option/index.vue +124 -124
  49. package/src/components/inputs/select/select.stories.js +32 -31
  50. package/src/components/inputs/slider/index.vue +99 -99
  51. package/src/components/inputs/switchField/index.vue +222 -220
  52. package/src/components/inputs/textAreaInput/TextAreaInput.stories.js +57 -57
  53. package/src/components/inputs/textAreaInput/index.vue +173 -171
  54. package/src/components/inputs/toggle/Toggle.stories.js +14 -14
  55. package/src/components/inputs/toggle/index.vue +217 -214
  56. package/src/components/label/index.vue +82 -82
  57. package/src/components/markerItem/index.vue +66 -68
  58. package/src/components/modals/actionModal/index.vue +54 -54
  59. package/src/components/modals/infoModal/index.vue +36 -39
  60. package/src/components/modals/modal/index.vue +134 -134
  61. package/src/components/modals/modal/modal.stories.js +5 -5
  62. package/src/components/navigationTabs/index.vue +94 -96
  63. package/src/components/pageSubtitle/index.vue +49 -55
  64. package/src/components/pageTitle/index.vue +56 -56
  65. package/src/components/pagination/index.vue +89 -92
  66. package/src/components/progressBar/index.vue +107 -107
  67. package/src/components/projectMarker/index.vue +244 -246
  68. package/src/components/rangeSlider/Slider.vue +465 -491
  69. package/src/components/rangeSlider/index.vue +410 -410
  70. package/src/components/rangeSlider/utils/dom.js +5 -5
  71. package/src/components/selectedOptions/index.vue +119 -119
  72. package/src/components/sideMenu/index.vue +199 -199
  73. package/src/components/spinner/index.vue +57 -57
  74. package/src/components/tableDropdown/index.vue +520 -520
  75. package/src/components/tables/mainTable/index.vue +362 -366
  76. package/src/components/tables/viewTable/index.vue +171 -171
  77. package/src/components/threeDots/index.vue +334 -340
  78. package/src/components/videoThumbnail/index.vue +86 -86
  79. package/src/components/videoThumbnail/videoThumbnail.stories.js +16 -14
  80. package/src/helpers/numberConverter.js +2 -2
  81. package/src/helpers/translateLang.js +9 -9
  82. package/src/mixins/inputValidations.js +5 -5
  83. package/.eslintrc.js +0 -184
@@ -1,22 +1,22 @@
1
1
  <template>
2
- <DropdownRow
2
+ <dropdown-row
3
3
  :colspan="colSpan"
4
- :disabled="disabled"
5
- :is-open="isOpen"
4
+ :isOpen="isOpen"
6
5
  @click="toggleOpen"
6
+ :disabled="disabled"
7
7
  >
8
- <ComponentContainer class="table-dropdown" :col-span="colSpan - 1">
9
- <ComponentItem
8
+ <component-container :colSpan="colSpan - 1" class="table-dropdown">
9
+ <component-item
10
10
  v-for="(item, index) in tableItems"
11
11
  :key="index"
12
12
  ref="dropdownItem"
13
+ :isNested="isNested"
13
14
  :class="{
14
- 'table-dropdown-item': item.type !== 'input',
15
+ 'table-dropdown-item': item.type !== 'input'
15
16
  }"
16
- :is-nested="isNested"
17
17
  >
18
- <NestedContainer :is-nested="isNested">
19
- <NestedIcon
18
+ <nested-container :isNested="isNested">
19
+ <nested-icon
20
20
  v-if="
21
21
  isNested &&
22
22
  (item.type === 'input' ||
@@ -24,52 +24,54 @@
24
24
  item.type === 'template')
25
25
  "
26
26
  />
27
- <TemplateButton
27
+ <template-button
28
+ @click.stop="onTemplateClick(item.row)"
28
29
  v-if="
29
30
  item.type &&
30
31
  item.type === 'template' &&
31
32
  (item.value === '' || item.value === '-')
32
33
  "
33
34
  :key="index + '_button'"
34
- @click.stop="onTemplateClick(item.row)"
35
+ >{{ $gettext('Use template...') }}</template-button
35
36
  >
36
- {{ $gettext('Use template...') }}
37
- </TemplateButton>
38
- <TemplateLink
37
+ <template-link
39
38
  v-else-if="
40
39
  item.type && item.type === 'template' && item.value !== ''
41
40
  "
42
41
  @click.stop="onSelectedTemplateClick(item.row)"
43
42
  >
44
43
  <!-- <img :src="fileIcon" alt="icon" width="12" height="16" /> -->
45
- <Icon
46
- :color="theme.colors.brightBlue"
44
+ <icon
47
45
  name="template_icon_not_clickable"
46
+ :color="theme.colors.brightBlue"
48
47
  size="14px"
49
48
  />
50
49
  <div>{{ item.value }}</div>
51
- </TemplateLink>
52
- <NoTemplate v-if="item.type && item.type === 'no-template'">
50
+ </template-link>
51
+ <no-template v-if="item.type && item.type === 'no-template'">
53
52
  {{ $gettext('No main component template') }}
54
- </NoTemplate>
55
- <InputContainer
53
+ </no-template>
54
+ <input-container
56
55
  v-if="item.type === 'input'"
57
56
  @click.stop="onInputClick()"
58
57
  >
59
- <TextContainer v-if="customInputDisabled" class="input-placeholder">
58
+ <text-container
59
+ v-if="customInputDisabled"
60
+ class="input-placeholder"
61
+ >
60
62
  <span> {{ item.value }}</span>
61
- </TextContainer>
62
- <InputText
63
+ </text-container>
64
+ <input-text
63
65
  v-else
64
66
  class="inputField"
65
- :disabled="customInputDisabled"
66
- :min-width="item.value.length + 'ch'"
67
- :no-border="true"
68
67
  :value="item.value"
68
+ :noBorder="true"
69
+ :minWidth="item.value.length + 'ch'"
70
+ :disabled="customInputDisabled"
69
71
  @input-change="onCustomInputChange($event)"
70
72
  />
71
- </InputContainer>
72
- <TextContainer
73
+ </input-container>
74
+ <text-container
73
75
  v-else-if="
74
76
  item.type !== 'input' &&
75
77
  item.type !== 'no-template' &&
@@ -77,182 +79,139 @@
77
79
  "
78
80
  >
79
81
  <span> {{ item.value }}</span>
80
- </TextContainer>
81
- </NestedContainer>
82
- </ComponentItem>
83
- <ArrowContainer class="arrow-container" :is-disabled="disabled">
84
- <ArrowWrapper :show-archived="showArchived">
85
- <EtPopover
82
+ </text-container>
83
+ </nested-container>
84
+ </component-item>
85
+ <arrow-container class="arrow-container" :isDisabled="disabled">
86
+ <arrow-wrapper :showArchived="showArchived">
87
+ <et-popover
86
88
  v-if="showArchived"
87
89
  button-class="error"
88
90
  :text="
89
91
  $gettext(`Component has been archived and shouldn't be used`)
90
92
  "
91
- trigger-type="hover"
92
- />
93
- <ArrowDown
93
+ triggerType="hover"
94
+ ></et-popover>
95
+ <arrow-down
96
+ @click.stop="toggleOpen"
94
97
  v-if="!isOpen"
95
98
  class="arrow-dropdown"
96
- @click.stop="toggleOpen"
97
99
  />
98
- <ArrowUp v-else @click.stop="toggleOpen" />
99
- </ArrowWrapper>
100
- <OptionsContainer v-if="isOpen" ref="optionsContainer">
101
- <OptionsWrapper @click.prevent.stop>
102
- <SearchContainer @click.prevent.stop>
103
- <SearchInput
104
- ref="searchInput"
105
- :placeholder="$gettext('Keyword') + '...'"
100
+ <arrow-up @click.stop="toggleOpen" v-else />
101
+ </arrow-wrapper>
102
+ <options-container v-if="isOpen" ref="optionsContainer">
103
+ <options-wrapper @click.prevent.stop>
104
+ <search-container @click.prevent.stop>
105
+ <search-input
106
106
  :value="inputText"
107
+ :placeholder="$gettext('Keyword') + '...'"
107
108
  @click.prevent.stop
108
109
  @on-change="onSearch($event)"
110
+ ref="searchInput"
109
111
  />
110
- </SearchContainer>
111
- <Spinner v-if="optionsLoading" />
112
- <EmptyText v-else-if="!optionsLoading && !optionItems.length">
112
+ </search-container>
113
+ <spinner v-if="optionsLoading" />
114
+ <empty-text v-else-if="!optionsLoading && !optionItems.length">
113
115
  {{ emptyText ? emptyText : $gettext('No components found.') }}
114
- </EmptyText>
115
- <OptionsItem
116
- v-for="(item, index) in optionItems"
116
+ </empty-text>
117
+ <options-item
117
118
  v-else
118
- :key="index"
119
- :col-span="colSpan - 1"
120
- :tabindex="0"
119
+ :colSpan="colSpan - 1"
121
120
  :width="dynamicGridWidth"
121
+ v-for="(item, index) in optionItems"
122
+ :key="index"
122
123
  @click="onItemClick(item)"
124
+ :tabindex="0"
123
125
  @keyup.enter="onItemClick(item)"
124
126
  >
125
127
  <template v-for="(option, idx) in optionsDisplay" :key="idx">
126
128
  <span v-if="option !== 'template'">
127
129
  {{ !!item[option] ? item[option] : '-' }}
128
130
  </span>
129
- <TemplateButton
130
- v-else-if="option === 'template' && item.has_template"
131
+ <template-button
131
132
  @click.stop="onTemplateClick(item)"
133
+ v-else-if="option === 'template' && item.has_template"
134
+ >{{ $gettext('Use template...') }}</template-button
132
135
  >
133
- {{ $gettext('Use template...') }}
134
- </TemplateButton>
135
- <NoTemplate
136
+ <no-template
136
137
  v-else-if="option === 'template' && !item.has_template"
137
138
  >
138
139
  {{ $gettext('No main component template') }}
139
- </NoTemplate>
140
+ </no-template>
140
141
  </template>
141
- </OptionsItem>
142
- </OptionsWrapper>
143
- <CustomContainer
142
+ </options-item>
143
+ </options-wrapper>
144
+ <custom-container
144
145
  v-if="inputText.length && allowFreeInputs"
145
146
  @click="onCustomNameClick()"
146
147
  >
147
- <CustomName>{{ getCustomName }}</CustomName>
148
- <CustomSubtext>
149
- ({{ $gettext('custom_component') }})
150
- </CustomSubtext>
151
- </CustomContainer>
152
- </OptionsContainer>
153
- </ArrowContainer>
154
- </ComponentContainer>
155
- </DropdownRow>
148
+ <custom-name>{{ getCustomName }}</custom-name>
149
+ <custom-subtext
150
+ >({{ $gettext('custom_component') }})</custom-subtext
151
+ >
152
+ </custom-container>
153
+ </options-container>
154
+ </arrow-container>
155
+ </component-container>
156
+ </dropdown-row>
156
157
  </template>
157
158
 
158
159
  <script>
159
- // import TableDropdown from "@eturnity/eturnity_reusable_components/src/components/tableDropdown"
160
- // To use:
161
- // <table-dropdown
162
- // :colSpan="2"
163
- // :tableItems="getDropdownValues(row)"
164
- // :showArchived="
165
- // row.selectedValue
166
- // ? row.selectedValue.status_active === false
167
- // : row.status_active === false
168
- // "
169
- // @toggle-dropdown-open="toggleDropdownOpen(row.id, $event)"
170
- // @dropdown-search="onDropdownSearch($event)"
171
- // @item-selected="onItemSelected({ item: $event, index })"
172
- // :isOpen="isDropdownOpen(row)"
173
- // :optionItems="groupComponents" // list of options
174
- // :optionsLoading="dropdownOptionsLoading"
175
- // :optionsDisplay="['display_name', 'company_item_number']" // Array. what should be displayed
176
- // :disabled="true"
177
- // />
178
- import styled from 'vue3-styled-components'
179
- import Spinner from '../spinner'
180
- import SearchInput from '../inputs/searchInput'
181
- import InputText from '../inputs/inputText'
182
- import CollapseArrowIcon from '../../assets/icons/collapse_arrow_icon.svg'
183
- import SubpositionMarkerIcon from '../../assets/icons/subposition_marker.svg'
184
- import fileIconPng from '../../assets/icons/file_icon.png'
185
- import Icon from '../icon'
186
- import theme from '@/assets/theme.js'
187
-
188
- const rowAttrs = { disabled: Boolean, isOpen: Boolean }
189
- const DropdownRow = styled('div', rowAttrs)`
190
- cursor: ${(props) => (props.disabled ? 'not-allowed' : 'pointer')};
191
- display: contents;
192
-
193
- input {
194
- cursor: ${(props) => (!props.isOpen ? 'pointer !important' : 'inherit')};
195
- }
196
-
197
- .input-placeholder {
198
- height: 25px;
199
- padding-left: 12px;
200
- }
201
- `
202
-
203
- const ItemAttrs = { isNested: Boolean }
204
- const ComponentItem = styled('td', ItemAttrs)`
205
- padding-left: ${(props) => (props.isNested ? '14px !important' : '0')};
206
- overflow: hidden;
207
- text-overflow: ellipsis;
208
- padding-right: 0 !important;
160
+ // import TableDropdown from "@eturnity/eturnity_reusable_components/src/components/tableDropdown"
161
+ // To use:
162
+ // <table-dropdown
163
+ // :colSpan="2"
164
+ // :tableItems="getDropdownValues(row)"
165
+ // :showArchived="
166
+ // row.selectedValue
167
+ // ? row.selectedValue.status_active === false
168
+ // : row.status_active === false
169
+ // "
170
+ // @toggle-dropdown-open="toggleDropdownOpen(row.id, $event)"
171
+ // @dropdown-search="onDropdownSearch($event)"
172
+ // @item-selected="onItemSelected({ item: $event, index })"
173
+ // :isOpen="isDropdownOpen(row)"
174
+ // :optionItems="groupComponents" // list of options
175
+ // :optionsLoading="dropdownOptionsLoading"
176
+ // :optionsDisplay="['display_name', 'company_item_number']" // Array. what should be displayed
177
+ // :disabled="true"
178
+ // />
179
+ import styled from 'vue3-styled-components'
180
+ import Spinner from '../spinner'
181
+ import SearchInput from '../inputs/searchInput'
182
+ import InputText from '../inputs/inputText'
183
+ import CollapseArrowIcon from '../../assets/icons/collapse_arrow_icon.svg'
184
+ import SubpositionMarkerIcon from '../../assets/icons/subposition_marker.svg'
185
+ import fileIconPng from '../../assets/icons/file_icon.png'
186
+ import Icon from '../icon'
187
+ import theme from '@/assets/theme.js'
188
+
189
+ const rowAttrs = { disabled: Boolean, isOpen: Boolean }
190
+ const DropdownRow = styled('div', rowAttrs)`
191
+ cursor: ${(props) => (props.disabled ? 'not-allowed' : 'pointer')};
192
+ display: contents;
193
+
194
+ input {
195
+ cursor: ${(props) => (!props.isOpen ? 'pointer !important' : 'inherit')};
196
+ }
209
197
 
210
- &.table-dropdown-item {
211
- background-clip: content-box;
212
- padding: 8px 0 7px 0 !important;
213
- vertical-align: middle;
198
+ .input-placeholder {
199
+ height: 25px;
200
+ padding-left: 12px;
201
+ }
202
+ `
214
203
 
215
- @media not all and (min-resolution: 0.001dpcm) {
216
- @supports (-webkit-appearance: none) {
217
- /* Safari Only CSS here */
218
- padding: 8px 0 10px 0 !important;
219
- }
220
- }
204
+ const ItemAttrs = { isNested: Boolean }
205
+ const ComponentItem = styled('td', ItemAttrs)`
206
+ padding-left: ${(props) => (props.isNested ? '14px !important' : '0')};
207
+ overflow: hidden;
208
+ text-overflow: ellipsis;
209
+ padding-right: 0 !important;
221
210
 
222
- span {
223
- padding-left: 15px;
224
- }
225
- }
226
- `
227
-
228
- const containerAttrs = { colSpan: Number, width: String }
229
- const ComponentContainer = styled('div', containerAttrs)`
230
- display: contents;
231
- align-items: center;
232
- background-color: ${(props) => props.theme.colors.white};
233
- border-radius: 4px;
234
- padding: 5px 4px;
235
- `
236
-
237
- const ArrowDown = styled(CollapseArrowIcon)`
238
- width: 8px;
239
- transition: transform 150ms ease;
240
- `
241
-
242
- const ArrowUp = styled.img`
243
- width: 8px;
244
- transform: rotate(180deg);
245
- transition: transform 150ms ease;
246
- `
247
-
248
- const ArrowAttrs = { isDisabled: Boolean }
249
- const ArrowContainer = styled('td', ArrowAttrs)`
250
- border-bottom: 1px solid ${(props) => props.theme.colors.grey4};
211
+ &.table-dropdown-item {
251
212
  background-clip: content-box;
252
213
  padding: 8px 0 7px 0 !important;
253
- border-radius: 0 4px 4px 0;
254
- cursor: ${(props) =>
255
- props.isDisabled ? 'not-allowed !important' : 'auto'};
214
+ vertical-align: middle;
256
215
 
257
216
  @media not all and (min-resolution: 0.001dpcm) {
258
217
  @supports (-webkit-appearance: none) {
@@ -261,378 +220,419 @@
261
220
  }
262
221
  }
263
222
 
264
- .arrow-dropdown {
265
- vertical-align: middle;
266
- margin-left: 11px;
267
- }
268
- `
269
-
270
- const arrowAttrs = { showArchived: Boolean }
271
- const ArrowWrapper = styled('div', arrowAttrs)`
272
- display: grid;
273
- grid-template-columns: ${(props) =>
274
- props.showArchived ? 'auto auto' : 'auto'};
275
- align-items: center;
276
- justify-items: center;
277
- height: 100%;
278
- `
279
-
280
- const optionsAttrs = { top: Number, left: Number }
281
- const OptionsContainer = styled('div', optionsAttrs)`
282
- position: absolute;
283
- margin-top: 10px;
284
- display: grid;
285
- grid-template-rows: 1fr auto;
286
- left: 20px;
287
- width: auto;
288
- max-height: 360px;
289
- min-height: 200px;
290
- overflow: auto;
291
- border: 1px solid ${(props) => props.theme.colors.grey3};
292
- z-index: 9999;
293
- background: ${(props) => props.theme.colors.white};
294
- border-radius: 4px;
295
- `
296
-
297
- const EmptyText = styled.div`
298
- align-self: center;
299
- justify-self: center;
300
- height: 100px;
301
- display: grid;
302
- align-content: center;
303
- `
304
-
305
- const OptionsWrapper = styled.div`
306
- display: grid;
307
- position: relative;
308
- padding: 12px;
309
- grid-gap: 4px;
310
- font-size: 13px;
311
- grid-template-rows: max-content;
312
- height: max-content;
313
- min-width: 400px; // kind of an arbitrary number until we know all use cases
314
- `
315
-
316
- const OptionsItem = styled('div', containerAttrs)`
317
- display: grid;
318
- grid-template-columns: ${(props) => props.width};
319
- grid-gap: 30px;
320
- padding: 10px;
321
- height: max-content;
322
- justify-items: flex-start;
323
-
324
223
  span {
325
- overflow: hidden;
326
- text-overflow: ellipsis;
224
+ padding-left: 15px;
327
225
  }
328
-
329
- &:hover {
330
- background-color: ${(props) => props.theme.colors.grey5};
226
+ }
227
+ `
228
+
229
+ const containerAttrs = { colSpan: Number, width: String }
230
+ const ComponentContainer = styled('div', containerAttrs)`
231
+ display: contents;
232
+ align-items: center;
233
+ background-color: ${(props) => props.theme.colors.white};
234
+ border-radius: 4px;
235
+ padding: 5px 4px;
236
+ `
237
+
238
+ const ArrowDown = styled(CollapseArrowIcon)`
239
+ width: 8px;
240
+ transition: transform 150ms ease;
241
+ `
242
+
243
+ const ArrowUp = styled.img`
244
+ width: 8px;
245
+ transform: rotate(180deg);
246
+ transition: transform 150ms ease;
247
+ `
248
+
249
+ const ArrowAttrs = { isDisabled: Boolean }
250
+ const ArrowContainer = styled('td', ArrowAttrs)`
251
+ border-bottom: 1px solid ${(props) => props.theme.colors.grey4};
252
+ background-clip: content-box;
253
+ padding: 8px 0 7px 0 !important;
254
+ border-radius: 0 4px 4px 0;
255
+ cursor: ${(props) => (props.isDisabled ? 'not-allowed !important' : 'auto')};
256
+
257
+ @media not all and (min-resolution: 0.001dpcm) {
258
+ @supports (-webkit-appearance: none) {
259
+ /* Safari Only CSS here */
260
+ padding: 8px 0 10px 0 !important;
331
261
  }
332
- `
333
-
334
- const SearchContainer = styled.div`
335
- position: sticky;
336
- top: 0;
337
- padding-top: 6px;
338
- background: ${(props) => props.theme.colors.white};
339
- height: 40px;
340
- `
341
-
342
- const TemplateButton = styled.div`
343
- cursor: pointer;
344
- background-color: #263238;
345
- color: ${(props) => props.theme.colors.white};
346
- padding: 4px 10px;
347
- display: inline-block;
348
- border-radius: 4px;
349
- text-align: center;
350
- margin-left: 15px;
351
- `
352
-
353
- const NoTemplate = styled.div`
354
- color: ${(props) => props.theme.colors.gray1};
355
- font-style: italic;
262
+ }
263
+
264
+ .arrow-dropdown {
265
+ vertical-align: middle;
266
+ margin-left: 11px;
267
+ }
268
+ `
269
+
270
+ const arrowAttrs = { showArchived: Boolean }
271
+ const ArrowWrapper = styled('div', arrowAttrs)`
272
+ display: grid;
273
+ grid-template-columns: ${(props) =>
274
+ props.showArchived ? 'auto auto' : 'auto'};
275
+ align-items: center;
276
+ justify-items: center;
277
+ height: 100%;
278
+ `
279
+
280
+ const optionsAttrs = { top: Number, left: Number }
281
+ const OptionsContainer = styled('div', optionsAttrs)`
282
+ position: absolute;
283
+ margin-top: 10px;
284
+ display: grid;
285
+ grid-template-rows: 1fr auto;
286
+ left: 20px;
287
+ width: auto;
288
+ max-height: 360px;
289
+ min-height: 200px;
290
+ overflow: auto;
291
+ border: 1px solid ${(props) => props.theme.colors.grey3};
292
+ z-index: 9999;
293
+ background: ${(props) => props.theme.colors.white};
294
+ border-radius: 4px;
295
+ `
296
+
297
+ const EmptyText = styled.div`
298
+ align-self: center;
299
+ justify-self: center;
300
+ height: 100px;
301
+ display: grid;
302
+ align-content: center;
303
+ `
304
+
305
+ const OptionsWrapper = styled.div`
306
+ display: grid;
307
+ position: relative;
308
+ padding: 12px;
309
+ grid-gap: 4px;
310
+ font-size: 13px;
311
+ grid-template-rows: max-content;
312
+ height: max-content;
313
+ min-width: 400px; // kind of an arbitrary number until we know all use cases
314
+ `
315
+
316
+ const OptionsItem = styled('div', containerAttrs)`
317
+ display: grid;
318
+ grid-template-columns: ${(props) => props.width};
319
+ grid-gap: 30px;
320
+ padding: 10px;
321
+ height: max-content;
322
+ justify-items: flex-start;
323
+
324
+ span {
356
325
  overflow: hidden;
357
326
  text-overflow: ellipsis;
358
- padding-left: 15px;
359
- `
360
-
361
- const TemplateLink = styled.div`
362
- color: ${(props) => props.theme.colors.brightBlue};
363
- cursor: pointer;
364
- display: grid;
365
- grid-template-columns: auto 1fr;
366
- grid-gap: 12px;
367
- padding-left: 15px;
368
- `
369
-
370
- const InputContainer = styled.div`
371
- .inputField input {
372
- border-radius: 4px 0 0 4px;
373
- }
374
- `
327
+ }
328
+
329
+ &:hover {
330
+ background-color: ${(props) => props.theme.colors.grey5};
331
+ }
332
+ `
333
+
334
+ const SearchContainer = styled.div`
335
+ position: sticky;
336
+ top: 0;
337
+ padding-top: 6px;
338
+ background: ${(props) => props.theme.colors.white};
339
+ height: 40px;
340
+ `
341
+
342
+ const TemplateButton = styled.div`
343
+ cursor: pointer;
344
+ background-color: #263238;
345
+ color: ${(props) => props.theme.colors.white};
346
+ padding: 4px 10px;
347
+ display: inline-block;
348
+ border-radius: 4px;
349
+ text-align: center;
350
+ margin-left: 15px;
351
+ `
352
+
353
+ const NoTemplate = styled.div`
354
+ color: ${(props) => props.theme.colors.gray1};
355
+ font-style: italic;
356
+ overflow: hidden;
357
+ text-overflow: ellipsis;
358
+ padding-left: 15px;
359
+ `
360
+
361
+ const TemplateLink = styled.div`
362
+ color: ${(props) => props.theme.colors.brightBlue};
363
+ cursor: pointer;
364
+ display: grid;
365
+ grid-template-columns: auto 1fr;
366
+ grid-gap: 12px;
367
+ padding-left: 15px;
368
+ `
369
+
370
+ const InputContainer = styled.div`
371
+ .inputField input {
372
+ border-radius: 4px 0 0 4px;
373
+ }
374
+ `
375
375
 
376
- const CustomContainer = styled.div`
377
- display: grid;
378
- grid-template-columns: auto 1fr;
379
- padding: 10px 22px;
380
- border-top: 1px solid ${(props) => props.theme.colors.grey3};
381
- height: 37px;
376
+ const CustomContainer = styled.div`
377
+ display: grid;
378
+ grid-template-columns: auto 1fr;
379
+ padding: 10px 22px;
380
+ border-top: 1px solid ${(props) => props.theme.colors.grey3};
381
+ height: 37px;
382
382
 
383
- &:hover {
384
- background-color: ${(props) => props.theme.colors.grey5};
385
- }
386
- `
387
-
388
- const CustomName = styled.div`
389
- justify-self: flex-start;
390
- `
391
-
392
- const CustomSubtext = styled.div`
393
- justify-self: flex-end;
394
- color: ${(props) => props.theme.colors.grey3};
395
- `
396
-
397
- const TextContainer = styled.div`
398
- height: 100%;
399
- display: grid;
400
- align-items: center;
401
- `
402
-
403
- const NestedIcon = styled(SubpositionMarkerIcon)`
404
- height: 10px;
405
- width: 6px;
406
- `
407
-
408
- const NestedAttrs = { isNested: Boolean }
409
- const NestedContainer = styled('div', NestedAttrs)`
410
- display: grid;
411
- grid-gap: 5px;
412
- grid-template-columns: ${(props) => (props.isNested ? 'auto 1fr' : '1fr')};
413
- align-items: center;
414
- `
415
-
416
- export default {
417
- name: 'TableDropdown',
418
- components: {
419
- DropdownRow,
420
- ComponentItem,
421
- ComponentContainer,
422
- ArrowDown,
423
- ArrowUp,
424
- OptionsContainer,
425
- Spinner,
426
- EmptyText,
427
- SearchInput,
428
- ArrowWrapper,
429
- OptionsWrapper,
430
- OptionsItem,
431
- SearchContainer,
432
- TemplateButton,
433
- NoTemplate,
434
- TemplateLink,
435
- InputText,
436
- InputContainer,
437
- CustomContainer,
438
- CustomName,
439
- CustomSubtext,
440
- ArrowContainer,
441
- TextContainer,
442
- NestedIcon,
443
- NestedContainer,
444
- Icon,
383
+ &:hover {
384
+ background-color: ${(props) => props.theme.colors.grey5};
385
+ }
386
+ `
387
+
388
+ const CustomName = styled.div`
389
+ justify-self: flex-start;
390
+ `
391
+
392
+ const CustomSubtext = styled.div`
393
+ justify-self: flex-end;
394
+ color: ${(props) => props.theme.colors.grey3};
395
+ `
396
+
397
+ const TextContainer = styled.div`
398
+ height: 100%;
399
+ display: grid;
400
+ align-items: center;
401
+ `
402
+
403
+ const NestedIcon = styled(SubpositionMarkerIcon)`
404
+ height: 10px;
405
+ width: 6px;
406
+ `
407
+
408
+ const NestedAttrs = { isNested: Boolean }
409
+ const NestedContainer = styled('div', NestedAttrs)`
410
+ display: grid;
411
+ grid-gap: 5px;
412
+ grid-template-columns: ${(props) => (props.isNested ? 'auto 1fr' : '1fr')};
413
+ align-items: center;
414
+ `
415
+
416
+ export default {
417
+ name: 'table-dropdown',
418
+ components: {
419
+ DropdownRow,
420
+ ComponentItem,
421
+ ComponentContainer,
422
+ ArrowDown,
423
+ ArrowUp,
424
+ OptionsContainer,
425
+ Spinner,
426
+ EmptyText,
427
+ SearchInput,
428
+ ArrowWrapper,
429
+ OptionsWrapper,
430
+ OptionsItem,
431
+ SearchContainer,
432
+ TemplateButton,
433
+ NoTemplate,
434
+ TemplateLink,
435
+ InputText,
436
+ InputContainer,
437
+ CustomContainer,
438
+ CustomName,
439
+ CustomSubtext,
440
+ ArrowContainer,
441
+ TextContainer,
442
+ NestedIcon,
443
+ NestedContainer,
444
+ Icon
445
+ },
446
+ props: {
447
+ colSpan: {
448
+ required: false,
449
+ default: 1
445
450
  },
446
- props: {
447
- colSpan: {
448
- required: false,
449
- default: 1,
450
- },
451
- customInputDisabled: {
452
- // whether the input field should be disabled
453
- required: false,
454
- default: true,
455
- },
456
- allowFreeInputs: {
457
- // whether we allow the user to select a custom input
458
- required: false,
459
- default: false,
460
- },
461
- tableItems: {
462
- required: true,
463
- },
464
- showArchived: {
465
- required: false,
466
- default: false,
467
- },
468
- isOpen: {
469
- required: true,
470
- default: false,
471
- },
472
- optionsLoading: {
473
- required: false,
474
- default: false,
475
- },
476
- emptyText: {
477
- required: false,
478
- default: null,
479
- },
480
- optionItems: {
481
- required: true,
482
- },
483
- optionsDisplay: {
484
- required: true,
485
- default: [], // should be like ['display_name', 'company_item_number', 'description']
486
- },
487
- disabled: {
488
- required: false,
489
- default: false,
490
- },
491
- isNested: {
492
- required: false,
493
- default: false,
494
- },
451
+ customInputDisabled: {
452
+ // whether the input field should be disabled
453
+ required: false,
454
+ default: true
495
455
  },
496
- data() {
497
- return {
498
- inputText: '',
499
- wasClicked: false, // prevents custom-name from being triggered on the <input-text />
500
- dynamicWidth: [], // for numbers
501
- dynamicGridWidth: [], // for grid values
502
- fileIcon: fileIconPng,
503
- }
456
+ allowFreeInputs: {
457
+ // whether we allow the user to select a custom input
458
+ required: false,
459
+ default: false
504
460
  },
505
- computed: {
506
- getCustomName() {
507
- return this.inputText
508
- },
509
- theme() {
510
- return theme
511
- },
461
+ tableItems: {
462
+ required: true
512
463
  },
513
- watch: {
514
- isOpen(newVal) {
515
- if (newVal) {
516
- document.addEventListener('click', this.clickOutside)
517
- this.$emit('dropdown-search', '')
518
- this.$nextTick(() => {
519
- this.$refs.searchInput.$el.children[0].children[0].focus()
520
- })
521
- this.$nextTick(() => {
522
- this.scrollToItem()
523
- })
524
- }
525
- },
526
- optionItems: {
527
- immediate: true,
528
- handler(val) {
529
- if (val && val.length) {
530
- this.setDropdownWidth(val)
531
- }
532
- },
533
- },
464
+ showArchived: {
465
+ required: false,
466
+ default: false
534
467
  },
535
- methods: {
536
- toggleOpen(event) {
537
- if (
538
- this.disabled ||
539
- (event &&
540
- !(event.target === this.$el) &&
541
- !this.$el.contains(event.target))
542
- ) {
543
- return
544
- }
545
- this.wasClicked = false
546
- if (!this.isOpen) {
547
- document.addEventListener('click', this.clickOutside)
548
- this.$emit('dropdown-search', '')
549
- this.$nextTick(() => {
550
- this.scrollToItem()
551
- })
552
- this.$emit('toggle-dropdown-open', { close: false })
553
- this.$nextTick(() => {
554
- this.$refs.searchInput.$el.children[0].children[1].focus()
555
- })
556
- } else {
557
- document.removeEventListener('click', this.clickOutside)
558
- this.$emit('toggle-dropdown-open', { close: true })
559
- this.inputText = ''
560
- }
561
- },
562
- onInputClick() {
563
- if (!this.isOpen) {
564
- this.toggleOpen()
565
- }
566
- },
567
- scrollToItem() {
568
- if (this.$refs.optionsContainer) {
569
- this.$refs.optionsContainer.$el.scrollIntoView({
570
- behavior: 'smooth',
571
- block: 'center',
572
- })
573
- }
574
- },
575
- onTemplateClick(item) {
576
- this.$emit('on-template-click', item)
577
- },
578
- onSelectedTemplateClick(item) {
579
- this.$emit('on-selected-template-click', item)
580
- },
581
- onItemClick(item) {
582
- this.wasClicked = true
583
- this.$emit('item-selected', item)
584
- },
585
- onSearch(value) {
586
- this.inputText = value
587
- this.$emit('dropdown-search', value)
588
- },
589
- clickOutside(event) {
590
- if (event.target === this.$el || this.$el.contains(event.target)) {
591
- return
592
- }
593
- this.inputText = ''
594
- // 'close: true' is needed in case a box is open and another box is clicked on
595
- // so this one will close properly
468
+ isOpen: {
469
+ required: true,
470
+ default: false
471
+ },
472
+ optionsLoading: {
473
+ required: false,
474
+ default: false
475
+ },
476
+ emptyText: {
477
+ required: false,
478
+ default: null
479
+ },
480
+ optionItems: {
481
+ required: true
482
+ },
483
+ optionsDisplay: {
484
+ required: true,
485
+ default: [] // should be like ['display_name', 'company_item_number', 'description']
486
+ },
487
+ disabled: {
488
+ required: false,
489
+ default: false
490
+ },
491
+ isNested: {
492
+ required: false,
493
+ default: false
494
+ }
495
+ },
496
+ data() {
497
+ return {
498
+ inputText: '',
499
+ wasClicked: false, // prevents custom-name from being triggered on the <input-text />
500
+ dynamicWidth: [], // for numbers
501
+ dynamicGridWidth: [], // for grid values
502
+ fileIcon: fileIconPng
503
+ }
504
+ },
505
+ methods: {
506
+ toggleOpen(event) {
507
+ if (
508
+ this.disabled ||
509
+ (event &&
510
+ !(event.target === this.$el) &&
511
+ !this.$el.contains(event.target))
512
+ ) {
513
+ return
514
+ }
515
+ this.wasClicked = false
516
+ if (!this.isOpen) {
517
+ document.addEventListener('click', this.clickOutside)
518
+ this.$emit('dropdown-search', '')
519
+ this.$nextTick(() => {
520
+ this.scrollToItem()
521
+ })
522
+ this.$emit('toggle-dropdown-open', { close: false })
523
+ this.$nextTick(() => {
524
+ this.$refs.searchInput.$el.children[0].children[1].focus()
525
+ })
526
+ } else {
596
527
  document.removeEventListener('click', this.clickOutside)
597
528
  this.$emit('toggle-dropdown-open', { close: true })
598
- },
599
- onCustomNameClick() {
600
- this.wasClicked = true
601
- this.$emit('on-custom-input-name', this.inputText)
602
- this.$emit('toggle-dropdown-open', { close: true })
603
529
  this.inputText = ''
604
- },
605
- onCustomInputChange(event) {
606
- if (this.wasClicked) {
607
- return
608
- }
609
- this.$emit('custom-input-change', event)
610
- },
611
- setDropdownWidth(options) {
612
- this.dynamicWidth = []
613
-
614
- options.forEach((item) => {
615
- this.optionsDisplay.forEach((header, index) => {
616
- let value =
617
- header === 'template'
618
- ? this.$gettext('No main component template')
619
- : item[header]
620
- value = value ? value : ''
621
-
622
- // Update dynamicWidth with the maximum value
623
- if (
624
- !this.dynamicWidth[index] ||
625
- value.length > this.dynamicWidth[index]
626
- ) {
627
- this.dynamicWidth[index] = value.length
628
- }
629
- })
530
+ }
531
+ },
532
+ onInputClick() {
533
+ if (!this.isOpen) {
534
+ this.toggleOpen()
535
+ }
536
+ },
537
+ scrollToItem() {
538
+ if (this.$refs.optionsContainer) {
539
+ this.$refs.optionsContainer.$el.scrollIntoView({
540
+ behavior: 'smooth',
541
+ block: 'center'
542
+ })
543
+ }
544
+ },
545
+ onTemplateClick(item) {
546
+ this.$emit('on-template-click', item)
547
+ },
548
+ onSelectedTemplateClick(item) {
549
+ this.$emit('on-selected-template-click', item)
550
+ },
551
+ onItemClick(item) {
552
+ this.wasClicked = true
553
+ this.$emit('item-selected', item)
554
+ },
555
+ onSearch(value) {
556
+ this.inputText = value
557
+ this.$emit('dropdown-search', value)
558
+ },
559
+ clickOutside(event) {
560
+ if (event.target === this.$el || this.$el.contains(event.target)) {
561
+ return
562
+ }
563
+ this.inputText = ''
564
+ // 'close: true' is needed in case a box is open and another box is clicked on
565
+ // so this one will close properly
566
+ document.removeEventListener('click', this.clickOutside)
567
+ this.$emit('toggle-dropdown-open', { close: true })
568
+ },
569
+ onCustomNameClick() {
570
+ this.wasClicked = true
571
+ this.$emit('on-custom-input-name', this.inputText)
572
+ this.$emit('toggle-dropdown-open', { close: true })
573
+ this.inputText = ''
574
+ },
575
+ onCustomInputChange(event) {
576
+ if (this.wasClicked) {
577
+ return
578
+ }
579
+ this.$emit('custom-input-change', event)
580
+ },
581
+ setDropdownWidth(options) {
582
+ this.dynamicWidth = []
583
+
584
+ options.forEach((item) => {
585
+ this.optionsDisplay.forEach((header, index) => {
586
+ let value =
587
+ header === 'template'
588
+ ? this.$gettext('No main component template')
589
+ : item[header]
590
+ value = value ? value : ''
591
+
592
+ // Update dynamicWidth with the maximum value
593
+ if (
594
+ !this.dynamicWidth[index] ||
595
+ value.length > this.dynamicWidth[index]
596
+ ) {
597
+ this.dynamicWidth[index] = value.length
598
+ }
630
599
  })
600
+ })
631
601
 
632
- this.dynamicGridWidth = this.dynamicWidth
633
- .map((width) => width + 'ch')
634
- .join(' ')
635
- },
602
+ this.dynamicGridWidth = this.dynamicWidth
603
+ .map((width) => width + 'ch')
604
+ .join(' ')
605
+ }
606
+ },
607
+ computed: {
608
+ getCustomName() {
609
+ return this.inputText
610
+ },
611
+ theme() {
612
+ return theme
613
+ }
614
+ },
615
+ watch: {
616
+ isOpen(newVal) {
617
+ if (newVal) {
618
+ document.addEventListener('click', this.clickOutside)
619
+ this.$emit('dropdown-search', '')
620
+ this.$nextTick(() => {
621
+ this.$refs.searchInput.$el.children[0].children[0].focus()
622
+ })
623
+ this.$nextTick(() => {
624
+ this.scrollToItem()
625
+ })
626
+ }
636
627
  },
628
+ optionItems: {
629
+ immediate: true,
630
+ handler(val) {
631
+ if (val && val.length) {
632
+ this.setDropdownWidth(val)
633
+ }
634
+ }
635
+ }
637
636
  }
637
+ }
638
638
  </script>