@infineon/infineon-vue-datatable 0.0.0

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.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/package.json +44 -0
  3. package/src/datatable/InfineonDatatable.vue +278 -0
  4. package/src/datatable/InfineonDatatablePager.vue +146 -0
  5. package/src/datatable/InfineonDatatableRow.vue +229 -0
  6. package/src/datatable/InfineonDatatableRowColumn.vue +88 -0
  7. package/src/datatable/InfineonDatatableShowColumnsPicker.vue +45 -0
  8. package/src/datatable/InfineonDatatableSortIcon.vue +49 -0
  9. package/src/index.js +4 -0
  10. package/src/plugins/axiosErrorHandler.js +11 -0
  11. package/src/plugins/axiosLoadingOverlay.js +42 -0
  12. package/src/plugins/fontawesome.js +70 -0
  13. package/src/plugins/treeView/index.js +12 -0
  14. package/src/plugins/treeView/src/components/Control.vue +152 -0
  15. package/src/plugins/treeView/src/components/HiddenFields.vue +40 -0
  16. package/src/plugins/treeView/src/components/Input.vue +298 -0
  17. package/src/plugins/treeView/src/components/Menu.vue +314 -0
  18. package/src/plugins/treeView/src/components/MenuPortal.vue +195 -0
  19. package/src/plugins/treeView/src/components/MultiValue.vue +60 -0
  20. package/src/plugins/treeView/src/components/MultiValueItem.vue +49 -0
  21. package/src/plugins/treeView/src/components/Option.vue +302 -0
  22. package/src/plugins/treeView/src/components/Placeholder.vue +20 -0
  23. package/src/plugins/treeView/src/components/SingleValue.vue +32 -0
  24. package/src/plugins/treeView/src/components/Tip.vue +40 -0
  25. package/src/plugins/treeView/src/components/Treeselect.vue +63 -0
  26. package/src/plugins/treeView/src/components/icons/Arrow.vue +14 -0
  27. package/src/plugins/treeView/src/components/icons/Delete.vue +17 -0
  28. package/src/plugins/treeView/src/constants.js +50 -0
  29. package/src/plugins/treeView/src/mixins/treeselectMixin.js +2083 -0
  30. package/src/plugins/treeView/src/utils/.eslintrc.js +6 -0
  31. package/src/plugins/treeView/src/utils/constant.js +1 -0
  32. package/src/plugins/treeView/src/utils/createMap.js +1 -0
  33. package/src/plugins/treeView/src/utils/debounce.js +1 -0
  34. package/src/plugins/treeView/src/utils/deepExtend.js +29 -0
  35. package/src/plugins/treeView/src/utils/find.js +6 -0
  36. package/src/plugins/treeView/src/utils/identity.js +1 -0
  37. package/src/plugins/treeView/src/utils/includes.js +3 -0
  38. package/src/plugins/treeView/src/utils/index.js +38 -0
  39. package/src/plugins/treeView/src/utils/isNaN.js +3 -0
  40. package/src/plugins/treeView/src/utils/isPromise.js +1 -0
  41. package/src/plugins/treeView/src/utils/last.js +1 -0
  42. package/src/plugins/treeView/src/utils/noop.js +1 -0
  43. package/src/plugins/treeView/src/utils/onLeftClick.js +7 -0
  44. package/src/plugins/treeView/src/utils/once.js +1 -0
  45. package/src/plugins/treeView/src/utils/quickDiff.js +9 -0
  46. package/src/plugins/treeView/src/utils/removeFromArray.js +4 -0
  47. package/src/plugins/treeView/src/utils/scrollIntoView.js +15 -0
  48. package/src/plugins/treeView/src/utils/setupResizeAndScrollEventListeners.js +34 -0
  49. package/src/plugins/treeView/src/utils/warning.js +11 -0
  50. package/src/plugins/treeView/src/utils/watchSize.js +67 -0
  51. package/src/plugins/treeView/styles/assets/checkbox-checked-disabled.png +0 -0
  52. package/src/plugins/treeView/styles/assets/checkbox-checked-disabled@2x.png +0 -0
  53. package/src/plugins/treeView/styles/assets/checkbox-checked-disabled@3x.png +0 -0
  54. package/src/plugins/treeView/styles/assets/checkbox-checked.png +0 -0
  55. package/src/plugins/treeView/styles/assets/checkbox-checked@2x.png +0 -0
  56. package/src/plugins/treeView/styles/assets/checkbox-checked@3x.png +0 -0
  57. package/src/plugins/treeView/styles/assets/checkbox-indeterminate-disabled.png +0 -0
  58. package/src/plugins/treeView/styles/assets/checkbox-indeterminate-disabled@2x.png +0 -0
  59. package/src/plugins/treeView/styles/assets/checkbox-indeterminate-disabled@3x.png +0 -0
  60. package/src/plugins/treeView/styles/assets/checkbox-indeterminate.png +0 -0
  61. package/src/plugins/treeView/styles/assets/checkbox-indeterminate@2x.png +0 -0
  62. package/src/plugins/treeView/styles/assets/checkbox-indeterminate@3x.png +0 -0
  63. package/src/plugins/treeView/styles/style.less +1150 -0
