@eturnity/eturnity_reusable_components 9.19.12 → 9.22.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": "9.19.12",
3
+ "version": "9.22.1",
4
4
  "files": [
5
5
  "dist",
6
6
  "src"
@@ -231,6 +231,11 @@
231
231
  v-if="!deferDropdownSlotContent || isSelectDropdownShown"
232
232
  name="dropdown"
233
233
  ></slot>
234
+ <slot
235
+ v-if="isCustomOptionVisible"
236
+ name="customOption"
237
+ :custom-option-value="customOptionValue"
238
+ />
234
239
  </SelectDropdown>
235
240
  </Component>
236
241
  </DropdownWrapper>
@@ -267,6 +272,10 @@
267
272
  // <Option value="3">value three</Option>
268
273
  // <Option value="4">value four</Option>
269
274
  // </template>
275
+ // <!-- optional: with is-customizable, render the typed-value row -->
276
+ // <template #customOption="{ customOptionValue }">
277
+ // <Option data-custom-option :value="customOptionAdapter(customOptionValue)">{{ customOptionValue }} (custom)</Option>
278
+ // </template>
270
279
  // </Select>
271
280
 
272
281
  import { Teleport, inject } from 'vue'
@@ -729,6 +738,16 @@
729
738
  required: false,
730
739
  default: true,
731
740
  },
741
+ isCustomizable: {
742
+ required: false,
743
+ type: Boolean,
744
+ default: false,
745
+ },
746
+ customOptionAdapter: {
747
+ type: Function,
748
+ required: false,
749
+ default: null,
750
+ },
732
751
  hasError: {
733
752
  type: Boolean,
734
753
  required: false,
@@ -891,11 +910,27 @@
891
910
  optionLength() {
892
911
  return this.optionLengthCount
893
912
  },
913
+ customOptionValue() {
914
+ return this.textSearch.trim()
915
+ },
916
+ resolvedCustomOption() {
917
+ if (this.customOptionAdapter) {
918
+ return this.customOptionAdapter(this.customOptionValue)
919
+ }
920
+ return this.customOptionValue
921
+ },
922
+ isCustomOptionVisible() {
923
+ return this.isCustomizable && this.customOptionValue.length > 0
924
+ },
894
925
  isSearchBarVisible() {
895
926
  return (
896
- this.searchPlacement !== 'dropdown' &&
897
- this.isSearchable &&
898
- this.optionLength >= this.minOptionLength &&
927
+ (this.isCustomizable ||
928
+ (
929
+ this.searchPlacement !== 'dropdown' &&
930
+ this.isSearchable &&
931
+ this.optionLength >= this.minOptionLength
932
+ )
933
+ ) &&
899
934
  this.isDropdownOpen
900
935
  )
901
936
  },
@@ -934,8 +969,7 @@
934
969
  isSelectDropdownShown() {
935
970
  return (
936
971
  this.isDropdownOpen &&
937
- this.dropdownPosition.left !== null &&
938
- (!this.isSearchable || this.isSearchable)
972
+ this.dropdownPosition.left !== null
939
973
  )
940
974
  },
941
975
  isMobileDevice() {
@@ -1022,7 +1056,7 @@
1022
1056
  this.isClickOutsideActive = false
1023
1057
  }, 10)
1024
1058
  }
