@eturnity/eturnity_reusable_components 7.48.1-EPDM-12680.11 → 7.48.1-dev-14.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 (31) hide show
  1. package/package.json +3 -2
  2. package/src/assets/theme.js +1 -0
  3. package/src/components/buttons/buttonIcon/index.vue +1 -3
  4. package/src/components/buttons/mainButton/index.vue +0 -10
  5. package/src/components/icon/index.vue +0 -1
  6. package/src/components/infoCard/InfoCard.stories.js +170 -0
  7. package/src/components/infoCard/defaultProps.js +7 -0
  8. package/src/components/infoCard/index.vue +107 -22
  9. package/src/components/infoCard/infoCard.spec.js +64 -0
  10. package/src/components/infoText/index.vue +125 -289
  11. package/src/components/inputs/inputNumber/index.vue +11 -185
  12. package/src/components/inputs/inputText/index.vue +2 -23
  13. package/src/components/inputs/radioButton/defaultProps.js +0 -2
  14. package/src/components/inputs/radioButton/index.vue +6 -27
  15. package/src/components/inputs/radioButton/radioButton.spec.js +62 -99
  16. package/src/components/inputs/select/index.vue +29 -69
  17. package/src/components/inputs/select/option/index.vue +2 -11
  18. package/src/components/markerItem/index.vue +1 -8
  19. package/src/components/modals/modal/index.vue +9 -3
  20. package/src/components/sideMenu/index.vue +12 -3
  21. package/src/components/spinner/index.vue +0 -11
  22. package/src/components/tables/mainTable/index.vue +12 -4
  23. package/src/assets/svgIcons/collapse_all.svg +0 -4
  24. package/src/assets/svgIcons/hybrid.svg +0 -4
  25. package/src/assets/svgIcons/module.svg +0 -3
  26. package/src/assets/svgIcons/move_down.svg +0 -3
  27. package/src/assets/svgIcons/move_up.svg +0 -3
  28. package/src/assets/svgIcons/optimizer.svg +0 -6
  29. package/src/assets/svgIcons/string_design.svg +0 -5
  30. package/src/components/infoText/placeholder.vue +0 -225
  31. package/src/components/stringDesign/DropdownMenu/index.vue +0 -715
@@ -1,35 +1,32 @@
1
1
  <template>
2
- <PageContainer ref="container">
3
- <div
4
- ref="icon"
5
- data-test-id="infoText_trigger"
6
- @click="openTrigger === 'onClick' && toggleInfo()"
7
- @mouseenter="openTrigger === 'onHover' && showInfo()"
8
- @mouseleave="openTrigger === 'onHover' && hideInfo()"
9
- >
10
- <IconComponent
11
- :color="iconColor"
12
- cursor="pointer"
13
- name="info"
14
- :size="size"
15
- />
16
- </div>
17
- <Teleport v-if="isVisible" to="body">
18
- <TextWrapper :style="wrapperStyle">
19
- <TextOverlay ref="infoBox" :image="image" :style="boxStyle">
20
- <OverlayImage
21
- v-if="image"
22
- ref="infoImage"
23
- alt="Info Image"
24
- :src="image"
25
- @load="onImageLoad"
26
- />
27
- <span ref="textContent" :style="textStyle" v-html="text"></span>
28
- </TextOverlay>
29
- <Arrow :image="image" :style="arrowStyle" />
30
- </TextWrapper>
31
- </Teleport>
32
- </PageContainer>
2
+ <ComponentWrapper>
3
+ <IconWrapper :size="size">
4
+ <IconImg
5
+ data-test-id="infoText_trigger"
6
+ @click.prevent="toggleShowInfo()"
7
+ @mouseenter="openTrigger == 'onHover' ? toggleShowInfo() : ''"
8
+ @mouseleave="openTrigger == 'onHover' ? toggleShowInfo() : ''"
9
+ >
10
+ <IconComponent
11
+ :color="iconColor"
12
+ cursor="pointer"
13
+ name="info"
14
+ :size="size"
15
+ />
16
+ </IconImg>
17
+ <TextOverlay
18
+ v-if="showInfo"
19
+ :align-arrow="alignArrow"
20
+ :half-computed-text-info-width="halfComputedTextInfoWidth"
21
+ :icon-size="size"
22
+ :info-position="infoPosition"
23
+ :max-width="maxWidth"
24
+ :width="width"
25
+ ><slot></slot>
26
+ <span v-if="text.length > 0" v-html="text"></span>
27
+ </TextOverlay>
28
+ </IconWrapper>
29
+ </ComponentWrapper>
33
30
  </template>
34
31
 
35
32
  <script>
@@ -38,77 +35,90 @@
38
35
  // <info-text
