@eturnity/eturnity_reusable_components 1.0.48 → 1.0.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eturnity/eturnity_reusable_components",
3
- "version": "1.0.48",
3
+ "version": "1.0.52",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "dev": "vue-cli-service serve",
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 5"><g data-name="Layer 2"><path fill="#263238" d="M0 0h8L4 5 0 0z" data-name="Layer 1"/></g></svg>
@@ -0,0 +1,289 @@
1
+ <template>
2
+ <dropdown-row :colspan="colSpan" @click="toggleOpen" ref="dropdownItem">
3
+ <component-container :colSpan="colSpan">
4
+ <component-item v-for="(item, index) in tableItems" :key="index">
5
+ {{ item.value }}
6
+ </component-item>
7
+ <et-popover
8
+ v-if="showArchived"
9
+ style="position: absolute; left: 5px; top: 13px; z-index: 99"
10
+ button-class="error"
11
+ :text="$gettext(`Component has been archived and shouldn't be used`)"
12
+ triggerType="hover"
13
+ ></et-popover>
14
+ <arrow-down
15
+ v-if="!isOpen"
16
+ class="arrow-dropdown"
17
+ :src="require('../../assets/icons/collapse_arrow_icon.svg')"
18
+ />
19
+ <arrow-up
20
+ v-else
21
+ :src="require('../../assets/icons/collapse_arrow_icon.svg')"
22
+ />
23
+ </component-container>
24
+ <options-container
25
+ v-if="isOpen"
26
+ :top="getItemLocation('top')"
27
+ :width="getItemLocation('width')"
28
+ ref="optionsContainer"
29
+ >
30
+ <options-wrapper @click.prevent.stop>
31
+ <search-container @click.prevent.stop>
32
+ <search-input
33
+ :value="inputText"
34
+ :placeholder="$gettext('Keyword') + '...'"
35
+ @click.prevent.stop
36
+ @on-change="onSearch($event)"
37
+ ref="searchInput"
38
+ />
39
+ </search-container>
40
+ <spinner v-if="optionsLoading" />
41
+ <empty-text v-else-if="!optionsLoading && !optionItems.length">
42
+ {{ emptyText ? emptyText : $gettext("No components found.") }}
43
+ </empty-text>
44
+ <options-item
45
+ v-else
46
+ :colSpan="colSpan"
47
+ v-for="(item, index) in optionItems"
48
+ :key="index"
49
+ @click="onItemClick(item)"
50
+ :tabindex="0"
51
+ @keyup.enter.native="onItemClick(item)"
52
+ >
53
+ <span v-for="(option, idx) in optionsDisplay" :key="idx">
54
+ {{ item[option] }}
55
+ </span>
56
+ </options-item>
57
+ </options-wrapper>
58
+ </options-container>
59
+ </dropdown-row>
60
+ </template>
61
+
62
+ <script>
63
+ // import TableDropdown from "@eturnity/eturnity_reusable_components/src/components/tableDropdown"
64
+ // To use:
65
+ // <table-dropdown
66
+ // :colSpan="2"
67
+ // :tableItems="getDropdownValues(row)"
68
+ // :showArchived="
69
+ // row.selectedValue
70
+ // ? row.selectedValue.status_active === false
71
+ // : row.status_active === false
72
+ // "
73
+ // @toggle-dropdown-open="toggleDropdownOpen(row.id, $event)"
74
+ // @dropdown-search="onDropdownSearch($event)"
75
+ // @item-selected="onItemSelected({ item: $event, index })"
76
+ // :isOpen="isDropdownOpen(row)"
77
+ // :optionItems="groupComponents" // list of options
78
+ // :optionsLoading="dropdownOptionsLoading"
79
+ // :optionsDisplay="['display_name', 'company_item_number']" // Array. what should be displayed
80
+ // />
81
+ import styled from "vue-styled-components"
82
+ import Spinner from "@eturnity/eturnity_reusable_components/src/components/spinner"
83
+ import SearchInput from "@eturnity/eturnity_reusable_components/src/components/inputs/searchInput"
84
+
85
+ const DropdownRow = styled.td``
86
+
87
+ const ComponentItem = styled.div`
88
+ padding-left: 12px;
89
+
90
+ span {
91
+ overflow: hidden;
92
+ text-overflow: ellipsis;
93
+ }
94
+ `
95
+
96
+ const containerAttrs = { colSpan: Number }
97
+ const ComponentContainer = styled("div", containerAttrs)`
98
+ display: grid;
99
+ grid-template-columns: repeat(${(props) => props.colSpan}, minmax(0, 1fr)) auto;
100
+ grid-gap: 12px;
101
+ align-items: center;
102
+ background-color: #fff;
103
+ border-radius: 4px;
104
+ padding: 5px 4px;
105
+ `
106
+
107
+ const ArrowDown = styled.img`
108
+ width: 8px;
109
+ transform: rotate(0deg);
110
+ transition: transform 150ms ease;
111
+ `
112
+
113
+ const ArrowUp = styled.img`
114
+ width: 8px;
115
+ transform: rotate(180deg);
116
+ transition: transform 150ms ease;
117
+ `
118
+
119
+ const optionsAttrs = { top: Number, width: Number }
120
+ const OptionsContainer = styled("div", optionsAttrs)`
121
+ position: absolute;
122
+ display: grid;
123
+ top: ${(props) => props.top + "px"};
124
+ width: ${(props) => props.width + "px"};
125
+ max-height: 360px;
126
+ min-height: 200px;
127
+ overflow: auto;
128
+ border: 1px solid ${(props) => props.theme.colors.grey3};
129
+ z-index: 9999;
130
+ background: #fff;
131
+ border-radius: 4px;
132
+ `
133
+
134
+ const EmptyText = styled.div`
135
+ align-self: center;
136
+ justify-self: center;
137
+ height: 100px;
138
+ display: grid;
139
+ align-content: center;
140
+ `
141
+
142
+ const OptionsWrapper = styled.div`
143
+ display: grid;
144
+ position: relative;
145
+ padding: 12px;
146
+ grid-gap: 4px;
147
+ font-size: 14px;
148
+ grid-template-rows: max-content;
149
+ height: max-content;
150
+ `
151
+
152
+ const OptionsItem = styled("div", containerAttrs)`
153
+ display: grid;
154
+ grid-template-columns: repeat(${(props) => props.colSpan}, minmax(0, 1fr));
155
+ grid-gap: 12px;
156
+ overflow: hidden;
157
+ text-overflow: ellipsis;
158
+ padding: 10px;
159
+ height: max-content;
160
+
161
+ &:hover {
162
+ background-color: ${(props) => props.theme.colors.grey5};
163
+ }
164
+ `
165
+
166
+ const SearchContainer = styled.div`
167
+ position: sticky;
168
+ top: 0;
169
+ padding-top: 6px;
170
+ background: #fff;
171
+ height: 40px;
172
+ `
173
+
174
+ export default {
175
+ name: "table-dropdown",
176
+ components: {
177
+ DropdownRow,
178
+ ComponentItem,
179
+ ComponentContainer,
180
+ ArrowDown,
181
+ ArrowUp,
182
+ OptionsContainer,
183
+ Spinner,
184
+ EmptyText,
185
+ SearchInput,
186
+ OptionsWrapper,
187
+ OptionsItem,
188
+ SearchContainer,
189
+ },
190
+ props: {
191
+ colSpan: {
192
+ required: false,
193
+ default: 1,
194
+ },
195
+ tableItems: {
196
+ required: true,
197
+ },
198
+ showArchived: {
199
+ required: false,
200
+ default: false,
201
+ },
202
+ isOpen: {
203
+ required: true,
204
+ default: false,
205
+ },
206
+ optionsLoading: {
207
+ required: false,
208
+ default: false,
209
+ },
210
+ emptyText: {
211
+ required: false,
212
+ default: null,
213
+ },
214
+ optionItems: {
215
+ required: true,
216
+ },
217
+ optionsDisplay: {
218
+ required: true,
219
+ default: [], // should be like ['display_name', 'company_item_number', 'description']
220
+ },
221
+ },
222
+ data() {
223
+ return {
224
+ inputText: "",
225
+ }
226
+ },
227
+ methods: {
228
+ toggleOpen() {
229
+ if (!this.isOpen) {
230
+ document.addEventListener("click", this.clickOutside)
231
+ this.$emit("dropdown-search", "")
232
+ this.$nextTick(() => {
233
+ this.scrollToItem()
234
+ })
235
+ this.$emit("toggle-dropdown-open", { close: false })
236
+ this.$nextTick(() => {
237
+ this.$refs.searchInput.$el.children[0].children[0].focus()
238
+ })
239
+ } else {
240
+ document.removeEventListener("click", this.clickOutside)
241
+ this.$emit("toggle-dropdown-open", { close: true })
242
+ }
243
+ },
244
+ scrollToItem() {
245
+ this.$refs.optionsContainer.$el.scrollIntoView({
246
+ behavior: "smooth",
247
+ block: "center",
248
+ })
249
+ },
250
+ onItemClick(item) {
251
+ this.$emit("item-selected", item)
252
+ },
253
+ onSearch(value) {
254
+ this.$emit("dropdown-search", value)
255
+ },
256
+ getItemLocation(value) {
257
+ let ref = this.$refs.dropdownItem
258
+ let location = ref.$el.getBoundingClientRect()[value]
259
+ if (value === "top") {
260
+ location = location + window.scrollY + 40
261
+ }
262
+ return location
263
+ },
264
+ clickOutside(event) {
265
+ if (event.target === this.$el || this.$el.contains(event.target)) {
266
+ return
267
+ }
268
+ // 'close: true' is needed in case a box is open and another box is clicked on
269
+ // so this one will close properly
270
+ document.removeEventListener("click", this.clickOutside)
271
+ this.$emit("toggle-dropdown-open", { close: true })
272
+ },
273
+ },
274
+ watch: {
275
+ isOpen(newVal) {
276
+ if (newVal) {
277
+ document.addEventListener("click", this.clickOutside)
278
+ this.$emit("dropdown-search", "")
279
+ this.$nextTick(() => {
280
+ this.$refs.searchInput.$el.children[0].children[0].focus()
281
+ })
282
+ this.$nextTick(() => {
283
+ this.scrollToItem()
284
+ })
285
+ }
286
+ },
287
+ },
288
+ }
289
+ </script>