feat: initial commit - Phase 1 & 2 core features

This commit is contained in:
hiderfong
2026-04-22 17:07:33 +08:00
commit 1773bda06b
25005 changed files with 6252106 additions and 0 deletions
+10
View File
@@ -0,0 +1,10 @@
import { SFCWithInstall } from "../../utils/vue/typescript.js";
import "../../utils/index.js";
import { MentionOption } from "./src/types.js";
import { MentionEmits, MentionInstance, MentionOptionProps, MentionProps, MentionPropsPublic, mentionDefaultProps, mentionEmits, mentionProps } from "./src/mention.js";
import { _default } from "./src/mention.vue.js";
//#region ../../packages/components/mention/index.d.ts
declare const ElMention: SFCWithInstall<typeof _default>;
//#endregion
export { ElMention, ElMention as default, MentionEmits, MentionInstance, MentionOption, MentionOptionProps, MentionProps, MentionPropsPublic, mentionDefaultProps, mentionEmits, mentionProps };
+15
View File
@@ -0,0 +1,15 @@
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } });
const require_install = require('../../utils/vue/install.js');
const require_mention = require('./src/mention.js');
const require_mention$1 = require('./src/mention2.js');
//#region ../../packages/components/mention/index.ts
const ElMention = require_install.withInstall(require_mention$1.default);
//#endregion
exports.ElMention = ElMention;
exports.default = ElMention;
exports.mentionDefaultProps = require_mention.mentionDefaultProps;
exports.mentionEmits = require_mention.mentionEmits;
exports.mentionProps = require_mention.mentionProps;
//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
{"version":3,"file":"index.js","names":["withInstall","Mention"],"sources":["../../../../../packages/components/mention/index.ts"],"sourcesContent":["import { withInstall } from '@element-plus/utils'\nimport Mention from './src/mention.vue'\n\nimport type { SFCWithInstall } from '@element-plus/utils'\n\nexport const ElMention: SFCWithInstall<typeof Mention> = withInstall(Mention)\nexport default ElMention\n\nexport * from './src/mention'\n"],"mappings":";;;;;;AAKA,MAAa,YAA4CA,4BAAYC,0BAAQ"}
@@ -0,0 +1,6 @@
import { MentionOption } from "./types.js";
//#region ../../packages/components/mention/src/helper.d.ts
declare const filterOption: <T extends MentionOption = MentionOption>(pattern: string, option: T & MentionOption) => boolean;
//#endregion
export { filterOption };
+152
View File
@@ -0,0 +1,152 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const require_runtime = require('../../../_virtual/_rolldown/runtime.js');
const require_browser = require('../../../utils/browser.js');
let lodash_unified = require("lodash-unified");
//#region ../../packages/components/mention/src/helper.ts
const filterOption = (pattern, option) => {
const lowerCase = pattern.toLowerCase();
return (option.label || option.value || "").toLowerCase().includes(lowerCase);
};
const getMentionCtx = (inputEl, prefix, split) => {
const { selectionEnd } = inputEl;
if (selectionEnd === null) return;
const inputValue = inputEl.value;
const prefixArray = (0, lodash_unified.castArray)(prefix);
let splitIndex = -1;
let mentionCtx;
for (let i = selectionEnd - 1; i >= 0; --i) {
const char = inputValue[i];
if (splitIndex === -1 && (char === split || char === "\n" || char === "\r")) {
splitIndex = i;
continue;
}
if (prefixArray.includes(char)) {
const end = splitIndex === -1 ? selectionEnd : splitIndex;
mentionCtx = {
pattern: inputValue.slice(i + 1, end),
start: i + 1,
end,
prefix: char,
prefixIndex: i,
splitIndex,
selectionEnd
};
break;
}
}
return mentionCtx;
};
/**
* fork from textarea-caret-position
* https://github.com/component/textarea-caret-position
* The MIT License (MIT)
* Copyright (c) 2015 Jonathan Ong me@jongleberry.com
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
const getCursorPosition = (element, options = {
debug: false,
useSelectionEnd: false
}) => {
const selectionStart = element.selectionStart !== null ? element.selectionStart : 0;
const selectionEnd = element.selectionEnd !== null ? element.selectionEnd : 0;
const position = options.useSelectionEnd ? selectionEnd : selectionStart;
const properties = [
"direction",
"boxSizing",
"width",
"height",
"overflowX",
"overflowY",
"borderTopWidth",
"borderRightWidth",
"borderBottomWidth",
"borderLeftWidth",
"borderStyle",
"paddingTop",
"paddingRight",
"paddingBottom",
"paddingLeft",
"fontStyle",
"fontVariant",
"fontWeight",
"fontStretch",
"fontSize",
"fontSizeAdjust",
"lineHeight",
"fontFamily",
"textAlign",
"textTransform",
"textIndent",
"textDecoration",
"letterSpacing",
"wordSpacing",
"tabSize",
"MozTabSize"
];
if (options.debug) {
const el = document.querySelector("#input-textarea-caret-position-mirror-div");
if (el?.parentNode) el.parentNode.removeChild(el);
}
const div = document.createElement("div");
div.id = "input-textarea-caret-position-mirror-div";
document.body.appendChild(div);
const style = div.style;
const computed = window.getComputedStyle(element);
const isInput = element.nodeName === "INPUT";
style.whiteSpace = isInput ? "nowrap" : "pre-wrap";
if (!isInput) style.wordWrap = "break-word";
style.position = "absolute";
if (!options.debug) style.visibility = "hidden";
properties.forEach((prop) => {
if (isInput && prop === "lineHeight") if (computed.boxSizing === "border-box") {
const height = Number.parseInt(computed.height);
const outerHeight = Number.parseInt(computed.paddingTop) + Number.parseInt(computed.paddingBottom) + Number.parseInt(computed.borderTopWidth) + Number.parseInt(computed.borderBottomWidth);
const targetHeight = outerHeight + Number.parseInt(computed.lineHeight);
if (height > targetHeight) style.lineHeight = `${height - outerHeight}px`;
else if (height === targetHeight) style.lineHeight = computed.lineHeight;
else style.lineHeight = "0";
} else style.lineHeight = computed.height;
else style[prop] = computed[prop];
});
if (require_browser.isFirefox()) {
if (element.scrollHeight > Number.parseInt(computed.height)) style.overflowY = "scroll";
} else style.overflow = "hidden";
div.textContent = element.value.slice(0, Math.max(0, position));
if (isInput && div.textContent) div.textContent = div.textContent.replace(/\s/g, "\xA0");
const span = document.createElement("span");
span.textContent = element.value.slice(Math.max(0, position)) || ".";
span.style.position = "relative";
span.style.left = `${-element.scrollLeft}px`;
span.style.top = `${-element.scrollTop}px`;
div.appendChild(span);
const relativePosition = {
top: span.offsetTop + Number.parseInt(computed.borderTopWidth),
left: span.offsetLeft + Number.parseInt(computed.borderLeftWidth),
height: Number.parseInt(computed.fontSize) * 1.5
};
if (options.debug) span.style.backgroundColor = "#aaa";
else document.body.removeChild(div);
if (relativePosition.left >= element.clientWidth) relativePosition.left = element.clientWidth;
return relativePosition;
};
//#endregion
exports.filterOption = filterOption;
exports.getCursorPosition = getCursorPosition;
exports.getMentionCtx = getMentionCtx;
//# sourceMappingURL=helper.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,25 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const require_runtime = require('../../../_virtual/_rolldown/runtime.js');
const require_runtime$1 = require('../../../utils/vue/props/runtime.js');
let _vue_shared = require("@vue/shared");
//#region ../../packages/components/mention/src/mention-dropdown.ts
/**
* @deprecated Removed after 3.0.0, Use `MentionDropdownProps` instead.
*/
const mentionDropdownProps = require_runtime$1.buildProps({
options: {
type: require_runtime$1.definePropType(Array),
default: () => []
},
loading: Boolean,
disabled: Boolean,
contentId: String,
ariaLabel: String
});
const mentionDropdownEmits = { select: (option) => (0, _vue_shared.isString)(option.value) };
//#endregion
exports.mentionDropdownEmits = mentionDropdownEmits;
exports.mentionDropdownProps = mentionDropdownProps;
//# sourceMappingURL=mention-dropdown.js.map
@@ -0,0 +1 @@
{"version":3,"file":"mention-dropdown.js","names":["buildProps","definePropType"],"sources":["../../../../../../packages/components/mention/src/mention-dropdown.ts"],"sourcesContent":["import { buildProps, definePropType, isString } from '@element-plus/utils'\n\nimport type { MentionOption } from './types'\n\nexport interface MentionDropdownProps {\n options?: MentionOption[]\n loading?: boolean\n disabled?: boolean\n contentId?: string\n ariaLabel?: string\n}\n\n/**\n * @deprecated Removed after 3.0.0, Use `MentionDropdownProps` instead.\n */\nexport const mentionDropdownProps = buildProps({\n options: {\n type: definePropType<MentionOption[]>(Array),\n default: () => [],\n },\n loading: Boolean,\n disabled: Boolean,\n contentId: String,\n ariaLabel: String,\n})\n\nexport const mentionDropdownEmits = {\n select: (option: MentionOption) => isString(option.value),\n}\n"],"mappings":";;;;;;;;;AAeA,MAAa,uBAAuBA,6BAAW;CAC7C,SAAS;EACP,MAAMC,iCAAgC,MAAM;EAC5C,eAAe,EAAE;EAClB;CACD,SAAS;CACT,UAAU;CACV,WAAW;CACX,WAAW;CACZ,CAAC;AAEF,MAAa,uBAAuB,EAClC,SAAS,qCAAmC,OAAO,MAAM,EAC1D"}
@@ -0,0 +1,148 @@
const require_runtime = require('../../../_virtual/_rolldown/runtime.js');
const require_scroll = require('../../../utils/dom/scroll.js');
const require_index = require('../../../hooks/use-locale/index.js');
const require_index$1 = require('../../../hooks/use-namespace/index.js');
const require_index$2 = require('../../scrollbar/index.js');
const require_mention_dropdown = require('./mention-dropdown.js');
let vue = require("vue");
//#region ../../packages/components/mention/src/mention-dropdown.vue?vue&type=script&setup=true&lang.ts
const _hoisted_1 = [
"id",
"aria-disabled",
"aria-selected",
"onMousemove",
"onClick"
];
var mention_dropdown_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({
name: "ElMentionDropdown",
__name: "mention-dropdown",
props: require_mention_dropdown.mentionDropdownProps,
emits: require_mention_dropdown.mentionDropdownEmits,
setup(__props, { expose: __expose, emit: __emit }) {
const props = __props;
const emit = __emit;
const ns = require_index$1.useNamespace("mention");
const { t } = require_index.useLocale();
const hoveringIndex = (0, vue.ref)(-1);
const scrollbarRef = (0, vue.ref)();
const optionRefs = (0, vue.ref)();
const dropdownRef = (0, vue.ref)();
const optionkls = (item, index) => [
ns.be("dropdown", "item"),
ns.is("hovering", hoveringIndex.value === index),
ns.is("disabled", item.disabled || props.disabled)
];
const handleSelect = (item) => {
if (item.disabled || props.disabled) return;
emit("select", item);
};
const handleMouseEnter = (index) => {
hoveringIndex.value = index;
};
const filteredAllDisabled = (0, vue.computed)(() => props.disabled || props.options.every((item) => item.disabled));
const hoverOption = (0, vue.computed)(() => props.options[hoveringIndex.value]);
const selectHoverOption = () => {
if (!hoverOption.value || hoverOption.value.disabled || props.disabled) return;
emit("select", hoverOption.value);
};
const navigateOptions = (direction) => {
const { options } = props;
if (options.length === 0 || filteredAllDisabled.value) return;
if (direction === "next") {
hoveringIndex.value++;
if (hoveringIndex.value === options.length) hoveringIndex.value = 0;
} else if (direction === "prev") {
hoveringIndex.value--;
if (hoveringIndex.value < 0) hoveringIndex.value = options.length - 1;
}
const option = options[hoveringIndex.value];
if (option.disabled) {
navigateOptions(direction);
return;
}
(0, vue.nextTick)(() => scrollToOption(option));
};
const scrollToOption = (option) => {
const { options } = props;
const index = options.findIndex((item) => item.value === option.value);
const target = optionRefs.value?.[index];
if (target) {
const menu = dropdownRef.value?.querySelector?.(`.${ns.be("dropdown", "wrap")}`);
if (menu) require_scroll.scrollIntoView(menu, target);
}
scrollbarRef.value?.handleScroll();
};
const resetHoveringIndex = () => {
if (filteredAllDisabled.value || props.options.length === 0) hoveringIndex.value = -1;
else hoveringIndex.value = props.options.findIndex((item) => !item.disabled);
};
(0, vue.watch)(() => props.options, resetHoveringIndex, { immediate: true });
__expose({
hoveringIndex,
navigateOptions,
selectHoverOption,
hoverOption
});
return (_ctx, _cache) => {
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
ref_key: "dropdownRef",
ref: dropdownRef,
class: (0, vue.normalizeClass)((0, vue.unref)(ns).b("dropdown"))
}, [
_ctx.$slots.header ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
key: 0,
class: (0, vue.normalizeClass)((0, vue.unref)(ns).be("dropdown", "header"))
}, [(0, vue.renderSlot)(_ctx.$slots, "header")], 2)) : (0, vue.createCommentVNode)("v-if", true),
(0, vue.withDirectives)((0, vue.createVNode)((0, vue.unref)(require_index$2.ElScrollbar), {
id: __props.contentId,
ref_key: "scrollbarRef",
ref: scrollbarRef,
tag: "ul",
"wrap-class": (0, vue.unref)(ns).be("dropdown", "wrap"),
"view-class": (0, vue.unref)(ns).be("dropdown", "list"),
role: "listbox",
"aria-label": __props.ariaLabel,
"aria-orientation": "vertical"
}, {
default: (0, vue.withCtx)(() => [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.options, (item, index) => {
return (0, vue.openBlock)(), (0, vue.createElementBlock)("li", {
id: `${__props.contentId}-${index}`,
ref_for: true,
ref_key: "optionRefs",
ref: optionRefs,
key: index,
class: (0, vue.normalizeClass)(optionkls(item, index)),
role: "option",
"aria-disabled": item.disabled || __props.disabled || void 0,
"aria-selected": hoveringIndex.value === index,
onMousemove: ($event) => handleMouseEnter(index),
onClick: (0, vue.withModifiers)(($event) => handleSelect(item), ["stop"])
}, [(0, vue.renderSlot)(_ctx.$slots, "label", {
item,
index
}, () => [(0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(item.label ?? item.value), 1)])], 42, _hoisted_1);
}), 128))]),
_: 3
}, 8, [
"id",
"wrap-class",
"view-class",
"aria-label"
]), [[vue.vShow, __props.options.length > 0 && !__props.loading]]),
__props.loading ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
key: 1,
class: (0, vue.normalizeClass)((0, vue.unref)(ns).be("dropdown", "loading"))
}, [(0, vue.renderSlot)(_ctx.$slots, "loading", {}, () => [(0, vue.createTextVNode)((0, vue.toDisplayString)((0, vue.unref)(t)("el.mention.loading")), 1)])], 2)) : (0, vue.createCommentVNode)("v-if", true),
_ctx.$slots.footer ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
key: 2,
class: (0, vue.normalizeClass)((0, vue.unref)(ns).be("dropdown", "footer"))
}, [(0, vue.renderSlot)(_ctx.$slots, "footer")], 2)) : (0, vue.createCommentVNode)("v-if", true)
], 2);
};
}
});
//#endregion
exports.default = mention_dropdown_vue_vue_type_script_setup_true_lang_default;
//# sourceMappingURL=mention-dropdown.vue_vue_type_script_setup_true_lang.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,9 @@
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } });
const require_mention_dropdown_vue_vue_type_script_setup_true_lang = require('./mention-dropdown.vue_vue_type_script_setup_true_lang.js');
//#region ../../packages/components/mention/src/mention-dropdown.vue
var mention_dropdown_default = require_mention_dropdown_vue_vue_type_script_setup_true_lang.default;
//#endregion
exports.default = mention_dropdown_default;
//# sourceMappingURL=mention-dropdown2.js.map
@@ -0,0 +1 @@
{"version":3,"file":"mention-dropdown2.js","names":[],"sources":["../../../../../../packages/components/mention/src/mention-dropdown.vue"],"sourcesContent":["<template>\n <div ref=\"dropdownRef\" :class=\"ns.b('dropdown')\">\n <div v-if=\"$slots.header\" :class=\"ns.be('dropdown', 'header')\">\n <slot name=\"header\" />\n </div>\n <el-scrollbar\n v-show=\"options.length > 0 && !loading\"\n :id=\"contentId\"\n ref=\"scrollbarRef\"\n tag=\"ul\"\n :wrap-class=\"ns.be('dropdown', 'wrap')\"\n :view-class=\"ns.be('dropdown', 'list')\"\n role=\"listbox\"\n :aria-label=\"ariaLabel\"\n aria-orientation=\"vertical\"\n >\n <li\n v-for=\"(item, index) in options\"\n :id=\"`${contentId}-${index}`\"\n ref=\"optionRefs\"\n :key=\"index\"\n :class=\"optionkls(item, index)\"\n role=\"option\"\n :aria-disabled=\"item.disabled || disabled || undefined\"\n :aria-selected=\"hoveringIndex === index\"\n @mousemove=\"handleMouseEnter(index)\"\n @click.stop=\"handleSelect(item)\"\n >\n <slot name=\"label\" :item=\"item\" :index=\"index\">\n <span>{{ item.label ?? item.value }}</span>\n </slot>\n </li>\n </el-scrollbar>\n <div v-if=\"loading\" :class=\"ns.be('dropdown', 'loading')\">\n <slot name=\"loading\"> {{ t('el.mention.loading') }} </slot>\n </div>\n <div v-if=\"$slots.footer\" :class=\"ns.be('dropdown', 'footer')\">\n <slot name=\"footer\" />\n </div>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { computed, nextTick, ref, watch } from 'vue'\nimport { useLocale, useNamespace } from '@element-plus/hooks'\nimport { scrollIntoView } from '@element-plus/utils'\nimport ElScrollbar from '@element-plus/components/scrollbar'\nimport { mentionDropdownEmits } from './mention-dropdown'\n\nimport type { MentionDropdownProps } from './mention-dropdown'\nimport type { MentionOption } from './types'\n\ndefineOptions({\n name: 'ElMentionDropdown',\n})\n\nconst props = withDefaults(defineProps<MentionDropdownProps>(), {\n options: () => [],\n})\nconst emit = defineEmits(mentionDropdownEmits)\n\nconst ns = useNamespace('mention')\nconst { t } = useLocale()\nconst hoveringIndex = ref(-1)\n\nconst scrollbarRef = ref<InstanceType<typeof ElScrollbar>>()\nconst optionRefs = ref<HTMLElement[]>()\nconst dropdownRef = ref<HTMLElement>()\n\nconst optionkls = (item: MentionOption, index: number) => [\n ns.be('dropdown', 'item'),\n ns.is('hovering', hoveringIndex.value === index),\n ns.is('disabled', item.disabled || props.disabled),\n]\n\nconst handleSelect = (item: MentionOption) => {\n if (item.disabled || props.disabled) return\n emit('select', item)\n}\n\nconst handleMouseEnter = (index: number) => {\n hoveringIndex.value = index\n}\n\nconst filteredAllDisabled = computed(\n () => props.disabled || props.options.every((item) => item.disabled)\n)\n\nconst hoverOption = computed(() => props.options[hoveringIndex.value])\n\nconst selectHoverOption = () => {\n if (!hoverOption.value || hoverOption.value.disabled || props.disabled) return\n emit('select', hoverOption.value)\n}\n\nconst navigateOptions = (direction: 'next' | 'prev') => {\n const { options } = props\n if (options.length === 0 || filteredAllDisabled.value) return\n\n if (direction === 'next') {\n hoveringIndex.value++\n if (hoveringIndex.value === options.length) {\n hoveringIndex.value = 0\n }\n } else if (direction === 'prev') {\n hoveringIndex.value--\n if (hoveringIndex.value < 0) {\n hoveringIndex.value = options.length - 1\n }\n }\n const option = options[hoveringIndex.value]\n if (option.disabled) {\n navigateOptions(direction)\n return\n }\n nextTick(() => scrollToOption(option))\n}\n\nconst scrollToOption = (option: MentionOption) => {\n const { options } = props\n\n const index = options.findIndex((item) => item.value === option.value)\n const target = optionRefs.value?.[index]\n\n if (target) {\n const menu = dropdownRef.value?.querySelector?.(\n `.${ns.be('dropdown', 'wrap')}`\n )\n if (menu) {\n scrollIntoView(menu as HTMLElement, target)\n }\n }\n scrollbarRef.value?.handleScroll()\n}\n\nconst resetHoveringIndex = () => {\n if (filteredAllDisabled.value || props.options.length === 0) {\n hoveringIndex.value = -1\n } else {\n hoveringIndex.value = props.options.findIndex((item) => !item.disabled)\n }\n}\n\nwatch(() => props.options, resetHoveringIndex, {\n immediate: true,\n})\n\ndefineExpose({\n hoveringIndex,\n navigateOptions,\n selectHoverOption,\n hoverOption,\n})\n</script>\n"],"mappings":""}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,84 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const require_runtime = require('../../../_virtual/_rolldown/runtime.js');
const require_event = require('../../../constants/event.js');
const require_runtime$1 = require('../../../utils/vue/props/runtime.js');
const require_content = require('../../tooltip/src/content.js');
const require_input = require('../../input/src/input.js');
const require_helper = require('./helper.js');
let _vue_shared = require("@vue/shared");
//#region ../../packages/components/mention/src/mention.ts
/**
* @deprecated Removed after 3.0.0, Use `MentionProps` instead.
*/
const mentionProps = require_runtime$1.buildProps({
...require_input.inputProps,
options: {
type: require_runtime$1.definePropType(Array),
default: () => []
},
prefix: {
type: require_runtime$1.definePropType([String, Array]),
default: "@",
validator: (val) => {
if ((0, _vue_shared.isString)(val)) return val.length === 1;
return val.every((v) => (0, _vue_shared.isString)(v) && v.length === 1);
}
},
split: {
type: String,
default: " ",
validator: (val) => val.length === 1
},
filterOption: {
type: require_runtime$1.definePropType([Boolean, Function]),
default: () => require_helper.filterOption,
validator: (val) => {
if (val === false) return true;
return (0, _vue_shared.isFunction)(val);
}
},
placement: {
type: require_runtime$1.definePropType(String),
default: "bottom"
},
showArrow: Boolean,
offset: {
type: Number,
default: 0
},
whole: Boolean,
checkIsWhole: { type: require_runtime$1.definePropType(Function) },
modelValue: String,
loading: Boolean,
popperClass: require_content.useTooltipContentProps.popperClass,
popperStyle: require_content.useTooltipContentProps.popperStyle,
popperOptions: {
type: require_runtime$1.definePropType(Object),
default: () => ({})
},
props: {
type: require_runtime$1.definePropType(Object),
default: () => mentionDefaultProps
}
});
const mentionEmits = {
[require_event.UPDATE_MODEL_EVENT]: (value) => (0, _vue_shared.isString)(value),
"whole-remove": (pattern, prefix) => (0, _vue_shared.isString)(pattern) && (0, _vue_shared.isString)(prefix),
input: (value) => (0, _vue_shared.isString)(value),
search: (pattern, prefix) => (0, _vue_shared.isString)(pattern) && (0, _vue_shared.isString)(prefix),
select: (option, prefix) => (0, _vue_shared.isObject)(option) && (0, _vue_shared.isString)(prefix),
focus: (evt) => evt instanceof FocusEvent,
blur: (evt) => evt instanceof FocusEvent
};
const mentionDefaultProps = {
value: "value",
label: "label",
disabled: "disabled"
};
//#endregion
exports.mentionDefaultProps = mentionDefaultProps;
exports.mentionEmits = mentionEmits;
exports.mentionProps = mentionProps;
//# sourceMappingURL=mention.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,60 @@
import { InputInstance } from "../../input/src/instance.js";
import "../../input/index.js";
import { TooltipInstance } from "../../tooltip/src/tooltip.js";
import "../../tooltip/index.js";
import { MentionOption } from "./types.js";
import { MentionProps } from "./mention.js";
import * as vue from "vue";
//#region ../../packages/components/mention/src/mention.vue.d.ts
declare const __VLS_export: <T extends MentionOption = MentionOption>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
props: vue.PublicProps & __VLS_PrettifyLocal<MentionProps<T> & {
onBlur?: ((evt: FocusEvent) => any) | undefined;
onFocus?: ((evt: FocusEvent) => any) | undefined;
onInput?: ((value: string) => any) | undefined;
onSelect?: ((option: MentionOption, prefix: string) => any) | undefined;
"onUpdate:modelValue"?: ((value: string) => any) | undefined;
onSearch?: ((pattern: string, prefix: string) => any) | undefined;
"onWhole-remove"?: ((pattern: string, prefix: string) => any) | undefined;
}> & (typeof globalThis extends {
__VLS_PROPS_FALLBACK: infer P;
} ? P : {});
expose: (exposed: vue.ShallowUnwrapRef<{
input: vue.Ref<InputInstance | undefined, InputInstance | undefined>;
tooltip: vue.Ref<TooltipInstance | undefined, TooltipInstance | undefined>;
dropdownVisible: vue.ComputedRef<boolean>;
}>) => void;
attrs: any;
slots: Readonly<{
[name: string]: vue.Slot<any> | undefined;
}> & {
prepend?: (props: {}) => any;
} & {
prefix?: (props: {}) => any;
} & {
suffix?: (props: {}) => any;
} & {
'password-icon'?: (props: {
visible: boolean;
}) => any;
} & {
append?: (props: {}) => any;
} & {
header?: () => any;
footer?: () => any;
loading?: () => any;
label?: (props: {
item: T & MentionOption;
index: number;
}) => any;
};
emit: ((event: "blur", evt: FocusEvent) => void) & ((event: "focus", evt: FocusEvent) => void) & ((event: "input", value: string) => void) & ((event: "select", option: MentionOption, prefix: string) => void) & ((event: "update:modelValue", value: string) => void) & ((event: "search", pattern: string, prefix: string) => void) & ((event: "whole-remove", pattern: string, prefix: string) => void);
}>) => vue.VNode<vue.RendererNode, vue.RendererElement, {
[key: string]: any;
}> & {
__ctx?: Awaited<typeof __VLS_setup>;
};
declare const _default: typeof __VLS_export;
type __VLS_PrettifyLocal<T> = (T extends any ? { [K in keyof T]: T[K] } : { [K in keyof T as K]: T[K] }) & {};
//#endregion
export { _default };
@@ -0,0 +1,298 @@
const require_runtime = require('../../../_virtual/_rolldown/runtime.js');
const require_aria = require('../../../constants/aria.js');
const require_event = require('../../../constants/event.js');
const require_event$1 = require('../../../utils/dom/event.js');
const require_index = require('../../../hooks/use-namespace/index.js');
const require_index$1 = require('../../../hooks/use-id/index.js');
const require_index$2 = require('../../../hooks/use-focus-controller/index.js');
const require_use_form_common_props = require('../../form/src/hooks/use-form-common-props.js');
const require_index$3 = require('../../tooltip/index.js');
const require_index$4 = require('../../input/index.js');
const require_helper = require('./helper.js');
const require_mention = require('./mention.js');
const require_mention_dropdown = require('./mention-dropdown2.js');
let lodash_unified = require("lodash-unified");
let vue = require("vue");
let _vue_shared = require("@vue/shared");
//#region ../../packages/components/mention/src/mention.vue?vue&type=script&setup=true&lang.ts
var mention_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({
name: "ElMention",
inheritAttrs: false,
__name: "mention",
props: require_mention.mentionProps,
emits: require_mention.mentionEmits,
setup(__props, { expose: __expose, emit: __emit }) {
const props = __props;
const emit = __emit;
const passInputProps = (0, vue.computed)(() => {
const inputProps = require_index$4.ElInput.props ?? [];
return (0, lodash_unified.pick)(props, (0, _vue_shared.isArray)(inputProps) ? inputProps : Object.keys(inputProps));
});
const ns = require_index.useNamespace("mention");
const disabled = require_use_form_common_props.useFormDisabled();
const contentId = require_index$1.useId();
const elInputRef = (0, vue.ref)();
const tooltipRef = (0, vue.ref)();
const dropdownRef = (0, vue.ref)();
const visible = (0, vue.ref)(false);
const cursorStyle = (0, vue.ref)();
const mentionCtx = (0, vue.ref)();
const computedPlacement = (0, vue.computed)(() => props.showArrow ? props.placement : `${props.placement}-start`);
const computedFallbackPlacements = (0, vue.computed)(() => props.showArrow ? ["bottom", "top"] : ["bottom-start", "top-start"]);
const aliasProps = (0, vue.computed)(() => ({
...require_mention.mentionDefaultProps,
...props.props
}));
const mapOption = (option) => {
const base = {
label: option[aliasProps.value.label],
value: option[aliasProps.value.value],
disabled: option[aliasProps.value.disabled]
};
return {
...option,
...base
};
};
const options = (0, vue.computed)(() => props.options.map(mapOption));
const filteredOptions = (0, vue.computed)(() => {
const { filterOption } = props;
if (!mentionCtx.value || !filterOption) return options.value;
return options.value.filter((option) => filterOption(mentionCtx.value.pattern, option));
});
const dropdownVisible = (0, vue.computed)(() => {
return visible.value && (!!filteredOptions.value.length || props.loading);
});
const hoveringId = (0, vue.computed)(() => {
return `${contentId.value}-${dropdownRef.value?.hoveringIndex}`;
});
const handleInputChange = (value) => {
emit(require_event.UPDATE_MODEL_EVENT, value);
emit(require_event.INPUT_EVENT, value);
syncAfterCursorMove();
};
const handleInputKeyDown = (event) => {
if (elInputRef.value?.isComposing) return;
const code = require_event$1.getEventCode(event);
switch (code) {
case require_aria.EVENT_CODE.left:
case require_aria.EVENT_CODE.right:
syncAfterCursorMove();
break;
case require_aria.EVENT_CODE.up:
case require_aria.EVENT_CODE.down:
if (!visible.value) return;
event.preventDefault();
dropdownRef.value?.navigateOptions(code === require_aria.EVENT_CODE.up ? "prev" : "next");
break;
case require_aria.EVENT_CODE.enter:
case require_aria.EVENT_CODE.numpadEnter:
if (!visible.value) {
props.type !== "textarea" && syncAfterCursorMove();
return;
}
event.preventDefault();
if (dropdownRef.value?.hoverOption) dropdownRef.value?.selectHoverOption();
else visible.value = false;
break;
case require_aria.EVENT_CODE.esc:
if (!visible.value) return;
event.preventDefault();
visible.value = false;
break;
case require_aria.EVENT_CODE.backspace: if (props.whole && mentionCtx.value) {
const { splitIndex, selectionEnd, pattern, prefixIndex, prefix } = mentionCtx.value;
const inputEl = getInputEl();
if (!inputEl) return;
const inputValue = inputEl.value;
const matchOption = options.value.find((item) => item.value === pattern);
if (((0, _vue_shared.isFunction)(props.checkIsWhole) ? props.checkIsWhole(pattern, prefix) : matchOption) && splitIndex !== -1 && splitIndex + 1 === selectionEnd) {
event.preventDefault();
const newValue = inputValue.slice(0, prefixIndex) + inputValue.slice(splitIndex + 1);
emit(require_event.UPDATE_MODEL_EVENT, newValue);
emit(require_event.INPUT_EVENT, newValue);
emit("whole-remove", pattern, prefix);
const newSelectionEnd = prefixIndex;
(0, vue.nextTick)(() => {
inputEl.selectionStart = newSelectionEnd;
inputEl.selectionEnd = newSelectionEnd;
syncDropdownVisible();
});
}
}
}
};
const { wrapperRef } = require_index$2.useFocusController(elInputRef, {
disabled,
afterFocus() {
syncAfterCursorMove();
},
beforeBlur(event) {
return tooltipRef.value?.isFocusInsideContent(event);
},
afterBlur() {
visible.value = false;
}
});
const handleInputMouseDown = () => {
syncAfterCursorMove();
};
const getOriginalOption = (mentionOption) => {
return props.options.find((option) => {
return mentionOption.value === option[aliasProps.value.value];
});
};
const handleSelect = (item) => {
if (!mentionCtx.value) return;
const inputEl = getInputEl();
if (!inputEl) return;
const inputValue = inputEl.value;
const { split } = props;
const newEndPart = inputValue.slice(mentionCtx.value.end);
const alreadySeparated = newEndPart.startsWith(split);
const newMiddlePart = `${item.value}${alreadySeparated ? "" : split}`;
const newValue = inputValue.slice(0, mentionCtx.value.start) + newMiddlePart + newEndPart;
emit(require_event.UPDATE_MODEL_EVENT, newValue);
emit(require_event.INPUT_EVENT, newValue);
emit("select", getOriginalOption(item), mentionCtx.value.prefix);
const newSelectionEnd = mentionCtx.value.start + newMiddlePart.length + (alreadySeparated ? 1 : 0);
(0, vue.nextTick)(() => {
inputEl.selectionStart = newSelectionEnd;
inputEl.selectionEnd = newSelectionEnd;
inputEl.focus();
syncDropdownVisible();
});
};
const getInputEl = () => props.type === "textarea" ? elInputRef.value?.textarea : elInputRef.value?.input;
const syncAfterCursorMove = () => {
setTimeout(() => {
syncCursor();
syncDropdownVisible();
(0, vue.nextTick)(() => tooltipRef.value?.updatePopper());
}, 0);
};
const syncCursor = () => {
const inputEl = getInputEl();
if (!inputEl) return;
const caretPosition = require_helper.getCursorPosition(inputEl);
const inputRect = inputEl.getBoundingClientRect();
const wrapperRect = wrapperRef.value.getBoundingClientRect();
cursorStyle.value = {
position: "absolute",
width: 0,
height: `${caretPosition.height}px`,
left: `${caretPosition.left + inputRect.left - wrapperRect.left}px`,
top: `${caretPosition.top + inputRect.top - wrapperRect.top}px`
};
};
const syncDropdownVisible = () => {
const inputEl = getInputEl();
if (document.activeElement !== inputEl) {
visible.value = false;
return;
}
const { prefix, split } = props;
mentionCtx.value = require_helper.getMentionCtx(inputEl, prefix, split);
if (mentionCtx.value && mentionCtx.value.splitIndex === -1) {
visible.value = true;
emit("search", mentionCtx.value.pattern, mentionCtx.value.prefix);
return;
}
visible.value = false;
};
__expose({
input: elInputRef,
tooltip: tooltipRef,
dropdownVisible
});
return (_ctx, _cache) => {
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
ref_key: "wrapperRef",
ref: wrapperRef,
class: (0, vue.normalizeClass)((0, vue.unref)(ns).b())
}, [(0, vue.createVNode)((0, vue.unref)(require_index$4.ElInput), (0, vue.mergeProps)((0, vue.mergeProps)(passInputProps.value, _ctx.$attrs), {
ref_key: "elInputRef",
ref: elInputRef,
"model-value": __props.modelValue,
disabled: (0, vue.unref)(disabled),
role: dropdownVisible.value ? "combobox" : void 0,
"aria-activedescendant": dropdownVisible.value ? hoveringId.value || "" : void 0,
"aria-controls": dropdownVisible.value ? (0, vue.unref)(contentId) : void 0,
"aria-expanded": dropdownVisible.value || void 0,
"aria-label": __props.ariaLabel,
"aria-autocomplete": dropdownVisible.value ? "none" : void 0,
"aria-haspopup": dropdownVisible.value ? "listbox" : void 0,
onInput: handleInputChange,
onKeydown: handleInputKeyDown,
onMousedown: handleInputMouseDown
}), (0, vue.createSlots)({ _: 2 }, [(0, vue.renderList)(_ctx.$slots, (_, name) => {
return {
name,
fn: (0, vue.withCtx)((slotProps) => [(0, vue.renderSlot)(_ctx.$slots, name, (0, vue.normalizeProps)((0, vue.guardReactiveProps)(slotProps)))])
};
})]), 1040, [
"model-value",
"disabled",
"role",
"aria-activedescendant",
"aria-controls",
"aria-expanded",
"aria-label",
"aria-autocomplete",
"aria-haspopup"
]), (0, vue.createVNode)((0, vue.unref)(require_index$3.ElTooltip), {
ref_key: "tooltipRef",
ref: tooltipRef,
visible: dropdownVisible.value,
"popper-class": [(0, vue.unref)(ns).e("popper"), __props.popperClass],
"popper-style": __props.popperStyle,
"popper-options": __props.popperOptions,
placement: computedPlacement.value,
"fallback-placements": computedFallbackPlacements.value,
effect: "light",
pure: "",
offset: __props.offset,
"show-arrow": __props.showArrow
}, {
default: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("div", { style: (0, vue.normalizeStyle)(cursorStyle.value) }, null, 4)]),
content: (0, vue.withCtx)(() => [(0, vue.createVNode)(require_mention_dropdown.default, {
ref_key: "dropdownRef",
ref: dropdownRef,
options: filteredOptions.value,
disabled: (0, vue.unref)(disabled),
loading: __props.loading,
"content-id": (0, vue.unref)(contentId),
"aria-label": __props.ariaLabel,
onSelect: handleSelect,
onClick: _cache[0] || (_cache[0] = (0, vue.withModifiers)(($event) => elInputRef.value?.focus(), ["stop"]))
}, (0, vue.createSlots)({ _: 2 }, [(0, vue.renderList)(_ctx.$slots, (_, name) => {
return {
name,
fn: (0, vue.withCtx)((slotProps) => [(0, vue.renderSlot)(_ctx.$slots, name, (0, vue.normalizeProps)((0, vue.guardReactiveProps)(slotProps)))])
};
})]), 1032, [
"options",
"disabled",
"loading",
"content-id",
"aria-label"
])]),
_: 3
}, 8, [
"visible",
"popper-class",
"popper-style",
"popper-options",
"placement",
"fallback-placements",
"offset",
"show-arrow"
])], 2);
};
}
});
//#endregion
exports.default = mention_vue_vue_type_script_setup_true_lang_default;
//# sourceMappingURL=mention.vue_vue_type_script_setup_true_lang.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,9 @@
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } });
const require_mention_vue_vue_type_script_setup_true_lang = require('./mention.vue_vue_type_script_setup_true_lang.js');
//#region ../../packages/components/mention/src/mention.vue
var mention_default = require_mention_vue_vue_type_script_setup_true_lang.default;
//#endregion
exports.default = mention_default;
//# sourceMappingURL=mention2.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,9 @@
//#region ../../packages/components/mention/src/types.d.ts
type MentionOption = {
value?: string;
label?: string;
disabled?: boolean;
[key: string]: any;
};
//#endregion
export { MentionOption };
@@ -0,0 +1 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
@@ -0,0 +1,6 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
require('../../base/style/css.js');
require('../../input/style/css.js');
require('../../scrollbar/style/css.js');
require('../../tooltip/style/css.js');
require("element-plus/theme-chalk/el-mention.css");
@@ -0,0 +1,6 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
require('../../base/style/index.js');
require('../../input/style/index.js');
require('../../scrollbar/style/index.js');
require('../../tooltip/style/index.js');
require("element-plus/theme-chalk/src/mention.scss");