39
36
  // text="Veritatis et quasi architecto beatae vitae"
40
37
  // size="20px"
41
- // openTrigger="onClick"
42
- // buttonType="error"
43
- // image="path/to/image.jpg"
38
+ // alignArrow="right" // which side the arrow should be on
44
39
  // />
45
- import { ref, onMounted, onUnmounted, watch, nextTick, computed } from 'vue'
46
- import IconComponent from '../icon'
47
- import styled from 'vue3-styled-components'
48
40
  import theme from '../../assets/theme.js'
41
+ import styled from 'vue3-styled-components'
42
+ import IconComponent from '../icon'
49
43
 
50
- const TextOverlay = styled('div')`
51
- background-color: ${(props) =>
52
- props.image ? props.theme.colors.white : props.theme.colors.black};
53
- color: ${(props) =>
54
- props.image ? props.theme.colors.grey1 : props.theme.colors.white};
55
- font-size: ${(props) => (props.image ? '12px' : '13px')};
56
- border-radius: 4px;
44
+ const textAttrs = {
45
+ iconSize: String,
46
+ alignArrow: String,
47
+ width: String,
48
+ halfComputedTextInfoWidth: Number,
49
+ infoPosition: String,
50
+ }
51
+ const TextOverlay = styled('div', textAttrs)`
52
+ position: absolute;
53
+ ${(props) =>
54
+ props.infoPosition == 'top'
55
+ ? 'bottom : calc(' + props.iconSize + ' + 15px)'
56
+ : 'top : calc(' + props.iconSize + ' + 15px)'};
57
+ ${(props) =>
58
+ props.alignArrow === 'left'
59
+ ? 'left: calc(' + props.iconSize + ' /2 - 18px)'
60
+ : props.alignArrow === 'center'
61
+ ? 'left: calc((-' + props.width + ' + ' + props.iconSize + ') /2 + 2px)'
62
+ : 'right: calc(' + props.iconSize + ' /2 - 17px)'};
63
+ text-align: left;
64
+ background: ${(props) => props.theme.colors.black};
57
65
  padding: 10px;
58
- word-wrap: break-word;
59
- overflow-wrap: break-word;
60
- white-space: normal;
61
- width: 100%; // Ensure the TextOverlay takes full width of its parent
62
- box-shadow: ${(props) =>
63
- props.image ? '0 2px 10px rgba(0, 0, 0, 0.1)' : 'none'};
66
+ width: ${(props) => props.width};
67
+ max-width: ${(props) => props.maxWidth};
68
+ font-size: 13px;
69
+ font-weight: 400;
70
+ line-height: normal;
71
+ border-radius: 4px;
72
+ z-index: 999;
73
+ color: ${(props) => props.theme.colors.white};
64
74
 
65
- a {
66
- color: ${(props) => props.theme.colors.blue};
67
- }
75
+ :before {
76
+ content: '';
77
+ background-color: ${(props) => props.theme.colors.black};
78
+ position: absolute;
68
79
 
69
- img + span {
70
- margin-top: 10px;
71
- display: block;
72
- }
73
- `
80
+ ${(props) =>
81
+ props.infoPosition == 'top' ? 'bottom : -10px' : 'top: 2px'};
74
82
 
75
- const Arrow = styled('div')`
76
- position: absolute;
77
- width: 0;
78
- height: 0;
79
- border-left: 8px solid transparent;
80
- border-right: 8px solid transparent;
81
- border-top: 8px solid
82
83
  ${(props) =>
83
- props.image ? props.theme.colors.white : props.theme.colors.black};
84
- filter: ${(props) =>
85
- props.image ? 'drop-shadow(0 2px 2px rgba(0, 0, 0, 0.1))' : 'none'};
84
+ props.alignArrow === 'left'
85
+ ? 'left:40px;'
86
+ : props.alignArrow == 'center'
87
+ ? 'left: calc(50% + 19px);'
88
+ : 'right:-13px;'};
89
+ height: 8px;
90
+ width: 8px;
91
+ transform-origin: center center;
92
+ transform: translate(-2em, -0.5em) rotate(45deg);
93
+ }
94
+
95
+ span a {
96
+ color: #2cc0eb;
97
+ }
86
98
  `
87
99
 
88
- const PageContainer = styled('div')`
89
- display: inline-block;
100
+ const iconAttrs = { size: String }
101
+ const IconWrapper = styled('div', iconAttrs)`
90
102
  position: relative;
103
+ height: ${(props) => props.size};
91
104
  `
92
105
 
