@eturnity/eturnity_reusable_components 8.7.5-EPDM-12618.3 → 8.7.5-qa-16-02-21.1

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eturnity/eturnity_reusable_components",
3
- "version": "8.7.5-EPDM-12618.3",
3
+ "version": "8.7.5-qa-16-02-21.1",
4
4
  "files": [
5
5
  "dist",
6
6
  "src"
@@ -59,7 +59,7 @@
59
59
  :show-linear-unit-name="showLinearUnitName"
60
60
  :slot-size="slotSize"
61
61
  :text-align="textAlign"
62
- :value="formatWithCurrency(value)"
62
+ :value="formattedValue"
63
63
  @blur="onInputBlur($event)"
64
64
  @focus="focusInput()"
65
65
  @input="onInput($event)"
@@ -73,7 +73,7 @@
73
73
 
74
74
  <UnitContainer
75
75
  v-if="unitName && showLinearUnitName && !hasSlot"
76
- :has-length="!!textInput.length"
76
+ :has-length="hasLength"
77
77
  :is-error="isError"
78
78
  >{{ unitName }}</UnitContainer
79
79
  >
@@ -90,7 +90,7 @@
90
90
  :disabled="isSelectDisabled"
91
91
  :select-width="`${selectWidth}px`"
92
92
  :show-border="false"
93
- @input-change="$emit('select-change', $event)"
93
+ @input-change="handleSelectChange"
94
94
  >
95
95
  <template #selector>
96
96
  <SelectText>{{ getSelectValue }}</SelectText>
@@ -448,8 +448,18 @@
448
448
  background-color: ${({ theme }) => theme.colors.grey4};
449
449
  `
450
450
 
451
+ const EVENT_TYPES = {
452
+ INPUT_FOCUS: 'input-focus',
453
+ INPUT_CHANGE: 'input-change',
454
+ INPUT_BLUR: 'input-blur',
455
+ PRESS_ENTER: 'on-enter-click',
456
+ INPUT_DRAG: 'on-input-drag',
457
+ SELECT_CHANGE: 'select-change',
458
+ }
459
+
451
460
  export default {
452
461
  name: 'InputNumber',
462
+ emits: [...Object.values(EVENT_TYPES)],
453
463
  components: {
454
464
  Container,
455
465
  InputContainer,
@@ -684,9 +694,10 @@
684
694
  },
685
695
  data() {
686
696
  return {
687
- textInput: '',
688
697
  isFocused: false,
689
698
  warningIcon: warningIcon,
699
+ inputValue: null,
700
+ enteredValue: null,
690
701
  }
691
702
  },
692
703
  computed: {
@@ -709,6 +720,14 @@
709
720
 
710
721
  return item ? item.label : '-'
711
722
  },
723
+ formattedValue() {
724
+ return this.isFocused
725
+ ? this.enteredValue
726
+ : this.formatWithCurrency(this.value)
727
+ },
728
+ hasLength() {
729
+ return this.formattedValue !== null && this.formattedValue.length > 0
730
+ },
712
731
  },
713
732
  watch: {
714
733
  focus(value) {
@@ -719,30 +738,19 @@
719
738
  clearInput: function (value) {
720
739
  if (value) {
721
740
  // If the value is typed, then we should clear the textInput on Continue
722
- this.textInput = ''
741
+ this.inputValue = ''
742
+ this.enteredValue = ''
723
743
  }
724
744
  },
725
- },
726
- created() {
727
- if (this.value) {
728
- this.textInput = numberToString({
729
- value: this.value,
730
- numberPrecision: this.numberPrecision,
731
- minDecimals: this.minDecimals,
732
- })
733
- } else if (this.defaultNumber !== null) {
734
- this.textInput = numberToString({
735
- value: this.defaultNumber,
736
- numberPrecision: this.numberPrecision,
737
- minDecimals: this.minDecimals,
738
- })
739
- } else if (this.minNumber !== null) {
740
- this.textInput = numberToString({
741
- value: this.minNumber,
742
- numberPrecision: this.numberPrecision,
743
- minDecimals: this.minDecimals,
744
- })
745
- }
745
+ value: {
746
+ immediate: true,
747
+ handler(val) {
748
+ if (this.value !== this.inputValue && !Number.isNaN(this.value)) {
749
+ this.inputValue = this.value
750
+ this.enteredValue = this.value
751
+ }
752
+ },
753
+ },
746
754
  },
747
755
  mounted() {
748
756
  if (this.focus) {
@@ -781,29 +789,28 @@
781
789
  }
782
790
  },
783
791
  onEnterPress() {
784
- this.$emit('on-enter-click')
792
+ this.$emit(EVENT_TYPES.PRESS_ENTER)
785
793
  this.$refs.inputField1.$el.blur()
786
794
  },
787
- onChangeHandler(event) {
788
- if (isNaN(event) || event === '') {
789
- event = this.defaultNumber
795
+ onChangeHandler(value) {
796
+ if (isNaN(value) || value === '') {
797
+ value = this.defaultNumber
790
798
  ? this.defaultNumber
791
799
  : this.minNumber || this.minNumber === 0
792
800
  ? this.minNumber
793
- : event
801
+ : value
794
802
  }
795
803
  if (!this.allowNegative) {
796
- event = Math.abs(event)
804
+ value = Math.abs(value)
797
805
  }
798
- event = parseFloat(event)
806
+ value = parseFloat(value)
799
807
  // Need to return an integer rather than a string
800
- this.$emit('input-change', event)
808
+ return parseFloat(value)
801
809
  },
802
- onEvaluateCode(event) {
810
+ onEvaluateCode(value) {
803
811
  // function to perform math on the code
804
812
  // filter the string in case of any malicious content
805
- const val = event.target.value
806
- let filtered = val.replace('(auto)', '').replace(/[^-()\d/*+.,]/g, '')
813
+ let filtered = value.replace('(auto)', '').replace(/[^-()\d/*+.,]/g, '')
807
814
  filtered = filtered.split(/([-+*/()])/)
808
815
  let formatted = filtered.map((item) => {
809
816
  if (
@@ -861,48 +868,29 @@
861
868
  return array
862
869
  },
863
870
  onInput(event) {
864
- if (!this.isFocused) {
871
+ this.enteredValue = event.target.value
872
+ if (!this.isFocused || this.enteredValue === this.inputValue) {
865
873
  return
866
874
  }
867
- if (event.target.value === '') {
868
- this.$emit('on-input', '')
869
- }
870
875
  let evaluatedVal
871
876
  try {
872
- evaluatedVal = this.onEvaluateCode(event)
877
+ evaluatedVal = this.onEvaluateCode(String(this.enteredValue))
873
878
  } finally {
874
- if (evaluatedVal && this.value != evaluatedVal) {
875
- this.$emit('on-input', evaluatedVal)
879
+ this.inputValue = this.onChangeHandler(evaluatedVal)
880
+
881
+ if (this.isFocused && typeof this.enteredValue !== 'number') {
882
+ this.$emit(EVENT_TYPES.INPUT_CHANGE, this.inputValue)
876
883
  }
877
884
  }
878
885
  this.textInput = evaluatedVal
879
886
  },
880
887
  onInputBlur(e) {
881
888
  this.isFocused = false
882
- let value = e.target.value
883
- let evaluatedInput = this.onEvaluateCode(e)
884
- this.onChangeHandler(evaluatedInput ? evaluatedInput : value)
885
- if ((evaluatedInput && value.length) || this.minNumber !== null) {
886
- this.textInput = numberToString({
887
- value:
888
- evaluatedInput && value.length
889
- ? evaluatedInput
890
- : this.defaultNumber
891
- ? this.defaultNumber
892
- : this.minNumber,
893
- numberPrecision: this.numberPrecision,
894
- minDecimals: this.minDecimals,
895
- })
896
- }
897
- let adjustedMinValue =
898
- evaluatedInput && evaluatedInput.length
899
- ? evaluatedInput
900
- : this.defaultNumber
901
- ? this.defaultNumber
902
- : this.minNumber || this.minNumber === 0
903
- ? this.minNumber
904
- : ''
905
- this.$emit('input-blur', adjustedMinValue)
889
+ this.enteredValue = this.inputValue
890
+ this.$emit(
891
+ EVENT_TYPES.INPUT_BLUR,
892
+ this.onEvaluateCode(String(this.inputValue))
893
+ )
906
894
  },
907
895
  focusInput() {
908
896
  if (this.disabled) {
@@ -912,7 +900,7 @@
912
900
  this.$nextTick(() => {
913
901
  this.$refs.inputField1.$el.select()
914
902
  })
915
- this.$emit('input-focus')
903
+ this.$emit(EVENT_TYPES.INPUT_FOCUS, this.inputValue)
916
904
  },
917
905
  blurInput() {
918
906
  if (this.disabled) {
@@ -932,7 +920,7 @@
932
920
  : this.minNumber || this.minNumber === 0
933
921
  ? this.minNumber
934
922
  : ''
935
- if ((adjustedMinValue || adjustedMinValue === 0) && !this.isFocused) {
923
+ if (adjustedMinValue || adjustedMinValue === 0) {
936
924
  let input = this.numberToStringEnabled
937
925
  ? numberToString({
938
926
  value: adjustedMinValue,
@@ -945,6 +933,8 @@
945
933
  return input + ' ' + unit
946
934
  } else if (!adjustedMinValue && adjustedMinValue !== 0) {
947
935
  return ''
936
+ } else if (this.isFocused) {
937
+ return value
948
938
  } else {
949
939
  return this.numberToStringEnabled
950
940
  ? numberToString({
@@ -965,14 +955,7 @@
965
955
  e.preventDefault()
966
956
  let value = parseFloat(this.value || 0)
967
957
  value += parseFloat(this.interactionStep) * parseInt(e.movementX)
968
- this.$emit('on-input-drag', value)
969
-
970
- this.textInput = numberToString({
971
- value: value && value.length ? value : this.minNumber,
972
- numberPrecision: this.numberPrecision,
973
- minDecimals: this.minDecimals,
974
- })
975
- //this.value=value
958
+ this.$emit(EVENT_TYPES.INPUT_DRAG, this.onChangeHandler(value))
976
959
  },
977
960
  stopInteract(e) {
978
961
  e.preventDefault()
@@ -980,6 +963,9 @@
980
963
  window.removeEventListener('mouseup', this.stopInteract, false)
981
964
  this.blurInput()
982
965
  },
966
+ handleSelectChange(value) {
967
+ this.$emit(EVENT_TYPES.SELECT_CHANGE, value)
968
+ },
983
969
  },
984
970
  }
985
971
  </script>
@@ -168,7 +168,9 @@
168
168
  position: relative;
169
169
  font-size: ${(props) => (props.fontSize ? props.fontSize : '16px')};
170
170
  color: ${(props) =>
171
- props.isDisabled
171
+ props.isError
172
+ ? props.theme.colors.grey6
173
+ : props.isDisabled
172
174
  ? props.theme.colors.grey2
173
175
  : props.fontColor
174
176
  ? props.fontColor + ' !important'
@@ -109,11 +109,7 @@
109
109
  >
110
110
  <slot name="selector" :selected-value="selectedValue"></slot>
111
111
  </Selector>
112
- <Caret
113
- class="caret_dropdown"
114
- :color-mode="colorMode"
115
- @click.stop="toggleCaretDropdown"
116
- >
112
+ <Caret class="caret_dropdown" :color-mode="colorMode">
117
113
  <Icon
118
114
  v-if="isDropdownOpen"
119
115
  :color="
@@ -142,9 +138,7 @@
142
138
  v-show="isSelectDropdownShown"
143
139
  ref="dropdown"
144
140
  :bg-color="
145
- dropdownBgColor ||
146
- colorMode == 'dark' ||
147
- colorMode == 'transparent'
141
+ colorMode == 'dark' || colorMode == 'transparent'
148
142
  ? 'black'
149
143
  : 'white'
150
144
  "
@@ -171,6 +165,11 @@
171
165
  :no-relative="noRelative"
172
166
  :option-width="getOptionWidth"
173
167
  :selected-value="selectedValue"
168
+ :style="{
169
+ transform: `translate(${dropdownPosition?.left}px, ${
170
+ noRelative ? 'auto' : `${dropdownPosition?.top}px`
171
+ })`,
172
+ }"
174
173
  @mouseleave="optionLeave"
175
174
  @option-hovered="optionHovered"
176
175
  @option-selected="optionSelected"
@@ -397,9 +396,8 @@
397
396
  box-sizing: border-box;
398
397
  z-index: ${(props) => (props.isActive ? '2' : '99999')};
399
398
  position: absolute;
400
- top: ${(props) =>
401
- props.noRelative ? 'auto' : props.dropdownPosition?.top + 'px'};
402
- left: ${(props) => props.dropdownPosition?.left}px;
399
+ top: 0px;
400
+ left: 0px;
403
401
  border: ${BORDER_WIDTH} solid ${(props) => props.theme.colors.grey4};
404
402
  border-radius: 4px;
405
403
  display: flex;
@@ -664,6 +662,10 @@
664
662
  },
665
663
  dropdownWidth: null,
666
664
  hoveredValue: null,
665
+ isDisplayedAtBottom: true,
666
+ selectTopPosition: 0,
667
+ selectAndDropdownDistance: 0,
668
+ animationFrameId: null,
667
669
  }
668
670
  },
669
671
  computed: {
@@ -734,8 +736,13 @@
734
736
  }, 10)
735
737
  await this.$nextTick()
736
738
  this.handleSetDropdownOffet()
739
+ this.calculateSelectTopPosition()
737
740
  } else {
738
741
  this.dropdownPosition.left = null
742
+ if (this.animationFrameId) {
743
+ cancelAnimationFrame(this.animationFrameId)
744
+ this.animationFrameId = null
745
+ }
739
746
  setTimeout(() => {
740
747
  this.isClickOutsideActive = false
741
748
  }, 10)
@@ -748,11 +755,26 @@
748
755
  })
749
756
  }
750
757
  },
758
+ isSelectDropdownShown(isShown) {
759
+ if (!isShown) return
760
+ // Need to wait for 1ms to make sure the dropdown menu is shown in the DOM
761
+ // before getting the distance between the select and the dropdown menu
762
+ setTimeout(() => {
763
+ this.getDistanceBetweenSelectAndDropdownMenu()
764
+ }, 100)
765
+ },
766
+ selectTopPosition() {
767
+ this.dropdownPosition.top =
768
+ this.selectTopPosition +
769
+ this.$refs.select.$el.clientHeight +
770
+ this.selectAndDropdownDistance
771
+ },
751
772
  },
752
773
  mounted() {
753
774
  this.observeDropdownHeight()
754
775
  this.observeSelectWidth()
755
776
  window.addEventListener('resize', this.handleSetDropdownOffet)
777
+ document.body.addEventListener('scroll', this.calculateSelectTopPosition)
756
778
  },
757
779
  beforeMount() {
758
780
  this.selectedValue = this.value
@@ -761,6 +783,10 @@
761
783
  window.removeEventListener('resize', this.handleSetDropdownOffet)
762
784
  if (this.dropdownResizeObserver) this.dropdownResizeObserver.disconnect()
763
785
  if (this.selectResizeObserver) this.selectResizeObserver.disconnect()
786
+ document.body.removeEventListener(
787
+ 'scroll',
788
+ this.calculateSelectTopPosition
789
+ )
764
790
  },
765
791
  unmounted() {
766
792
  document.removeEventListener('click', this.clickOutside)
@@ -828,6 +854,7 @@
828
854
  })
829
855
  },
830
856
  clickOutside(event) {
857
+ console.log('clickOutside')
831
858
  const dropdownRef = this.$refs.dropdown
832
859
  // we need to prevent closing on selecting an option, because in the case of
833
860
  // a disabled option, we don't want to close the dropdown
@@ -866,11 +893,11 @@
866
893
  return
867
894
  }
868
895
  await this.$nextTick()
869
- const isDisplayedAtBottom = await this.generateDropdownPosition()
896
+ this.isDisplayedAtBottom = await this.generateDropdownPosition()
870
897
  // If the dropdown menu is going to be displayed at the bottom,
871
898
  // we need reverify its position after a dom update (nextTick)
872
899
  await this.$nextTick()
873
- if (isDisplayedAtBottom) this.generateDropdownPosition()
900
+ if (this.isDisplayedAtBottom) this.generateDropdownPosition()
874
901
  },
875
902
  async generateDropdownPosition() {
876
903
  const isDropdownNotCompletelyVisible =
@@ -963,6 +990,25 @@
963
990
  }
964
991
  }
965
992
  },
993
+ getDistanceBetweenSelectAndDropdownMenu() {
994
+ const wholeSelectTopPosition =
995
+ this.selectTopPosition + this.$refs.select.$el.clientHeight
996
+ this.selectAndDropdownDistance =
997
+ this.dropdownPosition.top - wholeSelectTopPosition
998
+ },
999
+ calculateSelectTopPosition() {
1000
+ const selectRef = this.$refs.select
1001
+ if (selectRef) {
1002
+ const currentTopPosition =
1003
+ selectRef.$el.getBoundingClientRect().top + window.scrollY
1004
+ if (this.selectTopPosition !== currentTopPosition) {
1005
+ this.selectTopPosition = currentTopPosition
1006
+ }
1007
+ }
1008
+ this.animationFrameId = requestAnimationFrame(
1009
+ this.calculateSelectTopPosition
1010
+ )
1011
+ },
966
1012
  },
967
1013
  }
968
1014
  </script>
@@ -38,18 +38,18 @@
38
38
 
39
39
  const pageAttrs = { backdrop: String, position: String }
40
40
  const PageWrapper = styled('div', pageAttrs)`
41
- position: ${(props) => props.position}
42
- display: grid;
43
- top: 0;
44
- left: 0;
45
- width: 100%;
46
- height: 100%;
47
- background-color: ${(props) =>
48
- props.backdrop == 'dark'
49
- ? 'rgba(0, 0, 0, 0.4)'
50
- : 'rgba(255, 255, 255, 0.9)'};
51
- z-index: 99999;
52
- overflow: auto;
41
+ position: ${(props) => props.position}
42
+ display: grid;
43
+ top: 0;
44
+ left: 0;
45
+ width: 100%;
46
+ height: 100%;
47
+ background-color: ${(props) =>
48
+ props.backdrop == 'dark'
49
+ ? 'rgba(0, 0, 0, 0.4)'
50
+ : 'rgba(255, 255, 255, 0.9)'};
51
+ z-index: 99999;
52
+ overflow: auto;
53
53
 
54
54
  @media (max-width: 425px) {
55
55
  background: white;
@@ -74,13 +74,10 @@
74
74
  v-else
75
75
  class="inputField"
76
76
  :disabled="customInputDisabled"
77
- :error-message="item.errorMessage"
78
77
  :font-color="showArchived ? theme.colors.red : 'black'"
79
- :is-error="item.isError"
80
78
  :min-width="item.value.length + 'ch'"
81
79
  :no-border="true"
82
80
  :value="item.value"
83
- @input-blur="onCustomInputChange($event.trim())"
84
81
  @input-change="onCustomInputChange($event)"
85
82
  />
86
83
  </InputContainer>
@@ -157,7 +154,7 @@
157
154
  </OptionsItem>
158
155
  </OptionsWrapper>
159
156
  <CustomContainer
160
- v-if="getCustomName.length && allowFreeInputs"
157
+ v-if="inputText.length && allowFreeInputs"
161
158
  @click="onCustomNameClick()"
162
159
  >
163
160
  <CustomName>{{ getCustomName }}</CustomName>
@@ -220,6 +217,7 @@
220
217
  const ItemAttrs = { isNested: Boolean, showArchived: Boolean }
221
218
  const ComponentItem = styled('td', ItemAttrs)`
222
219
  padding-left: ${(props) => (props.isNested ? '14px !important' : '0')};
220
+ overflow: hidden;
223
221
  text-overflow: ellipsis;
224
222
  padding-right: 0 !important;
225
223
  color: ${(props) =>
@@ -553,7 +551,7 @@
553
551
  },
554
552
  computed: {
555
553
  getCustomName() {
556
- return this.inputText.trim()
554
+ return this.inputText
557
555
  },
558
556
  theme() {
559
557
  return theme
@@ -647,7 +645,7 @@
647
645
  },
648
646
  onCustomNameClick() {
649
647
  this.wasClicked = true
650
- this.$emit('on-custom-input-name', this.getCustomName)
648
+ this.$emit('on-custom-input-name', this.inputText)
651
649
  this.$emit('toggle-dropdown-open', { close: true })
652
650
  this.inputText = ''
653
651
  },
@@ -94,7 +94,7 @@ export const stringToNumber = ({
94
94
 
95
95
  export const numberToString = ({ value, numberPrecision, minDecimals }) => {
96
96
  const minimumRounding = minDecimals ? minDecimals : 0
97
- value = parseFloat(value)
97
+ value = !Number.isNaN(parseFloat(value)) ? parseFloat(value) : 0
98
98
  return value.toLocaleString(langForLocaleString(), {
99
99
  minimumFractionDigits: minimumRounding, // removing this for now. Why do we need this to be a minimum amount?
100
100
  maximumFractionDigits: