@eturnity/eturnity_reusable_components 1.0.46 → 1.0.50

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.46",
3
+ "version": "1.0.50",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "dev": "vue-cli-service serve",
package/src/App.vue CHANGED
@@ -13,20 +13,6 @@
13
13
  </thead>
14
14
  <tbody>
15
15
  <tr>
16
- <td>
17
- <input-number
18
- placeholder="Enter distance"
19
- :isError="false"
20
- :numberPrecision="2"
21
- unitName="pc"
22
- :value="inputValue"
23
- @input-change="onInputChange($event)"
24
- errorMessage="Enter a number between 1 and 10"
25
- :disabled="false"
26
- :noBorder="true"
27
- textAlign="left"
28
- />
29
- </td>
30
16
  <td class="text">Body 2</td>
31
17
  <td class="text">Body 3</td>
32
18
  <td class="text">Body 4</td>
@@ -36,6 +22,9 @@
36
22
  </tr>
37
23
  </tbody>
38
24
  </main-table>
25
+ <br />
26
+ <br />
27
+ <search-input :value="inputValue" @on-change="onInputChange" :disabled="false" placeholder="Search..." />
39
28
  </page-container>
40
29
  </ThemeProvider>
41
30
  </template>
@@ -46,7 +35,7 @@ import theme from "./assets/theme"
46
35
  import styled from "vue-styled-components"
47
36
  import MainTable from "@/components/tables/mainTable"
48
37
  import ThreeDots from "@/components/threeDots"
49
- import InputNumber from "@/components/inputs/inputNumber"
38
+ import SearchInput from "@/components/inputs/searchInput"
50
39
 
51
40
  const PageContainer = styled.div`
52
41
  padding: 40px;
@@ -59,7 +48,7 @@ export default {
59
48
  PageContainer,
60
49
  MainTable,
61
50
  ThreeDots,
62
- InputNumber,
51
+ SearchInput,
63
52
  },
64
53
  data() {
65
54
  return {
@@ -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,3 @@
1
+ <svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M14.9751 13.6383L11.3396 9.9957C12.0755 8.94938 12.4395 7.6858 12.3731 6.40752C12.3068 5.12923 11.8141 3.91027 10.9739 2.94605C10.1337 1.98183 8.9947 1.3282 7.73954 1.08993C6.48437 0.85166 5.1857 1.04256 4.05173 1.63202C2.91776 2.22148 2.01415 3.17536 1.48577 4.34076C0.957383 5.50615 0.834825 6.81556 1.13774 8.05906C1.44065 9.30257 2.1515 10.4082 3.15631 11.1986C4.16113 11.989 5.40173 12.4185 6.67922 12.4183C7.86776 12.418 9.02614 12.0434 9.99056 11.3474L13.626 14.9901L14.9751 13.6383ZM3.98109 9.38128C3.44671 8.84727 3.08262 8.16629 2.93499 7.42469C2.78736 6.68309 2.86284 5.91427 3.15185 5.2157C3.44086 4.51713 3.93039 3.92029 4.55837 3.50084C5.18635 3.08139 5.9245 2.85823 6.67922 2.85965C7.40253 2.85844 8.11118 3.06399 8.72198 3.45218C9.33279 3.84037 9.8204 4.39508 10.1276 5.05121C10.4348 5.70735 10.5488 6.43766 10.4562 7.15645C10.3637 7.87523 10.0684 8.55264 9.60512 9.10918L9.09703 9.61827C8.37063 10.2302 7.44086 10.5457 6.49283 10.5017C5.54479 10.4578 4.64804 10.0578 3.98109 9.38128Z" fill="#263238"/>
3
+ </svg>
@@ -89,6 +89,7 @@ const InputContainer = styled("input", inputProps)`
89
89
  props.isDisabled
90
90
  ? props.theme.colors.grey5 + " !important"
91
91
  : "#fff !important"};
92
+ box-sizing: border-box;
92
93
 
