✨(component): 完成 select 组件, 新增 tag-input 组件 disabled-input 属性
This commit is contained in:
parent
f52ff6207b
commit
06149b7e77
@ -43,7 +43,7 @@ const matchModule: string[] = [
|
|||||||
"dropdownMenu",
|
"dropdownMenu",
|
||||||
"dropdownMenuItem",
|
"dropdownMenuItem",
|
||||||
"tag",
|
"tag",
|
||||||
"tagInput"
|
"tagInput",
|
||||||
];
|
];
|
||||||
|
|
||||||
export default (): UserConfigExport => {
|
export default (): UserConfigExport => {
|
||||||
|
@ -70,7 +70,6 @@ export interface LayDropdownProps {
|
|||||||
alignPoint?: boolean;
|
alignPoint?: boolean;
|
||||||
contentClass?: string | Array<string | object> | object;
|
contentClass?: string | Array<string | object> | object;
|
||||||
contentStyle?: StyleValue;
|
contentStyle?: StyleValue;
|
||||||
// wip
|
|
||||||
popupContainer?: string | undefined;
|
popupContainer?: string | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,10 @@ const isVertical = computed(() => {
|
|||||||
return vNodes.some((vNode) => {
|
return vNodes.some((vNode) => {
|
||||||
const componentName = (vNode.type as Component).name;
|
const componentName = (vNode.type as Component).name;
|
||||||
if (!componentName) return false;
|
if (!componentName) return false;
|
||||||
return [Header.name].includes(componentName) || [Footer.name].includes(componentName);
|
return (
|
||||||
|
[Header.name].includes(componentName) ||
|
||||||
|
[Footer.name].includes(componentName)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -14,7 +14,16 @@
|
|||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.layui-select-options .layui-select-option .layui-form-checkbox[lay-skin="primary"] {
|
||||||
|
padding-left: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
.layui-select-options .layui-select-option.layui-this {
|
.layui-select-options .layui-select-option.layui-this {
|
||||||
background-color: var(--global-neutral-color-2);
|
background-color: var(--global-neutral-color-2);
|
||||||
color: var(--global-checked-color);
|
color: var(--global-checked-color);
|
||||||
|
font-size: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layui-select-search {
|
||||||
|
padding: 5px 10px;
|
||||||
}
|
}
|
@ -6,11 +6,13 @@ export default {
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import "./index.less";
|
import "./index.less";
|
||||||
import { provide, computed, WritableComputedRef } from "vue";
|
import { provide, computed, WritableComputedRef, ref } from "vue";
|
||||||
import LayInput from "../input/index.vue";
|
import LayInput from "../input/index.vue";
|
||||||
import LayTagInput from "../tagInput/index.vue";
|
import LayTagInput from "../tagInput/index.vue";
|
||||||
import LayDropdown from "../dropdown/index.vue";
|
import LayDropdown from "../dropdown/index.vue";
|
||||||
import LaySelectOption, { LaySelectOptionProps } from "../selectOption/index.vue";
|
import LaySelectOption, {
|
||||||
|
LaySelectOptionProps,
|
||||||
|
} from "../selectOption/index.vue";
|
||||||
|
|
||||||
export interface LaySelectProps {
|
export interface LaySelectProps {
|
||||||
name?: string;
|
name?: string;
|
||||||
@ -41,37 +43,51 @@ const props = withDefaults(defineProps<LaySelectProps>(), {
|
|||||||
|
|
||||||
const emits = defineEmits<SelectEmits>();
|
const emits = defineEmits<SelectEmits>();
|
||||||
|
|
||||||
|
const searchValue = ref("");
|
||||||
|
|
||||||
const selectedValue = computed({
|
const selectedValue = computed({
|
||||||
get() {
|
get() {
|
||||||
return props.modelValue;
|
return props.modelValue;
|
||||||
},
|
},
|
||||||
set(val) {
|
set(val) {
|
||||||
emits('update:modelValue', val);
|
emits("update:modelValue", val);
|
||||||
emits('change', val);
|
emits("change", val);
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
const multiple = computed(() => {
|
const multiple = computed(() => {
|
||||||
return props.multiple;
|
return props.multiple;
|
||||||
})
|
});
|
||||||
|
|
||||||
provide('selectedValue', selectedValue);
|
provide("selectedValue", selectedValue);
|
||||||
provide('multiple', multiple);
|
provide("searchValue", searchValue);
|
||||||
|
provide("multiple", multiple);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="layui-select">
|
<div class="layui-select">
|
||||||
<lay-dropdown update-at-scroll>
|
<lay-dropdown update-at-scroll>
|
||||||
<lay-tag-input v-if="multiple" v-model="selectedValue"></lay-tag-input>
|
<lay-tag-input v-if="multiple" v-model="selectedValue" :disabledInput="true"></lay-tag-input>
|
||||||
<lay-input v-else :placeholder="placeholder" v-model="selectedValue"></lay-input>
|
<lay-input
|
||||||
<template #content>
|
v-else
|
||||||
<dl class="layui-select-options">
|
:placeholder="placeholder"
|
||||||
<template v-if="items">
|
v-model="selectedValue"
|
||||||
<lay-select-option v-for="(item, index) in items" v-bind="item" :key="index"></lay-select-option>
|
></lay-input>
|
||||||
</template>
|
<template #content>
|
||||||
<slot></slot>
|
<dl class="layui-select-options">
|
||||||
</dl>
|
<div class="layui-select-search">
|
||||||
</template>
|
<lay-input v-model="searchValue" size="sm" placeholder="请选择" prefix-icon="layui-icon-search"></lay-input>
|
||||||
|
</div>
|
||||||
|
<template v-if="items">
|
||||||
|
<lay-select-option
|
||||||
|
v-for="(item, index) in items"
|
||||||
|
v-bind="item"
|
||||||
|
:key="index"
|
||||||
|
></lay-select-option>
|
||||||
|
</template>
|
||||||
|
<slot></slot>
|
||||||
|
</dl>
|
||||||
|
</template>
|
||||||
</lay-dropdown>
|
</lay-dropdown>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -6,13 +6,13 @@ export default {
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import LayCheckbox from "../checkbox/index.vue";
|
import LayCheckbox from "../checkbox/index.vue";
|
||||||
import { computed, ComputedRef, inject, WritableComputedRef } from "vue";
|
import { computed, ComputedRef, inject, WritableComputedRef, Ref } from "vue";
|
||||||
|
|
||||||
export interface LaySelectOptionProps {
|
export interface LaySelectOptionProps {
|
||||||
value: string | object;
|
|
||||||
label: string;
|
label: string;
|
||||||
keyword?: string;
|
value: string | object;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
keyword?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<LaySelectOptionProps>(), {
|
const props = withDefaults(defineProps<LaySelectOptionProps>(), {
|
||||||
@ -22,32 +22,38 @@ const props = withDefaults(defineProps<LaySelectOptionProps>(), {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const selectedValue: WritableComputedRef<any> = inject("selectedValue") as WritableComputedRef<any>;
|
const selectedValue: WritableComputedRef<any> = inject("selectedValue") as WritableComputedRef<any>;
|
||||||
|
const searchValue: Ref<string> = inject('searchValue') as Ref<string>;
|
||||||
const multiple: ComputedRef = inject("multiple") as ComputedRef;
|
const multiple: ComputedRef = inject("multiple") as ComputedRef;
|
||||||
|
|
||||||
const handleSelect = () => {
|
const handleSelect = () => {
|
||||||
if(!multiple.value) {
|
if (!multiple.value) {
|
||||||
selectedValue.value = props.value;
|
selectedValue.value = props.value;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const isSelected = computed(() => {
|
const selected = computed(() => {
|
||||||
if (multiple.value) {
|
if (multiple.value) {
|
||||||
return selectedValue.value.indexOf(props.value) != -1;
|
return selectedValue.value.indexOf(props.value) != -1;
|
||||||
} else {
|
} else {
|
||||||
|
// close dropdown
|
||||||
return selectedValue.value === props.value;
|
return selectedValue.value === props.value;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const display = computed(() => {
|
||||||
|
return props.keyword.indexOf(searchValue.value) > -1 || props.label.indexOf(searchValue.value) > -1;
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<dd class="layui-select-option" :class="{ 'layui-this': isSelected && !multiple }" @click="handleSelect">
|
<dd
|
||||||
|
v-show="display"
|
||||||
|
:class="['layui-select-option', { 'layui-this': selected && !multiple }]"
|
||||||
|
@click="handleSelect"
|
||||||
|
>
|
||||||
<template v-if="multiple">
|
<template v-if="multiple">
|
||||||
<lay-checkbox v-model="selectedValue" :value="value" skin="primary"
|
<lay-checkbox v-model="selectedValue" :value="value" skin="primary"></lay-checkbox>
|
||||||
><slot>{{ label }}</slot></lay-checkbox
|
|
||||||
>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<slot>{{ label }}</slot>
|
|
||||||
</template>
|
</template>
|
||||||
|
<slot>{{ label }}</slot>
|
||||||
</dd>
|
</dd>
|
||||||
</template>
|
</template>
|
||||||
|
@ -17,6 +17,7 @@ import {
|
|||||||
nextTick,
|
nextTick,
|
||||||
} from "vue";
|
} from "vue";
|
||||||
import { reactiveOmit, useResizeObserver, useVModel } from "@vueuse/core";
|
import { reactiveOmit, useResizeObserver, useVModel } from "@vueuse/core";
|
||||||
|
import { LayIcon } from "@layui/icons-vue";
|
||||||
|
|
||||||
export interface TagData {
|
export interface TagData {
|
||||||
value?: string | number;
|
value?: string | number;
|
||||||
@ -29,6 +30,7 @@ export interface LayInputTagProps {
|
|||||||
modelValue?: (string | number | TagData)[];
|
modelValue?: (string | number | TagData)[];
|
||||||
inputValue?: string;
|
inputValue?: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
disabledInput?: boolean;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
readonly?: boolean;
|
readonly?: boolean;
|
||||||
allowClear?: boolean;
|
allowClear?: boolean;
|
||||||
@ -41,12 +43,12 @@ export interface LayInputTagProps {
|
|||||||
|
|
||||||
const props = withDefaults(defineProps<LayInputTagProps>(), {
|
const props = withDefaults(defineProps<LayInputTagProps>(), {
|
||||||
disabled: false,
|
disabled: false,
|
||||||
|
disabledInput: false,
|
||||||
placeholder: "",
|
placeholder: "",
|
||||||
readonly: false,
|
readonly: false,
|
||||||
allowClear: true,
|
allowClear: true,
|
||||||
minCollapsedNum: 3,
|
minCollapsedNum: 3,
|
||||||
size: "md",
|
size: "md",
|
||||||
//max:3
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(["update:modelValue", "update:inputValue"]);
|
const emit = defineEmits(["update:modelValue", "update:inputValue"]);
|
||||||
@ -62,6 +64,7 @@ const tagData = useVModel(props, "modelValue", emit, {
|
|||||||
deep: true,
|
deep: true,
|
||||||
defaultValue: [] as TagData[],
|
defaultValue: [] as TagData[],
|
||||||
});
|
});
|
||||||
|
|
||||||
const tagProps = reactiveOmit(
|
const tagProps = reactiveOmit(
|
||||||
props.tagProps ?? {},
|
props.tagProps ?? {},
|
||||||
"closable",
|
"closable",
|
||||||
@ -183,10 +186,10 @@ watch(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const moreCount = computed(() => {
|
const moreCount = computed(() => {
|
||||||
if(tagData.value && computedTagData.value) {
|
if (tagData.value && computedTagData.value) {
|
||||||
return tagData.value.length - computedTagData.value.length
|
return tagData.value.length - computedTagData.value.length;
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
handleResize();
|
handleResize();
|
||||||
@ -240,7 +243,8 @@ defineExpose({
|
|||||||
</template>
|
</template>
|
||||||
</LayToopTip>
|
</LayToopTip>
|
||||||
</template>
|
</template>
|
||||||
<input
|
<template v-if="!disabledInput">
|
||||||
|
<input
|
||||||
ref="inputRefEl"
|
ref="inputRefEl"
|
||||||
class="layui-tag-input-inner-input"
|
class="layui-tag-input-inner-input"
|
||||||
:style="inputStyle"
|
:style="inputStyle"
|
||||||
@ -254,6 +258,7 @@ defineExpose({
|
|||||||
@compositionupdate="handleComposition"
|
@compositionupdate="handleComposition"
|
||||||
@compositionend="handleComposition"
|
@compositionend="handleComposition"
|
||||||
/>
|
/>
|
||||||
|
</template>
|
||||||
</span>
|
</span>
|
||||||
<span v-if="allowClear && tagData?.length" class="layui-tag-input-clear">
|
<span v-if="allowClear && tagData?.length" class="layui-tag-input-clear">
|
||||||
<lay-icon type="layui-icon-close-fill" @click.stop="handleClearClick" />
|
<lay-icon type="layui-icon-close-fill" @click.stop="handleClearClick" />
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
export const check = (arr: any[], value: any) => {
|
export const check = (arr: any[], value: any) => {
|
||||||
return arr.indexOf(value) > -1;
|
return arr.indexOf(value) > -1;
|
||||||
}
|
};
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
</lay-dropdown-menu>
|
</lay-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
</lay-dropdown>
|
</lay-dropdown>
|
||||||
<lay-dropdown popupContainer=".layui-body>div">
|
<lay-dropdown>
|
||||||
<lay-button type="primary">下拉菜单</lay-button>
|
<lay-button type="primary">下拉菜单</lay-button>
|
||||||
<template #content>
|
<template #content>
|
||||||
<lay-dropdown-menu>
|
<lay-dropdown-menu>
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
::: demo 使用 `lay-tag-input` 标签, 创建标签输入框。
|
::: demo 使用 `lay-tag-input` 标签, 创建标签输入框。
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<lay-tag-input v-model="data1" v-model:inputValue="inputValue"></lay-tag-input>
|
<lay-tag-input v-model="data1" v-model:inputValue="inputValue1"></lay-tag-input>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -22,17 +22,65 @@ import { ref,watch } from 'vue'
|
|||||||
export default {
|
export default {
|
||||||
setup() {
|
setup() {
|
||||||
const data1 = ref(['Vue', 'React']);
|
const data1 = ref(['Vue', 'React']);
|
||||||
const inputValue = ref();
|
const inputValue1 = ref("");
|
||||||
watch(data1, (val) => {
|
|
||||||
console.log("tagData",val)
|
|
||||||
})
|
|
||||||
watch(inputValue, (val) => {
|
|
||||||
console.log("inputValue",val)
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data1,
|
data1,
|
||||||
inputValue
|
inputValue1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: title 只读状态
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: demo 使用 `lay-tag-input` 标签, 创建标签输入框。
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<lay-tag-input v-model="data3" v-model:inputValue="inputValue3" :readonly="true"></lay-tag-input>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { ref,watch } from 'vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const data3 = ref(['Vue', 'React']);
|
||||||
|
const inputValue3 = ref("");
|
||||||
|
|
||||||
|
return {
|
||||||
|
data3,
|
||||||
|
inputValue3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: title 禁用状态
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: demo 使用 `lay-tag-input` 标签, 创建标签输入框。
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<lay-tag-input v-model="data4" v-model:inputValue="inputValue4" :disabled="true"></lay-tag-input>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { ref,watch } from 'vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const data4 = ref(['Vue', 'React']);
|
||||||
|
const inputValue4 = ref("");
|
||||||
|
|
||||||
|
return {
|
||||||
|
data4,
|
||||||
|
inputValue4
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ export default {
|
|||||||
name: "TreadIcon",
|
name: "TreadIcon",
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import LayIcon from "../component/icon/index";
|
import LayIcon from "../component/icon/index";
|
||||||
|
|
||||||
@ -11,6 +12,7 @@ const props = defineProps<{
|
|||||||
size?: string;
|
size?: string;
|
||||||
}>();
|
}>();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<lay-icon :color="props.color" :size="props.size" type="layui-icon-tread" />
|
<lay-icon :color="props.color" :size="props.size" type="layui-icon-tread" />
|
||||||
</template>
|
</template>
|
||||||
|
Loading…
Reference in New Issue
Block a user