diff --git a/devui/editable-select/src/components/option/index.tsx b/devui/editable-select/src/components/option/index.tsx
index e717d15849fa12b0d329e13d6251dd52576065a3..1dfd5c5c9dcf4814d07c5772d37d4ff5c4cce0f3 100644
--- a/devui/editable-select/src/components/option/index.tsx
+++ b/devui/editable-select/src/components/option/index.tsx
@@ -1,11 +1,36 @@
-import { defineComponent } from 'vue';
-
+import { defineComponent, renderSlot, getCurrentInstance, inject } from 'vue'
+import { className } from '../../utils/index'
+import { selectKey } from '../../editable-select-types'
export default defineComponent({
name: 'DEditableSelectOption',
+ props: {
+ label: {
+ type: [String, Number],
+ },
+ disabled: {
+ type: Boolean,
+ default: false,
+ },
+ },
setup(props, ctx) {
- const defaultSlot = ctx.slots.default && ctx.slots.default();
+ const optionsClassName = className('devui-dropdown-item', {
+ disabled: props.disabled,
+ })
+ const instance = getCurrentInstance()
+
+ const select = inject(selectKey)
+
+ const selectOptionClick = () => {
+ if (!props.disabled) {
+ select.handleOptionSelect(instance)
+ }
+ }
return () => {
- return
{defaultSlot};
- };
+ return (
+
+ {props.label ? props.label : renderSlot(ctx.slots, 'default')}
+
+ )
+ }
},
-});
+})
diff --git a/devui/editable-select/src/editable-select-types.ts b/devui/editable-select/src/editable-select-types.ts
index 4b35deb5e3626d97d28325bea4e7211f4607eaaf..cf83a584267d36446362cd7471f8bbf4aba4cdf1 100644
--- a/devui/editable-select/src/editable-select-types.ts
+++ b/devui/editable-select/src/editable-select-types.ts
@@ -1,5 +1,6 @@
-import type { ExtractPropTypes } from 'vue'
-
+import type { ExtractPropTypes, Ref, PropType, InjectionKey } from 'vue'
+export type ModelValue = number | string | Array
+// porps
export const editableSelectProps = {
/* test: {
type: Object as PropType<{ xxx: xxx }>
@@ -15,8 +16,41 @@ export const editableSelectProps = {
maxHeight: {
type: Number,
default: 300
- }
-
+ },
+ disabled: {
+ type: Boolean,
+ default: false
+ },
+ modelValue: {
+ type: [String, Number, Array] as PropType
+ },
+ 'onUpdate:modelValue': {
+ type: Function as PropType<(val: ModelValue) => void>,
+ },
} as const
export type EditableSelectProps = ExtractPropTypes
+type HorizontalConnectionPos = 'left' | 'center' | 'right';
+type VerticalConnectionPos = 'top' | 'center' | 'bottom';
+
+interface ConnectionPosition {
+ originX: HorizontalConnectionPos
+ originY: VerticalConnectionPos
+ overlayX: HorizontalConnectionPos
+ overlayY: VerticalConnectionPos
+}
+
+export interface SelectStatesReturnType {
+ visible: boolean
+ origin: Ref
+ position: ConnectionPosition
+}
+export interface SelectReturnType {
+ toggleMenu: () => void
+ handleOptionSelect: (vm: unknown) => void
+}
+
+export const selectKey = 'DSelect' as unknown as InjectionKey
+export interface SelectContext {
+ handleOptionSelect(vm: unknown): void
+}
diff --git a/devui/editable-select/src/editable-select.scss b/devui/editable-select/src/editable-select.scss
index 0b51029ae32c08ee188e25f46a064aebea9e06d7..94567edcb2db2f0608d459a8db2d5e94ee04e624 100644
--- a/devui/editable-select/src/editable-select.scss
+++ b/devui/editable-select/src/editable-select.scss
@@ -49,58 +49,78 @@
line-height: 26px;
}
+.devui-dropdown-bg.devui-dropdown-bg {
+ background-color: inherit;
+}
// 下拉部分
-.devui-dropdown-wrap {
+.devui-editable-select {
.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-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;
}
}
- // 选项disabled
- .devui-dropdown-item.disabled,
- .devui-dropdown-item.disabled:hover {
- cursor: not-allowed;
- color: $devui-disabled-text;
+ }
+
+ .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;
+ }
-.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;
+ 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
index 74d1f04683bed79b66749d42fe214b10ce856c49..f76b6e430d5eda57392572636429a9d1c7d3c077 100644
--- a/devui/editable-select/src/editable-select.tsx
+++ b/devui/editable-select/src/editable-select.tsx
@@ -1,55 +1,65 @@
-import './editable-select.scss';
-
-import { defineComponent, ref, reactive, renderSlot } from 'vue';
+import './editable-select.scss'
+import {
+ defineComponent,
+ reactive,
+ toRefs,
+ renderSlot,
+ provide,
+ SetupContext,
+} from 'vue'
import {
editableSelectProps,
EditableSelectProps,
-} from './editable-select-types';
-import { Icon } from '../../icon';
-
+ selectKey,
+} from './editable-select-types'
+import { Icon } from '../../icon'
+import { FlexibleOverlay } from '../../overlay'
+import { useSelectStates, useSelect } from './hooks/use-select'
+import { className } from './utils/index'
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',
- });
+ emits: ['update:modelValue'],
+
+ setup(props: EditableSelectProps, ctx: SetupContext) {
+ const states = useSelectStates()
+ const { origin, visible } = toRefs(states)
+
+ const inputCls = className('devui-form-control devui-dropdown-origin', {
+ disabled: props.disabled,
+ })
+ const { toggleMenu, handleOptionSelect } = useSelect(props, ctx, states)
- const toggleMenu = () => {
- visible.value = !visible.value;
- };
+ provide(
+ selectKey,
+ reactive({
+ handleOptionSelect,
+ })
+ )
return () => {
return (
<>
-
+
-
-
+
>
- );
- };
+ )
+ }
},
-});
+})
diff --git a/devui/editable-select/src/hooks/use-select.ts b/devui/editable-select/src/hooks/use-select.ts
new file mode 100644
index 0000000000000000000000000000000000000000..eb1ad70341dd6095e6f1658c01ac48a80af447af
--- /dev/null
+++ b/devui/editable-select/src/hooks/use-select.ts
@@ -0,0 +1,33 @@
+import { ref, reactive, computed, SetupContext } from 'vue'
+import { EditableSelectProps, SelectStatesReturnType, SelectReturnType } from '../editable-select-types'
+export type States = ReturnType
+export function useSelectStates(): SelectStatesReturnType {
+ return reactive({
+ visible: false,
+ origin: ref(null),
+ position: {
+ originX: 'left',
+ originY: 'bottom',
+ overlayX: 'left',
+ overlayY: 'top',
+ },
+ })
+}
+
+export function useSelect(props: EditableSelectProps, ctx: SetupContext, states: States,): SelectReturnType {
+ const selectDisabled = computed(() => props.disabled)
+
+ const toggleMenu = () => {
+ if (!selectDisabled.value) {
+ states.visible = !states.visible;
+ }
+ };
+ const handleOptionSelect = (optionInstance) => {
+ ctx.emit('update:modelValue', optionInstance.proxy.label)
+ states.visible = false
+ }
+ return {
+ toggleMenu,
+ handleOptionSelect
+ }
+}
\ No newline at end of file
diff --git a/devui/editable-select/src/utils/index.ts b/devui/editable-select/src/utils/index.ts
index fb6e5e684158315280b0aafec4bfdb4b319298d1..52113e135dd549f3952652283d02db3ed03a3580 100644
--- a/devui/editable-select/src/utils/index.ts
+++ b/devui/editable-select/src/utils/index.ts
@@ -8,11 +8,11 @@ export function className(
classStr: string,
classOpt?: { [key: string]: boolean; }
): string {
- let classname = classStr;
+ let classname = classStr
if (typeof classOpt === 'object') {
Object.keys(classOpt).forEach((key) => {
classOpt[key] && (classname += ` ${key}`);
});
}
- return classname;
+ return classname
}
\ No newline at end of file
diff --git a/docs/components/editable-select/index.md b/docs/components/editable-select/index.md
index f0fc0bbeee85d86c02730b7543fab57b781e4eb1..3c4124b873591dc98ca0f5059f25f797c9c99fe7 100644
--- a/docs/components/editable-select/index.md
+++ b/docs/components/editable-select/index.md
@@ -9,8 +9,8 @@
:::demo
```vue
-
-
+
+
{{ item }}
not Found data
@@ -23,8 +23,12 @@ export default defineComponent({
setup() {
const languages = ref(['C#', 'C', 'C++', 'CPython', 'Java', 'JavaScript', 'Go', 'Python', 'Ruby', 'F#', 'TypeScript', 'SQL',
'LiveScript', 'CoffeeScript']);
+ const languages1 = ref([{name: 'c'}, {name: 'C++', disabled: true}]);
+ const selectItem1 = ref("")
return {
languages,
+ languages1,
+ selectItem1
};
},
});