93
94
  &::placeholder {
94
95
  color: ${(props) =>
@@ -0,0 +1,84 @@
1
+ <template>
2
+ <container>
3
+ <input-wrapper>
4
+ <input-container
5
+ :placeholder="placeholder"
6
+ :value="value"
7
+ @input="onChangeHandler($event)"
8
+ :disabled="disabled"
9
+ :isDisabled="disabled"
10
+ />
11
+ <img
12
+ class="search-icn"
13
+ :src="require('../../../assets/icons/search_icon_black.svg')"
14
+ />
15
+ </input-wrapper>
16
+ </container>
17
+ </template>
18
+
19
+ <script>
20
+ // import SearchInput from "@eturnity/eturnity_reusable_components/src/components/inputs/searchInput"
21
+ import styled from 'vue-styled-components'
22
+
23
+ const Container = styled.div`
24
+ width: 100%;
25
+ position: relative;
26
+ `
27
+
28
+ const inputAttrs = { isDisabled: Boolean }
29
+ const InputContainer = styled('input', inputAttrs)`
30
+ border: 1px solid ${(props) => props.theme.colors.mediumGray};
31
+ padding: 11px 30px 11px 10px;
32
+ border-radius: 4px;
33
+ font-size: 16px;
34
+ color: ${(props) => props.theme.colors.black};
35
+ width: 100%;
36
+ box-sizing: border-box;
37
+ cursor: ${props => props.isDisabled ? 'not-allowed' : 'auto'};
38
+
39
+ &::placeholder {
40
+ color: ${(props) => props.theme.colors.darkGray};
41
+ }
42
+
43
+ &:focus {
44
+ outline: none;
45
+ }
46
+ `
47
+
48
+ const InputWrapper = styled.span`
49
+ position: relative;
50
+
51
+ img {
52
+ position: absolute;
53
+ right: 10px;
54
+ top: 0;
55
+ }
56
+ `
57
+
58
+ export default {
59
+ name: "search-input",
60
+ components: {
61
+ InputContainer,
62
+ InputWrapper,
63
+ Container
64
+ },
65
+ props: {
66
+ value: {
67
+ required: true
68
+ },
69
+ disabled: {
70
+ required: false,
71
+ default: false
72
+ },
73
+ placeholder: {
74
+ required: false,
75
+ default: ''
76
+ }
77
+ },
78
+ methods: {
79
+ onChangeHandler(event) {
80
+ this.$emit('on-change', event)
81
+ }
82
+ }
83
+ }
84
+ </script>
@@ -10,6 +10,7 @@
10
10
  </template>
11
11
 
12
12
  <script>
13
+ // import Spinner from "@eturnity/eturnity_reusable_components/src/components/spinner"
13
14
  import styled from "vue-styled-components"
14
15
 
15
16
  const SpinnerContainer = styled.div`
@@ -0,0 +1,286 @@
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/images/collapse_arrow_icon.svg')"
18
+ />
19
+ <arrow-up
20
+ v-else
21
+ :src="require('../../assets/images/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
+ overflow: hidden;
90
+ text-overflow: ellipsis;
91
+ `
92
+
93
+ const containerAttrs = { colSpan: Number }
94
+ const ComponentContainer = styled("div", containerAttrs)`
95
+ display: grid;
96
+ grid-template-columns: repeat(${(props) => props.colSpan}, minmax(0, 1fr)) auto;
97
+ grid-gap: 12px;
98
+ align-items: center;
99
+ background-color: #fff;
100
+ border-radius: 4px;
101
+ padding: 5px 4px;
102
+ `
103
+
104
+ const ArrowDown = styled.img`
105
+ width: 8px;
106
+ transform: rotate(0deg);
107
+ transition: transform 150ms ease;
108
+ `
109
+
110
+ const ArrowUp = styled.img`
111
+ width: 8px;
112
+ transform: rotate(180deg);
113
+ transition: transform 150ms ease;
114
+ `
115
+
116
+ const optionsAttrs = { top: Number, width: Number }
117
+ const OptionsContainer = styled("div", optionsAttrs)`
118
+ position: absolute;
119
+ display: grid;
120
+ top: ${(props) => props.top + "px"};
121
+ width: ${(props) => props.width + "px"};
122
+ max-height: 360px;
123
+ min-height: 200px;
124
+ overflow: auto;
125
+ border: 1px solid ${(props) => props.theme.colors.grey3};
126
+ z-index: 9999;
127
+ background: #fff;
128
+ border-radius: 4px;
129
+ `
130
+
131
+ const EmptyText = styled.div`
132
+ align-self: center;
133
+ justify-self: center;
134
+ height: 100px;
135
+ display: grid;
136
+ align-content: center;
137
+ `
138
+
139
+ const OptionsWrapper = styled.div`
140
+ display: grid;
141
+ position: relative;
142
+ padding: 12px;
143
+ grid-gap: 4px;
144
+ font-size: 14px;
145
+ grid-template-rows: max-content;
146
+ height: max-content;
147
+ `
148
+
149
+ const OptionsItem = styled("div", containerAttrs)`
150
+ display: grid;
151
+ grid-template-columns: repeat(${(props) => props.colSpan}, minmax(0, 1fr));
152
+ grid-gap: 12px;
153
+ overflow: hidden;
154
+ text-overflow: ellipsis;
155
+ padding: 10px;
156
+ height: max-content;
157
+
158
+ &:hover {
159
+ background-color: ${(props) => props.theme.colors.grey5};
160
+ }
161
+ `
162
+
163
+ const SearchContainer = styled.div`
164
+ position: sticky;
165
+ top: 0;
166
+ padding-top: 6px;
167
+ background: #fff;
168
+ height: 40px;
169
+ `
170
+
171
+ export default {
172
+ name: "table-dropdown",
173
+ components: {
174
+ DropdownRow,
175
+ ComponentItem,
176
+ ComponentContainer,
177
+ ArrowDown,
178
+ ArrowUp,
179
+ OptionsContainer,
180
+ Spinner,
181
+ EmptyText,
182
+ SearchInput,
183
+ OptionsWrapper,
184
+ OptionsItem,
185
+ SearchContainer,
186
+ },
187
+ props: {
188
+ colSpan: {
189
+ required: false,
190
+ default: 1,
191
+ },
192
+ tableItems: {
193
+ required: true,
194
+ },
195
+ showArchived: {
196
+ required: false,
197
+ default: false,
198
+ },
199
+ isOpen: {
200
+ required: true,
201
+ default: false,
202
+ },
203
+ optionsLoading: {
204
+ required: false,
205
+ default: false,
206
+ },
207
+ emptyText: {
208
+ required: false,
209
+ default: null,
210
+ },
211
+ optionItems: {
212
+ required: true,
213
+ },
214
+ optionsDisplay: {
215
+ required: true,
216
+ default: [], // should be like ['display_name', 'company_item_number', 'description']
217
+ },
218
+ },
219
+ data() {
220
+ return {
221
+ inputText: "",
222
+ }
223
+ },
224
+ methods: {
225
+ toggleOpen() {
226
+ if (!this.isOpen) {
227
+ document.addEventListener("click", this.clickOutside)
228
+ this.$emit("dropdown-search", "")
229
+ this.$nextTick(() => {
230
+ this.scrollToItem()
231
+ })
232
+ this.$emit("toggle-dropdown-open", { close: false })
233
+ this.$nextTick(() => {
234
+ this.$refs.searchInput.$el.children[0].children[0].focus()
235
+ })
236
+ } else {
237
+ document.removeEventListener("click", this.clickOutside)
238
+ this.$emit("toggle-dropdown-open", { close: true })
239
+ }
240
+ },
241
+ scrollToItem() {
242
+ this.$refs.optionsContainer.$el.scrollIntoView({
243
+ behavior: "smooth",
244
+ block: "center",
245
+ })
246
+ },
247
+ onItemClick(item) {
248
+ this.$emit("item-selected", item)
249
+ },
250
+ onSearch(value) {
251
+ this.$emit("dropdown-search", value)
252
+ },
253
+ getItemLocation(value) {
254
+ let ref = this.$refs.dropdownItem
255
+ let location = ref.$el.getBoundingClientRect()[value]
256
+ if (value === "top") {
257
+ location = location + window.scrollY + 40
258
+ }
259
+ return location
260
+ },
261
+ clickOutside(event) {
262
+ if (event.target === this.$el || this.$el.contains(event.target)) {
263
+ return
264
+ }
265
+ // 'close: true' is needed in case a box is open and another box is clicked on
266
+ // so this one will close properly
267
+ document.removeEventListener("click", this.clickOutside)
268
+ this.$emit("toggle-dropdown-open", { close: true })
269
+ },
270
+ },
271
+ watch: {
272
+ isOpen(newVal) {
273
+ if (newVal) {
274
+ document.addEventListener("click", this.clickOutside)
275
+ this.$emit("dropdown-search", "")
276
+ this.$nextTick(() => {
277
+ this.$refs.searchInput.$el.children[0].children[0].focus()
278
+ })
279
+ this.$nextTick(() => {
280
+ this.scrollToItem()
281
+ })
282
+ }
283
+ },
284
+ },
285
+ }
286
+ </script>
@@ -31,7 +31,7 @@ const TableTitle = styled.div`
31
31
  `
32
32
 
33
33
  const TableScroll = styled.div`
34
- position: relative;
34
+ /* position: relative; */
35
35
  max-width: 100%;
36
36
  `
37
37