@@ -0,0 +1,40 @@
1
+ <script>
2
+ import { defineComponent, h } from 'vue';
3
+ import { isNaN } from '../utils';
4
+
5
+ function stringifyValue(value) {
6
+ if (typeof value === 'string') return value;
7
+ // istanbul ignore else
8
+ if (value != null && !isNaN(value)) return JSON.stringify(value);
9
+ // istanbul ignore next
10
+ return '';
11
+ }
12
+
13
+ export default defineComponent({
14
+ functional: true,
15
+ inject: ['instance'],
16
+
17
+ render(context) {
18
+ const { instance } = context;
19
+
20
+ if (!instance.name || instance.disabled || !instance.hasValue) return null;
21
+
22
+ let stringifiedValues = instance.internalValue.map(stringifyValue);
23
+
24
+ if (instance.multiple && instance.joinValues) {
25
+ stringifiedValues = [
26
+ stringifiedValues.join(instance.delimiter),
27
+ ];
28
+ }
29
+
30
+ return stringifiedValues.map((stringifiedValue, i) => (
31
+ h('input', {
32
+ type: 'hidden',
33
+ name: instance.name,
34
+ value: stringifiedValue,
35
+ key: `hidden-field-${i}`,
36
+ })
37
+ ));
38
+ },
39
+ });
40
+ </script>
@@ -0,0 +1,298 @@
1
+ <script>
2
+ import { defineComponent, h } from 'vue';
3
+ import { debounce, deepExtend, includes } from '../utils';
4
+ import { MIN_INPUT_WIDTH, KEY_CODES, INPUT_DEBOUNCE_DELAY } from '../constants';
5
+
6
+ const keysThatRequireMenuBeingOpen = [
7
+ KEY_CODES.ENTER,
8
+ KEY_CODES.END,
9
+ KEY_CODES.HOME,
10
+ KEY_CODES.ARROW_LEFT,
11
+ KEY_CODES.ARROW_UP,
12
+ KEY_CODES.ARROW_RIGHT,
13
+ KEY_CODES.ARROW_DOWN,
14
+ ];
15
+
16
+ export default {
17
+ inject: ['instance'],
18
+
19
+ data: () => ({
20
+ inputWidth: MIN_INPUT_WIDTH,
21
+ value: '',
22
+ }),
23
+
24
+ computed: {
25
+ needAutoSize() {
26
+ const { instance } = this;
27
+
28
+ return (
29
+ instance.searchable
30
+ && !instance.disabled
31
+ && instance.multiple
32
+ );
33
+ },
34
+
35
+ inputStyle() {
36
+ return {
37
+ width: this.needAutoSize ? `${this.inputWidth}px` : null,
38
+ };
39
+ },
40
+ },
41
+
42
+ watch: {
43
+ // eslint-disable-next-line func-names
44
+ 'instance.trigger.searchQuery': function (newValue) {
45
+ this.value = newValue;
46
+ },
47
+
48
+ value() {
49
+ // istanbul ignore else
50
+ if (this.needAutoSize) this.$nextTick(this.updateInputWidth);
51
+ },
52
+ },
53
+
54
+ created() {
55
+ this.debouncedCallback = debounce(
56
+ this.updateSearchQuery,
57
+ INPUT_DEBOUNCE_DELAY,
58
+ { leading: true, trailing: true },
59
+ );
60
+ },
61
+
62
+ methods: {
63
+ clear() {
64
+ this.onInput({
65
+ target: { value: '' },
66
+ });
67
+ },
68
+
69
+ focus() {
70
+ const { instance } = this;
71
+
72
+ if (!instance.disabled) {
73
+ return this.$refs.input && this.$refs.input.focus();
74
+ }
75
+ return true;
76
+ },
77
+
78
+ blur() {
79
+ return this.$refs.input && this.$refs.input.blur();
80
+ },
81
+
82
+ onFocus() {
83
+ const { instance } = this;
84
+
85
+ instance.trigger.isFocused = true;
86
+ // istanbul ignore else
87
+ if (instance.openOnFocus) instance.openMenu();
88
+ },
89
+
90
+ onBlur() {
91
+ const { instance } = this;
92
+ const menu = instance.getMenu();
93
+
94
+ // #15
95
+ // istanbul ignore next
96
+ if (menu && document.activeElement === menu) {
97
+ return this.focus();
98
+ }
99
+
100
+ instance.trigger.isFocused = false;
101
+ instance.closeMenu();
102
+ return true;
103
+ },
104
+
105
+ onInput(evt) {
106
+ const { value } = evt.target;
107
+
108
+ this.value = value;
109
+
110
+ if (value) {
111
+ this.debouncedCallback();
112
+ } else {
113
+ this.debouncedCallback.cancel();
114
+ this.updateSearchQuery();
115
+ }
116
+ },
117
+
118
+ // 用 keyUp 事件存在一个问题,删除输入框最后一个字符也会导致取消选中最后一项
119
+ onKeyDown(evt) {
120
+ const { instance } = this;
121
+ // https://css-tricks.com/snippets/javascript/javascript-keycodes/
122
+ // https://stackoverflow.com/questions/4471582/javascript-keycode-vs-which
123
+ const key = 'which' in evt ? evt.which : /* istanbul ignore next */ evt.keyCode;
124
+
125
+ if (evt.ctrlKey || evt.shiftKey || evt.altKey || evt.metaKey) { return; }
126
+
127
+ if (!instance.menu.isOpen && includes(keysThatRequireMenuBeingOpen, key)) {
128
+ evt.preventDefault();
129
+ // eslint-disable-next-line consistent-return
130
+ return instance.openMenu();
131
+ }
132
+
133
+ switch (key) {
134
+ case KEY_CODES.BACKSPACE: {
135
+ if (instance.backspaceRemoves && !this.value.length) {
136
+ instance.removeLastValue();
137
+ }
138
+ break;
139
+ }
140
+ case KEY_CODES.ENTER: {
141
+ evt.preventDefault();
142
+ if (instance.menu.current === null) return;
143
+ const current = instance.getNode(instance.menu.current);
144
+ if (current.isBranch && instance.disableBranchNodes) return;
145
+ instance.select(current);
146
+ break;
147
+ }
148
+ case KEY_CODES.ESCAPE: {
149
+ if (this.value.length) {
150
+ this.clear();
151
+ } else if (instance.menu.isOpen) {
152
+ instance.closeMenu();
153
+ }
154
+ break;
155
+ }
156
+ case KEY_CODES.END: {
157
+ evt.preventDefault();
158
+ instance.highlightLastOption();
159
+ break;
160
+ }
161
+ case KEY_CODES.HOME: {
162
+ evt.preventDefault();
163
+ instance.highlightFirstOption();
164
+ break;
165
+ }
166
+ case KEY_CODES.ARROW_LEFT: {
167
+ const current = instance.getNode(instance.menu.current);
168
+ if (current.isBranch && instance.shouldExpand(current)) {
169
+ evt.preventDefault();
170
+ instance.toggleExpanded(current);
171
+ } else if (!current.isRootNode
172
+ && (current.isLeaf || (current.isBranch && !(instance.shouldExpand(current))))) {
173
+ evt.preventDefault();
174
+ instance.setCurrentHighlightedOption(current.parentNode);
175
+ }
176
+ break;
177
+ }
178
+ case KEY_CODES.ARROW_UP: {
179
+ evt.preventDefault();
180
+ instance.highlightPrevOption();
181
+ break;
182
+ }
183
+ case KEY_CODES.ARROW_RIGHT: {
184
+ const current = instance.getNode(instance.menu.current);
185
+ if (current.isBranch && !instance.shouldExpand(current)) {
186
+ evt.preventDefault();
187
+ instance.toggleExpanded(current);
188
+ }
189
+ break;
190
+ }
191
+ case KEY_CODES.ARROW_DOWN: {
192
+ evt.preventDefault();
193
+ instance.highlightNextOption();
194
+ break;
195
+ }
196
+ case KEY_CODES.DELETE: {
197
+ if (instance.deleteRemoves && !this.value.length) {
198
+ instance.removeLastValue();
199
+ }
200
+ break;
201
+ }
202
+ default: {
203
+ // istanbul ignore else
204
+ instance.openMenu();
205
+ }
206
+ }
207
+ },
208
+
209
+ onMouseDown(evt) {
210
+ // istanbul ignore next
211
+ if (this.value.length) {
212
+ // Prevent it from bubbling to the top level and triggering `preventDefault()`
213
+ // to make the textbox unselectable
214
+ evt.stopPropagation();
215
+ }
216
+ },
217
+
218
+ renderInputContainer() {
219
+ const { instance } = this;
220
+ const props = {};
221
+ const children = [];
222
+
223
+ if (instance.searchable && !instance.disabled) {
224
+ children.push(this.renderInput());
225
+ if (this.needAutoSize) children.push(this.renderSizer());
226
+ }
227
+
228
+ if (!instance.searchable) {
229
+ deepExtend(props, {
230
+ on: {
231
+ focus: this.onFocus,
232
+ blur: this.onBlur,
233
+ keydown: this.onKeyDown,
234
+ },
235
+ ref: 'input',
236
+ });
237
+ }
238
+
239
+ if (!instance.searchable && !instance.disabled) {
240
+ deepExtend(props, {
241
+ attrs: {
242
+ tabIndex: instance.tabIndex,
243
+ },
244
+ });
245
+ }
246
+
247
+ return (
248
+ h('div', { class: 'vue-treeselect__input-container', ...props }, children)
249
+ );
250
+ },
251
+
252
+ renderInput() {
253
+ const { instance } = this;
254
+
255
+ return (
256
+ h('input', {
257
+ ref: 'input',
258
+ class: 'vue-treeselect__input',
259
+ type: 'text',
260
+ autocomplete: 'off',
261
+ tabIndex: instance.tabIndex,
262
+ required: instance.required && !instance.hasValue,
263
+ value: this.value,
264
+ style: this.inputStyle,
265
+ onFocus: this.onFocus,
266
+ onInput: this.onInput,
267
+ onBlur: this.onBlur,
268
+ onKeydown: this.onKeyDown,
269
+ onMousedown: this.onMouseDown,
270
+ })
271
+ );
272
+ },
273
+
274
+ renderSizer() {
275
+ return (
276
+ h('div', { ref: 'sizer', class: 'vue-treeselect__sizer' }, [this.value])
277
+ );
278
+ },
279
+
280
+ updateInputWidth() {
281
+ this.inputWidth = Math.max(
282
+ MIN_INPUT_WIDTH,
283
+ this.$refs.sizer.scrollWidth + 15,
284
+ );
285
+ },
286
+
287
+ updateSearchQuery() {
288
+ const { instance } = this;
289
+
290
+ instance.trigger.searchQuery = this.value;
291
+ },
292
+ },
293
+
294
+ render() {
295
+ return this.renderInputContainer();
296
+ },
297
+ };
298
+ </script>
@@ -0,0 +1,314 @@
1
+ <script>
2
+ import { defineComponent, h } from 'vue';
3
+ import { MENU_BUFFER } from '../constants';
4
+ import { watchSize, setupResizeAndScrollEventListeners } from '../utils';
5
+ import Option from './Option.vue';
6
+ import Tip from './Tip.vue';
7
+
8
+ const directionMap = {
9
+ top: 'top',
10
+ bottom: 'bottom',
11
+ above: 'top',
12
+ below: 'bottom',
13
+ };
14
+
15
+ export default {
16
+ inject: ['instance'],
17
+
18
+ computed: {
19
+ menuStyle() {
20
+ const { instance } = this;
21
+
22
+ return {
23
+ maxHeight: `${instance.maxHeight}px`,
24
+ };
25
+ },
26
+
27
+ menuContainerStyle() {
28
+ const { instance } = this;
29
+
30
+ return {
31
+ zIndex: instance.appendToBody ? null : instance.zIndex,
32
+ };
33
+ },
34
+ },
35
+
36
+ watch: {
37
+ // eslint-disable-next-line func-names
38
+ 'instance.menu.isOpen': function (newValue) {
39
+ if (newValue) {
40
+ // In case `openMenu()` is just called and the menu is not rendered yet.
41
+ this.$nextTick(this.onMenuOpen);
42
+ } else {
43
+ this.onMenuClose();
44
+ }
45
+ },
46
+ },
47
+
48
+ created() {
49
+ this.menuSizeWatcher = null;
50
+ this.menuResizeAndScrollEventListeners = null;
51
+ },
52
+
53
+ mounted() {
54
+ const { instance } = this;
55
+
56
+ if (instance.menu.isOpen) this.$nextTick(this.onMenuOpen);
57
+ },
58
+
59
+ unmounted() {
60
+ this.onMenuClose();
61
+ },
62
+
63
+ methods: {
64
+ renderMenu() {
65
+ const { instance } = this;
66
+
67
+ if (!instance.menu.isOpen) return null;
68
+
69
+ return h('div', {
70
+ ref: 'menu',
71
+ class: 'vue-treeselect__menu',
72
+ onMousedown: instance.handleMouseDown,
73
+ style: this.menuStyle,
74
+ },
75
+ [
76
+ this.renderBeforeList(),
77
+ // eslint-disable-next-line no-nested-ternary
78
+ instance.async
79
+ ? this.renderAsyncSearchMenuInner()
80
+ : instance.localSearch.active
81
+ ? this.renderLocalSearchMenuInner()
82
+ : this.renderNormalMenuInner(),
83
+ this.renderAfterList(),
84
+ ]);
85
+ },
86
+
87
+ renderBeforeList() {
88
+ const { instance } = this;
89
+ const beforeListRenderer = instance.$slots['before-list'];
90
+
91
+ return beforeListRenderer
92
+ ? beforeListRenderer()
93
+ : null;
94
+ },
95
+
96
+ renderAfterList() {
97
+ const { instance } = this;
98
+ const afterListRenderer = instance.$slots['after-list'];
99
+
100
+ return afterListRenderer
101
+ ? afterListRenderer()
102
+ : null;
103
+ },
104
+
105
+ renderNormalMenuInner() {
106
+ const { instance } = this;
107
+
108
+ if (instance.rootOptionsStates.isLoading) {
109
+ return this.renderLoadingOptionsTip();
110
+ } if (instance.rootOptionsStates.loadingError) {
111
+ return this.renderLoadingRootOptionsErrorTip();
112
+ } if (instance.rootOptionsStates.isLoaded && instance.forest.normalizedOptions.length === 0) {
113
+ return this.renderNoAvailableOptionsTip();
114
+ }
115
+ return this.renderOptionList();
116
+ },
117
+
118
+ renderLocalSearchMenuInner() {
119
+ const { instance } = this;
120
+
121
+ if (instance.rootOptionsStates.isLoading) {
122
+ return this.renderLoadingOptionsTip();
123
+ } if (instance.rootOptionsStates.loadingError) {
124
+ return this.renderLoadingRootOptionsErrorTip();
125
+ } if (instance.rootOptionsStates.isLoaded && instance.forest.normalizedOptions.length === 0) {
126
+ return this.renderNoAvailableOptionsTip();
127
+ } if (instance.localSearch.noResults) {
128
+ return this.renderNoResultsTip();
129
+ }
130
+ return this.renderOptionList();
131
+ },
132
+
133
+ renderAsyncSearchMenuInner() {
134
+ const { instance } = this;
135
+ const entry = instance.getRemoteSearchEntry;
136
+ const shouldShowSearchPromptTip = instance.trigger.searchQuery === '' && !instance.defaultOptions;
137
+ const shouldShowNoResultsTip = shouldShowSearchPromptTip
138
+ ? false
139
+ : entry.isLoaded && entry.options.length === 0;
140
+
141
+ if (shouldShowSearchPromptTip) {
142
+ return this.renderSearchPromptTip();
143
+ } if (entry.isLoading) {
144
+ return this.renderLoadingOptionsTip();
145
+ } if (entry.loadingError) {
146
+ return this.renderAsyncSearchLoadingErrorTip();
147
+ } if (shouldShowNoResultsTip) {
148
+ return this.renderNoResultsTip();
149
+ }
150
+ return this.renderOptionList();
151
+ },
152
+
153
+ renderOptionList() {
154
+ const { instance } = this;
155
+
156
+ return (
157
+ h('div', { class: 'vue-treeselect__list' },
158
+ instance.forest.normalizedOptions.map((rootNode) => (
159
+ h(Option, { node: rootNode, key: rootNode.id })
160
+ )))
161
+ );
162
+ },
163
+
164
+ renderSearchPromptTip() {
165
+ const { instance } = this;
166
+
167
+ return (
168
+ h(Tip, { type: 'search-prompt', icon: 'warning' }, () => instance.searchPromptText)
169
+ );
170
+ },
171
+
172
+ renderLoadingOptionsTip() {
173
+ const { instance } = this;
174
+
175
+ return (
176
+ h(Tip, { type: 'loading', icon: 'loader' }, () => [instance.loadingText])
177
+ );
178
+ },
179
+
180
+ renderLoadingRootOptionsErrorTip() {
181
+ const { instance } = this;
182
+
183
+ return (
184
+ h(Tip, { type: 'error', icon: 'error' }, () => [
185
+ instance.rootOptionsStates.loadingError,
186
+ h('a', {
187
+ class: 'vue-treeselect__retry',
188
+ onClick: instance.loadRootOptions,
189
+ title: instance.retryTitle,
190
+ }, [instance.retryText]),
191
+ ])
192
+ );
193
+ },
194
+
195
+ renderAsyncSearchLoadingErrorTip() {
196
+ const { instance } = this;
197
+ const entry = instance.getRemoteSearchEntry;
198
+
199
+ return (
200
+ h(Tip, { type: 'error', icon: 'error' }, () => [
201
+ instance.rootOptionsStates.loadingError,
202
+ h('a', {
203
+ class: 'vue-treeselect__retry',
204
+ onClick: instance.handleRemoteSearch,
205
+ title: instance.retryTitle,
206
+ }, [instance.retryText]),
207
+ ])
208
+ );
209
+ },
210
+
211
+ renderNoAvailableOptionsTip() {
212
+ const { instance } = this;
213
+
214
+ return (
215
+ h(Tip, { type: 'no-options', icon: 'warning' }, () => [instance.searchPromptText])
216
+ );
217
+ },
218
+
219
+ renderNoResultsTip() {
220
+ const { instance } = this;
221
+ return (
222
+ h(Tip, { type: 'no-results', icon: 'warning' }, () => [instance.noResultsText])
223
+ );
224
+ },
225
+
226
+ onMenuOpen() {
227
+ this.adjustMenuOpenDirection();
228
+ this.setupMenuSizeWatcher();
229
+ this.setupMenuResizeAndScrollEventListeners();
230
+ },
231
+
232
+ onMenuClose() {
233
+ this.removeMenuSizeWatcher();
234
+ this.removeMenuResizeAndScrollEventListeners();
235
+ },
236
+
237
+ adjustMenuOpenDirection() {
238
+ const { instance } = this;
239
+ if (!instance.menu.isOpen) return;
240
+
241
+ const $menu = instance.getMenu();
242
+ const $control = instance.getControl();
243
+ const menuRect = $menu.getBoundingClientRect();
244
+ const controlRect = $control.getBoundingClientRect();
245
+ const menuHeight = menuRect.height;
246
+ const viewportHeight = window.innerHeight;
247
+ const spaceAbove = controlRect.top;
248
+ const spaceBelow = window.innerHeight - controlRect.bottom;
249
+ const isControlInViewport = (
250
+ (controlRect.top >= 0 && controlRect.top <= viewportHeight)
251
+ || (controlRect.top < 0 && controlRect.bottom > 0)
252
+ );
253
+ const hasEnoughSpaceBelow = spaceBelow > menuHeight + MENU_BUFFER;
254
+ const hasEnoughSpaceAbove = spaceAbove > menuHeight + MENU_BUFFER;
255
+
256
+ if (!isControlInViewport) {
257
+ instance.closeMenu();
258
+ } else if (instance.openDirection !== 'auto') {
259
+ instance.menu.placement = directionMap[instance.openDirection];
260
+ } else if (hasEnoughSpaceBelow || !hasEnoughSpaceAbove) {
261
+ instance.menu.placement = 'bottom';
262
+ } else {
263
+ instance.menu.placement = 'top';
264
+ }
265
+ },
266
+
267
+ setupMenuSizeWatcher() {
268
+ const { instance } = this;
269
+ const $menu = instance.getMenu();
270
+
271
+ // istanbul ignore next
272
+ if (this.menuSizeWatcher) return;
273
+
274
+ this.menuSizeWatcher = {
275
+ remove: watchSize($menu, this.adjustMenuOpenDirection),
276
+ };
277
+ },
278
+
279
+ setupMenuResizeAndScrollEventListeners() {
280
+ const { instance } = this;
281
+ const $control = instance.getControl();
282
+
283
+ // istanbul ignore next
284
+ if (this.menuResizeAndScrollEventListeners) return;
285
+
286
+ this.menuResizeAndScrollEventListeners = {
287
+ remove: setupResizeAndScrollEventListeners($control, this.adjustMenuOpenDirection),
288
+ };
289
+ },
290
+
291
+ removeMenuSizeWatcher() {
292
+ if (!this.menuSizeWatcher) return;
293
+
294
+ this.menuSizeWatcher.remove();
295
+ this.menuSizeWatcher = null;
296
+ },
297
+
298
+ removeMenuResizeAndScrollEventListeners() {
299
+ if (!this.menuResizeAndScrollEventListeners) return;
300
+
301
+ this.menuResizeAndScrollEventListeners.remove();
302
+ this.menuResizeAndScrollEventListeners = null;
303
+ },
304
+ },
305
+
306
+ render() {
307
+ return (
308
+ h('div', { ref: 'menu-container', class: 'vue-treeselect__menu-container', style: this.menuContainerStyle }, [
309
+ h('transition', { name: 'vue-treeselect__menu--transition' }, this.renderMenu()),
310
+ ])
311
+ );
312
+ },
313
+ };
314
+ </script>