@eturnity/eturnity_reusable_components 7.39.5-qa-elisee-7.42.1 → 7.45.0-EPDM-4900.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,225 @@
1
+ <template>
2
+ <ComponentWrapper>
3
+ <IconWrapper :size="size">
4
+ <IconImg
5
+ ref="iconImg"
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
+ :arrow-position="arrowPosition"
20
+ :icon-size="size"
21
+ :max-width="maxWidth"
22
+ :position="overlayPosition"
23
+ :style="overlayStyle"
24
+ :width="width"
25
+ ><slot></slot>
26
+ <span v-html="text"></span>
27
+ </TextOverlay>
28
+ </IconWrapper>
29
+ </ComponentWrapper>
30
+ </template>
31
+
32
+ <script>
33
+ // import InfoText from "@eturnity/eturnity_reusable_components/src/components/infoText"
34
+ //To use:
35
+ // <info-text
36
+ // text="Veritatis et quasi architecto beatae vitae"
37
+ // size="20px"
38
+ // />
39
+ import theme from '../../assets/theme.js'
40
+ import styled from 'vue3-styled-components'
41
+ import IconComponent from '../icon'
42
+
43
+ const textAttrs = {
44
+ iconSize: String,
45
+ width: String,
46
+ position: String,
47
+ arrowPosition: String,
48
+ }
49
+ const TextOverlay = styled('div', textAttrs)`
50
+ position: absolute;
51
+ text-align: left;
52
+ background: ${(props) => props.theme.colors.black};
53
+ padding: 10px;
54
+ width: ${(props) => props.width};
55
+ max-width: ${(props) => props.maxWidth};
56
+ font-size: 13px;
57
+ font-weight: 400;
58
+ line-height: normal;
59
+ border-radius: 4px;
60
+ z-index: 9999;
61
+ color: ${(props) => props.theme.colors.white};
62
+ word-wrap: break-word;
63
+ overflow-wrap: break-word;
64
+
65
+ :before {
66
+ content: '';
67
+ background-color: ${(props) => props.theme.colors.black};
68
+ position: absolute;
69
+ ${(props) => (props.position === 'top' ? 'bottom: -4px;' : 'top: -4px;')}
70
+ ${(props) => {
71
+ switch (props.arrowPosition) {
72
+ case 'left':
73
+ return 'left: 40px;'
74
+ case 'center':
75
+ return 'left: calc(50% - 4px);'
76
+ case 'right':
77
+ return 'right: 40px;'
78
+ default:
79
+ return 'left: calc(50% - 4px);'
80
+ }
81
+ }}
82
+ height: 8px;
83
+ width: 8px;
84
+ transform-origin: center center;
85
+ transform: rotate(45deg);
86
+ }
87
+
88
+ span a {
89
+ color: #2cc0eb;
90
+ }
91
+ `
92
+
93
+ const iconAttrs = { size: String }
94
+ const IconWrapper = styled('div', iconAttrs)`
95
+ position: relative;
96
+ height: ${(props) => props.size};
97
+ `
98
+
99
+ const IconImg = styled.div`
100
+ line-height: 0;
101
+ `
102
+
103
+ const ComponentWrapper = styled.div`
104
+ display: inline-block;
105
+ `
106
+
107
+ export default {
108
+ name: 'InfoText',
109
+ components: {
110
+ IconWrapper,
111
+ TextOverlay,
112
+ ComponentWrapper,
113
+ IconImg,
114
+ IconComponent,
115
+ },
116
+ props: {
117
+ text: {
118
+ required: false,
119
+ },
120
+ size: {
121
+ required: false,
122
+ default: '14px',
123
+ },
124
+ openTrigger: {
125
+ required: false,
126
+ default: 'onHover', // onHover, onClick
127
+ },
128
+ width: {
129
+ required: false,
130
+ default: '200px',
131
+ },
132
+ maxWidth: {
133
+ type: String,
134
+ default: '400px',
135
+ },
136
+ },
137
+ data() {
138
+ return {
139
+ showInfo: false,
140
+ overlayStyle: {},
141
+ overlayPosition: 'top',
142
+ arrowPosition: 'center',
143
+ }
144
+ },
145
+ computed: {
146
+ iconColor() {
147
+ return theme.colors.mediumGray
148
+ },
149
+ },
150
+ mounted() {
151
+ window.addEventListener('resize', this.positionOverlay)
152
+ },
153
+ beforeUnmount() {
154
+ window.removeEventListener('resize', this.positionOverlay)
155
+ },
156
+ methods: {
157
+ toggleShowInfo() {
158
+ this.showInfo = !this.showInfo
159
+
160
+ if (this.showInfo) {
161
+ document.addEventListener('click', this.clickOutside)
162
+ this.$nextTick(() => {
163
+ this.positionOverlay()
164
+ })
165
+ } else {
166
+ document.removeEventListener('click', this.clickOutside)
167
+ }
168
+ },
169
+ clickOutside(event) {
170
+ if (this.$el.contains(event.target)) {
171
+ return
172
+ }
173
+ this.toggleShowInfo()
174
+ },
175
+ positionOverlay() {
176
+ const iconRect = this.$refs.iconImg.getBoundingClientRect()
177
+ const overlayRect = this.$el
178
+ .querySelector('.TextOverlay')
179
+ .getBoundingClientRect()
180
+
181
+ let top, left
182
+
183
+ // Check if there's enough space above the icon
184
+ if (
185
+ iconRect.top > overlayRect.height + 10 &&
186
+ iconRect.top > window.innerHeight / 2
187
+ ) {
188
+ top = -overlayRect.height - 10
189
+ this.overlayPosition = 'top'
190
+ } else {
191
+ // If not, position it below the icon
192
+ top = iconRect.height + 10
193
+ this.overlayPosition = 'bottom'
194
+ }
195
+
196
+ left = -(overlayRect.width / 2) + iconRect.width / 2
197
+
198
+ // Ensure the overlay doesn't go off-screen horizontally
199
+ if (iconRect.left + left < 0) {
200
+ left = -iconRect.left
201
+ this.arrowPosition = 'left'
202
+ } else if (
203
+ iconRect.left + left + overlayRect.width >
204
+ window.innerWidth
205
+ ) {
206
+ left = window.innerWidth - (iconRect.left + overlayRect.width)
207
+ this.arrowPosition = 'right'
208
+ } else {
209
+ this.arrowPosition = 'center'
210
+ }
211
+
212
+ // Adjust vertical position if it goes off-screen
213
+ const totalHeight = iconRect.top + top + overlayRect.height
214
+ if (totalHeight > window.innerHeight) {
215
+ top -= totalHeight - window.innerHeight + 10
216
+ }
217
+
218
+ this.overlayStyle = {
219
+ top: `${top}px`,
220
+ left: `${left}px`,
221
+ }
222
+ },
223
+ },
224
+ }
225
+ </script>
@@ -3,68 +3,73 @@ import InputText from './index.vue'
3
3
  export default {
4
4
  title: 'InputText',
5
5
  component: InputText,
6
- tags: ['autodocs'],
6
+ // argTypes: {},
7
7
  }
