♻️(wip): [tagInput] 重构 tagInput
This commit is contained in:
		
							parent
							
								
									5d5546d748
								
							
						
					
					
						commit
						583a6428a3
					
				@ -1,65 +1,138 @@
 | 
				
			|||||||
.layui-input-tag {
 | 
					@import "../tag/index.less";
 | 
				
			||||||
  position: relative;
 | 
					@import "../popper/index.less";
 | 
				
			||||||
  display: block;
 | 
					@import "../tooltip/index.less";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@tag-input-lg: 44px;
 | 
				
			||||||
 | 
					@tag-input-md: 38px;
 | 
				
			||||||
 | 
					@tag-input-sm: 32px;
 | 
				
			||||||
 | 
					@tag-input-xs: 26px;
 | 
				
			||||||
 | 
					@tag-input-boeder: 1px;
 | 
				
			||||||
 | 
					@tag-input-inner-padding-lg: 2px;
 | 
				
			||||||
 | 
					@tag-input-inner-padding-md: 2px;
 | 
				
			||||||
 | 
					@tag-input-inner-padding-sm: 1px;
 | 
				
			||||||
 | 
					@tag-input-inner-padding-xs: 1px;
 | 
				
			||||||
 | 
					@tag-margin-top-lg: 2px;
 | 
				
			||||||
 | 
					@tag-margin-top-md: 2px;
 | 
				
			||||||
 | 
					@tag-margin-top-sm: 1px;
 | 
				
			||||||
 | 
					@tag-margin-top-xs: 1px;
 | 
				
			||||||
 | 
					@tag-margin-bottom-lg: 2px;
 | 
				
			||||||
 | 
					@tag-margin-bottom-md: 2px;
 | 
				
			||||||
 | 
					@tag-margin-bottom-sm: 1px;
 | 
				
			||||||
 | 
					@tag-margin-bottom-xs: 1px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.layui-tag-input {
 | 
				
			||||||
 | 
					  display: inline-flex;
 | 
				
			||||||
 | 
					  box-sizing: border-box;
 | 
				
			||||||
 | 
					  width: auto;
 | 
				
			||||||
 | 
					  border-width: @tag-input-boeder;
 | 
				
			||||||
 | 
					  border-style: solid;
 | 
				
			||||||
 | 
					  border-color: var(--input-border-color);
 | 
				
			||||||
 | 
					  border-radius: var(--input-border-radius);
 | 
				
			||||||
  padding: 0 5px;
 | 
					  padding: 0 5px;
 | 
				
			||||||
  height: auto;
 | 
					  cursor: text;
 | 
				
			||||||
  overflow: hidden;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  .layui-input-prefix {
 | 
					  &-inner {
 | 
				
			||||||
    display: inline;
 | 
					 | 
				
			||||||
    text-align: left;
 | 
					 | 
				
			||||||
    height: 100%;
 | 
					 | 
				
			||||||
    flex: unset;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  .layui-input-suffix{
 | 
					 | 
				
			||||||
    position: absolute;
 | 
					 | 
				
			||||||
    right: 3px;
 | 
					 | 
				
			||||||
    bottom: 0;
 | 
					 | 
				
			||||||
    height: 100%;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  .layui-input {
 | 
					 | 
				
			||||||
    display: inline-block;
 | 
					 | 
				
			||||||
    padding-left: 0;
 | 
					 | 
				
			||||||
    width: auto;
 | 
					 | 
				
			||||||
    flex: 1;
 | 
					    flex: 1;
 | 
				
			||||||
    max-width: 100%;
 | 
					    overflow: hidden;
 | 
				
			||||||
    min-width: 12px;
 | 
					    line-height: 0;
 | 
				
			||||||
 | 
					    padding: @tag-input-inner-padding-md 0;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
.layui-input-tag-collapsed-panel,
 | 
					  &-mirror {
 | 
				
			||||||
.layui-input-tag {
 | 
					    position: absolute;
 | 
				
			||||||
  .layui-badge {
 | 
					    top: 0;
 | 
				
			||||||
    margin-right: 5px;
 | 
					    left: 0;
 | 
				
			||||||
    height: 28px;
 | 
					    white-space: pre;
 | 
				
			||||||
    line-height: 28px;
 | 
					    visibility: hidden;
 | 
				
			||||||
    user-select: none;
 | 
					    pointer-events: none;
 | 
				
			||||||
    white-space: pre-wrap;
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    .layui-icon {
 | 
					  &-clear {
 | 
				
			||||||
      font-size: 12px;
 | 
					    display: none;
 | 
				
			||||||
      padding-left: 3px;
 | 
					    align-items: center;
 | 
				
			||||||
 | 
					    cursor: pointer;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      &:hover {
 | 
					  &-clear:hover {
 | 
				
			||||||
        cursor: pointer;
 | 
					    opacity: 0.5;
 | 
				
			||||||
        color: #ff5722;
 | 
					  }
 | 
				
			||||||
      }
 | 
					
 | 
				
			||||||
 | 
					  & &-inner-input {
 | 
				
			||||||
 | 
					    box-sizing: border-box;
 | 
				
			||||||
 | 
					    border: none;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  &-disabled {
 | 
				
			||||||
 | 
					    cursor: not-allowed;
 | 
				
			||||||
 | 
					    opacity: 0.4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .layui-tag-input-clear {
 | 
				
			||||||
 | 
					      cursor: not-allowed;
 | 
				
			||||||
 | 
					      opacity: 0.4;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .layui-tag {
 | 
				
			||||||
 | 
					    margin-right: 5px;
 | 
				
			||||||
 | 
					    margin-top: 2px;
 | 
				
			||||||
 | 
					    margin-bottom: 2px;
 | 
				
			||||||
 | 
					    white-space: pre-wrap;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  &-collapsed-panel {
 | 
				
			||||||
 | 
					    white-space: normal;
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    align-items: center;
 | 
				
			||||||
 | 
					    flex-wrap: wrap;
 | 
				
			||||||
 | 
					    width: fit-content;
 | 
				
			||||||
 | 
					    max-width: 240px;
 | 
				
			||||||
 | 
					    height: auto;
 | 
				
			||||||
 | 
					    overflow: hidden;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .layui-tag {
 | 
				
			||||||
 | 
					      margin-right: 5px;
 | 
				
			||||||
 | 
					      margin-bottom: 4px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .set-size(@size) {
 | 
				
			||||||
 | 
					    @height: ~'tag-input-@{size}';
 | 
				
			||||||
 | 
					    @tag-margin-top: ~'tag-margin-top-@{size}';
 | 
				
			||||||
 | 
					    @tag-margin-bottom: ~'tag-margin-bottom-@{size}';
 | 
				
			||||||
 | 
					    @inner-padding: ~'tag-input-inner-padding-@{size}';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    &.layui-tag-input-@{size} {
 | 
				
			||||||
 | 
					      min-height: @@height;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      .layui-tag-input-inner-input {
 | 
				
			||||||
 | 
					        height: @@height - (@@inner-padding + @tag-input-boeder)* 2;
 | 
				
			||||||
 | 
					        vertical-align: middle;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      .layui-tag-input-inner {
 | 
				
			||||||
 | 
					        padding: @@inner-padding 0;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      .layui-tag {
 | 
				
			||||||
 | 
					        margin-top: @@tag-margin-top;
 | 
				
			||||||
 | 
					        margin-bottom: @@tag-margin-bottom;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .set-size(lg);
 | 
				
			||||||
 | 
					  .set-size(md);
 | 
				
			||||||
 | 
					  .set-size(sm);
 | 
				
			||||||
 | 
					  .set-size(xs);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.layui-input-tag-collapsed-panel {
 | 
					.layui-tag-input:hover,
 | 
				
			||||||
  white-space: normal;
 | 
					.layui-tag-input:focus-within {
 | 
				
			||||||
  display: flex;
 | 
					  border-color: #d2d2d2 !important;
 | 
				
			||||||
  align-items: center;
 | 
					  .layui-tag-input-clear{
 | 
				
			||||||
  flex-wrap: wrap;
 | 
					    display: flex;
 | 
				
			||||||
  width: fit-content;
 | 
					 | 
				
			||||||
  max-width: 200px;
 | 
					 | 
				
			||||||
  height: auto;
 | 
					 | 
				
			||||||
  overflow: hidden;
 | 
					 | 
				
			||||||
  .layui-badge{
 | 
					 | 
				
			||||||
    margin-bottom: 4px;
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -5,9 +5,18 @@ export default {
 | 
				
			|||||||
</script>
 | 
					</script>
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import "./index.less";
 | 
					import "./index.less";
 | 
				
			||||||
import Tag from "./Tag.vue";
 | 
					import LayTag, { LayTagProps } from "../tag/index.vue";
 | 
				
			||||||
import LayToopTip from "../tooltip/index.vue";
 | 
					import LayToopTip from "../tooltip/index.vue";
 | 
				
			||||||
import { onMounted, shallowRef, ref, watch, computed } from "vue";
 | 
					import {
 | 
				
			||||||
 | 
					  onMounted,
 | 
				
			||||||
 | 
					  shallowRef,
 | 
				
			||||||
 | 
					  ref,
 | 
				
			||||||
 | 
					  watch,
 | 
				
			||||||
 | 
					  computed,
 | 
				
			||||||
 | 
					  reactive,
 | 
				
			||||||
 | 
					  nextTick,
 | 
				
			||||||
 | 
					} from "vue";
 | 
				
			||||||
 | 
					import { reactiveOmit, useResizeObserver, useVModel } from "@vueuse/core";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface TagData {
 | 
					export interface TagData {
 | 
				
			||||||
  value?: string | number;
 | 
					  value?: string | number;
 | 
				
			||||||
@ -17,7 +26,7 @@ export interface TagData {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface LayInputTagProps {
 | 
					export interface LayInputTagProps {
 | 
				
			||||||
  modelValue?: TagData[];
 | 
					  modelValue?: (string | number | TagData)[];
 | 
				
			||||||
  inputValue?: string;
 | 
					  inputValue?: string;
 | 
				
			||||||
  disabled?: boolean;
 | 
					  disabled?: boolean;
 | 
				
			||||||
  placeholder?: string;
 | 
					  placeholder?: string;
 | 
				
			||||||
@ -26,7 +35,8 @@ export interface LayInputTagProps {
 | 
				
			|||||||
  max?: number;
 | 
					  max?: number;
 | 
				
			||||||
  minCollapsedNum?: number;
 | 
					  minCollapsedNum?: number;
 | 
				
			||||||
  collapseTagsTooltip?: boolean;
 | 
					  collapseTagsTooltip?: boolean;
 | 
				
			||||||
  size?: "md" | "sm" | "xs";
 | 
					  size?: "lg" | "md" | "sm" | "xs";
 | 
				
			||||||
 | 
					  tagProps?: LayTagProps;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const props = withDefaults(defineProps<LayInputTagProps>(), {
 | 
					const props = withDefaults(defineProps<LayInputTagProps>(), {
 | 
				
			||||||
@ -34,33 +44,60 @@ const props = withDefaults(defineProps<LayInputTagProps>(), {
 | 
				
			|||||||
  placeholder: "",
 | 
					  placeholder: "",
 | 
				
			||||||
  readonly: false,
 | 
					  readonly: false,
 | 
				
			||||||
  allowClear: true,
 | 
					  allowClear: true,
 | 
				
			||||||
  minCollapsedNum: 10,
 | 
					  minCollapsedNum: 3,
 | 
				
			||||||
 | 
					  size: "md",
 | 
				
			||||||
  //max:3
 | 
					  //max:3
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const emit = defineEmits(["update:modelValue", "update:inputValue"]);
 | 
					const emit = defineEmits(["update:modelValue", "update:inputValue"]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const mirrorRef = shallowRef<HTMLElement | undefined>(undefined);
 | 
					const mirrorRefEl = shallowRef<HTMLElement | undefined>(undefined);
 | 
				
			||||||
const inputRef = shallowRef<HTMLElement | undefined>(undefined);
 | 
					const inputRefEl = shallowRef<HTMLInputElement | undefined>(undefined);
 | 
				
			||||||
 | 
					const oldInputValue = ref<string>("");
 | 
				
			||||||
const tagData = ref<TagData[]>(props.modelValue ?? []);
 | 
					const compositionValue = ref<string>("");
 | 
				
			||||||
const inputValue = ref<string>();
 | 
					const isComposing = ref(false);
 | 
				
			||||||
const oldInputValue = ref<string>();
 | 
					const inputStyle = reactive({ width: "15px" });
 | 
				
			||||||
 | 
					const inputValue = useVModel(props, "inputValue", emit, { defaultValue: "" });
 | 
				
			||||||
 | 
					const tagData = useVModel(props, "modelValue", emit, {
 | 
				
			||||||
 | 
					  deep: true,
 | 
				
			||||||
 | 
					  defaultValue: [] as TagData[],
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					const tagProps = reactiveOmit(props.tagProps ?? {}, 'closable','size', 'disabled')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const computedTagData = computed(() => {
 | 
					const computedTagData = computed(() => {
 | 
				
			||||||
 | 
					  if (!tagData.value) return;
 | 
				
			||||||
  return props.minCollapsedNum
 | 
					  return props.minCollapsedNum
 | 
				
			||||||
    ? tagData.value?.slice(0, props.minCollapsedNum)
 | 
					    ? tagData.value?.slice(0, props.minCollapsedNum)
 | 
				
			||||||
    : tagData.value;
 | 
					    : tagData.value;
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const collapsedTagData = computed(() => {
 | 
					const collapsedTagData = computed(() => {
 | 
				
			||||||
 | 
					  if (!tagData.value) return;
 | 
				
			||||||
  return props.minCollapsedNum && tagData.value?.length > props.minCollapsedNum
 | 
					  return props.minCollapsedNum && tagData.value?.length > props.minCollapsedNum
 | 
				
			||||||
    ? tagData.value?.slice(props.minCollapsedNum)
 | 
					    ? tagData.value?.slice(props.minCollapsedNum)
 | 
				
			||||||
    : [];
 | 
					    : [];
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const handleInputEnter = (e: KeyboardEvent) => {
 | 
					const handleInput = function (event: Event) {
 | 
				
			||||||
  e.preventDefault();
 | 
					  if (isComposing.value) {
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  inputValue.value = (event.target as HTMLInputElement).value;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const handleComposition = (event: CompositionEvent) => {
 | 
				
			||||||
 | 
					  if (event.type === "compositionend") {
 | 
				
			||||||
 | 
					    isComposing.value = false;
 | 
				
			||||||
 | 
					    compositionValue.value = "";
 | 
				
			||||||
 | 
					    handleInput(event);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    isComposing.value = true;
 | 
				
			||||||
 | 
					    compositionValue.value = inputValue.value + (event.data ?? "");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const handleEnter = (event: KeyboardEvent) => {
 | 
				
			||||||
 | 
					  event.preventDefault();
 | 
				
			||||||
  const valueStr = inputValue.value ? String(inputValue.value).trim() : "";
 | 
					  const valueStr = inputValue.value ? String(inputValue.value).trim() : "";
 | 
				
			||||||
  if (!valueStr || !tagData.value) return;
 | 
					  if (!valueStr || !tagData.value) return;
 | 
				
			||||||
  const isLimit = props.max && tagData.value?.length >= props.max;
 | 
					  const isLimit = props.max && tagData.value?.length >= props.max;
 | 
				
			||||||
@ -73,86 +110,137 @@ const handleInputEnter = (e: KeyboardEvent) => {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const handlerInputBackspaceKeyUp = (e: KeyboardEvent) => {
 | 
					const handleBackspaceKeyUp = (event: KeyboardEvent) => {
 | 
				
			||||||
  if (!tagData.value || !tagData.value.length) return;
 | 
					  if (!tagData.value || !tagData.value.length) return;
 | 
				
			||||||
  if (!oldInputValue.value && ["Backspace", "Delete"].includes(e.code)) {
 | 
					  if (!oldInputValue.value && ["Backspace", "Delete"].includes(event.code)) {
 | 
				
			||||||
    tagData.value = tagData.value.slice(0, -1);
 | 
					    tagData.value = tagData.value.slice(0, -1);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  oldInputValue.value = inputValue.value;
 | 
					  oldInputValue.value = inputValue.value ?? "";
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const handlerClearClick = (e: MouseEvent) => {
 | 
					const handleFocus = () => {
 | 
				
			||||||
 | 
					  (inputRefEl.value as HTMLInputElement)?.focus();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const handleBlur = () => {
 | 
				
			||||||
 | 
					  (inputRefEl.value as HTMLInputElement)?.blur();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const handleClearClick = (e: MouseEvent) => {
 | 
				
			||||||
 | 
					  if (props.disabled || props.readonly || !props.allowClear) {
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  tagData.value = [];
 | 
					  tagData.value = [];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const handlerClose = (index: number) => {
 | 
					const handleClose = (index: number) => {
 | 
				
			||||||
  if (!tagData.value) return;
 | 
					  if (!tagData.value) return;
 | 
				
			||||||
  const arr = [...tagData.value];
 | 
					  const arr = [...tagData.value];
 | 
				
			||||||
  arr.splice(index, 1);
 | 
					  arr.splice(index, 1);
 | 
				
			||||||
  tagData.value = arr;
 | 
					  tagData.value = arr;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const handlerFocus = (e: MouseEvent) => {
 | 
					const setInputWidth = (width: number) => {
 | 
				
			||||||
  (
 | 
					  if (width > 15) {
 | 
				
			||||||
    (e.target as HTMLElement).querySelector(".layui-input") as HTMLInputElement
 | 
					    inputStyle.width = `${width}px`;
 | 
				
			||||||
  )?.focus();
 | 
					  } else {
 | 
				
			||||||
 | 
					    inputStyle.width = "15px";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
watch(tagData, (val) => {
 | 
					const handleResize = () => {
 | 
				
			||||||
  emit("update:modelValue", val);
 | 
					  if (mirrorRefEl.value) {
 | 
				
			||||||
 | 
					    setInputWidth(mirrorRefEl.value.offsetWidth);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const cls = computed(() => [
 | 
				
			||||||
 | 
					  `layui-tag-input`,
 | 
				
			||||||
 | 
					  `layui-tag-input-${props.size}`,
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    "layui-tag-input-disabled": props.disabled,
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					useResizeObserver(mirrorRefEl, () => {
 | 
				
			||||||
 | 
					  handleResize();
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
watch(inputValue, (val) => {
 | 
					watch(
 | 
				
			||||||
  emit("update:inputValue", val);
 | 
					  () => inputValue.value,
 | 
				
			||||||
 | 
					  (val) => {
 | 
				
			||||||
 | 
					    if (inputRefEl.value && !isComposing.value) {
 | 
				
			||||||
 | 
					      nextTick(() => {
 | 
				
			||||||
 | 
					        inputRefEl.value!.value = val ?? "";
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					onMounted(() => {
 | 
				
			||||||
 | 
					  handleResize();
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
onMounted(() => {});
 | 
					defineExpose({
 | 
				
			||||||
 | 
					  focus: handleFocus,
 | 
				
			||||||
 | 
					  blur: handleBlur,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <lay-input
 | 
					  <div :class="cls" @click="handleFocus">
 | 
				
			||||||
    class="layui-input-tag"
 | 
					    <span ref="mirrorRefEl" class="layui-tag-input-mirror">
 | 
				
			||||||
    v-model="inputValue"
 | 
					      {{ compositionValue || inputValue || placeholder }}
 | 
				
			||||||
    :placeholder="placeholder"
 | 
					    </span>
 | 
				
			||||||
    :readonly="readonly"
 | 
					    <span v-if="$slots.prefix">
 | 
				
			||||||
    @keydown.enter="handleInputEnter"
 | 
					      <slot name="prefix"></slot>
 | 
				
			||||||
    @keyup="handlerInputBackspaceKeyUp"
 | 
					    </span>
 | 
				
			||||||
    @click="handlerFocus"
 | 
					    <span class="layui-tag-input-inner">
 | 
				
			||||||
  >
 | 
					 | 
				
			||||||
    <template #prefix>
 | 
					 | 
				
			||||||
      <template
 | 
					      <template
 | 
				
			||||||
        v-for="(item, index) of computedTagData"
 | 
					        v-for="(item, index) of computedTagData"
 | 
				
			||||||
        :key="`${item}-${index}`"
 | 
					        :key="`${item}-${index}`"
 | 
				
			||||||
      >
 | 
					      >
 | 
				
			||||||
        <Tag :closable="!readonly" @close="handlerClose(index)">
 | 
					        <LayTag v-bind="tagProps" :closable="!readonly && !disabled" :size="size" @close="handleClose(index)">
 | 
				
			||||||
          {{ item }}
 | 
					          {{ item }}
 | 
				
			||||||
        </Tag>
 | 
					        </LayTag>
 | 
				
			||||||
      </template>
 | 
					      </template>
 | 
				
			||||||
      <template v-if="computedTagData?.length != tagData?.length">
 | 
					      <template v-if="computedTagData?.length != tagData?.length">
 | 
				
			||||||
        <LayToopTip :isDark="false">
 | 
					        <LayToopTip :isDark="false" trigger="click" popperStyle="padding:6px">
 | 
				
			||||||
          <Tag key="more" :closable="false"
 | 
					          <LayTag v-bind="tagProps" key="more" :closable="false" :size="size">
 | 
				
			||||||
            >+{{ tagData?.length - computedTagData?.length }}...</Tag
 | 
					            +{{tagData!.length - computedTagData!.length }}...
 | 
				
			||||||
          >
 | 
					          </LayTag>
 | 
				
			||||||
          <template #content>
 | 
					          <template #content>
 | 
				
			||||||
            <div class="layui-input-tag-collapsed-panel">
 | 
					            <div class="layui-tag-input-collapsed-panel">
 | 
				
			||||||
              <template
 | 
					              <LayTag
 | 
				
			||||||
                v-for="(item, index) of tagData"
 | 
					                v-for="(item, index) of collapsedTagData"
 | 
				
			||||||
                :key="`${item}-${index}`"
 | 
					                :key="`${item}-${index}`"
 | 
				
			||||||
 | 
					                v-bind="tagProps"
 | 
				
			||||||
 | 
					                :closable="!readonly && !disabled"
 | 
				
			||||||
 | 
					                :size="size"
 | 
				
			||||||
 | 
					                @close="handleClose(index + (minCollapsedNum ?? 0))"
 | 
				
			||||||
              >
 | 
					              >
 | 
				
			||||||
                <Tag
 | 
					                {{ item }}
 | 
				
			||||||
                  v-if="index >= minCollapsedNum"
 | 
					              </LayTag>
 | 
				
			||||||
                  :closable="!readonly"
 | 
					 | 
				
			||||||
                  @close="handlerClose(index)"
 | 
					 | 
				
			||||||
                >
 | 
					 | 
				
			||||||
                  {{ item }}
 | 
					 | 
				
			||||||
                </Tag>
 | 
					 | 
				
			||||||
              </template>
 | 
					 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
          </template>
 | 
					          </template>
 | 
				
			||||||
        </LayToopTip>
 | 
					        </LayToopTip>
 | 
				
			||||||
      </template>
 | 
					      </template>
 | 
				
			||||||
    </template>
 | 
					      <input
 | 
				
			||||||
    <template #suffix v-if="allowClear && tagData?.length">
 | 
					        ref="inputRefEl"
 | 
				
			||||||
      <lay-icon type="layui-icon-close-fill" @click.stop="handlerClearClick" />
 | 
					        class="layui-tag-input-inner-input"
 | 
				
			||||||
    </template>
 | 
					        :style="inputStyle"
 | 
				
			||||||
  </lay-input>
 | 
					        :disabled="disabled"
 | 
				
			||||||
 | 
					        :placeholder="placeholder"
 | 
				
			||||||
 | 
					        :readonly="readonly"
 | 
				
			||||||
 | 
					        @keydown.enter="handleEnter"
 | 
				
			||||||
 | 
					        @keyup="handleBackspaceKeyUp"
 | 
				
			||||||
 | 
					        @input="handleInput"
 | 
				
			||||||
 | 
					        @compositionstart="handleComposition"
 | 
				
			||||||
 | 
					        @compositionupdate="handleComposition"
 | 
				
			||||||
 | 
					        @compositionend="handleComposition"
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					    </span>
 | 
				
			||||||
 | 
					    <span v-if="allowClear && tagData?.length" class="layui-tag-input-clear">
 | 
				
			||||||
 | 
					      <lay-icon type="layui-icon-close-fill" @click.stop="handleClearClick" />
 | 
				
			||||||
 | 
					    </span>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user