@eturnity/eturnity_reusable_components 7.51.13 → 7.51.15--EPDM-12129.7

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eturnity/eturnity_reusable_components",
3
- "version": "7.51.13",
3
+ "version": "7.51.15--EPDM-12129.7",
4
4
  "files": [
5
5
  "dist",
6
6
  "src"
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <PageContainer :should-position="shouldPosition">
3
- <ButtonContainer :data-id="dataId">
3
+ <ButtonContainer :data-id="dataId" :data-qa-id="dataQaId">
4
4
  <PlusButtonSvg />
5
5
  </ButtonContainer>
6
6
  </PageContainer>
@@ -57,6 +57,10 @@
57
57
  type: String,
58
58
  default: '',
59
59
  },
60
+ dataQaId: {
61
+ type: String,
62
+ default: '',
63
+ },
60
64
  },
61
65
  }
62
66
  </script>
@@ -4,6 +4,7 @@
4
4
  :id="id"
5
5
  :custom-color="customColor"
6
6
  :data-id="dataId"
7
+ :data-qa-id="dataQaId"
7
8
  :font-color="fontColor"
8
9
  :height="height"
9
10
  :is-disabled="isDisabled"
@@ -164,6 +165,10 @@
164
165
  type: String,
165
166
  default: '',
166
167
  },
168
+ dataQaId: {
169
+ type: String,
170
+ default: '',
171
+ },
167
172
  },
168
173
  }
169
174
  </script>
@@ -4,6 +4,7 @@
4
4
  :border-radius="borderRadius"
5
5
  :color="iconColor"
6
6
  :data-id="dataId"
7
+ :data-qa-id="dataQaId"
7
8
  :disabled="disabled"
8
9
  :has-border="hasBorder"
9
10
  :hovered-background-color="hoveredBackgroundColor"
@@ -154,6 +155,10 @@
154
155
  type: String,
155
156
  default: '',
156
157
  },