93
- const TextWrapper = styled('div')`
94
- z-index: 99999;
95
- position: absolute;
106
+ const IconImg = styled.div`
107
+ line-height: 0;
96
108
  `
97
109
 
98
- const OverlayImage = styled('img')`
99
- width: 100%;
100
- height: auto;
110
+ const ComponentWrapper = styled.div`
111
+ display: inline-block;
101
112
  `
102
113
 
103
114
  export default {
104
115
  name: 'InfoText',
105
116
  components: {
106
- IconComponent,
117
+ IconWrapper,
107
118
  TextOverlay,
108
- Arrow,
109
- PageContainer,
110
- TextWrapper,
111
- OverlayImage,
119
+ ComponentWrapper,
120
+ IconImg,
121
+ IconComponent,
112
122
  },
113
123
  props: {
114
124
  text: {
@@ -117,7 +127,7 @@
117
127
  type: String,
118
128
  },
119
129
  size: {
120
- type: String,
130
+ required: false,
121
131
  default: '14px',
122
132
  type: String,
123
133
  },
@@ -126,228 +136,54 @@
126
136
  default: 'bottom',
127
137
  type: String,
128
138
  },
129
- maxWidth: {
130
- default: '400px',
139
+ alignArrow: {
140
+ required: false,
141
+ default: 'center',
131
142
  type: String,
132
143
  },
133
144
  openTrigger: {
145
+ required: false,
146
+ default: 'onHover', // onHover, onClick
134
147
  type: String,
135
- default: 'onHover',
136
- validator: (value) => ['onHover', 'onClick'].includes(value),
137
148
  },
138
- buttonType: {
149
+ width: {
150
+ required: false,
151
+ default: '165px',
139
152
  type: String,
140
- default: 'regular',
141
- validator: (value) => ['regular', 'error'].includes(value),
142
153
  },
143
- image: {
154
+ maxWidth: {
155
+ default: '400px',
144
156
  type: String,
145
- default: '',
146
157
  },
147
158
  },
148
- setup(props) {
149
- const isVisible = ref(false)
150
- const container = ref(null)
151
- const icon = ref(null)
152
- const infoBox = ref(null)
153
- const textContent = ref(null)
154
- const infoImage = ref(null)
155
- const infoBoxWidth = ref(0)
156
- const infoBoxHeight = ref(0)
157
- const boxStyle = ref({})
158
- const arrowStyle = ref({})
159
- const wrapperStyle = ref({})
160
-
161
- const textStyle = computed(() => ({
162
- fontSize: props.image ? '12px' : '13px',
163
- color: props.image ? theme.colors.grey1 : theme.colors.white,
164
- textAlign: props.image ? 'right' : 'left',
165
- }))
166
-
167
- const calculatePosition = (width) => {
168
- if (!icon.value) return {}
169
-
170
- const iconRect = icon.value.getBoundingClientRect()
171
- const windowHeight = window.innerHeight
172
- const windowWidth = window.innerWidth
173
-
174
- let top = iconRect.bottom + 10
175
- let left = iconRect.left
176
-
177
- // Adjust left based on the infoBoxWidth
178
- if (left + width > windowWidth) {
179
- left = windowWidth - width - 10
180
- }
181
-
182
- // Ensure there's enough space below or place above if not
183
- const isAbove = top + infoBoxHeight.value > windowHeight
184
- if (isAbove) {
185
- top = iconRect.top - infoBoxHeight.value - 10
186
- }
187
-
188
- // Calculate arrow position
189
- let arrowLeft = iconRect.left - left + iconRect.width / 2 - 8
190
-
191
- // Adjust arrow position if it's too close to the edges
192
- const edgeThreshold = 2 // pixels from the edge to start adjusting
193
- if (arrowLeft < edgeThreshold) {
194
- arrowLeft = edgeThreshold
195
- } else if (arrowLeft > width - 16 - edgeThreshold) {
196
- arrowLeft = width - 16 - edgeThreshold
197
- }
198
-
199
- const arrowTop = isAbove ? 'auto' : '-7px'
200
- const arrowBottom = isAbove ? '-7px' : 'auto'
201
-
202
- arrowStyle.value = {
203
- left: `${arrowLeft}px`,
204
- top: arrowTop,
205
- bottom: arrowBottom,
206
- transform: isAbove ? 'none' : 'rotate(180deg)',
207
- }
208
-
209
- wrapperStyle.value = {
210
- position: 'fixed',
211
- top: `${top}px`,
212
- left: `${left}px`,
213
- transform: 'none',
214
- width: `${width}px`, // Set a fixed width for the wrapper
215
- }
216
-
217
- return {
218
- width: '100%', // Always use 100% width for the TextOverlay
219
- maxWidth: props.maxWidth,
220
- overflowY: 'auto',
221
- backgroundColor: props.image
222
- ? theme.colors.white
223
- : theme.colors.black,
224
- }
225
- }
226
-
227
- const showInfo = async () => {
228
- isVisible.value = true
229
- await nextTick()
230
- updatePosition()
231
- }
232
-
233
- const hideInfo = () => {
234
- isVisible.value = false
235
- }
236
-
237
- const toggleInfo = () => {
238
- isVisible.value ? hideInfo() : showInfo()
239
- }
240
-
241
- const handleScroll = () => {
242
- if (isVisible.value) {
243
- hideInfo()
244
- }
245
- updatePosition()
246
- }
247
-
248
- const isIconInView = () => {
249
- if (!icon.value) return false
250
- const rect = icon.value.getBoundingClientRect()
251
- return (
252
- rect.top >= 0 &&
253
- rect.left >= 0 &&
254
- rect.bottom <=
255
- (window.innerHeight || document.documentElement.clientHeight) &&
256
- rect.right <=
257
- (window.innerWidth || document.documentElement.clientWidth)
258
- )
259
- }
260
-
261
- const updatePosition = async () => {
262
- if (infoBox.value && textContent.value) {
263
- await nextTick()
264
-
265
- if (isIconInView()) {
266
- const contentWidth = textContent.value.offsetWidth
267
- infoBoxWidth.value = Math.min(
268
- Math.max(contentWidth, 200), // Set a minimum width of 200px
269
- parseInt(props.maxWidth, 10)
270
- )
271
- infoBoxHeight.value = infoBox.value.$el.offsetHeight
272
- boxStyle.value = calculatePosition(infoBoxWidth.value)
273
-
274
- // Now make it visible if it should be
275
- if (isVisible.value) {
276
- infoBox.value.$el.style.visibility = 'visible'
277
- }
278
- } else if (isVisible.value) {
279
- hideInfo()
280
- }
281
- }
282
- }
283
-
284
- const onImageLoad = () => {
285
- if (infoImage.value) {
286
- infoBoxHeight.value = infoBox.value.$el.offsetHeight
287
- updatePosition()
288
- }
289
- }
290
-
291
- const handleClickOutside = (event) => {
292
- if (props.openTrigger === 'onClick' && isVisible.value) {
293
- const clickedElement = event.target
294
- if (
295
- infoBox.value &&
296
- !infoBox.value.$el.contains(clickedElement) &&
297
- !icon.value.contains(clickedElement)
298
- ) {
299
- hideInfo()
300
- }
301
- }
302
- }
303
-
304
- onMounted(() => {
305
- window.addEventListener('scroll', handleScroll, { passive: true })
306
- window.addEventListener('resize', updatePosition)
307
- document.addEventListener('scroll', handleScroll, {
308
- passive: true,
309
- capture: true,
310
- })
311
- document.addEventListener('click', handleClickOutside)
312
- })
313
-
314
- onUnmounted(() => {
315
- window.removeEventListener('scroll', handleScroll)
316
- window.removeEventListener('resize', updatePosition)
317
- document.removeEventListener('scroll', handleScroll, { capture: true })
318
- document.removeEventListener('click', handleClickOutside)
319
- })
320
-
321
- watch(isVisible, (newValue) => {
322
- if (newValue) {
323
- updatePosition()
324
- }
325
- })
326
-
159
+ data() {
327
160
  return {
328
- isVisible,
329
- boxStyle,
330
- arrowStyle,
331
- showInfo,
332
- hideInfo,
333
- toggleInfo,
334
- container,
335
- icon,
336
- infoBox,
337
- textContent,
338
- infoImage,
339
- infoBoxWidth,
340
- infoBoxHeight,
341
- wrapperStyle,
342
- textStyle,
343
- onImageLoad,
161
+ showInfo: false,
344
162
  }
345
163
  },
346
164
  computed: {
347
165
  iconColor() {
348
- return this.buttonType === 'error'
349
- ? theme.colors.red
350
- : theme.colors.mediumGray
166
+ return theme.colors.mediumGray
167
+ },
168
+ halfComputedTextInfoWidth() {
169
+ return parseInt(this.width) / 2
170
+ },
171
+ },
172
+ methods: {
173
+ toggleShowInfo() {
174
+ this.showInfo = !this.showInfo
175
+
176
+ if (this.showInfo) {
177
+ document.addEventListener('click', this.clickOutside)
178
+ } else {
179
+ document.removeEventListener('click', this.clickOutside)
180
+ }
181
+ },
182
+ clickOutside(event) {
183
+ if (this.$el.contains(event.target)) {
184
+ return
185
+ }
186
+ this.toggleShowInfo()
351
187
  },
352
188
  },
353
189
  }