@eturnity/eturnity_reusable_components 7.51.3-EPDM-12810.1 → 7.51.3-EPDM-12810.2
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 +2 -3
- package/src/assets/gifs/spinner.gif +0 -0
- package/src/assets/svgIcons/checkmark.svg +3 -0
- package/src/assets/svgIcons/collapse_all.svg +4 -0
- package/src/assets/svgIcons/expand_all.svg +4 -0
- package/src/assets/svgIcons/export_document.svg +3 -0
- package/src/assets/svgIcons/hybrid.svg +4 -0
- package/src/assets/svgIcons/module.svg +3 -0
- package/src/assets/svgIcons/move_down.svg +3 -0
- package/src/assets/svgIcons/move_up.svg +3 -0
- package/src/assets/svgIcons/optimizer.svg +6 -0
- package/src/assets/svgIcons/string_design.svg +5 -0
- package/src/assets/svgIcons/string_directions.svg +10 -0
- package/src/components/banner/notificationBanner/index.vue +131 -0
- package/src/components/buttons/buttonIcon/index.vue +4 -2
- package/src/components/buttons/mainButton/index.vue +16 -2
- package/src/components/card/index.vue +1 -1
- package/src/components/icon/Icons.stories.js +9 -19
- package/src/components/icon/icon.spec.js +66 -0
- package/src/components/icon/iconCollection.vue +4 -3
- package/src/components/icon/index.vue +9 -2
- package/src/components/infoText/index.vue +210 -74
- package/src/components/inputs/checkbox/index.vue +19 -8
- package/src/components/inputs/inputNumber/index.vue +202 -12
- package/src/components/inputs/inputText/index.vue +36 -2
- package/src/components/inputs/radioButton/index.vue +27 -6
- package/src/components/inputs/select/index.vue +68 -24
- package/src/components/inputs/select/option/index.vue +11 -2
- package/src/components/label/index.vue +1 -2
- package/src/components/markerItem/index.vue +8 -1
- package/src/components/spinner/index.vue +11 -0
- package/src/components/spinnerGif/index.vue +98 -0
- package/src/components/stringDesign/DropdownMenu/index.vue +983 -0
- package/src/components/tableDropdown/index.vue +51 -20
@@ -2,20 +2,27 @@
|
|
2
2
|
<PageContainer ref="container">
|
3
3
|
<div
|
4
4
|
ref="icon"
|
5
|
-
|
6
|
-
@
|
7
|
-
@
|
5
|
+
data-test-id="infoText_trigger"
|
6
|
+
@click=";(isMobile || openTrigger === 'onClick') && toggleInfo()"
|
7
|
+
@mouseenter="!isMobile && openTrigger === 'onHover' && showInfo()"
|
8
|
+
@mouseleave="!isMobile && openTrigger === 'onHover' && hideInfo()"
|
8
9
|
>
|
9
10
|
<IconComponent
|
10
|
-
:color="iconColor"
|
11
|
-
cursor="pointer"
|
12
|
-
|
11
|
+
:color="iconColor || computedIconColor"
|
12
|
+
:cursor="isDisabled ? 'not-allowed' : 'pointer'"
|
13
|
+
:disabled="isDisabled"
|
14
|
+
:name="iconName"
|
13
15
|
:size="size"
|
14
16
|
/>
|
15
17
|
</div>
|
16
18
|
<Teleport v-if="isVisible" to="body">
|
17
19
|
<TextWrapper :style="wrapperStyle">
|
18
|
-
<TextOverlay
|
20
|
+
<TextOverlay
|
21
|
+
ref="infoBox"
|
22
|
+
:image="image"
|
23
|
+
:style="boxStyle"
|
24
|
+
:width="infoBoxWidth"
|
25
|
+
>
|
19
26
|
<OverlayImage
|
20
27
|
v-if="image"
|
21
28
|
ref="infoImage"
|
@@ -23,7 +30,11 @@
|
|
23
30
|
:src="image"
|
24
31
|
@load="onImageLoad"
|
25
32
|
/>
|
26
|
-
<span ref="textContent" :style="textStyle"
|
33
|
+
<span ref="textContent" :style="textStyle">
|
34
|
+
<slot>
|
35
|
+
<span v-html="text"></span>
|
36
|
+
</slot>
|
37
|
+
</span>
|
27
38
|
</TextOverlay>
|
28
39
|
<Arrow :image="image" :style="arrowStyle" />
|
29
40
|
</TextWrapper>
|
@@ -57,7 +68,7 @@
|
|
57
68
|
word-wrap: break-word;
|
58
69
|
overflow-wrap: break-word;
|
59
70
|
white-space: normal;
|
60
|
-
width:
|
71
|
+
width: ${(props) => (props.width ? `${props.width}px` : '100%')};
|
61
72
|
box-shadow: ${(props) =>
|
62
73
|
props.image ? '0 2px 10px rgba(0, 0, 0, 0.1)' : 'none'};
|
63
74
|
|
@@ -75,11 +86,9 @@
|
|
75
86
|
position: absolute;
|
76
87
|
width: 0;
|
77
88
|
height: 0;
|
78
|
-
border
|
79
|
-
border-
|
80
|
-
|
81
|
-
${(props) =>
|
82
|
-
props.image ? props.theme.colors.white : props.theme.colors.black};
|
89
|
+
border: 8px solid transparent;
|
90
|
+
border-top-color: ${(props) =>
|
91
|
+
props.image ? props.theme.colors.white : props.theme.colors.black};
|
83
92
|
filter: ${(props) =>
|
84
93
|
props.image ? 'drop-shadow(0 2px 2px rgba(0, 0, 0, 0.1))' : 'none'};
|
85
94
|
`
|
@@ -111,13 +120,13 @@
|
|
111
120
|
},
|
112
121
|
props: {
|
113
122
|
text: {
|
114
|
-
|
123
|
+
required: false,
|
115
124
|
default: '',
|
125
|
+
type: String,
|
116
126
|
},
|
117
127
|
size: {
|
118
128
|
type: String,
|
119
129
|
default: '14px',
|
120
|
-
type: String,
|
121
130
|
},
|
122
131
|
infoPosition: {
|
123
132
|
required: false,
|
@@ -142,6 +151,20 @@
|
|
142
151
|
type: String,
|
143
152
|
default: '',
|
144
153
|
},
|
154
|
+
iconName: {
|
155
|
+
type: String,
|
156
|
+
default: 'info',
|
157
|
+
},
|
158
|
+
iconColor: {
|
159
|
+
type: String,
|
160
|
+
default: null,
|
161
|
+
required: false,
|
162
|
+
},
|
163
|
+
isDisabled: {
|
164
|
+
type: Boolean,
|
165
|
+
default: false,
|
166
|
+
required: false,
|
167
|
+
},
|
145
168
|
},
|
146
169
|
setup(props) {
|
147
170
|
const isVisible = ref(false)
|
@@ -155,6 +178,7 @@
|
|
155
178
|
const boxStyle = ref({})
|
156
179
|
const arrowStyle = ref({})
|
157
180
|
const wrapperStyle = ref({})
|
181
|
+
const isMobile = ref(window.innerWidth <= 768)
|
158
182
|
|
159
183
|
const textStyle = computed(() => ({
|
160
184
|
fontSize: props.image ? '12px' : '13px',
|
@@ -163,57 +187,127 @@
|
|
163
187
|
}))
|
164
188
|
|
165
189
|
const calculatePosition = (width) => {
|
166
|
-
if (!icon.value) return {}
|
190
|
+
if (!icon.value || !width) return {}
|
167
191
|
|
168
192
|
const iconRect = icon.value.getBoundingClientRect()
|
169
193
|
const windowHeight = window.innerHeight
|
170
194
|
const windowWidth = window.innerWidth
|
171
195
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
196
|
+
// Calculate available space in all directions
|
197
|
+
const spaceBelow = windowHeight - iconRect.bottom - 10
|
198
|
+
const spaceAbove = iconRect.top - 10
|
199
|
+
const spaceRight = windowWidth - iconRect.right - 10
|
200
|
+
const spaceLeft = iconRect.left - 10
|
201
|
+
|
202
|
+
// Determine the best position based on available space
|
203
|
+
const positions = [
|
204
|
+
{ position: 'bottom', space: spaceBelow },
|
205
|
+
{ position: 'top', space: spaceAbove },
|
206
|
+
{ position: 'right', space: spaceRight },
|
207
|
+
{ position: 'left', space: spaceLeft },
|
208
|
+
].sort((a, b) => b.space - a.space)
|
209
|
+
|
210
|
+
const bestPosition = positions[0].position
|
211
|
+
|
212
|
+
let top, left, arrowPosition
|
213
|
+
|
214
|
+
switch (bestPosition) {
|
215
|
+
case 'bottom':
|
216
|
+
top = Math.round(iconRect.bottom + 10)
|
217
|
+
left = Math.round(Math.min(iconRect.left, windowWidth - width - 10))
|
218
|
+
arrowPosition = {
|
219
|
+
left: `${Math.round(
|
220
|
+
Math.min(
|
221
|
+
Math.max(iconRect.left - left + iconRect.width / 2 - 8, 2),
|
222
|
+
width - 18
|
223
|
+
)
|
224
|
+
)}px`,
|
225
|
+
top: '-7px',
|
226
|
+
bottom: 'auto',
|
227
|
+
transform: 'rotate(180deg)',
|
228
|
+
}
|
229
|
+
break
|
230
|
+
|
231
|
+
case 'top':
|
232
|
+
top = Math.round(iconRect.top - infoBoxHeight.value - 10)
|
233
|
+
left = Math.round(Math.min(iconRect.left, windowWidth - width - 10))
|
234
|
+
arrowPosition = {
|
235
|
+
left: `${Math.round(
|
236
|
+
Math.min(
|
237
|
+
Math.max(iconRect.left - left + iconRect.width / 2 - 8, 2),
|
238
|
+
width - 18
|
239
|
+
)
|
240
|
+
)}px`,
|
241
|
+
top: 'auto',
|
242
|
+
bottom: '-7px',
|
243
|
+
transform: 'none',
|
244
|
+
}
|
245
|
+
break
|
246
|
+
|
247
|
+
case 'right':
|
248
|
+
top = Math.round(
|
249
|
+
Math.max(
|
250
|
+
Math.min(
|
251
|
+
iconRect.top - (infoBoxHeight.value - iconRect.height) / 2,
|
252
|
+
windowHeight - infoBoxHeight.value - 10
|
253
|
+
),
|
254
|
+
10
|
255
|
+
)
|
256
|
+
)
|
257
|
+
left = Math.round(iconRect.right + 10)
|
258
|
+
arrowPosition = {
|
259
|
+
left: '-7px',
|
260
|
+
top: `${Math.round(
|
261
|
+
Math.min(
|
262
|
+
Math.max(iconRect.top - top + iconRect.height / 2 - 8, 2),
|
263
|
+
infoBoxHeight.value - 18
|
264
|
+
)
|
265
|
+
)}px`,
|
266
|
+
bottom: 'auto',
|
267
|
+
transform: 'rotate(90deg)',
|
268
|
+
}
|
269
|
+
break
|
270
|
+
|
271
|
+
case 'left':
|
272
|
+
top = Math.round(
|
273
|
+
Math.max(
|
274
|
+
Math.min(
|
275
|
+
iconRect.top - (infoBoxHeight.value - iconRect.height) / 2,
|
276
|
+
windowHeight - infoBoxHeight.value - 10
|
277
|
+
),
|
278
|
+
10
|
279
|
+
)
|
280
|
+
)
|
281
|
+
left = Math.round(iconRect.left - width - 10)
|
282
|
+
arrowPosition = {
|
283
|
+
left: 'auto',
|
284
|
+
right: '-7px',
|
285
|
+
top: `${Math.round(
|
286
|
+
Math.min(
|
287
|
+
Math.max(iconRect.top - top + iconRect.height / 2 - 8, 2),
|
288
|
+
infoBoxHeight.value - 18
|
289
|
+
)
|
290
|
+
)}px`,
|
291
|
+
bottom: 'auto',
|
292
|
+
transform: 'rotate(-90deg)',
|
293
|
+
}
|
294
|
+
break
|
195
295
|
}
|
196
296
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
arrowStyle.value = {
|
201
|
-
left: `${arrowLeft}px`,
|
202
|
-
top: arrowTop,
|
203
|
-
bottom: arrowBottom,
|
204
|
-
transform: isAbove ? 'none' : 'rotate(180deg)',
|
205
|
-
}
|
297
|
+
// Set arrow styles
|
298
|
+
arrowStyle.value = arrowPosition
|
206
299
|
|
300
|
+
// Set wrapper styles
|
207
301
|
wrapperStyle.value = {
|
208
302
|
position: 'fixed',
|
209
303
|
top: `${top}px`,
|
210
304
|
left: `${left}px`,
|
211
305
|
transform: 'none',
|
212
|
-
width: `${width}px`,
|
306
|
+
width: `${width}px`,
|
213
307
|
}
|
214
308
|
|
215
309
|
return {
|
216
|
-
width: '100%',
|
310
|
+
width: '100%',
|
217
311
|
maxWidth: props.maxWidth,
|
218
312
|
overflowY: 'auto',
|
219
313
|
backgroundColor: props.image
|
@@ -224,12 +318,15 @@
|
|
224
318
|
|
225
319
|
const showInfo = async () => {
|
226
320
|
isVisible.value = true
|
321
|
+
// Wait for two render cycles to ensure content is stable
|
227
322
|
await nextTick()
|
228
|
-
|
323
|
+
await nextTick()
|
324
|
+
await updatePosition()
|
229
325
|
}
|
230
326
|
|
231
327
|
const hideInfo = () => {
|
232
328
|
isVisible.value = false
|
329
|
+
infoBoxWidth.value = 0 // Reset width when hiding
|
233
330
|
}
|
234
331
|
|
235
332
|
const toggleInfo = () => {
|
@@ -257,25 +354,55 @@
|
|
257
354
|
}
|
258
355
|
|
259
356
|
const updatePosition = async () => {
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
if (isIconInView()) {
|
264
|
-
const contentWidth = textContent.value.offsetWidth
|
265
|
-
infoBoxWidth.value = Math.min(
|
266
|
-
Math.max(contentWidth, 200), // Set a minimum width of 200px
|
267
|
-
parseInt(props.maxWidth, 10)
|
268
|
-
)
|
269
|
-
infoBoxHeight.value = infoBox.value.$el.offsetHeight
|
270
|
-
boxStyle.value = calculatePosition(infoBoxWidth.value)
|
357
|
+
console.log('updatePosition')
|
358
|
+
if (!infoBox.value || !textContent.value) return
|
271
359
|
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
360
|
+
// First make the content visible but hidden to get accurate measurements
|
361
|
+
if (infoBox.value.$el) {
|
362
|
+
infoBox.value.$el.style.visibility = 'hidden'
|
363
|
+
infoBox.value.$el.style.display = 'block'
|
364
|
+
}
|
365
|
+
|
366
|
+
await nextTick()
|
367
|
+
|
368
|
+
if (!isIconInView()) {
|
369
|
+
if (isVisible.value) hideInfo()
|
370
|
+
return
|
371
|
+
}
|
372
|
+
|
373
|
+
// Create a temporary clone to measure true width
|
374
|
+
const clone = textContent.value.cloneNode(true)
|
375
|
+
clone.style.position = 'absolute'
|
376
|
+
clone.style.visibility = 'hidden'
|
377
|
+
clone.style.width = 'auto'
|
378
|
+
clone.style.maxWidth = 'none'
|
379
|
+
clone.style.whiteSpace = 'nowrap' // Prevent text wrapping during measurement
|
380
|
+
document.body.appendChild(clone)
|
381
|
+
|
382
|
+
// Get fresh content width from clone
|
383
|
+
const contentWidth = clone.offsetWidth
|
384
|
+
document.body.removeChild(clone)
|
385
|
+
|
386
|
+
// Calculate new width
|
387
|
+
const calculatedWidth = Math.min(
|
388
|
+
Math.max(contentWidth, 200),
|
389
|
+
parseInt(props.maxWidth, 10)
|
390
|
+
)
|
391
|
+
|
392
|
+
// Set new dimensions
|
393
|
+
infoBoxWidth.value = calculatedWidth
|
394
|
+
|
395
|
+
// Wait for width to be applied
|
396
|
+
await nextTick()
|
397
|
+
|
398
|
+
infoBoxHeight.value = infoBox.value.$el.offsetHeight
|
399
|
+
|
400
|
+
// Calculate and apply position
|
401
|
+
boxStyle.value = calculatePosition(calculatedWidth)
|
402
|
+
|
403
|
+
// Make visible after position is set
|
404
|
+
if (isVisible.value && infoBox.value.$el) {
|
405
|
+
infoBox.value.$el.style.visibility = 'visible'
|
279
406
|
}
|
280
407
|
}
|
281
408
|
|
@@ -287,7 +414,10 @@
|
|
287
414
|
}
|
288
415
|
|
289
416
|
const handleClickOutside = (event) => {
|
290
|
-
if (
|
417
|
+
if (
|
418
|
+
(props.openTrigger === 'onClick' || isMobile.value) &&
|
419
|
+
isVisible.value
|
420
|
+
) {
|
291
421
|
const clickedElement = event.target
|
292
422
|
if (
|
293
423
|
infoBox.value &&
|
@@ -299,9 +429,14 @@
|
|
299
429
|
}
|
300
430
|
}
|
301
431
|
|
432
|
+
const handleResize = () => {
|
433
|
+
isMobile.value = window.innerWidth <= 768
|
434
|
+
updatePosition()
|
435
|
+
}
|
436
|
+
|
302
437
|
onMounted(() => {
|
303
438
|
window.addEventListener('scroll', handleScroll, { passive: true })
|
304
|
-
window.addEventListener('resize',
|
439
|
+
window.addEventListener('resize', handleResize)
|
305
440
|
document.addEventListener('scroll', handleScroll, {
|
306
441
|
passive: true,
|
307
442
|
capture: true,
|
@@ -311,7 +446,7 @@
|
|
311
446
|
|
312
447
|
onUnmounted(() => {
|
313
448
|
window.removeEventListener('scroll', handleScroll)
|
314
|
-
window.removeEventListener('resize',
|
449
|
+
window.removeEventListener('resize', handleResize)
|
315
450
|
document.removeEventListener('scroll', handleScroll, { capture: true })
|
316
451
|
document.removeEventListener('click', handleClickOutside)
|
317
452
|
})
|
@@ -339,10 +474,11 @@
|
|
339
474
|
wrapperStyle,
|
340
475
|
textStyle,
|
341
476
|
onImageLoad,
|
477
|
+
isMobile,
|
342
478
|
}
|
343
479
|
},
|
344
480
|
computed: {
|
345
|
-
|
481
|
+
computedIconColor() {
|
346
482
|
return this.buttonType === 'error'
|
347
483
|
? theme.colors.red
|
348
484
|
: theme.colors.mediumGray
|
@@ -19,7 +19,7 @@
|
|
19
19
|
<CheckWrapper :has-label="hasLabel">
|
20
20
|
<span class="checkmark"></span>
|
21
21
|
</CheckWrapper>
|
22
|
-
<LabelText v-if="hasLabel">
|
22
|
+
<LabelText v-if="hasLabel" :is-disabled="isDisabled">
|
23
23
|
{{ label }}
|
24
24
|
</LabelText>
|
25
25
|
</Container>
|
@@ -90,18 +90,20 @@
|
|
90
90
|
? '16px'
|
91
91
|
: '25px'};
|
92
92
|
background-color: ${(props) =>
|
93
|
-
props.
|
93
|
+
props.isDisabled
|
94
|
+
? props.theme.colors.lightGray
|
95
|
+
: props.isChecked
|
94
96
|
? props.backgroundColor
|
95
97
|
? props.backgroundColor
|
96
98
|
: props.theme.colors.green
|
97
|
-
: props.isDisabled
|
98
|
-
? props.theme.colors.lightGray
|
99
99
|
: props.theme.colors.white};
|
100
100
|
border-radius: 4px;
|
101
101
|
border: 1px solid
|
102
102
|
${(props) =>
|
103
103
|
props.isChecked
|
104
|
-
? props.
|
104
|
+
? props.isDisabled
|
105
|
+
? props.theme.colors.lightGray
|
106
|
+
: props.backgroundColor
|
105
107
|
? props.backgroundColor
|
106
108
|
: props.theme.colors.green
|
107
109
|
: props.theme.colors.mediumGray};
|
@@ -140,7 +142,11 @@
|
|
140
142
|
: '10px'};
|
141
143
|
border: solid
|
142
144
|
${(props) =>
|
143
|
-
props.
|
145
|
+
props.isDisabled
|
146
|
+
? props.theme.colors.green
|
147
|
+
: props.checkColor
|
148
|
+
? props.checkColor
|
149
|
+
: props.theme.colors.white};
|
144
150
|
border-width: ${(props) =>
|
145
151
|
props.size === 'medium'
|
146
152
|
? '0 3px 3px 0'
|
@@ -160,11 +166,16 @@
|
|
160
166
|
width: 0;
|
161
167
|
`
|
162
168
|
|
163
|
-
const
|
169
|
+
const LabelTextAttrs = {
|
170
|
+
isDisabled: Boolean,
|
171
|
+
}
|
172
|
+
const LabelText = styled('div', LabelTextAttrs)`
|
164
173
|
font-size: 13px;
|
165
174
|
display: grid;
|
166
|
-
align-items:
|
175
|
+
align-items: center;
|
167
176
|
min-height: 18px;
|
177
|
+
color: ${(props) =>
|
178
|
+
props.isDisabled ? props.theme.colors.grey2 : props.theme.colors.black};
|
168
179
|
`
|
169
180
|
|
170
181
|
export default {
|