diff --git a/devui/editable-select/index.ts b/devui/editable-select/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7b053c0c34ec8e88740a3949906891fed6fabf66
--- /dev/null
+++ b/devui/editable-select/index.ts
@@ -0,0 +1,20 @@
+import type { App } from 'vue'
+import EditableSelect from './src/editable-select'
+import EditableSelectOption from './src/components/option'
+
+EditableSelect.install = function (app: App): void {
+ app.component(EditableSelect.name, EditableSelect)
+ app.component(EditableSelectOption.name, EditableSelectOption)
+
+}
+
+export { EditableSelect, EditableSelectOption }
+
+export default {
+ title: 'EditableSelect 可输入下拉选择框',
+ category: '数据录入',
+ status: undefined, // TODO: 组件若开发完成则填入"已完成",并删除该注释
+ install(app: App): void {
+ app.use(EditableSelect as any)
+ }
+}
diff --git a/devui/editable-select/src/components/option/index.tsx b/devui/editable-select/src/components/option/index.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..e717d15849fa12b0d329e13d6251dd52576065a3
--- /dev/null
+++ b/devui/editable-select/src/components/option/index.tsx
@@ -0,0 +1,11 @@
+import { defineComponent } from 'vue';
+
+export default defineComponent({
+ name: 'DEditableSelectOption',
+ setup(props, ctx) {
+ const defaultSlot = ctx.slots.default && ctx.slots.default();
+ return () => {
+ return
{defaultSlot};
+ };
+ },
+});
diff --git a/devui/editable-select/src/editable-select-types.ts b/devui/editable-select/src/editable-select-types.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4b35deb5e3626d97d28325bea4e7211f4607eaaf
--- /dev/null
+++ b/devui/editable-select/src/editable-select-types.ts
@@ -0,0 +1,22 @@
+import type { ExtractPropTypes } from 'vue'
+
+export const editableSelectProps = {
+ /* test: {
+ type: Object as PropType<{ xxx: xxx }>
+ } */
+ width: {
+ type: Number,
+ default: 450
+ },
+ appendToBody: {
+ type: Boolean,
+ default: true,
+ },
+ maxHeight: {
+ type: Number,
+ default: 300
+ }
+
+} as const
+
+export type EditableSelectProps = ExtractPropTypes
diff --git a/devui/editable-select/src/editable-select.scss b/devui/editable-select/src/editable-select.scss
new file mode 100644
index 0000000000000000000000000000000000000000..0af1fe5e0cec5c839d5fa0ac63c173acb19a0148
--- /dev/null
+++ b/devui/editable-select/src/editable-select.scss
@@ -0,0 +1,106 @@
+@import '../../style/theme/color';
+@import '../../style/core/animation';
+
+.devui-select-chevron-icon {
+ display: inline-flex;
+ vertical-align: middle;
+ transition:
+ transform $devui-animation-duration-slow
+ $devui-animation-ease-in-out-smooth;
+}
+
+.devui-select-open .devui-select-chevron-icon {
+ transform: rotate(180deg);
+}
+
+.devui-select-chevron-icon svg path {
+ fill: $devui-text-weak; // TODO: Color-Question
+}
+
+input::-ms-clear {
+ display: none;
+}
+
+.devui-no-data-tip {
+ user-select: none;
+ cursor: not-allowed;
+}
+
+.devui-form-control {
+ outline: none;
+ padding-right: 24px;
+}
+
+.devui-form-group.devui-has-feedback > .devui-form-control-feedback {
+ line-height: 26px;
+}
+// 下拉部分
+.devui-dropdown-menu {
+ width: 100%;
+ display: block;
+}
+
+.devui-dropdown-item {
+ cursor: pointer;
+ display: block;
+ width: 100%;
+ padding: 8px 12px;
+ clear: both;
+ border: 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ line-height: 14px;
+}
+
+.devui-dropdown-menu {
+ .devui-dropdown-item:not(.disabled) {
+ &.selected {
+ color: $devui-list-item-active-text;
+ background-color: $devui-list-item-active-bg;
+ }
+ }
+}
+
+.devui-no-result-template,
+.devui-is-searching-template {
+ display: block;
+ width: 100%;
+ padding: 8px 12px;
+ clear: both;
+ border: 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ cursor: not-allowed;
+ background-color: $devui-disabled-bg;
+ color: $devui-disabled-text;
+ line-height: 14px;
+
+ &:hover,
+ &:active,
+ &:hover:active {
+ background-color: $devui-unavailable;
+ }
+}
+// 选项disabled
+.devui-dropdown-item.disabled,
+.devui-dropdown-item.disabled:hover {
+ cursor: not-allowed;
+ color: $devui-disabled-text;
+}
+
+ul.devui-list-unstyled {
+ margin: 0;
+ overflow-y: auto;
+ padding: 0;
+}
+
+.devui-dropdown-bg {
+ background: $devui-list-item-hover-bg;
+}
+
+.devui-popup-tips {
+ color: $devui-text-weak;
+ padding: 4px 12px;
+}
diff --git a/devui/editable-select/src/editable-select.tsx b/devui/editable-select/src/editable-select.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..74d1f04683bed79b66749d42fe214b10ce856c49
--- /dev/null
+++ b/devui/editable-select/src/editable-select.tsx
@@ -0,0 +1,71 @@
+import './editable-select.scss';
+
+import { defineComponent, ref, reactive, renderSlot } from 'vue';
+import {
+ editableSelectProps,
+ EditableSelectProps,
+} from './editable-select-types';
+import { Icon } from '../../icon';
+
+export default defineComponent({
+ name: 'DEditableSelect',
+ props: editableSelectProps,
+ emits: [],
+ setup(props: EditableSelectProps, ctx) {
+ const origin = ref(null);
+ const visible = ref(false);
+ const position = reactive({
+ originX: 'left',
+ originY: 'bottom',
+ overlayX: 'left',
+ overlayY: 'top',
+ });
+
+ const toggleMenu = () => {
+ visible.value = !visible.value;
+ };
+
+ return () => {
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+ };
+ },
+});
diff --git a/devui/editable-select/src/utils/index.ts b/devui/editable-select/src/utils/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fb6e5e684158315280b0aafec4bfdb4b319298d1
--- /dev/null
+++ b/devui/editable-select/src/utils/index.ts
@@ -0,0 +1,18 @@
+/**
+ * 动态获取class字符串
+ * @param classStr 是一个字符串,固定的class名
+ * @param classOpt 是一个对象,key表示class名,value为布尔值,true则添加,否则不添加
+ * @returns 最终的class字符串
+ */
+export function className(
+ classStr: string,
+ classOpt?: { [key: string]: boolean; }
+): string {
+ let classname = classStr;
+ if (typeof classOpt === 'object') {
+ Object.keys(classOpt).forEach((key) => {
+ classOpt[key] && (classname += ` ${key}`);
+ });
+ }
+ return classname;
+}
\ No newline at end of file
diff --git a/devui/style/core/_dropdown.scss b/devui/style/core/_dropdown.scss
index a4332380bda053d9e8dd811cd61188618ad5fb85..085045d0498aa8864e4a4404185f2783f49df889 100755
--- a/devui/style/core/_dropdown.scss
+++ b/devui/style/core/_dropdown.scss
@@ -48,6 +48,7 @@
z-index: 1000;
display: none;
min-width: calc(min(100%, 102px));
+ margin: 4px 0;
padding-bottom: 5px;
background-clip: padding-box;
border-radius: 2px;
diff --git a/docs/.vitepress/config/sidebar.ts b/docs/.vitepress/config/sidebar.ts
index aca6bee619416b36d9e9e6fda5be2b21341e973a..e196e88b9124bf8a192251dd95b3c785693d763c 100644
--- a/docs/.vitepress/config/sidebar.ts
+++ b/docs/.vitepress/config/sidebar.ts
@@ -12,7 +12,7 @@ const sidebar = {
{ text: 'Search 搜索框', link: '/components/search/', status: '已完成' },
{ text: 'Status 状态', link: '/components/status/', status: '已完成' },
{ text: 'Sticky 便贴', link: '/components/sticky/' },
- { text: 'Overlay 遮罩层', link: '/components/overlay/'}
+ { text: 'Overlay 遮罩层', link: '/components/overlay/' }
]
},
{
@@ -53,7 +53,7 @@ const sidebar = {
{ text: 'Checkbox 复选框', link: '/components/checkbox/', status: '已完成' },
{ text: 'DatePicker 日期选择器', link: '/components/date-picker/', status: '开发中' },
{ text: 'DatePickerPro 日期选择器', link: '/components/date-picker-pro/' },
- { text: 'EditableSelect 可编辑下拉框', link: '/components/editable-select/' },
+ { text: 'EditableSelect 可编辑下拉框', link: '/components/editable-select/', status: '开发中' },
{ text: 'Form 表单', link: '/components/form/' },
{ text: 'Input 文本框', link: '/components/input/', status: '已完成' },
{ text: 'InputNumber 数字输入框', link: '/components/input-number/' },
diff --git a/docs/components/editable-select/index.md b/docs/components/editable-select/index.md
new file mode 100644
index 0000000000000000000000000000000000000000..f0fc0bbeee85d86c02730b7543fab57b781e4eb1
--- /dev/null
+++ b/docs/components/editable-select/index.md
@@ -0,0 +1,34 @@
+# EditableSelect 可输入下拉选择框
+
+同时支持输入和下拉选择的输入框。
+
+### 何时使用
+
+当需要同时支持用户输入数据和选择已有数据的时候使用,加入输入联想功能,方便用户搜索已有数据。
+
+:::demo
+```vue
+
+
+
+ {{ item }}
+
+ not Found data
+
+
+
+
+```
+:::