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