158
+ dataQaId: {
159
+ type: String,
160
+ default: '',
161
+ },
157
162
  isHovered: {
158
163
  required: false,
159
164
  default: false,
@@ -17,7 +17,12 @@
17
17
  </div>
18
18
  <Teleport v-if="isVisible" to="body">
19
19
  <TextWrapper :style="wrapperStyle">
20
- <TextOverlay ref="infoBox" :image="image" :style="boxStyle">
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: 100%; // Ensure the TextOverlay takes full width of its parent
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-left: 8px solid transparent;
85
- border-right: 8px solid transparent;
86
- border-top: 8px solid
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
- let top = iconRect.bottom + 10
194
- let left = iconRect.left
195
-
196
- // Adjust left based on the infoBoxWidth
197
- if (left + width > windowWidth) {
198
- left = windowWidth - width - 10
199
- }
200
-
201
- // Ensure there's enough space below or place above if not
202
- const isAbove = top + infoBoxHeight.value > windowHeight
203
- if (isAbove) {
204
- top = iconRect.top - infoBoxHeight.value - 10
205
- }
206
-
207
- // Calculate arrow position
208
- let arrowLeft = iconRect.left - left + iconRect.width / 2 - 8
209
-
210
- // Adjust arrow position if it's too close to the edges
211
- const edgeThreshold = 2 // pixels from the edge to start adjusting
212
- if (arrowLeft < edgeThreshold) {
213
- arrowLeft = edgeThreshold
214
- } else if (arrowLeft > width - 16 - edgeThreshold) {
215
- arrowLeft = width - 16 - edgeThreshold
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
- const arrowTop = isAbove ? 'auto' : '-7px'
219
- const arrowBottom = isAbove ? '-7px' : 'auto'
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`, // Set a fixed width for the wrapper
306
+ width: `${width}px`,
234
307
  }
235
308
 
236
309
  return {
237
- width: '100%', // Always use 100% width for the TextOverlay
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
- updatePosition()
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
- if (infoBox.value && textContent.value) {
282
- await nextTick()
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
- // Now make it visible if it should be
294
- if (isVisible.value) {
295
- infoBox.value.$el.style.visibility = 'visible'
296
- }
297
- } else if (isVisible.value) {
298
- hideInfo()
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
 
@@ -13,6 +13,7 @@
13
13
  <InputCheckbox
14
14
  :checked="isChecked"
15
15
  :data-id="dataId"
16
+ :data-qa-id="dataQaId"
16
17
  type="checkbox"
17
18
  @change="onChangeHandler(!isChecked)"
18
19
  />
@@ -214,6 +215,10 @@
214
215
  type: String,
215
216
  default: '',
216
217
  },
218
+ dataQaId: {
219
+ type: String,
220
+ default: '',
221
+ },
217
222
  cursorType: {
218
223
  type: String,
219
224
  default: 'pointer',
@@ -15,6 +15,7 @@
15
15
  <LabelWrapper v-if="labelText">
16
16
  <LabelText
17
17
  :data-id="labelDataId"
18
+ :data-test-id="labelDataTestId"
18
19
  :label-font-color="labelFontColor"
19
20
  :label-font-weight="labelFontWeight"
20
21
  >
@@ -40,6 +41,7 @@
40
41
  "
41
42
  :color-mode="colorMode"
42
43
  :data-id="inputDataId"
44
+ :data-qa-id="dataQaId"
43
45
  :disabled="disabled"
44
46
  :font-color="colorMode === 'transparent' ? 'white' : fontColor"
45
47
  :font-size="fontSize"
@@ -647,6 +649,10 @@
647
649
  required: false,
648
650
  default: '',
649
651
  },
652
+ dataQaId: {
653
+ required: false,
654
+ default: '',
655
+ },
650
656
  showSelect: {
651
657
  type: Boolean,
652
658
  default: false,
@@ -34,6 +34,7 @@
34
34
  :background-color="backgroundColor"
35
35
  :border-color="borderColor"
36
36
  :data-id="inputDataId"
37
+ :data-qa-id="dataQaId"
37
38
  data-test-id="input"
38
39
  :default-padding="defaultPadding"
39
40
  :disabled="disabled"
@@ -377,6 +378,11 @@
377
378
  default: '',
378
379
  type: String,
379
380
  },
381
+ dataQaId: {
382
+ required: false,
383
+ default: '',
384
+ type: String,
385
+ },
380
386
  iconName: {
381
387
  required: false,
382
388
  default: null,
@@ -17,6 +17,7 @@
17
17
  <Radio
18
18
  :checked="selectedOption === item.value"
19
19
  :data-id="`radio_button_${dataId}_option_${item.value}`"
20
+ :data-qa-id="dataQaId"
20
21
  :data-test-id="'radioInput_' + item.value"
21
22
  :disabled="item.disabled"
22
23
  :name="'radioButtons_' + radioName"
@@ -296,6 +297,11 @@
296
297
  required: false,
297
298
  type: String,
298
299
  },
300
+ dataQaId: {
301
+ type: String,
302
+ default: '',
303
+ required: false,
304
+ },
299
305
  colorMode: {
300
306
  default: '',
301
307
  required: false,
@@ -5,6 +5,7 @@
5
5
  <InputContainer
6
6
  ref="inputElement"
7
7
  :data-id="dataId"
8
+ :data-qa-id="dataQaId"
8
9
  :disabled="disabled"
9
10
  :has-focus="hasFocus"
10
11
  :input-width="inputWidth"
@@ -128,6 +129,11 @@
128
129
  default: '',
129
130
  type: [String, Number],
130
131
  },
132
+ dataQaId: {
133
+ required: false,
134
+ default: '',
135
+ type: String,
136
+ },
131
137
  iconPosition: {
132
138
  type: String,
133
139
  default: 'right',
@@ -13,6 +13,7 @@
13
13
  <LabelWrapper
14
14
  v-if="label"
15
15
  :data-id="labelDataId"
16
+ :data-qa-id="dataQaId + '_label'"
16
17
  :info-text-message="!!infoTextMessage || !!$slots.infoText"
17
18
  >
18
19
  <InputLabel
@@ -51,6 +52,7 @@
51
52
  class="select-button"
52
53
  :color-mode="colorMode"
53
54
  :data-id="dataId"
55
+ :data-qa-id="dataQaId"
54
56
  :disabled="disabled"
55
57
  :font-color="
56
58
  buttonFontColor || colorMode == 'dark' || colorMode == 'transparent'
@@ -605,6 +607,10 @@
605
607
  type: String,
606
608
  default: '',
607
609
  },
610
+ dataQaId: {
611
+ type: String,
612
+ default: '',
613
+ },
608
614
  hasSelectButtonPadding: {
609
615
  required: false,
610
616
  type: Boolean,
@@ -18,6 +18,7 @@
18
18
  >
19
19
  <textarea
20
20
  :data-id="inputDataId"
21
+ :data-qa-id="dataQaId"
21
22
  :disabled="isDisabled"
22
23
  :placeholder="placeholder"
23
24
  :resize="resize"
@@ -185,6 +186,11 @@
185
186
  required: false,
186
187
  default: '',
187
188
  },
189
+ dataQaId: {
190
+ required: false,
191
+ default: '',
192
+ type: String,
193
+ },
188
194
  },
189
195
  methods: {
190
196
  onChangeHandler($event) {
@@ -2,6 +2,7 @@
2
2
  <Container>
3
3
  <FlexWrapper
4
4
  :data-id="dataId"
5
+ :data-qa-id="dataQaId"
5
6
  data-test-id="page_wrapper"
6
7
  :disabled="disabled"
7
8
  :size="size"
@@ -304,6 +305,10 @@
304
305
  type: String,
305
306
  default: '',
306
307
  },
308
+ dataQaId: {
309
+ type: String,
310
+ default: '',
311
+ },
307
312
  },
308
313
  methods: {
309
314
  onToggleChange() {
@@ -9,8 +9,7 @@
9
9
  <InfoText
10
10
  v-if="infoTextMessage"
11
11
  :align-arrow="infoTextAlign"
12
- border-color="#ccc"
13
- :size="fontSize ? fontSize : '16px'"
12
+ :size="fontSize ? fontSize : '14px'"
14
13
  :text="infoTextMessage"
15
14
  />
16
15
  </LabelWrapper>
@@ -2,6 +2,7 @@
2
2
  <div
3
3
  :class="className"
4
4
  :data-id="dataId"
5
+ :data-qa-id="dataQaId"
5
6
  :style="style"
6
7
  @mousedown="elementMouseDown"
7
8
  @touchstart="elementTouchDown"
@@ -64,6 +65,10 @@
64
65
  type: String,
65
66
  default: '',
66
67
  },
68
+ dataQaId: {
69
+ type: String,
70
+ default: '',
71
+ },
67
72
  className: {
68
73
  type: String,
69
74
  default: 'vdr',
@@ -93,13 +93,14 @@
93
93
  </ComponentItem>
94
94
  <ArrowContainer class="arrow-container" :is-disabled="disabled">
95
95
  <ArrowWrapper :show-archived="showArchived">
96
- <InfoText
97
- v-if="showArchived"
98
- icon-color="red"
99
- :text="
100
- $gettext(`Component has been archived and shouldn't be used`)
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: {