diff --git a/components/vc-select/DropdownMenu.vue b/components/vc-select/DropdownMenu.vue
index e69de29bb..35bf7f5ef 100644
--- a/components/vc-select/DropdownMenu.vue
+++ b/components/vc-select/DropdownMenu.vue
@@ -0,0 +1,186 @@
+
diff --git a/components/vc-select/OptGroup.vue b/components/vc-select/OptGroup.vue
new file mode 100644
index 000000000..3d7d08eea
--- /dev/null
+++ b/components/vc-select/OptGroup.vue
@@ -0,0 +1,5 @@
+
diff --git a/components/vc-select/Option.vue b/components/vc-select/Option.vue
new file mode 100644
index 000000000..af6f3ab5b
--- /dev/null
+++ b/components/vc-select/Option.vue
@@ -0,0 +1,13 @@
+
diff --git a/components/vc-select/PropTypes.js b/components/vc-select/PropTypes.js
new file mode 100644
index 000000000..6b6b2bc18
--- /dev/null
+++ b/components/vc-select/PropTypes.js
@@ -0,0 +1,84 @@
+import PropTypes from '../_util/vue-types'
+
+function valueType (props, propName, componentName) {
+ const basicType = PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ ])
+
+ const labelInValueShape = PropTypes.shape({
+ key: basicType.isRequired,
+ label: PropTypes.node,
+ })
+ if (props.labelInValue) {
+ const validate = PropTypes.oneOfType([
+ PropTypes.arrayOf(labelInValueShape),
+ labelInValueShape,
+ ])
+ const error = validate(...arguments)
+ if (error) {
+ return new Error(
+ `Invalid prop \`${propName}\` supplied to \`${componentName}\`, ` +
+ `when you set \`labelInValue\` to \`true\`, \`${propName}\` should in ` +
+ `shape of \`{ key: string | number, label?: ReactNode }\`.`
+ )
+ }
+ } else if (
+ (props.mode === 'multiple' || props.mode === 'tags' || props.multiple || props.tags) &&
+ props[propName] === ''
+ ) {
+ return new Error(
+ `Invalid prop \`${propName}\` of type \`string\` supplied to \`${componentName}\`, ` +
+ `expected \`array\` when \`multiple\` or \`tags\` is \`true\`.`
+ )
+ } else {
+ const validate = PropTypes.oneOfType([
+ PropTypes.arrayOf(basicType),
+ basicType,
+ ])
+ return validate(...arguments)
+ }
+}
+
+export const SelectPropTypes = {
+ defaultActiveFirstOption: PropTypes.bool,
+ multiple: PropTypes.bool,
+ filterOption: PropTypes.any,
+ // children: PropTypes.any,
+ showSearch: PropTypes.bool,
+ disabled: PropTypes.bool,
+ allowClear: PropTypes.bool,
+ showArrow: PropTypes.bool,
+ tags: PropTypes.bool,
+ prefixCls: PropTypes.string,
+ // className: PropTypes.string,
+ transitionName: PropTypes.string,
+ optionLabelProp: PropTypes.string,
+ optionFilterProp: PropTypes.string,
+ animation: PropTypes.string,
+ choiceTransitionName: PropTypes.string,
+ // onChange: PropTypes.func,
+ // onBlur: PropTypes.func,
+ // onFocus: PropTypes.func,
+ // onSelect: PropTypes.func,
+ // onSearch: PropTypes.func,
+ // onPopupScroll: PropTypes.func,
+ // onMouseEnter: PropTypes.func,
+ // onMouseLeave: PropTypes.func,
+ // onInputKeyDown: PropTypes.func,
+ placeholder: PropTypes.any,
+ // onDeselect: PropTypes.func,
+ labelInValue: PropTypes.bool,
+ value: valueType,
+ defaultValue: valueType,
+ dropdownStyle: PropTypes.object,
+ maxTagTextLength: PropTypes.number,
+ maxTagCount: PropTypes.number,
+ maxTagPlaceholder: PropTypes.oneOfType([
+ PropTypes.node,
+ PropTypes.func,
+ ]),
+ tokenSeparators: PropTypes.arrayOf(PropTypes.string),
+ getInputElement: PropTypes.func,
+ showAction: PropTypes.arrayOf(PropTypes.string),
+}
diff --git a/components/vc-select/Select.vue b/components/vc-select/Select.vue
new file mode 100644
index 000000000..e69de29bb
diff --git a/components/vc-select/SelectTrigger.vue b/components/vc-select/SelectTrigger.vue
new file mode 100644
index 000000000..e69de29bb
diff --git a/components/vc-select/util.js b/components/vc-select/util.js
new file mode 100644
index 000000000..24e88768c
--- /dev/null
+++ b/components/vc-select/util.js
@@ -0,0 +1,165 @@
+export function getValuePropValue (child) {
+ const props = child.props
+ if ('value' in props) {
+ return props.value
+ }
+ if (child.key) {
+ return child.key
+ }
+ if (child.type && child.type.isSelectOptGroup && props.label) {
+ return props.label
+ }
+ throw new Error(
+ `Need at least a key or a value or a label (only for OptGroup) for ${child}`
+ )
+}
+
+export function getPropValue (child, prop) {
+ if (prop === 'value') {
+ return getValuePropValue(child)
+ }
+ return child.props[prop]
+}
+
+export function isMultiple (props) {
+ return props.multiple
+}
+
+export function isCombobox (props) {
+ return props.combobox
+}
+
+export function isMultipleOrTags (props) {
+ return props.multiple || props.tags
+}
+
+export function isMultipleOrTagsOrCombobox (props) {
+ return isMultipleOrTags(props) || isCombobox(props)
+}
+
+export function isSingleMode (props) {
+ return !isMultipleOrTagsOrCombobox(props)
+}
+
+export function toArray (value) {
+ let ret = value
+ if (value === undefined) {
+ ret = []
+ } else if (!Array.isArray(value)) {
+ ret = [value]
+ }
+ return ret
+}
+
+export function preventDefaultEvent (e) {
+ e.preventDefault()
+}
+
+export function findIndexInValueByKey (value, key) {
+ let index = -1
+ for (let i = 0; i < value.length; i++) {
+ if (value[i].key === key) {
+ index = i
+ break
+ }
+ }
+ return index
+}
+
+export function findIndexInValueByLabel (value, label) {
+ let index = -1
+ for (let i = 0; i < value.length; i++) {
+ if (toArray(value[i].label).join('') === label) {
+ index = i
+ break
+ }
+ }
+ return index
+}
+
+export function getSelectKeys (menuItems, value) {
+ if (value === null || value === undefined) {
+ return []
+ }
+ let selectedKeys = []
+ menuItems.forEach(item => {
+ if (item.type.isMenuItemGroup) {
+ selectedKeys = selectedKeys.concat(
+ getSelectKeys(item.props.children, value)
+ )
+ } else {
+ const itemValue = getValuePropValue(item)
+ const itemKey = item.key
+ if (findIndexInValueByKey(value, itemValue) !== -1 && itemKey) {
+ selectedKeys.push(itemKey)
+ }
+ }
+ })
+ return selectedKeys
+}
+
+export const UNSELECTABLE_STYLE = {
+ userSelect: 'none',
+ WebkitUserSelect: 'none',
+}
+
+export const UNSELECTABLE_ATTRIBUTE = {
+ unselectable: 'unselectable',
+}
+
+export function findFirstMenuItem (children) {
+ for (let i = 0; i < children.length; i++) {
+ const child = children[i]
+ if (child.type.isMenuItemGroup) {
+ const found = findFirstMenuItem(child.props.children)
+ if (found) {
+ return found
+ }
+ } else if (!child.props.disabled) {
+ return child
+ }
+ }
+ return null
+}
+
+export function includesSeparators (string, separators) {
+ for (let i = 0; i < separators.length; ++i) {
+ if (string.lastIndexOf(separators[i]) > 0) {
+ return true
+ }
+ }
+ return false
+}
+
+export function splitBySeparators (string, separators) {
+ const reg = new RegExp(`[${separators.join()}]`)
+ return string.split(reg).filter(token => token)
+}
+
+export function defaultFilterFn (input, child) {
+ if (child.props.disabled) {
+ return false
+ }
+ const value = String(getPropValue(child, this.props.optionFilterProp))
+ return (
+ value.toLowerCase().indexOf(input.toLowerCase()) > -1
+ )
+}
+
+export function validateOptionValue (value, props) {
+ if (isSingleMode(props) || isMultiple(props)) {
+ return
+ }
+ if (typeof value !== 'string') {
+ throw new Error(
+ `Invalid \`value\` of type \`${typeof value}\` supplied to Option, ` +
+ `expected \`string\` when \`tags/combobox\` is \`true\`.`
+ )
+ }
+}
+
+export function saveRef (instance, name) {
+ return (node) => {
+ instance[name] = node
+ }
+}