1025
- if (val && this.isSearchable) {
1059
+ if (val && this.isSearchBarVisible) {
1026
1060
  this.$nextTick(() => {
1027
1061
  if (this.searchPlacement === 'dropdown') {
1028
1062
  const ref = this.$refs.dropdownSearchInput
@@ -1196,7 +1230,7 @@
1196
1230
  }
1197
1231
 
1198
1232
  nodes.forEach((el) => {
1199
- let show = el.textContent.toLowerCase().includes(q)
1233
+ let show = el.textContent.toLowerCase().includes(q) || el.hasAttribute('data-custom-option')
1200
1234
  if (
1201
1235
  show &&
1202
1236
  hideUnassignedWhenOthers &&
@@ -1278,6 +1312,10 @@
1278
1312
  } else if (e.key == 'Enter') {
1279
1313
  const root = this.$refs.dropdown?.$el
1280
1314
  if (!root) return
1315
+ if (this.isCustomOptionVisible) {
1316
+ this.optionSelected(this.resolvedCustomOption)
1317
+ return
1318
+ }
1281
1319
  const opts = [...root.querySelectorAll('[data-value]')].filter(
1282
1320
  (el) => getComputedStyle(el).display !== 'none'
1283
1321
  )
@@ -1,26 +1,38 @@
1
+ import { computed, ref } from 'vue'
1
2
  import Select from './index.vue'
2
3
  import Option from './option/index.vue'
3
4
 
5
+ const SELECT_SAMPLE_OPTIONS = [
6
+ { key: '1', label: 'value one' },
7
+ { key: '2', label: 'value two' },
8
+ { key: '3', label: 'value three' },
9
+ { key: '4', label: 'value four' },
10
+ ]
11
+
4
12
  export default {
5
13
  title: 'select',
6
14
  component: Select,
7
- // argTypes: {},
8
15
  }
9
16
 
10
- const Template = (args, { argTypes }) => ({
17
+ const Template = (args) => ({
11
18
  // Components used in your story `template` are defined in the `components` object
12
19
  components: { Select, Option },
13
20
  // The story's `args` need to be mapped into the template through the `setup()` method
14
- props: Object.keys(argTypes),
15
- template: `<Select v-bind="$props">
16
- <template #selector="{selectedValue}">
17
- value selected: {{selectedValue}}
21
+ setup() {
22
+ return { args, selectSampleOptions: SELECT_SAMPLE_OPTIONS }
23
+ },
24
+ template: `<Select v-bind="args">
25
+ <template #selector="{ selectedValue }">
26
+ value selected: {{ selectedValue.label }}
18
27
  </template>
19
28
  <template #dropdown>
20
- <Option value="1">value one</Option>
21
- <Option value="2">value two</Option>
22
- <Option value="3">value three</Option>
23
- <Option value="4">value four</Option>
29
+ <Option
30
+ v-for="item in selectSampleOptions"
31
+ :key="item.key"
32
+ :value="item"
33
+ >
34
+ {{ item.label }}
35
+ </Option>
24
36
  </template>
25
37
  </Select>`,
26
38
 
@@ -49,10 +61,82 @@ const Template = (args, { argTypes }) => ({
49
61
 
50
62
  export const Default = Template.bind({})
51
63
  Default.args = {
52
- hoverDropdown: 'true',
64
+ hoverDropdown: false,
53
65
  selectWidth: '100%',
54
66
  optionWidth: '50%',
55
67
  label: 'that is a label',
56
68
  alignItems: 'vertical',
57
- value: '2',
69
+ value: SELECT_SAMPLE_OPTIONS[1],
70
+ }
71
+
72
+ /**
73
+ * Customizable Select
74
+ */
75
+ const CustomizableTemplate = (args) => ({
76
+ components: { Select, Option },
77
+ setup() {
78
+ const CUSTOM_OPTION_KEY = 'custom-option'
79
+ const customOption = ref(null)
80
+ const createCustomOption = (customOptionValue) => ({
81
+ key: CUSTOM_OPTION_KEY,
82
+ label: customOptionValue,
83
+ })
84
+ const customizableOptions = computed(() => {
85
+ const options = [...SELECT_SAMPLE_OPTIONS]
86
+ if (customOption.value) {
87
+ options.push(customOption.value)
88
+ }
89
+ return options.filter(
90
+ (item, index, self) =>
91
+ self.findIndex((candidate) => candidate.label === item.label) === index
92
+ )
93
+ })
94
+ const onInputChange = (value) => {
95
+ args.value = value
96
+ if (value?.key === CUSTOM_OPTION_KEY) {
97
+ customOption.value = value
98
+ }
99
+ }
100
+ return {
101
+ args,
102
+ customizableOptions,
103
+ createCustomOption,
104
+ onInputChange,
105
+ }
106
+ },
107
+ template: `<Select
108
+ v-bind="args"
109
+ :custom-option-adapter="createCustomOption"
110
+ @input-change="onInputChange"
111
+ >
112
+ <template #selector="{ selectedValue }">
113
+ value selected: {{ selectedValue.label }}
114
+ </template>
115
+ <template #dropdown>
116
+ <Option
117
+ v-for="(item) in customizableOptions"
118
+ :key="item.key"
119
+ :value="item"
120
+ >
121
+ {{ item.label }}
122
+ </Option>
123
+ </template>
124
+ <template #customOption="{ customOptionValue }">
125
+ <Option
126
+ data-custom-option
127
+ :value="createCustomOption(customOptionValue)"
128
+ >
129
+ {{ customOptionValue }}
130
+ <div>(custom)</div>
131
+ </Option>
132
+ </template>
133
+ </Select>`,
134
+ })
135
+
136
+ export const Customizable = CustomizableTemplate.bind({})
137
+ Customizable.args = {
138
+ label: 'Customizable select',
139
+ alignItems: 'vertical',
140
+ isCustomizable: true,
141
+ value: SELECT_SAMPLE_OPTIONS[1],
58
142
  }
@@ -31,6 +31,8 @@
31
31
  :font-color="
32
32
  stepIndex === currentStepIndex
33
33
  ? theme.semanticColors.grey[900]
34
+ : step.isDisabled
35
+ ? theme.semanticColors.grey[600]
34
36
  : theme.semanticColors.grey[800]
35
37
  "
36
38
  :type="labelTextType"
@@ -1,6 +1,7 @@
1
1
  <template>
2
- <TagContainer :data-id="dataId" :data-qa-id="dataQaId">
2
+ <TagContainer :data-id="dataId" :data-qa-id="dataQaId" :height="height">
3
3
  <RcIcon
4
+ v-if="!noIcon"
4
5
  :color="getIconColor"
5
6
  :hovered-color="getIconColor"
6
7
  name="star"
@@ -23,6 +24,7 @@
23
24
  padding: 2px 4px;
24
25
  background-color: ${(props) => props.theme.semanticColors.yellow[200]};
25
26
  cursor: pointer;
27
+ height: ${(props) => props.height};
26
28
  `
27
29
 
28
30
  const TextContainer = styled.div`
@@ -56,6 +58,15 @@
56
58
  default: '',
57
59
  type: String,
58
60
  },
61
+ noIcon: {
62
+ type: Boolean,
63
+ default: false,
64
+ },
65
+ height: {
66
+ required: false,
67
+ type: String,
68
+ default: 'auto',
69
+ },
59
70
  },
60
71
  computed: {
61
72
  getIconColor() {