8
8
 
9
- // import InputText from "@eturnity/eturnity_reusable_components/src/components/inputs/inputText"
10
- // To use:
11
- // <input-text
12
- // placeholder="Company name"
13
- // :value="companyName"
14
- // @input-change="onInputChange({ value: $event, type: 'companyName' })"
15
- // :isError="checkErrors()"
16
- // :errorMessage="This is my error message"
17
- // infoTextAlign="right" // left by default
18
- // infoTextMessage="My info message"
19
- // label="Question 5"
20
- // alignItems="horizontal" // horizontal, vertical
21
- // inputWidth="250px"
22
- // minWidth="100px"
23
- // />
9
+ const Template = (args, { argTypes }) => ({
10
+ // Components used in your story `template` are defined in the `components` object
11
+ components: { InputText },
12
+ // The story's `args` need to be mapped into the template through the `setup()` method
13
+ props: Object.keys(argTypes),
14
+ template: '<input-text v-bind="$props" />',
24
15
 
25
- export const Default = {
26
- args: {
27
- placeholder: 'Company name',
28
- disabled: false,
29
- value: '',
30
- inputWidth: '200px',
31
- minWidth: '10ch',
32
- isError: false,
33
- label: 'label test',
34
- labelOptional: true,
35
- },
16
+ // import InputText from "@eturnity/eturnity_reusable_components/src/components/inputs/inputText"
17
+ // To use:
18
+ // <input-text
19
+ // placeholder="Company name"
20
+ // :value="companyName"
21
+ // @input-change="onInputChange({ value: $event, type: 'companyName' })"
22
+ // :isError="checkErrors()"
23
+ // :errorMessage="This is my error message"
24
+ // infoTextAlign="right" // left by default
25
+ // infoTextMessage="My info message"
26
+ // label="Question 5"
27
+ // alignItems="horizontal" // horizontal, vertical
28
+ // inputWidth="250px"
29
+ // minWidth="100px"
30
+ // />
31
+ })
32
+
33
+ export const Default = Template.bind({})
34
+ Default.args = {
35
+ placeholder: 'Company name',
36
+ disabled: false,
37
+ value: '',
38
+ inputWidth: '200px',
39
+ minWidth: '10ch',
40
+ unitName: 'pc',
41
+ isError: false,
42
+ textAlign: 'left',
36
43
  }
37
44
 
38
- export const HasError = {
39
- args: {
40
- placeholder: 'Enter Value',
41
- errorMessage: 'This field is required',
42
- isError: true,
43
- disabled: false,
44
- inputWidth: '200px',
45
- },
45
+ export const hasError = Template.bind({})
46
+ hasError.args = {
47
+ placeholder: 'Enter Value',
48
+ errorMessage: 'This field is required',
49
+ isError: true,
50
+ disabled: false,
51
+ inputWidth: '200px',
46
52
  }
47
53
 
48
- export const Disabled = {
49
- args: {
50
- placeholder: 'Enter Value',
51
- disabled: true,
52
- value: '',
53
- inputWidth: '200px',
54
- isError: false,
55
- },
54
+ export const Disabled = Template.bind({})
55
+ Disabled.args = {
56
+ placeholder: 'Enter Value',
57
+ disabled: true,
58
+ value: '',
59
+ inputWidth: '200px',
60
+ isError: false,
56
61
  }
57
62
 
58
- export const WithLabel = {
59
- args: {
60
- placeholder: 'Company name',
61
- disabled: false,
62
- label: 'What is the best company in Switzerland?',
63
- value: 'Eturnity',
64
- inputWidth: '200px',
65
- unitName: 'pc',
66
- isError: false,
67
- errorMessage: 'Maximum 5 characters',
68
- alignItems: 'vertical',
69
- },
63
+ export const WithLabel = Template.bind({})
64
+ WithLabel.args = {
65
+ placeholder: 'Company name',
66
+ disabled: false,
67
+ label: 'What is the best company in Switzerland?',
68
+ value: 'Eturnity',
69
+ inputWidth: '200px',
70
+ unitName: 'pc',
71
+ isError: false,
72
+ errorMessage: 'Maximum 5 characters',
73
+ textAlign: 'left',
74
+ alignItems: 'vertical',
70
75
  }
@@ -2,26 +2,22 @@
2
2
  <Container>
3
3
  <InputWrapper
4
4
  :align-items="alignItems"
5
- data-test-id="input_wrapper"
6
5
  :has-label="!!label && label.length > 0"
7
6
  >
8
7
  <LabelWrapper v-if="label">
9
8
  <InputLabel
10
- ref="label"
11
9
  :data-id="labelDataId"
12
- data-test-id="label_wrapper"
13
10
  :font-size="fontSize"
14
11
  :label-font-color="labelFontColor"
15
12
  >
16
13
  {{ label }}
17
- <OptionalLabel v-if="labelOptional" data-test-id="label_optional">
14
+ <OptionalLabel v-if="labelOptional">
18
15
  ({{ $gettext('Optional') }})
19
16
  </OptionalLabel>
20
17
  </InputLabel>
21
18
  <InfoText
22
- v-if="infoTextMessage != ''"
19
+ v-if="infoTextMessage"
23
20
  :align-arrow="infoTextAlign"
24
- data-test-id="info_text_message"
25
21
  :size="fontSize ? fontSize : '16px'"
26
22
  :text="infoTextMessage"
27
23
  />
@@ -32,7 +28,6 @@
32
28
  ref="inputElement"
33
29
  :background-color="backgroundColor"
34
30
  :data-id="inputDataId"
35
- data-test-id="input"
36
31
  :disabled="disabled"
37
32
  :disabled-background-color="disabledBackgroundColor"
38
33
  :font-color="fontColor"
@@ -49,26 +44,21 @@
49
44
  :type="inputTypeData"
50
45
  :value="value"
51
46
  @blur="onInputBlur"
52
- @focus="onInputFocus"
53
47
  @input="onChangeHandler"
54
48
  @keyup.enter="onEnterPress"
55
49
  />
56
50
  <IconWrapper
57
51
  v-if="inputType === 'password' && !isError"
58
- data-test-id="password_visiblity_change_icon"
59
52
  size="20px"
60
53
  @click="toggleShowPassword()"
61
54
  >
62
55
  <Icon name="current_variant" size="20px" />
63
56
  </IconWrapper>
64
- <IconWrapper v-if="hasError" data-test-id="error_wrapper" size="16px">
57
+ <IconWrapper v-if="hasError" size="16px">
65
58
  <Icon cursor="default" name="warning" size="16px" />
66
59
  </IconWrapper>
67
60
  </IconContainer>
68
- <ErrorMessage
69
- v-if="hasError && hasErrorMessage"
70
- data-test-id="error_message_wrapper"
71
- >
61
+ <ErrorMessage v-if="hasError && hasErrorMessage">
72
62
  {{ dynamicErrorMessage }}
73
63
  </ErrorMessage>
74
64
  </InputErrorWrapper>
@@ -246,123 +236,93 @@
246
236
  placeholder: {
247
237
  required: false,
248
238
  default: '',
249
- type: String,
250
239
  },
251
240
  alignItems: {
252
241
  required: false,
253
242
  default: 'horizontal',
254
- type: String,
255
- validator(value) {
256
- return ['horizontal', 'vertical'].includes(value)
257
- },
258
243
  },
259
244
  isError: {
260
245
  required: false,
261
246
  default: false,
262
- type: Boolean,
263
247
  },
264
248
  inputWidth: {
265
249
  required: false,
266
250
  default: null,
267
- type: String,
268
251
  },
269
252
  inputHeight: {
270
253
  required: false,
271
254
  default: null,
272
- type: String,
273
255
  },
274
256
  minWidth: {
275
257
  required: false,
276
258
  default: null,
277
- type: String,
278
259
  },
279
260
  value: {
280
261
  required: true,
281
262
  default: null,
282
- type: String,
283
263
  },
284
264
  errorMessage: {
285
265
  required: false,
286
266
  default: '',
287
- type: String,
288
267
  },
289
268
  infoTextMessage: {
290
269
  required: false,
291
- default: '',
292
- type: String,
293
270
  },
294
271
  infoTextAlign: {
295
272
  required: false,
296
- default: 'left',
297
- type: String,
298
273
  },
299
274
  label: {
300
275
  required: false,
301
- default: '',
302
- type: String,
303
276
  },
304
277
  labelOptional: {
305
278
  required: false,
306
279
  default: false,
307
- type: Boolean,
308
280
  },
309
281
  noBorder: {
310
282
  required: false,
311
283
  default: false,
312
- type: Boolean,
313
284
  },
314
285
  disabled: {
315
286
  required: false,
316
287
  default: false,
317
- type: Boolean,
318
288
  },
319
289
  fontSize: {
320
290
  required: false,
321
291
  default: null,
322
- type: String,
323
292
  },
324
293
  inputType: {
325
294
  required: false,
326
295
  default: 'text',
327
- type: String,
328
296
  },
329
297
  labelFontColor: {
330
298
  required: false,
331
299
  default: 'black',
332
- type: String,
333
300
  },
334
301
  backgroundColor: {
335
302
  required: false,
336
- type: String,
337
303
  },
338
304
  disabledBackgroundColor: {
339
305
  required: false,
340
306
  default: null,
341
- type: String,
342
307
  },
343
308
  fontColor: {
344
309
  required: false,
345
310
  default: 'black',
346
- type: String,
347
311
  },
348
312
  hasFocus: {
349
313
  required: false,
350
314
  default: false,
351
- type: Boolean,
352
315
  },
353
316
  borderColor: {
354
317
  required: false,
355
- type: String,
356
318
  },
357
319
  labelDataId: {
358
320
  required: false,
359
321
  default: '',
360
- type: String,
361
322
  },
362
323
  inputDataId: {
363
324
  required: false,
364
325
  default: '',
365
- type: String,
366
326
  },
367
327
  },
368
328
  data() {
@@ -375,10 +335,12 @@
375
335
  return this.isError || this.error
376
336
  },
377
337
  hasErrorMessage() {
378
- return this.errorMessage && this.errorMessage.length > 0
338
+ return (
339
+ (this.errorMessage && this.errorMessage.length > 0) || this.errMessage
340
+ )
379
341
  },
380
342
  dynamicErrorMessage() {
381
- return this.errorMessage
343
+ return this.errMessage || this.errorMessage
382
344
  },
383
345
  },
384
346
  watch: {
@@ -405,9 +367,6 @@
405
367
  this.validateInput($event.target.value)
406
368
  this.$emit('input-blur', $event.target.value)
407
369
  },
408
- onInputFocus($event) {
409
- this.$emit('input-focus', $event.target.value)
410
- },
411
370
  toggleShowPassword() {
412
371
  this.inputTypeData =
413
372
  this.inputTypeData === 'password' ? 'text' : 'password'
@@ -1,58 +1,77 @@
1
+ import { useArgs } from '@storybook/preview-api'
2
+ import { action } from '@storybook/addon-actions'
3
+ import defaultRadioButtonProps from './defaultProps'
1
4
  import RadioButton from './index.vue'
2
5
 
3
6
  export default {
4
7
  title: 'RadioButton',
5
8
  component: RadioButton,
6
- // argTypes: {},
9
+ tags: ['autodocs'],
7
10
  }
8
11
 
9
- const Template = (args, { argTypes }) => ({
10
- // Components used in your story `template` are defined in the `components` object
11
- components: { RadioButton },
12
- // The story's `args` need to be mapped into the template through the `setup()` method
13
- props: Object.keys(argTypes),
14
- template: '<radio-button v-bind="$props" />',
15
-
16
- // import RadioButton from "@eturnity/eturnity_reusable_components/src/components/inputs/radioButton"
17
- // To use:
18
- // <radio-button
19
- // :options="radioOptions"
20
- // :selectedOption="checkedOption"
21
- // @on-radio-change="onInputChange($event)"
22
- // layout="vertical"
23
- // size="large"
24
- // />
25
- // Data being passed should look like:
26
- // radioOptions: [
27
- // { label: 'Button 1', value: 'button_1', img: 'www.imagesrc.com', infoText: 'my info text' },
28
- // { label: 'Button 2', value: 'button_2', img: 'www.imagesrc.com', infoText: 'my info text 2' },
29
- // { label: 'Button 3', value: 'button_3', img: 'www.imagesrc.com', disabled: true },
30
- // { label: 'Button 4', value: 'button_4', disabled: true }
31
- // ]
32
- })
12
+ // To use:
13
+ // import RadioButton from "@eturnity/eturnity_reusable_components/src/components/inputs/radioButton"
14
+ // <radio-button
15
+ // checkmarkColor="red"
16
+ // dataId="radio_button"
17
+ // layout="horizontal" //2 options: 'vertical' (only 1 per row) & 'horizontal' (many per row)
18
+ // name="Name for Radio buttons"
19
+ // :options="radioOptions"
20
+ // :selectedOption="checkedOption"
21
+ // size="medium" // small, medium, large
22
+ // @on-radio-change="onInputChange($event)"
23
+ // />
24
+ // Data being passed should look like:
25
+ // radioOptions: [
26
+ // { label: 'Option 1', value: 'option_1', img: 'www.imagesrc.com', infoText: 'my info text' },
27
+ // { label: 'Option 2', value: 'option_2', img: 'www.imagesrc.com', infoText: 'my info text 2' },
28
+ // { label: 'Option 3', value: 'option_3', img: 'www.imagesrc.com', disabled: true },
29
+ // { label: 'Option 4', value: 'option_4', disabled: true }
30
+ // ]
31
+
32
+ const defaultProps = defaultRadioButtonProps
33
+
34
+ const Template = (args) => {
35
+ const [currentArgs, updateArgs] = useArgs()
36
+
37
+ const handleRadioChange = ($event) => {
38
+ action('on-radio-change')($event)
39
+ updateArgs({ selectedOption: $event })
40
+ }
41
+
42
+ return {
43
+ components: { RadioButton },
44
+ setup() {
45
+ return { args: currentArgs, handleRadioChange }
46
+ },
47
+ template: `
48
+ <RadioButton
49
+ v-bind="args"
50
+ @on-radio-change="handleRadioChange"
51
+ />
52
+ `,
53
+ }
54
+ }
33
55
 
34
56
  export const Default = Template.bind({})
35
57
  Default.args = {
36
- options: [
37
- { label: 'Button 1', value: 'button_1', infoText: 'my info text' },
38
- { label: 'Button 2', value: 'button_2', infoText: 'my info text 2' },
39
- { label: 'Button 3', value: 'button_3', disabled: true },
40
- { label: 'Button 4', value: 'button_4', disabled: true },
41
- ],
42
- selectedOption: 'button_2',
43
- layout: 'horizontal',
44
- size: 'medium',
58
+ ...defaultProps,
59
+ }
60
+
61
+ export const BlueCheckmark = Template.bind({})
62
+ BlueCheckmark.args = {
63
+ ...defaultProps,
64
+ checkmarkColor: '#00f',
65
+ }
66
+
67
+ export const Small = Template.bind({})
68
+ Small.args = {
69
+ ...defaultProps,
70
+ size: 'small',
45
71
  }
46
72
 
47
- export const VerticalLayout = Template.bind({})
48
- VerticalLayout.args = {
49
- options: [
50
- { label: 'Button 1', value: 'button_1' },
51
- { label: 'Button 2', value: 'button_2' },
52
- { label: 'Button 3', value: 'button_3' },
53
- { label: 'Button 4', value: 'button_4', disabled: true },
54
- ],
55
- selectedOption: 'button_2',
73
+ export const Vertical = Template.bind({})
74
+ Vertical.args = {
75
+ ...defaultProps,
56
76
  layout: 'vertical',
57
- size: 'medium',
58
77
  }