@eturnity/eturnity_reusable_components 8.7.5-EPIC-8593.2 → 8.7.5-EPIC-8593.4
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 +1 -1
- package/src/assets/icons/collapse_arrow_icon_white.svg +1 -0
- package/src/assets/svgIcons/ac_power.svg +4 -0
- package/src/assets/svgIcons/arrow_long_left.svg +3 -0
- package/src/assets/svgIcons/arrow_long_right.svg +3 -0
- package/src/assets/svgIcons/chassis_ground_symbol.svg +27 -0
- package/src/assets/svgIcons/dc_power.svg +8 -0
- package/src/assets/svgIcons/double_arrow_long.svg +4 -0
- package/src/assets/svgIcons/ed_ac.svg +3 -0
- package/src/assets/svgIcons/ed_acgrid.svg +4 -0
- package/src/assets/svgIcons/ed_arrow_both.svg +7 -0
- package/src/assets/svgIcons/ed_arrow_left.svg +7 -0
- package/src/assets/svgIcons/ed_arrow_right.svg +7 -0
- package/src/assets/svgIcons/ed_battery.svg +10 -0
- package/src/assets/svgIcons/ed_batteryacinverter.svg +16 -0
- package/src/assets/svgIcons/ed_batteryintegratedinverter.svg +19 -0
- package/src/assets/svgIcons/ed_cirquitbreaker.svg +4 -0
- package/src/assets/svgIcons/ed_cirquitbreaker_magnetic.svg +6 -0
- package/src/assets/svgIcons/ed_cirquitbreaker_thermal.svg +4 -0
- package/src/assets/svgIcons/ed_cirquitbreaker_thermal_magnetic.svg +5 -0
- package/src/assets/svgIcons/ed_consumption.svg +3 -0
- package/src/assets/svgIcons/ed_dc.svg +6 -0
- package/src/assets/svgIcons/ed_disconnector.svg +4 -0
- package/src/assets/svgIcons/ed_disconnector_fuse.svg +4 -0
- package/src/assets/svgIcons/ed_disconnector_fuse_switch.svg +4 -0
- package/src/assets/svgIcons/ed_disconnector_loadbreak switch.svg +4 -0
- package/src/assets/svgIcons/ed_disconnector_switch.svg +4 -0
- package/src/assets/svgIcons/ed_disconnector_switch_auto_release.svg +5 -0
- package/src/assets/svgIcons/ed_energymanagement_rectangle.svg +3 -0
- package/src/assets/svgIcons/ed_evcharger.svg +19 -0
- package/src/assets/svgIcons/ed_flexiblecomponent_circle.svg +3 -0
- package/src/assets/svgIcons/ed_flexiblecomponent_square.svg +3 -0
- package/src/assets/svgIcons/ed_fuse.svg +3 -0
- package/src/assets/svgIcons/ed_ground.svg +5 -0
- package/src/assets/svgIcons/ed_heatpump.svg +4 -0
- package/src/assets/svgIcons/ed_icon_battery.svg +9 -0
- package/src/assets/svgIcons/ed_icon_circle.svg +3 -0
- package/src/assets/svgIcons/ed_icon_heatpump.svg +3 -0
- package/src/assets/svgIcons/ed_icon_inverter.svg +8 -0
- package/src/assets/svgIcons/ed_icon_optimizer.svg +11 -0
- package/src/assets/svgIcons/ed_integratedbatteryinverter.svg +10 -0
- package/src/assets/svgIcons/ed_inverter-blank.svg +3 -0
- package/src/assets/svgIcons/ed_mainsconnection.svg +3 -0
- package/src/assets/svgIcons/ed_meter_arrowleft.svg +4 -0
- package/src/assets/svgIcons/ed_meter_arrowright.svg +4 -0
- package/src/assets/svgIcons/ed_meter_bidirectional.svg +5 -0
- package/src/assets/svgIcons/ed_networkandsystemprotection_double.svg +14 -0
- package/src/assets/svgIcons/ed_networkandsystemprotection_single.svg +7 -0
- package/src/assets/svgIcons/ed_pvpanel.svg +7 -0
- package/src/assets/svgIcons/ed_rcd.svg +5 -0
- package/src/assets/svgIcons/ed_rcd_simple.svg +3 -0
- package/src/assets/svgIcons/ed_spd.svg +6 -0
- package/src/assets/svgIcons/ed_stringwithoptimizer.svg +33 -0
- package/src/assets/svgIcons/ed_stringwithoutoptimizer.svg +17 -0
- package/src/assets/svgIcons/ed_transformer.svg +3 -0
- package/src/assets/svgIcons/ground_symbol.svg +28 -0
- package/src/assets/svgIcons/house_sun.svg +3 -0
- package/src/assets/svgIcons/move_left.svg +3 -0
- package/src/assets/svgIcons/move_right.svg +3 -0
- package/src/assets/svgIcons/rectangle.svg +3 -0
- package/src/assets/svgIcons/refresh.svg +3 -0
- package/src/assets/svgIcons/text_icon.svg +3 -0
- package/src/assets/theme.js +18 -1
- package/src/components/banner/infoBanner/InfoBanner.spec.js +29 -42
- package/src/components/barchart/BottomFields.vue +253 -0
- package/src/components/barchart/ChartControls.vue +113 -0
- package/src/components/barchart/SelectionBox.vue +150 -0
- package/src/components/barchart/composables/index.js +5 -0
- package/src/components/barchart/composables/useAxisCalculations.js +104 -0
- package/src/components/barchart/composables/useChartData.js +114 -0
- package/src/components/barchart/composables/useChartScroll.js +61 -0
- package/src/components/barchart/composables/useSelection.js +75 -0
- package/src/components/barchart/composables/useTooltip.js +100 -0
- package/src/components/barchart/index.vue +385 -0
- package/src/components/barchart/styles/bottomFields.js +66 -0
- package/src/components/barchart/styles/chart.js +272 -0
- package/src/components/barchart/styles/chartControls.js +59 -0
- package/src/components/buttons/buttonIcon/index.vue +5 -0
- package/src/components/buttons/splitButtons/index.vue +86 -0
- package/src/components/collapsableInfoText/index.vue +2 -2
- package/src/components/draggableCard/defaultProps.js +16 -0
- package/src/components/draggableCard/draggableCard.spec.js +99 -0
- package/src/components/draggableCard/draggableCard.stories.js +79 -0
- package/src/components/draggableCard/index.vue +363 -0
- package/src/components/errorMessage/errorMessage.spec.js +34 -0
- package/src/components/errorMessage/errorMessage.stories.js +35 -0
- package/src/components/filter/filterSettings.vue +2 -0
- package/src/components/icon/index.vue +32 -9
- package/src/components/infoText/index.vue +2 -2
- package/src/components/infoText/infoText.spec.js +6 -1
- package/src/components/inputs/checkbox/index.vue +2 -2
- package/src/components/inputs/inputNumber/index.vue +14 -2
- package/src/components/inputs/searchInput/index.vue +18 -2
- package/src/components/inputs/select/index.vue +104 -13
- package/src/components/modals/actionModal/actionModal.spec.js +52 -0
- package/src/components/modals/actionModal/actionModal.stories.js +53 -0
- package/src/components/modals/actionModal/index.vue +6 -6
- package/src/components/modals/infoModal/index.vue +49 -19
- package/src/components/modals/infoModal/infoModal.spec.js +55 -0
- package/src/components/modals/infoModal/infoModal.stories.js +47 -0
- package/src/components/modals/modal/index.vue +16 -5
- package/src/components/pageSubtitle/PageSubtitle.stories.js +0 -1
- package/src/components/spinnerGif/index.vue +3 -3
- package/src/components/tabsHeader/index.vue +29 -1
- package/src/helpers/dateTimeFormatting.js +51 -0
- package/src/helpers/isObjectEqual.js +22 -0
- package/src/helpers/toLocaleNumber.js +11 -0
- package/src/main.js +1 -0
@@ -1,6 +1,10 @@
|
|
1
1
|
<template>
|
2
2
|
<Container :input-width="inputWidth">
|
3
|
-
<InputWrapper
|
3
|
+
<InputWrapper
|
4
|
+
:icon-color="iconColor"
|
5
|
+
:icon-position="iconPosition"
|
6
|
+
:is-full-height="isFullHeight"
|
7
|
+
>
|
4
8
|
<SearchIconSvg class="search-icn" />
|
5
9
|
<InputContainer
|
6
10
|
ref="inputElement"
|
@@ -11,6 +15,7 @@
|
|
11
15
|
:input-width="inputWidth"
|
12
16
|
:is-disabled="disabled"
|
13
17
|
:is-filter="isFilter"
|
18
|
+
:is-full-height="isFullHeight"
|
14
19
|
:placeholder="placeholder"
|
15
20
|
:value="value"
|
16
21
|
@input="onChangeHandler($event)"
|
@@ -41,6 +46,7 @@
|
|
41
46
|
isDisabled: Boolean,
|
42
47
|
inputWidth: String,
|
43
48
|
isFilter: Boolean,
|
49
|
+
isFullHeight: Boolean,
|
44
50
|
}
|
45
51
|
const Container = styled('div', inputAttrs)`
|
46
52
|
width: ${(props) => (props.inputWidth ? props.inputWidth : '100%')};
|
@@ -55,6 +61,7 @@
|
|
55
61
|
font-size: 13px;
|
56
62
|
color: ${(props) => props.theme.colors.black};
|
57
63
|
width: ${(props) => (props.inputWidth ? props.inputWidth : '100%')};
|
64
|
+
height: ${(props) => (props.isFullHeight ? '100%' : 'auto')};
|
58
65
|
box-sizing: border-box;
|
59
66
|
cursor: ${(props) => (props.isDisabled ? 'not-allowed' : 'auto')};
|
60
67
|
background: ${(props) => props.theme.colors.white} !important;
|
@@ -67,9 +74,14 @@
|
|
67
74
|
}
|
68
75
|
`
|
69
76
|
|
70
|
-
const wrapperAttrs = {
|
77
|
+
const wrapperAttrs = {
|
78
|
+
iconColor: String,
|
79
|
+
iconPosition: String,
|
80
|
+
isFullHeight: Boolean,
|
81
|
+
}
|
71
82
|
const InputWrapper = styled('div', wrapperAttrs)`
|
72
83
|
position: relative;
|
84
|
+
height: ${(props) => (props.isFullHeight ? '100%' : 'auto')};
|
73
85
|
|
74
86
|
svg {
|
75
87
|
position: absolute;
|
@@ -142,6 +154,10 @@
|
|
142
154
|
type: String,
|
143
155
|
default: 'black',
|
144
156
|
},
|
157
|
+
isFullHeight: {
|
158
|
+
type: Boolean,
|
159
|
+
default: false,
|
160
|
+
},
|
145
161
|
},
|
146
162
|
emits: ['on-change'],
|
147
163
|
watch: {
|
@@ -143,17 +143,19 @@
|
|
143
143
|
</Caret>
|
144
144
|
</SelectButton>
|
145
145
|
<DropdownWrapper ref="dropdownWrapperRef" :no-relative="noRelative">
|
146
|
-
<
|
146
|
+
<component
|
147
|
+
:is="shouldUseTeleport ? 'Teleport' : 'div'"
|
148
|
+
:to="shouldUseTeleport ? 'body' : undefined"
|
149
|
+
>
|
147
150
|
<SelectDropdown
|
148
151
|
v-show="isSelectDropdownShown"
|
149
152
|
ref="dropdown"
|
150
153
|
:bg-color="
|
151
|
-
|
152
|
-
colorMode == 'dark' ||
|
153
|
-
colorMode == 'transparent'
|
154
|
+
colorMode == 'dark' || colorMode == 'transparent'
|
154
155
|
? 'black'
|
155
156
|
: 'white'
|
156
157
|
"
|
158
|
+
class="rc-select-dropdown"
|
157
159
|
:dropdown-position="dropdownPosition"
|
158
160
|
:font-color="
|
159
161
|
dropdownFontColor ||
|
@@ -173,17 +175,29 @@
|
|
173
175
|
:hovered-index="hoveredIndex"
|
174
176
|
:hovered-value="hoveredValue"
|
175
177
|
:is-active="isActive"
|
178
|
+
:is-fixed-dropdown-position="isFixedDropdownPosition"
|
179
|
+
:is-parent-modal="isParentModal"
|
180
|
+
:is-teleport="shouldUseTeleport"
|
176
181
|
:min-width="minWidth"
|
177
182
|
:no-relative="noRelative"
|
178
183
|
:option-width="getOptionWidth"
|
179
184
|
:selected-value="selectedValue"
|
185
|
+
:style="
|
186
|
+
shouldUseTeleport
|
187
|
+
? {
|
188
|
+
transform: `translate(${dropdownPosition?.left}px, ${
|
189
|
+
noRelative ? 'auto' : `${dropdownPosition?.top}px`
|
190
|
+
})`,
|
191
|
+
}
|
192
|
+
: undefined
|
193
|
+
"
|
180
194
|
@mouseleave="optionLeave"
|
181
195
|
@option-hovered="optionHovered"
|
182
196
|
@option-selected="optionSelected"
|
183
197
|
>
|
184
198
|
<slot name="dropdown"></slot>
|
185
199
|
</SelectDropdown>
|
186
|
-
</
|
200
|
+
</component>
|
187
201
|
</DropdownWrapper>
|
188
202
|
</SelectButtonWrapper>
|
189
203
|
</InputWrapper>
|
@@ -214,7 +228,7 @@
|
|
214
228
|
// </template>
|
215
229
|
// </Select>
|
216
230
|
|
217
|
-
import { Teleport } from 'vue'
|
231
|
+
import { Teleport, inject } from 'vue'
|
218
232
|
import styled from 'vue3-styled-components'
|
219
233
|
import InfoText from '../../infoText'
|
220
234
|
import Icon from '../../icon'
|
@@ -401,14 +415,18 @@
|
|
401
415
|
selectedValue: Number | String,
|
402
416
|
noRelative: Boolean,
|
403
417
|
minWidth: String,
|
418
|
+
isParentModal: Boolean,
|
419
|
+
isFixedDropdownPosition: Boolean,
|
420
|
+
isTeleport: Boolean,
|
404
421
|
}
|
405
422
|
const SelectDropdown = styled('div', selectDropdownAttrs)`
|
406
423
|
box-sizing: border-box;
|
407
|
-
z-index: ${(props) =>
|
408
|
-
|
409
|
-
|
410
|
-
props.
|
411
|
-
|
424
|
+
z-index: ${(props) =>
|
425
|
+
props.isActive ? '2' : props.isParentModal ? '9999999' : '99999'};
|
426
|
+
position: ${(props) =>
|
427
|
+
props.isFixedDropdownPosition ? 'fixed' : 'absolute'};
|
428
|
+
top: ${(props) => (props.isTeleport ? '0px' : '4px')};
|
429
|
+
left: 0px;
|
412
430
|
border: ${BORDER_WIDTH} solid ${(props) => props.theme.colors.grey4};
|
413
431
|
border-radius: 4px;
|
414
432
|
display: flex;
|
@@ -667,6 +685,23 @@
|
|
667
685
|
required: false,
|
668
686
|
default: false,
|
669
687
|
},
|
688
|
+
isFixedDropdownPosition: {
|
689
|
+
type: Boolean,
|
690
|
+
required: false,
|
691
|
+
default: false,
|
692
|
+
},
|
693
|
+
shouldUseTeleport: {
|
694
|
+
type: Boolean,
|
695
|
+
required: false,
|
696
|
+
default: true,
|
697
|
+
},
|
698
|
+
},
|
699
|
+
setup() {
|
700
|
+
const modalRef = inject('modalRef')
|
701
|
+
|
702
|
+
return {
|
703
|
+
modalRef,
|
704
|
+
}
|
670
705
|
},
|
671
706
|
|
672
707
|
data() {
|
@@ -684,6 +719,10 @@
|
|
684
719
|
},
|
685
720
|
dropdownWidth: null,
|
686
721
|
hoveredValue: null,
|
722
|
+
isDisplayedAtBottom: true,
|
723
|
+
selectTopPosition: 0,
|
724
|
+
selectAndDropdownDistance: 0,
|
725
|
+
animationFrameId: null,
|
687
726
|
}
|
688
727
|
},
|
689
728
|
computed: {
|
@@ -741,6 +780,9 @@
|
|
741
780
|
/windows phone/i.test(userAgent)
|
742
781
|
)
|
743
782
|
},
|
783
|
+
isParentModal() {
|
784
|
+
return !!this.modalRef
|
785
|
+
},
|
744
786
|
},
|
745
787
|
watch: {
|
746
788
|
value(val) {
|
@@ -754,8 +796,13 @@
|
|
754
796
|
}, 10)
|
755
797
|
await this.$nextTick()
|
756
798
|
this.handleSetDropdownOffet()
|
799
|
+
if (!this.isFixedDropdownPosition) this.calculateSelectTopPosition()
|
757
800
|
} else {
|
758
801
|
this.dropdownPosition.left = null
|
802
|
+
if (this.animationFrameId) {
|
803
|
+
cancelAnimationFrame(this.animationFrameId)
|
804
|
+
this.animationFrameId = null
|
805
|
+
}
|
759
806
|
setTimeout(() => {
|
760
807
|
this.isClickOutsideActive = false
|
761
808
|
}, 10)
|
@@ -768,11 +815,30 @@
|
|
768
815
|
})
|
769
816
|
}
|
770
817
|
},
|
818
|
+
isSelectDropdownShown(isShown) {
|
819
|
+
if (!isShown) return
|
820
|
+
// Need to wait for 1ms to make sure the dropdown menu is shown in the DOM
|
821
|
+
// before getting the distance between the select and the dropdown menu
|
822
|
+
setTimeout(() => {
|
823
|
+
this.getDistanceBetweenSelectAndDropdownMenu()
|
824
|
+
}, 100)
|
825
|
+
},
|
826
|
+
selectTopPosition() {
|
827
|
+
this.dropdownPosition.top =
|
828
|
+
this.selectTopPosition +
|
829
|
+
this.$refs.select.$el.clientHeight +
|
830
|
+
this.selectAndDropdownDistance
|
831
|
+
},
|
771
832
|
},
|
772
833
|
mounted() {
|
773
834
|
this.observeDropdownHeight()
|
774
835
|
this.observeSelectWidth()
|
775
836
|
window.addEventListener('resize', this.handleSetDropdownOffet)
|
837
|
+
if (!this.isFixedDropdownPosition)
|
838
|
+
document.body.addEventListener(
|
839
|
+
'scroll',
|
840
|
+
this.calculateSelectTopPosition
|
841
|
+
)
|
776
842
|
},
|
777
843
|
beforeMount() {
|
778
844
|
this.selectedValue = this.value
|
@@ -781,6 +847,12 @@
|
|
781
847
|
window.removeEventListener('resize', this.handleSetDropdownOffet)
|
782
848
|
if (this.dropdownResizeObserver) this.dropdownResizeObserver.disconnect()
|
783
849
|
if (this.selectResizeObserver) this.selectResizeObserver.disconnect()
|
850
|
+
if (!this.isFixedDropdownPosition) {
|
851
|
+
document.body.removeEventListener(
|
852
|
+
'scroll',
|
853
|
+
this.calculateSelectTopPosition
|
854
|
+
)
|
855
|
+
}
|
784
856
|
},
|
785
857
|
unmounted() {
|
786
858
|
document.removeEventListener('click', this.clickOutside)
|
@@ -886,11 +958,11 @@
|
|
886
958
|
return
|
887
959
|
}
|
888
960
|
await this.$nextTick()
|
889
|
-
|
961
|
+
this.isDisplayedAtBottom = await this.generateDropdownPosition()
|
890
962
|
// If the dropdown menu is going to be displayed at the bottom,
|
891
963
|
// we need reverify its position after a dom update (nextTick)
|
892
964
|
await this.$nextTick()
|
893
|
-
if (isDisplayedAtBottom) this.generateDropdownPosition()
|
965
|
+
if (this.isDisplayedAtBottom) this.generateDropdownPosition()
|
894
966
|
},
|
895
967
|
async generateDropdownPosition() {
|
896
968
|
const isDropdownNotCompletelyVisible =
|
@@ -983,6 +1055,25 @@
|
|
983
1055
|
}
|
984
1056
|
}
|
985
1057
|
},
|
1058
|
+
getDistanceBetweenSelectAndDropdownMenu() {
|
1059
|
+
const wholeSelectTopPosition =
|
1060
|
+
this.selectTopPosition + this.$refs.select.$el.clientHeight
|
1061
|
+
this.selectAndDropdownDistance =
|
1062
|
+
this.dropdownPosition.top - wholeSelectTopPosition
|
1063
|
+
},
|
1064
|
+
calculateSelectTopPosition() {
|
1065
|
+
const selectRef = this.$refs.select
|
1066
|
+
if (selectRef) {
|
1067
|
+
const currentTopPosition =
|
1068
|
+
selectRef.$el.getBoundingClientRect().top + window.scrollY
|
1069
|
+
if (this.selectTopPosition !== currentTopPosition) {
|
1070
|
+
this.selectTopPosition = currentTopPosition
|
1071
|
+
}
|
1072
|
+
}
|
1073
|
+
this.animationFrameId = requestAnimationFrame(
|
1074
|
+
this.calculateSelectTopPosition
|
1075
|
+
)
|
1076
|
+
},
|
986
1077
|
},
|
987
1078
|
}
|
988
1079
|
</script>
|
@@ -0,0 +1,52 @@
|
|
1
|
+
/* eslint-disable */
|
2
|
+
import { mount } from '@vue/test-utils'
|
3
|
+
import ActionModal from '@/components/modals/actionModal'
|
4
|
+
import theme from '@/assets/theme'
|
5
|
+
|
6
|
+
describe('ActionModal Component', () => {
|
7
|
+
let wrapper
|
8
|
+
|
9
|
+
beforeEach(() => {
|
10
|
+
wrapper = mount(ActionModal, {
|
11
|
+
props: {
|
12
|
+
isOpen: true,
|
13
|
+
buttonText: 'Close',
|
14
|
+
},
|
15
|
+
slots: {
|
16
|
+
title: 'Sample title',
|
17
|
+
body: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tincidunt commodo mollis. Fusce urna felis, malesuada sed elementum et, fermentum ac massa. Integer in massa vel orci fermentum bibendum in ut ante. Donec risus risus, luctus quis ex a, pulvinar placerat lacus. Sed pharetra augue a elit volutpat, eu dignissim ex pretium. Aenean imperdiet, nulla in pharetra rutrum, mauris mauris tincidunt tellus, non tempus quam lorem laoreet lectus.',
|
18
|
+
buttons: '<button @click="closeAction">Close</button>',
|
19
|
+
},
|
20
|
+
global: {
|
21
|
+
provide: {
|
22
|
+
theme,
|
23
|
+
},
|
24
|
+
},
|
25
|
+
})
|
26
|
+
})
|
27
|
+
|
28
|
+
test('renders ActionModal component with default props', () => {
|
29
|
+
expect(wrapper.find('[data-test-id="actionModal"]').exists()).toBe(true)
|
30
|
+
|
31
|
+
expect(wrapper.vm.isOpen).toBe(true)
|
32
|
+
})
|
33
|
+
|
34
|
+
test('action modal slots is display when user passed slots content', () => {
|
35
|
+
const modalTitleEl = wrapper.find('[data-test-id="modal_title"]')
|
36
|
+
expect(modalTitleEl.text()).toBe('Sample title')
|
37
|
+
|
38
|
+
const modalBodyEl = wrapper.find('[data-test-id="modal_body"]')
|
39
|
+
expect(modalBodyEl.text()).toContain('Lorem ipsum dolor sit amet')
|
40
|
+
|
41
|
+
const modalActionButton = wrapper.find('[data-test-id="modal_buttons"]')
|
42
|
+
expect(modalActionButton.text()).toContain('Close')
|
43
|
+
})
|
44
|
+
|
45
|
+
test('action modal on-close event is emitted when modal close button is clicked', async () => {
|
46
|
+
const modalCloseButton = wrapper.find('.close')
|
47
|
+
|
48
|
+
modalCloseButton.trigger('click')
|
49
|
+
await wrapper.vm.$nextTick()
|
50
|
+
expect(wrapper.emitted('on-close')).toBeTruthy()
|
51
|
+
})
|
52
|
+
})
|
@@ -0,0 +1,53 @@
|
|
1
|
+
import ActionModal from './index.vue'
|
2
|
+
|
3
|
+
export default {
|
4
|
+
title: 'Components/ActionModal',
|
5
|
+
component: ActionModal,
|
6
|
+
tags: ['autodocs'],
|
7
|
+
parameters: {
|
8
|
+
layout: 'centered',
|
9
|
+
},
|
10
|
+
}
|
11
|
+
|
12
|
+
// import ActionModal from "@eturnity/eturnity_reusable_components/src/components/modals/ActionModal"
|
13
|
+
// This is a reusable modal component that can be used to display information to the user.
|
14
|
+
// To use:
|
15
|
+
// <ActionModal :isOpen="isOpen" @on-close="$emit('on-close-summary')" >
|
16
|
+
// <template #title>
|
17
|
+
// <h1>Header</h1>
|
18
|
+
// </template>
|
19
|
+
// <template #body>
|
20
|
+
// <p>Body</p>
|
21
|
+
// </template>
|
22
|
+
// <template #buttons>
|
23
|
+
// <button @click="closeModal">Close</button>
|
24
|
+
// </template>
|
25
|
+
// </ActionModal>
|
26
|
+
|
27
|
+
export const Default = {
|
28
|
+
args: {
|
29
|
+
isOpen: true,
|
30
|
+
},
|
31
|
+
render: (args) => ({
|
32
|
+
components: { ActionModal },
|
33
|
+
setup() {
|
34
|
+
return { args }
|
35
|
+
},
|
36
|
+
template: `
|
37
|
+
<ActionModal v-bind="args">
|
38
|
+
<template #title>Sample title</template>
|
39
|
+
<template #body>
|
40
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tincidunt commodo mollis. Fusce urna felis,
|
41
|
+
malesuada sed elementum et, fermentum ac massa. Integer in massa vel orci fermentum bibendum in ut ante.
|
42
|
+
Donec risus risus, luctus quis ex a, pulvinar placerat lacus. Sed pharetra augue a elit volutpat, eu dignissim
|
43
|
+
ex pretium. Aenean imperdiet, nulla in pharetra rutrum, mauris mauris tincidunt tellus, non tempus quam lorem
|
44
|
+
laoreet lectus.
|
45
|
+
</template>
|
46
|
+
<template #buttons>
|
47
|
+
<button @click="saveAction">Save</button>
|
48
|
+
<button @click="closeAction">Close</button>
|
49
|
+
</template>
|
50
|
+
</ActionModal>
|
51
|
+
`,
|
52
|
+
}),
|
53
|
+
}
|
@@ -1,13 +1,13 @@
|
|
1
1
|
<template>
|
2
|
-
<Modal :is-open="isOpen" @on-close="closeModal">
|
2
|
+
<Modal data-test-id="actionModal" :is-open="isOpen" @on-close="closeModal">
|
3
3
|
<ModalContainer>
|
4
|
-
<ModalTitle v-if="$slots.title">
|
4
|
+
<ModalTitle v-if="$slots.title" data-test-id="modal_title">
|
5
5
|
<slot name="title"></slot>
|
6
6
|
</ModalTitle>
|
7
|
-
<TextContainer v-if="$slots.body">
|
7
|
+
<TextContainer v-if="$slots.body" data-test-id="modal_body">
|
8
8
|
<slot name="body"></slot>
|
9
9
|
</TextContainer>
|
10
|
-
<ButtonContainer v-if="$slots.buttons">
|
10
|
+
<ButtonContainer v-if="$slots.buttons" data-test-id="modal_buttons">
|
11
11
|
<slot name="buttons"></slot>
|
12
12
|
</ButtonContainer>
|
13
13
|
</ModalContainer>
|
@@ -23,7 +23,7 @@
|
|
23
23
|
`
|
24
24
|
const ModalTitle = styled.div`
|
25
25
|
color: ${(props) => props.theme.colors.black};
|
26
|
-
font-family:
|
26
|
+
font-family: inherit;
|
27
27
|
font-size: 18px;
|
28
28
|
font-style: normal;
|
29
29
|
font-weight: 700;
|
@@ -37,7 +37,7 @@
|
|
37
37
|
`
|
38
38
|
const TextContainer = styled.div`
|
39
39
|
color: ${(props) => props.theme.colors.black};
|
40
|
-
font-family:
|
40
|
+
font-family: inherit;
|
41
41
|
font-size: 13px;
|
42
42
|
font-style: normal;
|
43
43
|
font-weight: 400;
|
@@ -1,48 +1,78 @@
|
|
1
1
|
<template>
|
2
|
-
<
|
2
|
+
<RCModal data-test-id="infoModal" :is-open="isOpen" @on-close="closeModal">
|
3
3
|
<ModalContainer>
|
4
|
-
<
|
4
|
+
<ModalTitle v-if="$slots.title" data-test-id="modal_title">
|
5
5
|
<slot name="title"></slot>
|
6
|
-
</
|
7
|
-
<
|
6
|
+
</ModalTitle>
|
7
|
+
<TextContainer v-if="$slots.body" data-test-id="modal_body">
|
8
8
|
<slot name="body"></slot>
|
9
|
-
</
|
10
|
-
<
|
11
|
-
<
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
</ButtonContainer>
|
19
|
-
</template>
|
9
|
+
</TextContainer>
|
10
|
+
<ButtonContainer>
|
11
|
+
<RCMainButton
|
12
|
+
min-width="150px"
|
13
|
+
:text="buttonText"
|
14
|
+
type="primary"
|
15
|
+
@click="closeModal"
|
16
|
+
/>
|
17
|
+
</ButtonContainer>
|
20
18
|
</ModalContainer>
|
21
|
-
</
|
19
|
+
</RCModal>
|
22
20
|
</template>
|
23
21
|
<script>
|
24
22
|
import styled from 'vue3-styled-components'
|
25
|
-
import
|
23
|
+
import RCModal from '../modal'
|
26
24
|
import RCMainButton from '../../buttons/mainButton'
|
25
|
+
|
27
26
|
const ModalContainer = styled.div`
|
28
27
|
width: 450px;
|
29
28
|
min-height: 205px;
|
30
29
|
padding: 40px 40px 30px 40px;
|
31
30
|
`
|
31
|
+
const ModalTitle = styled.div`
|
32
|
+
color: ${(props) => props.theme.colors.black};
|
33
|
+
font-family: inherit;
|
34
|
+
font-size: 18px;
|
35
|
+
font-style: normal;
|
36
|
+
font-weight: 700;
|
37
|
+
line-height: 120%;
|
38
|
+
text-transform: uppercase;
|
39
|
+
`
|
32
40
|
const ButtonContainer = styled.div`
|
33
41
|
display: inline-flex;
|
34
42
|
align-items: flex-start;
|
35
43
|
gap: 20px;
|
36
44
|
`
|
45
|
+
const TextContainer = styled.div`
|
46
|
+
color: ${(props) => props.theme.colors.black};
|
47
|
+
font-family: inherit;
|
48
|
+
font-size: 13px;
|
49
|
+
font-style: normal;
|
50
|
+
font-weight: 400;
|
51
|
+
line-height: normal;
|
52
|
+
padding: 30px 0px;
|
53
|
+
white-space: pre-wrap;
|
54
|
+
`
|
55
|
+
|
37
56
|
export default {
|
38
57
|
name: 'InfoModal',
|
39
58
|
components: {
|
59
|
+
RCModal,
|
40
60
|
ModalContainer,
|
61
|
+
ModalTitle,
|
41
62
|
ButtonContainer,
|
42
|
-
|
63
|
+
TextContainer,
|
43
64
|
RCMainButton,
|
44
65
|
},
|
45
|
-
props:
|
66
|
+
props: {
|
67
|
+
isOpen: {
|
68
|
+
type: Boolean,
|
69
|
+
required: true,
|
70
|
+
},
|
71
|
+
buttonText: {
|
72
|
+
type: String,
|
73
|
+
default: 'Got it',
|
74
|
+
},
|
75
|
+
},
|
46
76
|
methods: {
|
47
77
|
closeModal() {
|
48
78
|
this.$emit('on-close')
|
@@ -0,0 +1,55 @@
|
|
1
|
+
/* eslint-disable */
|
2
|
+
import { mount } from '@vue/test-utils'
|
3
|
+
import InfoModal from '@/components/modals/infoModal'
|
4
|
+
import theme from '@/assets/theme'
|
5
|
+
|
6
|
+
jest.mock('@/components/icon/iconCache.mjs', () => ({
|
7
|
+
// need to mock this due to how jest handles import.meta
|
8
|
+
fetchIcon: jest.fn(() => Promise.resolve('')),
|
9
|
+
}))
|
10
|
+
|
11
|
+
|
12
|
+
describe('InfoModal Component', () => {
|
13
|
+
let wrapper
|
14
|
+
|
15
|
+
beforeEach(() => {
|
16
|
+
wrapper = mount(InfoModal, {
|
17
|
+
props: {
|
18
|
+
isOpen: true,
|
19
|
+
buttonText: 'Close',
|
20
|
+
},
|
21
|
+
slots: {
|
22
|
+
title: 'Sample title',
|
23
|
+
body: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tincidunt commodo mollis. Fusce urna felis, malesuada sed elementum et, fermentum ac massa. Integer in massa vel orci fermentum bibendum in ut ante. Donec risus risus, luctus quis ex a, pulvinar placerat lacus. Sed pharetra augue a elit volutpat, eu dignissim ex pretium. Aenean imperdiet, nulla in pharetra rutrum, mauris mauris tincidunt tellus, non tempus quam lorem laoreet lectus.',
|
24
|
+
},
|
25
|
+
global: {
|
26
|
+
provide: {
|
27
|
+
theme,
|
28
|
+
},
|
29
|
+
},
|
30
|
+
})
|
31
|
+
})
|
32
|
+
|
33
|
+
test('renders InfoModal component with default props', () => {
|
34
|
+
expect(wrapper.find('[data-test-id="infoModal"]').exists()).toBe(true)
|
35
|
+
|
36
|
+
expect(wrapper.vm.isOpen).toBe(true)
|
37
|
+
expect(wrapper.vm.buttonText).toContain('Close')
|
38
|
+
})
|
39
|
+
|
40
|
+
test('info modal slots is display when user passed slots content', () => {
|
41
|
+
const modalTitleEl = wrapper.find('[data-test-id="modal_title"]')
|
42
|
+
expect(modalTitleEl.text()).toBe('Sample title')
|
43
|
+
|
44
|
+
const modalBodyEl = wrapper.find('[data-test-id="modal_body"]')
|
45
|
+
expect(modalBodyEl.text()).toContain('Lorem ipsum dolor sit amet')
|
46
|
+
})
|
47
|
+
|
48
|
+
test('info modal on-close event is emitted when modal close button is clicked', async () => {
|
49
|
+
const modalCloseButton = wrapper.find('.close')
|
50
|
+
|
51
|
+
modalCloseButton.trigger('click')
|
52
|
+
await wrapper.vm.$nextTick()
|
53
|
+
expect(wrapper.emitted('on-close')).toBeTruthy()
|
54
|
+
})
|
55
|
+
})
|
@@ -0,0 +1,47 @@
|
|
1
|
+
import InfoModal from './index.vue'
|
2
|
+
|
3
|
+
export default {
|
4
|
+
title: 'Components/InfoModal',
|
5
|
+
component: InfoModal,
|
6
|
+
tags: ['autodocs'],
|
7
|
+
parameters: {
|
8
|
+
layout: 'centered',
|
9
|
+
},
|
10
|
+
}
|
11
|
+
|
12
|
+
// import InfoModal from "@eturnity/eturnity_reusable_components/src/components/modals/infoModal"
|
13
|
+
// This is a reusable modal component that can be used to display information to the user.
|
14
|
+
// To use:
|
15
|
+
// <InfoModal :isOpen="isOpen" @on-close="$emit('on-close-summary')" >
|
16
|
+
// <template #title>
|
17
|
+
// <h1>Header</h1>
|
18
|
+
// </template>
|
19
|
+
// <template #body>
|
20
|
+
// <p>Body</p>
|
21
|
+
// </template>
|
22
|
+
// </InfoModal>
|
23
|
+
|
24
|
+
export const Default = {
|
25
|
+
args: {
|
26
|
+
isOpen: true,
|
27
|
+
buttonText: 'Close',
|
28
|
+
},
|
29
|
+
render: (args) => ({
|
30
|
+
components: { InfoModal },
|
31
|
+
setup() {
|
32
|
+
return { args }
|
33
|
+
},
|
34
|
+
template: `
|
35
|
+
<InfoModal v-bind="args">
|
36
|
+
<template #title>Sample title</template>
|
37
|
+
<template #body>
|
38
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tincidunt commodo mollis. Fusce urna felis,
|
39
|
+
malesuada sed elementum et, fermentum ac massa. Integer in massa vel orci fermentum bibendum in ut ante.
|
40
|
+
Donec risus risus, luctus quis ex a, pulvinar placerat lacus. Sed pharetra augue a elit volutpat, eu dignissim
|
41
|
+
ex pretium. Aenean imperdiet, nulla in pharetra rutrum, mauris mauris tincidunt tellus, non tempus quam lorem
|
42
|
+
laoreet lectus.
|
43
|
+
</template>
|
44
|
+
</InfoModal>
|
45
|
+
`,
|
46
|
+
}),
|
47
|
+
}
|
@@ -1,8 +1,10 @@
|
|
1
1
|
<template>
|
2
2
|
<PageWrapper
|
3
3
|
v-if="isOpen"
|
4
|
+
ref="modalRef"
|
4
5
|
:add-padding-top="addPaddingTop"
|
5
6
|
:backdrop="backdrop"
|
7
|
+
class="rc-modal-wrapper"
|
6
8
|
:is-open="isOpen"
|
7
9
|
:position="position"
|
8
10
|
>
|
@@ -36,6 +38,7 @@
|
|
36
38
|
// <div>Data....</div>
|
37
39
|
// </modal>
|
38
40
|
|
41
|
+
import { ref, provide } from 'vue'
|
39
42
|
import styled from 'vue3-styled-components'
|
40
43
|
import CloseButton from '../../buttons/closeButton'
|
41
44
|
import Spinner from '../../spinner'
|
@@ -58,14 +61,14 @@
|
|
58
61
|
props.backdrop == 'dark'
|
59
62
|
? 'rgba(0, 0, 0, 0.4)'
|
60
63
|
: 'rgba(255, 255, 255, 0.9)'};
|
61
|
-
z-index:
|
64
|
+
z-index: 9999999;
|
62
65
|
overflow: auto;
|
63
66
|
padding-top: ${(props) => (props.addPaddingTop ? '80px' : '0')};
|
64
67
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
`
|
68
|
+
@media (max-width: 425px) {
|
69
|
+
background: white;
|
70
|
+
}
|
71
|
+
`
|
69
72
|
|
70
73
|
const modalContainerAttrs = { overflow: String, isLoading: Boolean }
|
71
74
|
const ModalContainer = styled('div', modalContainerAttrs)`
|
@@ -163,6 +166,14 @@
|
|
163
166
|
default: false,
|
164
167
|
},
|
165
168
|
},
|
169
|
+
setup() {
|
170
|
+
const modalRef = ref(null)
|
171
|
+
provide('modalRef', modalRef)
|
172
|
+
|
173
|
+
return {
|
174
|
+
modalRef,
|
175
|
+
}
|
176
|
+
},
|
166
177
|
watch: {
|
167
178
|
isOpen: {
|
168
179
|
immediate: true,
|