|
3 | 3 | position: relative;
|
4 | 4 | font-family: inherit;
|
5 | 5 | }
|
6 |
| -
|
7 | 6 | .v-select,
|
8 | 7 | .v-select * {
|
9 | 8 | -webkit-box-sizing: border-box;
|
10 | 9 | -moz-box-sizing: border-box;
|
11 | 10 | box-sizing: border-box;
|
12 | 11 | }
|
13 |
| - /* Rtl support */ |
14 |
| - .v-select.rtl .open-indicator { |
15 |
| - left: 10px; |
16 |
| - right: auto; |
| 12 | +
|
| 13 | + /* Rtl support - Because we're using a flexbox-based layout, the `dir="rtl"` HTML |
| 14 | + attribute does most of the work for us by rearranging the child elements visually. |
| 15 | + */ |
| 16 | + .v-select[dir="rtl"] .v-select__actions { |
| 17 | + padding: 0 3px 0 6px; |
17 | 18 | }
|
18 |
| - .v-select.rtl .selected-tag { |
19 |
| - float: right; |
| 19 | + .v-select[dir="rtl"] .dropdown-toggle .clear { |
| 20 | + margin-left: 6px; |
| 21 | + margin-right: 0; |
| 22 | + } |
| 23 | + .v-select[dir="rtl"] .selected-tag { |
20 | 24 | margin-right: 3px;
|
21 | 25 | margin-left: 1px;
|
22 | 26 | }
|
23 |
| - .v-select.rtl .dropdown-menu { |
24 |
| - text-align: right; |
| 27 | + .v-select[dir="rtl"] .selected-tag .close { |
| 28 | + margin-left: 0; |
| 29 | + margin-right: 2px; |
25 | 30 | }
|
26 |
| - .v-select.rtl .dropdown-toggle .clear { |
27 |
| - left: 30px; |
28 |
| - right: auto; |
| 31 | + .v-select[dir="rtl"] .dropdown-menu { |
| 32 | + text-align: right; |
29 | 33 | }
|
| 34 | +
|
30 | 35 | /* Open Indicator */
|
31 | 36 | .v-select .open-indicator {
|
32 |
| - position: absolute; |
33 |
| - bottom: 6px; |
34 |
| - right: 10px; |
35 | 37 | display: inline-block;
|
36 | 38 | cursor: pointer;
|
37 | 39 | pointer-events: all;
|
38 | 40 | transition: all 150ms cubic-bezier(1.000, -0.115, 0.975, 0.855);
|
39 | 41 | transition-timing-function: cubic-bezier(1.000, -0.115, 0.975, 0.855);
|
40 | 42 | opacity: 1;
|
41 |
| - height: 20px; width: 10px; |
| 43 | + height: 16px; |
| 44 | + width: 12px; /* To account for extra width from rotating. */ |
42 | 45 | }
|
43 | 46 | .v-select .open-indicator:before {
|
44 | 47 | border-color: rgba(60, 60, 60, .5);
|
|
48 | 51 | display: inline-block;
|
49 | 52 | height: 10px;
|
50 | 53 | width: 10px;
|
51 |
| - vertical-align: top; |
| 54 | + vertical-align: text-top; |
52 | 55 | transform: rotate(133deg);
|
53 | 56 | transition: all 150ms cubic-bezier(1.000, -0.115, 0.975, 0.855);
|
54 | 57 | transition-timing-function: cubic-bezier(1.000, -0.115, 0.975, 0.855);
|
|
64 | 67 | .v-select.open .open-indicator {
|
65 | 68 | bottom: 1px;
|
66 | 69 | }
|
| 70 | +
|
67 | 71 | /* Dropdown Toggle */
|
68 | 72 | .v-select .dropdown-toggle {
|
69 | 73 | -webkit-appearance: none;
|
70 | 74 | -moz-appearance: none;
|
71 | 75 | appearance: none;
|
72 |
| - display: block; |
| 76 | + display: flex; |
73 | 77 | padding: 0;
|
74 | 78 | background: none;
|
75 | 79 | border: 1px solid rgba(60, 60, 60, .26);
|
76 |
| - min-height: 36px; |
77 | 80 | border-radius: 4px;
|
78 | 81 | white-space: normal;
|
79 | 82 | }
|
|
85 | 88 | clear: both;
|
86 | 89 | height: 0;
|
87 | 90 | }
|
| 91 | + .v-select .v-select__selected-options { |
| 92 | + display: flex; |
| 93 | + flex-basis: 100%; |
| 94 | + flex-grow: 1; |
| 95 | + flex-wrap: wrap; |
| 96 | + } |
| 97 | + .v-select .v-select__actions { |
| 98 | + display: flex; |
| 99 | + align-items: center; |
| 100 | + padding: 0 6px 0 3px; |
| 101 | + } |
88 | 102 |
|
89 | 103 | /* Clear Button */
|
90 | 104 | .v-select .dropdown-toggle .clear {
|
91 |
| - position: absolute; |
92 |
| - bottom: 9px; |
93 |
| - right: 30px; |
94 | 105 | font-size: 23px;
|
95 | 106 | font-weight: 700;
|
96 | 107 | line-height: 1;
|
|
99 | 110 | border: 0;
|
100 | 111 | background-color: transparent;
|
101 | 112 | cursor: pointer;
|
| 113 | + margin-right: 6px; |
102 | 114 | }
|
103 | 115 |
|
104 | 116 | /* Dropdown Toggle States */
|
|
138 | 150 | }
|
139 | 151 | /* Selected Tags */
|
140 | 152 | .v-select .selected-tag {
|
| 153 | + display: flex; |
| 154 | + align-items: baseline; |
141 | 155 | color: #333;
|
142 | 156 | background-color: #f0f0f0;
|
143 | 157 | border: 1px solid #ccc;
|
144 | 158 | border-radius: 4px;
|
145 | 159 | height: 26px;
|
146 | 160 | margin: 4px 1px 0px 3px;
|
147 | 161 | padding: 1px 0.25em;
|
148 |
| - float: left; |
149 | 162 | line-height: 24px;
|
150 | 163 | }
|
151 | 164 | .v-select.single .selected-tag {
|
152 | 165 | background-color: transparent;
|
153 | 166 | border-color: transparent;
|
154 | 167 | }
|
155 |
| - .v-select.single.open .selected-tag { |
156 |
| - position: absolute; |
157 |
| - opacity: .5; |
158 |
| - } |
159 |
| - .v-select.single.open.searching .selected-tag, |
| 168 | + .v-select.single.open .selected-tag, |
160 | 169 | .v-select.single.loading .selected-tag {
|
161 | 170 | display: none;
|
162 | 171 | }
|
163 | 172 | .v-select .selected-tag .close {
|
164 |
| - float: none; |
165 |
| - margin-right: 0; |
| 173 | + margin-left: 2px; |
166 | 174 | font-size: 20px;
|
167 | 175 | appearance: none;
|
168 | 176 | padding: 0;
|
|
257 | 265 | /* Loading Spinner */
|
258 | 266 | .v-select .spinner {
|
259 | 267 | opacity: 0;
|
260 |
| - position: absolute; |
261 |
| - top: 5px; |
262 |
| - right: 10px; |
263 | 268 | font-size: 5px;
|
264 | 269 | text-indent: -9999em;
|
265 | 270 | overflow: hidden;
|
|
322 | 327 |
|
323 | 328 | <template>
|
324 | 329 | <div :dir="dir" class="dropdown v-select" :class="dropdownClasses">
|
325 |
| - <div ref="toggle" @mousedown.prevent="toggleDropdown" :class="['dropdown-toggle', 'clearfix']"> |
326 |
| - |
327 |
| - <slot v-for="option in valueAsArray" name="selected-option-container" |
328 |
| - :option="(typeof option === 'object')?option:{[label]: option}" :deselect="deselect" :multiple="multiple" :disabled="disabled"> |
329 |
| - <span class="selected-tag" v-bind:key="option.index"> |
330 |
| - <slot name="selected-option" v-bind="(typeof option === 'object')?option:{[label]: option}"> |
331 |
| - {{ getOptionLabel(option) }} |
332 |
| - </slot> |
333 |
| - <button v-if="multiple" :disabled="disabled" @click="deselect(option)" type="button" class="close" aria-label="Remove option"> |
334 |
| - <span aria-hidden="true">×</span> |
335 |
| - </button> |
336 |
| - </span> |
337 |
| - </slot> |
338 |
| - |
339 |
| - <input |
340 |
| - ref="search" |
341 |
| - v-model="search" |
342 |
| - @keydown.delete="maybeDeleteValue" |
343 |
| - @keyup.esc="onEscape" |
344 |
| - @keydown.up.prevent="typeAheadUp" |
345 |
| - @keydown.down.prevent="typeAheadDown" |
346 |
| - @keydown.enter.prevent="typeAheadSelect" |
347 |
| - @blur="onSearchBlur" |
348 |
| - @focus="onSearchFocus" |
349 |
| - type="search" |
350 |
| - class="form-control" |
351 |
| - :class="inputClasses" |
352 |
| - autocomplete="off" |
353 |
| - :disabled="disabled" |
354 |
| - :placeholder="searchPlaceholder" |
355 |
| - :tabindex="tabindex" |
356 |
| - :readonly="!searchable" |
357 |
| - :id="inputId" |
358 |
| - aria-label="Search for option" |
359 |
| - > |
360 |
| - |
361 |
| - <button |
362 |
| - v-show="showClearButton" |
363 |
| - :disabled="disabled" |
364 |
| - @click="clearSelection" |
365 |
| - type="button" |
366 |
| - class="clear" |
367 |
| - title="Clear selection" |
368 |
| - > |
369 |
| - <span aria-hidden="true">×</span> |
370 |
| - </button> |
371 |
| - |
372 |
| - <i v-if="!noDrop" ref="openIndicator" role="presentation" class="open-indicator"></i> |
373 |
| - |
374 |
| - <slot name="spinner"> |
375 |
| - <div class="spinner" v-show="mutableLoading">Loading...</div> |
376 |
| - </slot> |
| 330 | + <div ref="toggle" @mousedown.prevent="toggleDropdown" class="dropdown-toggle clearfix"> |
| 331 | + |
| 332 | + <div class="v-select__selected-options"> |
| 333 | + <slot v-for="option in valueAsArray" name="selected-option-container" |
| 334 | + :option="(typeof option === 'object')?option:{[label]: option}" :deselect="deselect" :multiple="multiple" :disabled="disabled"> |
| 335 | + <span class="selected-tag" v-bind:key="option.index"> |
| 336 | + <slot name="selected-option" v-bind="(typeof option === 'object')?option:{[label]: option}"> |
| 337 | + {{ getOptionLabel(option) }} |
| 338 | + </slot> |
| 339 | + <button v-if="multiple" :disabled="disabled" @click="deselect(option)" type="button" class="close" aria-label="Remove option"> |
| 340 | + <span aria-hidden="true">×</span> |
| 341 | + </button> |
| 342 | + </span> |
| 343 | + </slot> |
| 344 | + |
| 345 | + <input |
| 346 | + ref="search" |
| 347 | + v-model="search" |
| 348 | + @keydown.delete="maybeDeleteValue" |
| 349 | + @keyup.esc="onEscape" |
| 350 | + @keydown.up.prevent="typeAheadUp" |
| 351 | + @keydown.down.prevent="typeAheadDown" |
| 352 | + @keydown.enter.prevent="typeAheadSelect" |
| 353 | + @blur="onSearchBlur" |
| 354 | + @focus="onSearchFocus" |
| 355 | + type="search" |
| 356 | + class="form-control" |
| 357 | + :class="inputClasses" |
| 358 | + autocomplete="off" |
| 359 | + :disabled="disabled" |
| 360 | + :placeholder="searchPlaceholder" |
| 361 | + :tabindex="tabindex" |
| 362 | + :readonly="!searchable" |
| 363 | + :id="inputId" |
| 364 | + aria-label="Search for option" |
| 365 | + > |
| 366 | + |
| 367 | + </div> |
| 368 | + <div class="v-select__actions"> |
| 369 | + <button |
| 370 | + v-show="showClearButton" |
| 371 | + :disabled="disabled" |
| 372 | + @click="clearSelection" |
| 373 | + type="button" |
| 374 | + class="clear" |
| 375 | + title="Clear selection" |
| 376 | + > |
| 377 | + <span aria-hidden="true">×</span> |
| 378 | + </button> |
| 379 | + |
| 380 | + <i v-if="!noDrop" ref="openIndicator" role="presentation" class="open-indicator"></i> |
| 381 | + |
| 382 | + <slot name="spinner"> |
| 383 | + <div class="spinner" v-show="mutableLoading">Loading...</div> |
| 384 | + </slot> |
| 385 | + </div> |
377 | 386 | </div>
|
378 | 387 |
|
379 | 388 | <transition :name="transition">
|
|
706 | 715 | watch: {
|
707 | 716 | /**
|
708 | 717 | * When the value prop changes, update
|
709 |
| - * the internal mutableValue. |
| 718 | + * the internal mutableValue. |
710 | 719 | * @param {mixed} val
|
711 | 720 | * @return {void}
|
712 | 721 | */
|
713 | 722 | value(val) {
|
714 |
| - this.mutableValue = val |
| 723 | + this.mutableValue = val |
715 | 724 | },
|
716 | 725 |
|
717 | 726 | /**
|
|
720 | 729 | * @param {string|object} old
|
721 | 730 | * @return {void}
|
722 | 731 | */
|
723 |
| - mutableValue(val, old) { |
| 732 | + mutableValue(val, old) { |
724 | 733 | if (this.multiple) {
|
725 | 734 | this.onChange ? this.onChange(val) : null
|
726 | 735 | } else {
|
|
739 | 748 | },
|
740 | 749 |
|
741 | 750 | /**
|
742 |
| - * Maybe reset the mutableValue |
| 751 | + * Maybe reset the mutableValue |
743 | 752 | * when mutableOptions change.
|
744 | 753 | * @return {[type]} [description]
|
745 | 754 | */
|
746 | 755 | mutableOptions() {
|
747 | 756 | if (!this.taggable && this.resetOnOptionsChange) {
|
748 |
| - this.mutableValue = this.multiple ? [] : null |
| 757 | + this.mutableValue = this.multiple ? [] : null |
749 | 758 | }
|
750 | 759 | },
|
751 | 760 |
|
752 | 761 | /**
|
753 |
| - * Always reset the mutableValue when |
| 762 | + * Always reset the mutableValue when |
754 | 763 | * the multiple prop changes.
|
755 | 764 | * @param {Boolean} val
|
756 | 765 | * @return {void}
|
757 | 766 | */
|
758 | 767 | multiple(val) {
|
759 |
| - this.mutableValue = val ? [] : null |
| 768 | + this.mutableValue = val ? [] : null |
760 | 769 | }
|
761 | 770 | },
|
762 | 771 |
|
|
765 | 774 | * attach any event listeners.
|
766 | 775 | */
|
767 | 776 | created() {
|
768 |
| - this.mutableValue = this.value |
| 777 | + this.mutableValue = this.value |
769 | 778 | this.mutableOptions = this.options.slice(0)
|
770 |
| - this.mutableLoading = this.loading |
| 779 | + this.mutableLoading = this.loading |
771 | 780 |
|
772 | 781 | this.$on('option:created', this.maybePushTag)
|
773 | 782 | },
|
|
979 | 988 | searchable: this.searchable,
|
980 | 989 | unsearchable: !this.searchable,
|
981 | 990 | loading: this.mutableLoading,
|
982 |
| - rtl: this.dir === 'rtl', |
| 991 | + rtl: this.dir === 'rtl', // This can be removed - styling is handled by `dir="rtl"` attribute |
983 | 992 | disabled: this.disabled
|
984 | 993 | }
|
985 | 994 | },
|
|
0 commit comments