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
+13
View File
@@ -0,0 +1,13 @@
import { SFCWithInstall } from "../../utils/vue/typescript.js";
import "../../utils/index.js";
import { AnchorEmits, AnchorInstance, AnchorProps, AnchorPropsPublic, anchorEmits, anchorProps } from "./src/anchor.js";
import { _default } from "./src/anchor.vue.js";
import { _default as _default$1 } from "./src/anchor-link.vue.js";
//#region ../../packages/components/anchor/index.d.ts
declare const ElAnchor: SFCWithInstall<typeof _default> & {
AnchorLink: typeof _default$1;
};
declare const ElAnchorLink: SFCWithInstall<typeof _default$1>;
//#endregion
export { AnchorEmits, AnchorInstance, AnchorProps, AnchorPropsPublic, ElAnchor, ElAnchor as default, ElAnchorLink, anchorEmits, anchorProps };
+12
View File
@@ -0,0 +1,12 @@
import { withInstall, withNoopInstall } from "../../utils/vue/install.mjs";
import { anchorEmits, anchorProps } from "./src/anchor.mjs";
import anchor_default from "./src/anchor2.mjs";
import anchor_link_default from "./src/anchor-link2.mjs";
//#region ../../packages/components/anchor/index.ts
const ElAnchor = withInstall(anchor_default, { AnchorLink: anchor_link_default });
const ElAnchorLink = withNoopInstall(anchor_link_default);
//#endregion
export { ElAnchor, ElAnchor as default, ElAnchorLink, anchorEmits, anchorProps };
//# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"index.mjs","names":["Anchor","AnchorLink"],"sources":["../../../../../packages/components/anchor/index.ts"],"sourcesContent":["import { withInstall, withNoopInstall } from '@element-plus/utils'\nimport Anchor from './src/anchor.vue'\nimport AnchorLink from './src/anchor-link.vue'\n\nimport type { SFCWithInstall } from '@element-plus/utils'\n\nexport const ElAnchor: SFCWithInstall<typeof Anchor> & {\n AnchorLink: typeof AnchorLink\n} = withInstall(Anchor, {\n AnchorLink,\n})\nexport const ElAnchorLink: SFCWithInstall<typeof AnchorLink> =\n withNoopInstall(AnchorLink)\nexport default ElAnchor\n\nexport * from './src/anchor'\n"],"mappings":";;;;;;AAMA,MAAa,WAET,YAAYA,gBAAQ,EACtB,iCACD,CAAC;AACF,MAAa,eACX,gBAAgBC,oBAAW"}
@@ -0,0 +1,15 @@
import { ExtractPublicPropTypes } from "vue";
//#region ../../packages/components/anchor/src/anchor-link.d.ts
interface AnchorLinkProps {
/**
* @description the text content of the anchor link
*/
title?: string;
/**
* @description The address of the anchor link
*/
href?: string;
}
//#endregion
export { AnchorLinkProps };
@@ -0,0 +1,14 @@
import { buildProps } from "../../../utils/vue/props/runtime.mjs";
//#region ../../packages/components/anchor/src/anchor-link.ts
/**
* @deprecated Removed after 3.0.0, Use `AnchorLinkProps` instead.
*/
const anchorLinkProps = buildProps({
title: String,
href: String
});
//#endregion
export { anchorLinkProps };
//# sourceMappingURL=anchor-link.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"anchor-link.mjs","names":[],"sources":["../../../../../../packages/components/anchor/src/anchor-link.ts"],"sourcesContent":["import { buildProps } from '@element-plus/utils'\n\nimport type { ExtractPublicPropTypes } from 'vue'\n\nexport interface AnchorLinkProps {\n /**\n * @description the text content of the anchor link\n */\n title?: string\n /**\n * @description The address of the anchor link\n */\n href?: string\n}\n\n/**\n * @deprecated Removed after 3.0.0, Use `AnchorLinkProps` instead.\n */\nexport const anchorLinkProps = buildProps({\n /**\n * @description the text content of the anchor link\n */\n title: String,\n /**\n * @description The address of the anchor link\n */\n href: String,\n})\n\n/**\n * @deprecated Removed after 3.0.0, Use `AnchorLinkProps` instead.\n */\nexport type AnchorLinkPropsPublic = ExtractPublicPropTypes<\n typeof anchorLinkProps\n>\n"],"mappings":";;;;;;AAkBA,MAAa,kBAAkB,WAAW;CAIxC,OAAO;CAIP,MAAM;CACP,CAAC"}
@@ -0,0 +1,20 @@
import { AnchorLinkProps } from "./anchor-link.js";
import * as vue from "vue";
//#region ../../packages/components/anchor/src/anchor-link.vue.d.ts
declare var __VLS_1: {}, __VLS_3: {};
type __VLS_Slots = {} & {
default?: (props: typeof __VLS_1) => any;
} & {
'sub-link'?: (props: typeof __VLS_3) => any;
};
declare const __VLS_base: vue.DefineComponent<AnchorLinkProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<AnchorLinkProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
declare const _default: typeof __VLS_export;
type __VLS_WithSlots<T, S> = T & {
new (): {
$slots: S;
};
};
//#endregion
export { _default };
@@ -0,0 +1,56 @@
import { anchorKey } from "./constants.mjs";
import { anchorLinkProps } from "./anchor-link.mjs";
import { computed, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, defineComponent, inject, nextTick, normalizeClass, onBeforeUnmount, onMounted, openBlock, ref, renderSlot, toDisplayString, unref, watch } from "vue";
//#region ../../packages/components/anchor/src/anchor-link.vue?vue&type=script&setup=true&lang.ts
const _hoisted_1 = ["href"];
var anchor_link_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
name: "ElAnchorLink",
__name: "anchor-link",
props: anchorLinkProps,
setup(__props) {
const props = __props;
const linkRef = ref(null);
const { ns, direction, currentAnchor, addLink, removeLink, handleClick: contextHandleClick } = inject(anchorKey);
const cls = computed(() => [ns.e("link"), ns.is("active", currentAnchor.value === props.href)]);
const handleClick = (e) => {
contextHandleClick(e, props.href);
};
watch(() => props.href, (val, oldVal) => {
nextTick(() => {
if (oldVal) removeLink(oldVal);
if (val) addLink({
href: val,
el: linkRef.value
});
});
});
onMounted(() => {
const { href } = props;
if (href) addLink({
href,
el: linkRef.value
});
});
onBeforeUnmount(() => {
const { href } = props;
if (href) removeLink(href);
});
return (_ctx, _cache) => {
return openBlock(), createElementBlock("div", { class: normalizeClass(unref(ns).e("item")) }, [createElementVNode("a", {
ref_key: "linkRef",
ref: linkRef,
class: normalizeClass(cls.value),
href: __props.href,
onClick: handleClick
}, [renderSlot(_ctx.$slots, "default", {}, () => [createTextVNode(toDisplayString(__props.title), 1)])], 10, _hoisted_1), _ctx.$slots["sub-link"] && unref(direction) === "vertical" ? (openBlock(), createElementBlock("div", {
key: 0,
class: normalizeClass(unref(ns).e("list"))
}, [renderSlot(_ctx.$slots, "sub-link")], 2)) : createCommentVNode("v-if", true)], 2);
};
}
});
//#endregion
export { anchor_link_vue_vue_type_script_setup_true_lang_default as default };
//# sourceMappingURL=anchor-link.vue_vue_type_script_setup_true_lang.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"anchor-link.vue_vue_type_script_setup_true_lang.mjs","names":["$slots"],"sources":["../../../../../../packages/components/anchor/src/anchor-link.vue"],"sourcesContent":["<template>\n <div :class=\"ns.e('item')\">\n <a ref=\"linkRef\" :class=\"cls\" :href=\"href\" @click=\"handleClick\">\n <slot>{{ title }}</slot>\n </a>\n <div\n v-if=\"$slots['sub-link'] && direction === 'vertical'\"\n :class=\"ns.e('list')\"\n >\n <slot name=\"sub-link\" />\n </div>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport {\n computed,\n inject,\n nextTick,\n onBeforeUnmount,\n onMounted,\n ref,\n watch,\n} from 'vue'\nimport { anchorKey } from './constants'\n\nimport type { AnchorLinkProps } from './anchor-link'\n\ndefineOptions({\n name: 'ElAnchorLink',\n})\n\nconst props = defineProps<AnchorLinkProps>()\n\nconst linkRef = ref<HTMLElement | null>(null)\n\nconst {\n ns,\n direction,\n currentAnchor,\n addLink,\n removeLink,\n handleClick: contextHandleClick,\n} = inject(anchorKey)!\n\nconst cls = computed(() => [\n ns.e('link'),\n ns.is('active', currentAnchor.value === props.href),\n])\n\nconst handleClick = (e: MouseEvent) => {\n contextHandleClick(e, props.href)\n}\n\nwatch(\n () => props.href,\n (val, oldVal) => {\n nextTick(() => {\n if (oldVal) removeLink(oldVal)\n if (val) {\n addLink({\n href: val,\n el: linkRef.value!,\n })\n }\n })\n }\n)\n\nonMounted(() => {\n const { href } = props\n if (href) {\n addLink({\n href,\n el: linkRef.value!,\n })\n }\n})\n\nonBeforeUnmount(() => {\n const { href } = props\n if (href) {\n removeLink(href)\n }\n})\n</script>\n"],"mappings":";;;;;;;;;;;EAgCA,MAAM,QAAQ;EAEd,MAAM,UAAU,IAAwB,KAAI;EAE5C,MAAM,EACJ,IACA,WACA,eACA,SACA,YACA,aAAa,uBACX,OAAO,UAAU;EAErB,MAAM,MAAM,eAAe,CACzB,GAAG,EAAE,OAAO,EACZ,GAAG,GAAG,UAAU,cAAc,UAAU,MAAM,KAAK,CACpD,CAAA;EAED,MAAM,eAAe,MAAkB;AACrC,sBAAmB,GAAG,MAAM,KAAI;;AAGlC,cACQ,MAAM,OACX,KAAK,WAAW;AACf,kBAAe;AACb,QAAI,OAAQ,YAAW,OAAM;AAC7B,QAAI,IACF,SAAQ;KACN,MAAM;KACN,IAAI,QAAQ;KACb,CAAA;KAEJ;IAEL;AAEA,kBAAgB;GACd,MAAM,EAAE,SAAS;AACjB,OAAI,KACF,SAAQ;IACN;IACA,IAAI,QAAQ;IACb,CAAA;IAEJ;AAED,wBAAsB;GACpB,MAAM,EAAE,SAAS;AACjB,OAAI,KACF,YAAW,KAAI;IAElB;;uBAnFC,mBAUM,OAAA,EAVA,OAAK,eAAE,MAAA,GAAE,CAAC,EAAC,OAAA,CAAA,KACf,mBAEI,KAAA;aAFG;IAAJ,KAAI;IAAW,OAAK,eAAE,IAAA,MAAG;IAAG,MAAM,QAAA;IAAO,SAAO;OACjD,WAAwB,KAAA,QAAA,WAAA,EAAA,QAAA,iCAAf,QAAA,MAAK,EAAA,EAAA,sBAGRA,KAAAA,OAAM,eAAgB,MAAA,UAAS,KAAA,2BADvC,mBAKM,OAAA;;IAHH,OAAK,eAAE,MAAA,GAAE,CAAC,EAAC,OAAA,CAAA;OAEZ,WAAwB,KAAA,QAAA,WAAA"}
@@ -0,0 +1,8 @@
import anchor_link_vue_vue_type_script_setup_true_lang_default from "./anchor-link.vue_vue_type_script_setup_true_lang.mjs";
//#region ../../packages/components/anchor/src/anchor-link.vue
var anchor_link_default = anchor_link_vue_vue_type_script_setup_true_lang_default;
//#endregion
export { anchor_link_default as default };
//# sourceMappingURL=anchor-link2.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"anchor-link2.mjs","names":[],"sources":["../../../../../../packages/components/anchor/src/anchor-link.vue"],"sourcesContent":["<template>\n <div :class=\"ns.e('item')\">\n <a ref=\"linkRef\" :class=\"cls\" :href=\"href\" @click=\"handleClick\">\n <slot>{{ title }}</slot>\n </a>\n <div\n v-if=\"$slots['sub-link'] && direction === 'vertical'\"\n :class=\"ns.e('list')\"\n >\n <slot name=\"sub-link\" />\n </div>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport {\n computed,\n inject,\n nextTick,\n onBeforeUnmount,\n onMounted,\n ref,\n watch,\n} from 'vue'\nimport { anchorKey } from './constants'\n\nimport type { AnchorLinkProps } from './anchor-link'\n\ndefineOptions({\n name: 'ElAnchorLink',\n})\n\nconst props = defineProps<AnchorLinkProps>()\n\nconst linkRef = ref<HTMLElement | null>(null)\n\nconst {\n ns,\n direction,\n currentAnchor,\n addLink,\n removeLink,\n handleClick: contextHandleClick,\n} = inject(anchorKey)!\n\nconst cls = computed(() => [\n ns.e('link'),\n ns.is('active', currentAnchor.value === props.href),\n])\n\nconst handleClick = (e: MouseEvent) => {\n contextHandleClick(e, props.href)\n}\n\nwatch(\n () => props.href,\n (val, oldVal) => {\n nextTick(() => {\n if (oldVal) removeLink(oldVal)\n if (val) {\n addLink({\n href: val,\n el: linkRef.value!,\n })\n }\n })\n }\n)\n\nonMounted(() => {\n const { href } = props\n if (href) {\n addLink({\n href,\n el: linkRef.value!,\n })\n }\n})\n\nonBeforeUnmount(() => {\n const { href } = props\n if (href) {\n removeLink(href)\n }\n})\n</script>\n"],"mappings":""}
@@ -0,0 +1,71 @@
import { EpPropFinalized, EpPropMergeType } from "../../../utils/vue/props/types.js";
import "../../../utils/index.js";
import { _default } from "./anchor.vue.js";
import * as vue from "vue";
import { ExtractPublicPropTypes } from "vue";
//#region ../../packages/components/anchor/src/anchor.d.ts
interface AnchorProps {
/**
* @description scroll container
*/
container?: string | HTMLElement | Window | null;
/**
* @description Set the offset of the anchor scroll
*/
offset?: number;
/**
* @description The offset of the element starting to trigger the anchor
*/
bound?: number;
/**
* @description Set the scroll duration of the container when the anchor is clicked, in milliseconds
*/
duration?: number;
/**
* @description Whether to show the marker
*/
marker?: boolean;
/**
* @description Set Anchor type
*/
type?: 'default' | 'underline';
/**
* @description Set Anchor direction
*/
direction?: 'vertical' | 'horizontal';
/**
* @description Scroll whether link is selected at the top
*/
selectScrollTop?: boolean;
}
/**
* @deprecated Removed after 3.0.0, Use `AnchorProps` instead.
*/
declare const anchorProps: {
container: {
readonly type: vue.PropType<EpPropMergeType<(new (...args: any[]) => string | HTMLElement | Window) | (() => string | HTMLElement | Window | null) | (((new (...args: any[]) => string | HTMLElement | Window) | (() => string | HTMLElement | Window | null)) | null)[], unknown, unknown>>;
readonly required: false;
readonly validator: ((val: unknown) => boolean) | undefined;
__epPropKey: true;
};
offset: EpPropFinalized<NumberConstructor, unknown, unknown, number, boolean>;
bound: EpPropFinalized<NumberConstructor, unknown, unknown, number, boolean>;
duration: EpPropFinalized<NumberConstructor, unknown, unknown, number, boolean>;
marker: EpPropFinalized<BooleanConstructor, unknown, unknown, boolean, boolean>;
type: EpPropFinalized<(new (...args: any[]) => "default" | "underline") | (() => "default" | "underline") | (((new (...args: any[]) => "default" | "underline") | (() => "default" | "underline")) | null)[], unknown, unknown, string, boolean>;
direction: EpPropFinalized<(new (...args: any[]) => "horizontal" | "vertical") | (() => "horizontal" | "vertical") | (((new (...args: any[]) => "horizontal" | "vertical") | (() => "horizontal" | "vertical")) | null)[], unknown, unknown, string, boolean>;
selectScrollTop: BooleanConstructor;
};
/**
* @deprecated Removed after 3.0.0, Use `AnchorProps` instead.
*/
type AnchorPropsPublic = ExtractPublicPropTypes<typeof anchorProps>;
type AnchorInstance = InstanceType<typeof _default> & unknown;
declare const anchorEmits: {
change: (href: string) => boolean;
click: (e: MouseEvent, href?: string) => boolean;
};
type AnchorEmits = typeof anchorEmits;
//#endregion
export { AnchorEmits, AnchorInstance, AnchorProps, AnchorPropsPublic, anchorEmits, anchorProps };
+43
View File
@@ -0,0 +1,43 @@
import { isString, isUndefined } from "../../../utils/types.mjs";
import { buildProps, definePropType } from "../../../utils/vue/props/runtime.mjs";
//#region ../../packages/components/anchor/src/anchor.ts
/**
* @deprecated Removed after 3.0.0, Use `AnchorProps` instead.
*/
const anchorProps = buildProps({
container: { type: definePropType([String, Object]) },
offset: {
type: Number,
default: 0
},
bound: {
type: Number,
default: 15
},
duration: {
type: Number,
default: 300
},
marker: {
type: Boolean,
default: true
},
type: {
type: definePropType(String),
default: "default"
},
direction: {
type: definePropType(String),
default: "vertical"
},
selectScrollTop: Boolean
});
const anchorEmits = {
change: (href) => isString(href),
click: (e, href) => e instanceof MouseEvent && (isString(href) || isUndefined(href))
};
//#endregion
export { anchorEmits, anchorProps };
//# sourceMappingURL=anchor.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"anchor.mjs","names":[],"sources":["../../../../../../packages/components/anchor/src/anchor.ts"],"sourcesContent":["import {\n buildProps,\n definePropType,\n isString,\n isUndefined,\n} from '@element-plus/utils'\n\nimport type { ExtractPublicPropTypes } from 'vue'\nimport type Anchor from './anchor.vue'\n\nexport interface AnchorProps {\n /**\n * @description scroll container\n */\n container?: string | HTMLElement | Window | null\n /**\n * @description Set the offset of the anchor scroll\n */\n offset?: number\n /**\n * @description The offset of the element starting to trigger the anchor\n */\n bound?: number\n /**\n * @description Set the scroll duration of the container when the anchor is clicked, in milliseconds\n */\n duration?: number\n /**\n * @description Whether to show the marker\n */\n marker?: boolean\n /**\n * @description Set Anchor type\n */\n type?: 'default' | 'underline'\n /**\n * @description Set Anchor direction\n */\n direction?: 'vertical' | 'horizontal'\n /**\n * @description Scroll whether link is selected at the top\n */\n selectScrollTop?: boolean\n}\n\n/**\n * @deprecated Removed after 3.0.0, Use `AnchorProps` instead.\n */\nexport const anchorProps = buildProps({\n /**\n * @description scroll container\n */\n container: {\n type: definePropType<string | HTMLElement | Window | null>([\n String,\n Object,\n ]),\n },\n /**\n * @description Set the offset of the anchor scroll\n */\n offset: {\n type: Number,\n default: 0,\n },\n /**\n * @description The offset of the element starting to trigger the anchor\n */\n bound: {\n type: Number,\n default: 15,\n },\n /**\n * @description Set the scroll duration of the container when the anchor is clicked, in milliseconds\n */\n duration: {\n type: Number,\n default: 300,\n },\n /**\n * @description Whether to show the marker\n */\n marker: {\n type: Boolean,\n default: true,\n },\n /**\n * @description Set Anchor type\n */\n type: {\n type: definePropType<'default' | 'underline'>(String),\n default: 'default',\n },\n /**\n * @description Set Anchor direction\n */\n direction: {\n type: definePropType<'vertical' | 'horizontal'>(String),\n default: 'vertical',\n },\n /**\n * @description Scroll whether link is selected at the top\n */\n selectScrollTop: Boolean,\n})\n\n/**\n * @deprecated Removed after 3.0.0, Use `AnchorProps` instead.\n */\nexport type AnchorPropsPublic = ExtractPublicPropTypes<typeof anchorProps>\nexport type AnchorInstance = InstanceType<typeof Anchor> & unknown\n\nexport const anchorEmits = {\n change: (href: string) => isString(href),\n click: (e: MouseEvent, href?: string) =>\n e instanceof MouseEvent && (isString(href) || isUndefined(href)),\n}\nexport type AnchorEmits = typeof anchorEmits\n"],"mappings":";;;;;;;AAgDA,MAAa,cAAc,WAAW;CAIpC,WAAW,EACT,MAAM,eAAqD,CACzD,QACA,OACD,CAAC,EACH;CAID,QAAQ;EACN,MAAM;EACN,SAAS;EACV;CAID,OAAO;EACL,MAAM;EACN,SAAS;EACV;CAID,UAAU;EACR,MAAM;EACN,SAAS;EACV;CAID,QAAQ;EACN,MAAM;EACN,SAAS;EACV;CAID,MAAM;EACJ,MAAM,eAAwC,OAAO;EACrD,SAAS;EACV;CAID,WAAW;EACT,MAAM,eAA0C,OAAO;EACvD,SAAS;EACV;CAID,iBAAiB;CAClB,CAAC;AAQF,MAAa,cAAc;CACzB,SAAS,SAAiB,SAAS,KAAK;CACxC,QAAQ,GAAe,SACrB,aAAa,eAAe,SAAS,KAAK,IAAI,YAAY,KAAK;CAClE"}
@@ -0,0 +1,33 @@
import { AnchorProps } from "./anchor.js";
import * as vue from "vue";
//#region ../../packages/components/anchor/src/anchor.vue.d.ts
declare var __VLS_1: {};
type __VLS_Slots = {} & {
default?: (props: typeof __VLS_1) => any;
};
declare const __VLS_base: vue.DefineComponent<AnchorProps, {
scrollTo: (href?: string) => void;
}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {
change: (href: string) => void;
click: (e: MouseEvent, href?: string | undefined) => void;
}, string, vue.PublicProps, Readonly<AnchorProps> & Readonly<{
onChange?: ((href: string) => any) | undefined;
onClick?: ((e: MouseEvent, href?: string | undefined) => any) | undefined;
}>, {
offset: number;
type: "default" | "underline";
direction: "vertical" | "horizontal";
marker: boolean;
duration: number;
bound: number;
}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
declare const _default: typeof __VLS_export;
type __VLS_WithSlots<T, S> = T & {
new (): {
$slots: S;
};
};
//#endregion
export { _default };
@@ -0,0 +1,178 @@
import { CHANGE_EVENT } from "../../../constants/event.mjs";
import { getOffsetTopDistance } from "../../../utils/dom/position.mjs";
import { isUndefined, isWindow } from "../../../utils/types.mjs";
import { animateScrollTo, getScrollElement, getScrollTop } from "../../../utils/dom/scroll.mjs";
import { getElement } from "../../../utils/dom/element.mjs";
import { throttleByRaf } from "../../../utils/throttleByRaf.mjs";
import { useNamespace } from "../../../hooks/use-namespace/index.mjs";
import { anchorEmits, anchorProps } from "./anchor.mjs";
import { anchorKey } from "./constants.mjs";
import { useEventListener } from "@vueuse/core";
import { computed, createCommentVNode, createElementBlock, createElementVNode, defineComponent, nextTick, normalizeClass, normalizeStyle, onMounted, openBlock, provide, ref, renderSlot, unref, useSlots, watch } from "vue";
//#region ../../packages/components/anchor/src/anchor.vue?vue&type=script&setup=true&lang.ts
var anchor_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
name: "ElAnchor",
__name: "anchor",
props: anchorProps,
emits: anchorEmits,
setup(__props, { expose: __expose, emit: __emit }) {
const props = __props;
const emit = __emit;
const slots = useSlots();
const currentAnchor = ref("");
const markerStyle = ref({});
const anchorRef = ref(null);
const markerRef = ref(null);
const containerEl = ref();
const links = {};
let isScrolling = false;
let currentScrollTop = 0;
const ns = useNamespace("anchor");
const cls = computed(() => [
ns.b(),
props.type === "underline" ? ns.m("underline") : "",
ns.m(props.direction)
]);
const addLink = (state) => {
links[state.href] = state.el;
};
const removeLink = (href) => {
delete links[href];
};
const setCurrentAnchor = (href) => {
if (currentAnchor.value !== href) {
currentAnchor.value = href;
emit(CHANGE_EVENT, href);
}
};
let clearAnimate = null;
let currentTargetHref = "";
const scrollToAnchor = (href) => {
if (!containerEl.value) return;
const target = getElement(href);
if (!target) return;
if (clearAnimate) {
if (currentTargetHref === href) return;
clearAnimate();
}
currentTargetHref = href;
isScrolling = true;
const scrollEle = getScrollElement(target, containerEl.value);
const distance = getOffsetTopDistance(target, scrollEle);
const max = scrollEle.scrollHeight - scrollEle.clientHeight;
const to = Math.min(distance - props.offset, max);
clearAnimate = animateScrollTo(containerEl.value, currentScrollTop, to, props.duration, () => {
setTimeout(() => {
isScrolling = false;
currentTargetHref = "";
}, 20);
});
};
const scrollTo = (href) => {
if (href) {
setCurrentAnchor(href);
scrollToAnchor(href);
}
};
const handleClick = (e, href) => {
emit("click", e, href);
scrollTo(href);
};
const handleScroll = throttleByRaf(() => {
if (containerEl.value) currentScrollTop = getScrollTop(containerEl.value);
const currentHref = getCurrentHref();
if (isScrolling || isUndefined(currentHref)) return;
setCurrentAnchor(currentHref);
});
const getCurrentHref = () => {
if (!containerEl.value) return;
const scrollTop = getScrollTop(containerEl.value);
const anchorTopList = [];
for (const href of Object.keys(links)) {
const target = getElement(href);
if (!target) continue;
const distance = getOffsetTopDistance(target, getScrollElement(target, containerEl.value));
anchorTopList.push({
top: distance - props.offset - props.bound,
href
});
}
anchorTopList.sort((prev, next) => prev.top - next.top);
for (let i = 0; i < anchorTopList.length; i++) {
const item = anchorTopList[i];
const next = anchorTopList[i + 1];
if (i === 0 && scrollTop === 0) return props.selectScrollTop ? item.href : "";
if (item.top <= scrollTop && (!next || next.top > scrollTop)) return item.href;
}
};
const getContainer = () => {
const el = getElement(props.container);
if (!el || isWindow(el)) containerEl.value = window;
else containerEl.value = el;
};
useEventListener(containerEl, "scroll", handleScroll);
const updateMarkerStyle = () => {
nextTick(() => {
if (!anchorRef.value || !markerRef.value || !currentAnchor.value) {
markerStyle.value = {};
return;
}
const currentLinkEl = links[currentAnchor.value];
if (!currentLinkEl) {
markerStyle.value = {};
return;
}
const anchorRect = anchorRef.value.getBoundingClientRect();
const markerRect = markerRef.value.getBoundingClientRect();
const linkRect = currentLinkEl.getBoundingClientRect();
if (props.direction === "horizontal") markerStyle.value = {
left: `${linkRect.left - anchorRect.left}px`,
width: `${linkRect.width}px`,
opacity: 1
};
else markerStyle.value = {
top: `${linkRect.top - anchorRect.top + (linkRect.height - markerRect.height) / 2}px`,
opacity: 1
};
});
};
watch(currentAnchor, updateMarkerStyle);
watch(() => slots.default?.(), updateMarkerStyle);
onMounted(() => {
getContainer();
const hash = decodeURIComponent(window.location.hash);
if (getElement(hash)) scrollTo(hash);
else handleScroll();
});
watch(() => props.container, () => {
getContainer();
});
provide(anchorKey, {
ns,
direction: props.direction,
currentAnchor,
addLink,
removeLink,
handleClick
});
__expose({ scrollTo });
return (_ctx, _cache) => {
return openBlock(), createElementBlock("div", {
ref_key: "anchorRef",
ref: anchorRef,
class: normalizeClass(cls.value)
}, [__props.marker ? (openBlock(), createElementBlock("div", {
key: 0,
ref_key: "markerRef",
ref: markerRef,
class: normalizeClass(unref(ns).e("marker")),
style: normalizeStyle(markerStyle.value)
}, null, 6)) : createCommentVNode("v-if", true), createElementVNode("div", { class: normalizeClass(unref(ns).e("list")) }, [renderSlot(_ctx.$slots, "default")], 2)], 2);
};
}
});
//#endregion
export { anchor_vue_vue_type_script_setup_true_lang_default as default };
//# sourceMappingURL=anchor.vue_vue_type_script_setup_true_lang.mjs.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,8 @@
import anchor_vue_vue_type_script_setup_true_lang_default from "./anchor.vue_vue_type_script_setup_true_lang.mjs";
//#region ../../packages/components/anchor/src/anchor.vue
var anchor_default = anchor_vue_vue_type_script_setup_true_lang_default;
//#endregion
export { anchor_default as default };
//# sourceMappingURL=anchor2.mjs.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,6 @@
//#region ../../packages/components/anchor/src/constants.ts
const anchorKey = Symbol("anchor");
//#endregion
export { anchorKey };
//# sourceMappingURL=constants.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"constants.mjs","names":[],"sources":["../../../../../../packages/components/anchor/src/constants.ts"],"sourcesContent":["import type { InjectionKey, Ref } from 'vue'\nimport type { UseNamespaceReturn } from '@element-plus/hooks'\n\nexport interface AnchorLinkState {\n el: HTMLElement\n href: string\n}\n\nexport interface AnchorContext {\n ns: UseNamespaceReturn\n direction: string\n currentAnchor: Ref<string>\n addLink(state: AnchorLinkState): void\n removeLink(href: string): void\n handleClick(e: MouseEvent, href?: string): void\n}\n\nexport const anchorKey: InjectionKey<AnchorContext> = Symbol('anchor')\n"],"mappings":";AAiBA,MAAa,YAAyC,OAAO,SAAS"}
@@ -0,0 +1,2 @@
import "../../base/style/css.mjs";
import "element-plus/theme-chalk/el-anchor.css";
@@ -0,0 +1,2 @@
import "../../base/style/index.mjs";
import "element-plus/theme-chalk/src/anchor.scss";