@eturnity/eturnity_reusable_components 7.51.13 → 7.51.15
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
|
@@ -17,7 +17,12 @@
|
|
|
17
17
|
</div>
|
|
18
18
|
<Teleport v-if="isVisible" to="body">
|
|
19
19
|
<TextWrapper :style="wrapperStyle">
|
|
20
|
-
<TextOverlay
|
|
20
|
+
<TextOverlay
|
|
21
|
+
ref="infoBox"
|
|
22
|
+
:image="image"
|
|
23
|
+
:style="boxStyle"
|
|
24
|
+
:width="infoBoxWidth"
|
|
25
|
+
>
|
|
21
26
|
<OverlayImage
|
|
22
27
|
v-if="image"
|
|
23
28
|
ref="infoImage"
|
|
@@ -63,7 +68,7 @@
|
|
|
63
68
|
word-wrap: break-word;
|
|
64
69
|
overflow-wrap: break-word;
|
|
65
70
|
white-space: normal;
|
|
66
|
-
width:
|
|
71
|
+
width: ${(props) => (props.width ? `${props.width}px` : '100%')};
|
|
67
72
|
box-shadow: ${(props) =>
|
|
68
73
|
props.image ? '0 2px 10px rgba(0, 0, 0, 0.1)' : 'none'};
|
|
69
74
|
|
|
@@ -81,11 +86,9 @@
|
|
|
81
86
|
position: absolute;
|
|
82
87
|
width: 0;
|
|
83
88
|
height: 0;
|
|
84
|
-
border
|
|
85
|
-
border-
|
|
86
|
-
|
|
87
|
-
${(props) =>
|
|
88
|
-
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};
|
|
89
92
|
filter: ${(props) =>
|
|
90
93
|
props.image ? 'drop-shadow(0 2px 2px rgba(0, 0, 0, 0.1))' : 'none'};
|
|
91
94
|
`
|
|
@@ -184,57 +187,127 @@
|
|
|
184
187
|
}))
|
|
185
188
|
|
|
186
189
|
const calculatePosition = (width) => {
|
|
187
|
-
if (!icon.value) return {}
|
|
190
|
+
if (!icon.value || !width) return {}
|
|
188
191
|
|
|
189
192
|
const iconRect = icon.value.getBoundingClientRect()
|
|
190
193
|
const windowHeight = window.innerHeight
|
|
191
194
|
const windowWidth = window.innerWidth
|
|
192
195
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
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
|
|
216
295
|
}
|
|
217
296
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
arrowStyle.value = {
|
|
222
|
-
left: `${arrowLeft}px`,
|
|
223
|
-
top: arrowTop,
|
|
224
|
-
bottom: arrowBottom,
|
|
225
|
-
transform: isAbove ? 'none' : 'rotate(180deg)',
|
|
226
|
-
}
|
|
297
|
+
// Set arrow styles
|
|
298
|
+
arrowStyle.value = arrowPosition
|
|
227
299
|
|
|
300
|
+
// Set wrapper styles
|
|
228
301
|
wrapperStyle.value = {
|
|
229
302
|
position: 'fixed',
|
|
230
303
|
top: `${top}px`,
|
|
231
304
|
left: `${left}px`,
|
|
232
305
|
transform: 'none',
|
|
233
|
-
width: `${width}px`,
|
|
306
|
+
width: `${width}px`,
|
|
234
307
|
}
|
|
235
308
|
|
|
236
309
|
return {
|
|
237
|
-
width: '100%',
|
|
310
|
+
width: '100%',
|
|
238
311
|
maxWidth: props.maxWidth,
|
|
239
312
|
overflowY: 'auto',
|
|
240
313
|
backgroundColor: props.image
|
|
@@ -245,12 +318,15 @@
|
|
|
245
318
|
|
|
246
319
|
const showInfo = async () => {
|
|
247
320
|
isVisible.value = true
|
|
321
|
+
// Wait for two render cycles to ensure content is stable
|
|
248
322
|
await nextTick()
|
|
249
|
-
|
|
323
|
+
await nextTick()
|
|
324
|
+
await updatePosition()
|
|
250
325
|
}
|
|
251
326
|
|
|
252
327
|
const hideInfo = () => {
|
|
253
328
|
isVisible.value = false
|
|
329
|
+
infoBoxWidth.value = 0 // Reset width when hiding
|
|
254
330
|
}
|
|
255
331
|
|
|
256
332
|
const toggleInfo = () => {
|
|
@@ -278,25 +354,55 @@
|
|
|
278
354
|
}
|
|
279
355
|
|
|
280
356
|
const updatePosition = async () => {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
if (isIconInView()) {
|
|
285
|
-
const contentWidth = textContent.value.offsetWidth
|
|
286
|
-
infoBoxWidth.value = Math.min(
|
|
287
|
-
Math.max(contentWidth, 200), // Set a minimum width of 200px
|
|
288
|
-
parseInt(props.maxWidth, 10)
|
|
289
|
-
)
|
|
290
|
-
infoBoxHeight.value = infoBox.value.$el.offsetHeight
|
|
291
|
-
boxStyle.value = calculatePosition(infoBoxWidth.value)
|
|
357
|
+
console.log('updatePosition')
|
|
358
|
+
if (!infoBox.value || !textContent.value) return
|
|
292
359
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
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'
|
|
300
406
|
}
|
|
301
407
|
}
|
|
302
408
|
|
|
@@ -93,13 +93,14 @@
|
|
|
93
93
|
</ComponentItem>
|
|
94
94
|
<ArrowContainer class="arrow-container" :is-disabled="disabled">
|
|
95
95
|
<ArrowWrapper :show-archived="showArchived">
|
|
96
|
-
<
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
96
|
+
<InfoWrapper v-if="showArchived">
|
|
97
|
+
<InfoText
|
|
98
|
+
icon-color="red"
|
|
99
|
+
:text="
|
|
100
|
+
$gettext(`Component has been archived and shouldn't be used`)
|
|
101
|
+
"
|
|
102
|
+
/>
|
|
103
|
+
</InfoWrapper>
|
|
103
104
|
<ArrowDown
|
|
104
105
|
v-if="!isOpen"
|
|
105
106
|
class="arrow-dropdown"
|
|
@@ -434,6 +435,13 @@
|
|
|
434
435
|
align-items: center;
|
|
435
436
|
`
|
|
436
437
|
|
|
438
|
+
const InfoWrapper = styled.div`
|
|
439
|
+
display: flex;
|
|
440
|
+
align-items: center;
|
|
441
|
+
justify-content: center;
|
|
442
|
+
padding-left: 8px;
|
|
443
|
+
`
|
|
444
|
+
|
|
437
445
|
export default {
|
|
438
446
|
name: 'TableDropdown',
|
|
439
447
|
components: {
|
|
@@ -464,6 +472,7 @@
|
|
|
464
472
|
NestedContainer,
|
|
465
473
|
Icon,
|
|
466
474
|
InfoText,
|
|
475
|
+
InfoWrapper,
|
|
467
476
|
},
|
|
468
477
|
props: {
|
|
469
478
|
colSpan: {
|