@veltra/directives 1.0.9 → 1.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -61,7 +61,8 @@ var Ripple = class Ripple {
61
61
  * @returns 容器矩形区域
62
62
  */
63
63
  getContainerRect() {
64
- this.containerRect = this.container.getBoundingClientRect();
64
+ const rect = this.container.getBoundingClientRect();
65
+ this.containerRect = rect;
65
66
  return this.containerRect;
66
67
  }
67
68
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ripple.js","names":[],"sources":["../../src/ripple/ripple.ts"],"sourcesContent":["import { bem, nextFrame, removeStyles, setStyles, type BEM } from '@veltra/utils'\nimport type { CSSProperties } from 'vue'\n\nfunction pick<T extends object, K extends keyof T>(obj: T, keys: readonly K[]): Pick<T, K> {\n const out: Partial<Pick<T, K>> = {}\n for (const k of keys) {\n if (k in obj) out[k] = obj[k]\n }\n return out as Pick<T, K>\n}\n\n/** 鼠标或触摸事件类型 */\ntype MouseOrTouchEvent = MouseEvent | Touch\n\n/** 波纹位置接口 */\ninterface RipplePosition {\n /** X 坐标 */\n x: number\n /** Y 坐标 */\n y: number\n}\n\n/** 波纹配置接口 */\ninterface RippleConfig {\n /** 波纹类 */\n rippleClass?: string\n /** 波纹动画时长 */\n duration?: number\n /** 是否自动移除 */\n autoRemove?: boolean\n}\n\n/** 容器样式接口 */\ninterface ContainerStyle {\n /** 定位方式 */\n position: string\n /** 溢出处理 */\n overflow: string\n}\n\n/**\n * 波纹效果类\n * 用于在指定容器中创建和管理波纹动画效果\n * 支持鼠标点击和触摸事件触发的波纹动画\n */\nexport class Ripple {\n /** 波纹样式类名生成器 */\n static cls: BEM<'ripple'> = bem('ripple')\n\n /** 波纹容器元素 */\n private container: HTMLElement\n /** 容器矩形区域缓存 */\n private containerRect?: DOMRect\n /** 容器计算样式缓存 */\n private containerComputedStyle?: ContainerStyle\n /** 容器原始样式备份 */\n private containerStyle?: ContainerStyle\n\n /** 当前活跃的波纹元素 */\n private currentRippleEl?: HTMLElement\n\n /** 波纹配置 */\n private config?: RippleConfig\n\n /** 波纹元素数量(私有) */\n private _amount = 0\n\n /**\n * 设置波纹元素数量\n * 当数量为 0 时自动重置容器样式\n */\n private set amount(amount: number) {\n this._amount = amount\n amount === 0 && this.resetContainerStyle()\n }\n\n /** 获取当前波纹元素数量 */\n private get amount(): number {\n return this._amount\n }\n\n /**\n * 构造函数\n * @param container 波纹容器元素\n * @param config 波纹配置选项\n */\n constructor(container: HTMLElement, config?: RippleConfig) {\n this.container = container\n if (config) {\n this.config = config\n }\n }\n\n /**\n * 获取波纹容器元素\n * @returns 容器元素\n */\n getContainer(): HTMLElement {\n return this.container\n }\n\n /**\n * 获取容器矩形区域\n * 使用缓存机制避免重复计算\n * @returns 容器矩形区域\n */\n private getContainerRect(): DOMRect {\n // if (this.containerRect) return this.containerRect\n const rect = this.container.getBoundingClientRect()\n this.containerRect = rect\n return this.containerRect\n }\n\n /**\n * 获取波纹圆心位置\n * 根据鼠标或触摸事件计算相对于容器的坐标\n * @param e 鼠标或触摸事件\n * @returns 波纹圆心位置\n */\n private getRippleCenterPosition(e: MouseOrTouchEvent): { x: number; y: number } {\n const { left, top } = this.getContainerRect()\n const { clientX, clientY } = e\n return { x: clientX - left, y: clientY - top }\n }\n\n /**\n * 标记元素过渡动画结束\n * @param el 目标元素\n */\n private markTransitionEnd(el: HTMLElement) {\n el.dataset.transitionend = 'true'\n }\n\n /**\n * 标记元素为可移除状态\n * @param el 目标元素\n */\n private markRemovable(el: HTMLElement) {\n el.dataset.removable = 'true'\n }\n\n /**\n * 计算波纹半径\n * 根据点击位置计算能覆盖整个容器的最小半径\n * @param centerPosition 波纹圆心位置\n * @returns 波纹半径\n */\n private calcRippleRadius(centerPosition: RipplePosition) {\n const { x, y } = centerPosition\n const { width, height } = this.getContainerRect()\n const edgeA = Math.max(x, width - x)\n const edgeB = Math.max(y, height - y)\n return Math.ceil(Math.sqrt(edgeA ** 2 + edgeB ** 2))\n }\n\n /**\n * 设置容器样式\n * 确保容器具有正确的定位和溢出隐藏属性以支持波纹效果\n */\n private setContainerStyle() {\n const { container } = this\n\n // 获取元素原本的内联样式\n if (this.amount === 0 && !this.containerStyle) {\n this.containerStyle = {\n position: container.style.position,\n overflow: container.style.overflow\n }\n }\n\n if (!this.containerComputedStyle) {\n this.containerComputedStyle = pick(window.getComputedStyle(container), [\n 'overflow',\n 'position'\n ])\n }\n const { position, overflow } = this.containerComputedStyle\n const style: CSSProperties = {}\n\n // 如果是静态定位,改为相对定位以支持绝对定位的波纹元素\n if (position === 'static') {\n style.position = 'relative'\n }\n\n // 如果溢出不是隐藏,设置为隐藏以裁剪波纹边界\n if (overflow !== 'hidden') {\n style.overflow = 'hidden'\n }\n\n setStyles(container, style)\n }\n\n /**\n * 重置容器样式\n * 恢复容器的原始样式设置\n */\n private resetContainerStyle() {\n const { container, containerStyle } = this\n if (!containerStyle) {\n return removeStyles(container, ['overflow', 'position'])\n }\n\n const attrsToRemoved: string[] = []\n\n if (!containerStyle.overflow) {\n attrsToRemoved.push('overflow')\n }\n\n if (!containerStyle.position) {\n attrsToRemoved.push('position')\n }\n\n removeStyles(container, attrsToRemoved)\n\n if (!attrsToRemoved.length) {\n setStyles(container, containerStyle as CSSProperties)\n }\n }\n\n /**\n * 创建波纹元素\n * 生成波纹DOM元素并设置样式和动画\n * @param centerPosition 波纹圆心位置\n */\n private createRipple(centerPosition: RipplePosition) {\n const { config } = this\n\n // 必须在创建ripple元素之前调用\n this.setContainerStyle()\n\n const rippleEl = document.createElement('span')\n this.currentRippleEl = rippleEl\n rippleEl.classList.add(Ripple.cls.b)\n config?.rippleClass && rippleEl.classList.add(config.rippleClass)\n\n const radius = this.calcRippleRadius(centerPosition)\n const diameter = radius * 2\n\n // 设置波纹元素的基础样式\n const rippleStyle: CSSProperties = {\n width: `${diameter}px`,\n height: `${diameter}px`,\n left: `${centerPosition.x - radius}px`,\n top: `${centerPosition.y - radius}px`\n }\n\n // 设置自定义动画时长\n if (config?.duration) {\n rippleStyle.transitionDuration = `${config.duration}ms`\n }\n\n setStyles(rippleEl, rippleStyle)\n\n // 监听过渡动画结束事件\n const transitionEndHandler = (e: TransitionEvent) => {\n if (e.propertyName !== 'transform') return\n\n rippleEl.removeEventListener('transitionend', transitionEndHandler)\n this.markTransitionEnd(rippleEl)\n // 尝试移除\n this.removeRippleEl(rippleEl)\n }\n\n rippleEl.addEventListener('transitionend', transitionEndHandler)\n\n this.container.appendChild(rippleEl)\n this.amount++\n\n // 如果配置了自动移除,标记为可移除\n if (config?.autoRemove) {\n this.markRemovable(rippleEl)\n }\n\n // 触发缩放动画\n nextFrame(() => {\n setStyles(rippleEl, { transform: 'scale3d(1, 1, 1)' })\n })\n }\n\n /**\n * 移除波纹元素\n * 检查元素状态,符合条件时执行淡出动画并移除DOM\n * @param rippleEl 要移除的波纹元素\n */\n private removeRippleEl(rippleEl: HTMLElement): void {\n const { transitionend, removable } = rippleEl.dataset\n\n // 只有在过渡结束且标记为可移除时才执行移除\n if (transitionend !== 'true' || removable !== 'true') return\n\n const transitionEndOrCancelHandler = (e: TransitionEvent) => {\n if (e.propertyName !== 'opacity') return\n\n rippleEl.removeEventListener('transitionend', transitionEndOrCancelHandler)\n rippleEl.removeEventListener('transitioncancel', transitionEndOrCancelHandler)\n rippleEl.remove()\n this.amount--\n }\n\n rippleEl.addEventListener('transitionend', transitionEndOrCancelHandler)\n rippleEl.addEventListener('transitioncancel', transitionEndOrCancelHandler)\n rippleEl.classList.add(bem.is('removing'))\n }\n\n /**\n * 显示波纹\n * 根据指定位置创建波纹效果\n * @param centerPosition 波纹圆心位置\n */\n show(centerPosition: RipplePosition): void {\n this.createRipple(centerPosition)\n }\n\n /**\n * 根据事件对象显示波纹\n * 从鼠标或触摸事件中提取位置信息并创建波纹\n * @param e 鼠标或触摸事件对象\n */\n showByEvent(e: MouseEvent | TouchEvent): void {\n const centerPosition = this.getRippleCenterPosition(e instanceof MouseEvent ? e : e.touches[0]!)\n this.createRipple(centerPosition)\n }\n\n /**\n * 移除波纹\n * 手动移除当前活跃的波纹元素\n * 注意:如果已经在Ripple配置中增加了autoRemove属性,则不需要调用此方法\n */\n remove(): void {\n let el = this.currentRippleEl\n if (el) {\n this.markRemovable(el)\n this.removeRippleEl(el)\n el = undefined\n this.currentRippleEl = undefined\n }\n }\n\n /**\n * 重置容器矩形\n * 当容器大小发生变化时,需要重置容器矩形缓存\n * 否则计算的波纹半径不准确\n * 注意:大部分情况下不需要调用此方法\n */\n resetContainerRect(): void {\n this.containerRect = undefined\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ripple.js","names":[],"sources":["../../src/ripple/ripple.ts"],"sourcesContent":["import { bem, nextFrame, removeStyles, setStyles, type BEM } from '@veltra/utils'\nimport type { CSSProperties } from 'vue'\n\nfunction pick<T extends object, K extends keyof T>(obj: T, keys: readonly K[]): Pick<T, K> {\n const out: Partial<Pick<T, K>> = {}\n for (const k of keys) {\n if (k in obj) out[k] = obj[k]\n }\n return out as Pick<T, K>\n}\n\n/** 鼠标或触摸事件类型 */\ntype MouseOrTouchEvent = MouseEvent | Touch\n\n/** 波纹位置接口 */\ninterface RipplePosition {\n /** X 坐标 */\n x: number\n /** Y 坐标 */\n y: number\n}\n\n/** 波纹配置接口 */\ninterface RippleConfig {\n /** 波纹类 */\n rippleClass?: string\n /** 波纹动画时长 */\n duration?: number\n /** 是否自动移除 */\n autoRemove?: boolean\n}\n\n/** 容器样式接口 */\ninterface ContainerStyle {\n /** 定位方式 */\n position: string\n /** 溢出处理 */\n overflow: string\n}\n\n/**\n * 波纹效果类\n * 用于在指定容器中创建和管理波纹动画效果\n * 支持鼠标点击和触摸事件触发的波纹动画\n */\nexport class Ripple {\n /** 波纹样式类名生成器 */\n static cls: BEM<'ripple'> = bem('ripple')\n\n /** 波纹容器元素 */\n private container: HTMLElement\n /** 容器矩形区域缓存 */\n private containerRect?: DOMRect\n /** 容器计算样式缓存 */\n private containerComputedStyle?: ContainerStyle\n /** 容器原始样式备份 */\n private containerStyle?: ContainerStyle\n\n /** 当前活跃的波纹元素 */\n private currentRippleEl?: HTMLElement\n\n /** 波纹配置 */\n private config?: RippleConfig\n\n /** 波纹元素数量(私有) */\n private _amount = 0\n\n /**\n * 设置波纹元素数量\n * 当数量为 0 时自动重置容器样式\n */\n private set amount(amount: number) {\n this._amount = amount\n amount === 0 && this.resetContainerStyle()\n }\n\n /** 获取当前波纹元素数量 */\n private get amount(): number {\n return this._amount\n }\n\n /**\n * 构造函数\n * @param container 波纹容器元素\n * @param config 波纹配置选项\n */\n constructor(container: HTMLElement, config?: RippleConfig) {\n this.container = container\n if (config) {\n this.config = config\n }\n }\n\n /**\n * 获取波纹容器元素\n * @returns 容器元素\n */\n getContainer(): HTMLElement {\n return this.container\n }\n\n /**\n * 获取容器矩形区域\n * 使用缓存机制避免重复计算\n * @returns 容器矩形区域\n */\n private getContainerRect(): DOMRect {\n // if (this.containerRect) return this.containerRect\n const rect = this.container.getBoundingClientRect()\n this.containerRect = rect\n return this.containerRect\n }\n\n /**\n * 获取波纹圆心位置\n * 根据鼠标或触摸事件计算相对于容器的坐标\n * @param e 鼠标或触摸事件\n * @returns 波纹圆心位置\n */\n private getRippleCenterPosition(e: MouseOrTouchEvent): { x: number; y: number } {\n const { left, top } = this.getContainerRect()\n const { clientX, clientY } = e\n return { x: clientX - left, y: clientY - top }\n }\n\n /**\n * 标记元素过渡动画结束\n * @param el 目标元素\n */\n private markTransitionEnd(el: HTMLElement) {\n el.dataset.transitionend = 'true'\n }\n\n /**\n * 标记元素为可移除状态\n * @param el 目标元素\n */\n private markRemovable(el: HTMLElement) {\n el.dataset.removable = 'true'\n }\n\n /**\n * 计算波纹半径\n * 根据点击位置计算能覆盖整个容器的最小半径\n * @param centerPosition 波纹圆心位置\n * @returns 波纹半径\n */\n private calcRippleRadius(centerPosition: RipplePosition) {\n const { x, y } = centerPosition\n const { width, height } = this.getContainerRect()\n const edgeA = Math.max(x, width - x)\n const edgeB = Math.max(y, height - y)\n return Math.ceil(Math.sqrt(edgeA ** 2 + edgeB ** 2))\n }\n\n /**\n * 设置容器样式\n * 确保容器具有正确的定位和溢出隐藏属性以支持波纹效果\n */\n private setContainerStyle() {\n const { container } = this\n\n // 获取元素原本的内联样式\n if (this.amount === 0 && !this.containerStyle) {\n this.containerStyle = {\n position: container.style.position,\n overflow: container.style.overflow\n }\n }\n\n if (!this.containerComputedStyle) {\n this.containerComputedStyle = pick(window.getComputedStyle(container), [\n 'overflow',\n 'position'\n ])\n }\n const { position, overflow } = this.containerComputedStyle\n const style: CSSProperties = {}\n\n // 如果是静态定位,改为相对定位以支持绝对定位的波纹元素\n if (position === 'static') {\n style.position = 'relative'\n }\n\n // 如果溢出不是隐藏,设置为隐藏以裁剪波纹边界\n if (overflow !== 'hidden') {\n style.overflow = 'hidden'\n }\n\n setStyles(container, style)\n }\n\n /**\n * 重置容器样式\n * 恢复容器的原始样式设置\n */\n private resetContainerStyle() {\n const { container, containerStyle } = this\n if (!containerStyle) {\n return removeStyles(container, ['overflow', 'position'])\n }\n\n const attrsToRemoved: string[] = []\n\n if (!containerStyle.overflow) {\n attrsToRemoved.push('overflow')\n }\n\n if (!containerStyle.position) {\n attrsToRemoved.push('position')\n }\n\n removeStyles(container, attrsToRemoved)\n\n if (!attrsToRemoved.length) {\n setStyles(container, containerStyle as CSSProperties)\n }\n }\n\n /**\n * 创建波纹元素\n * 生成波纹DOM元素并设置样式和动画\n * @param centerPosition 波纹圆心位置\n */\n private createRipple(centerPosition: RipplePosition) {\n const { config } = this\n\n // 必须在创建ripple元素之前调用\n this.setContainerStyle()\n\n const rippleEl = document.createElement('span')\n this.currentRippleEl = rippleEl\n rippleEl.classList.add(Ripple.cls.b)\n config?.rippleClass && rippleEl.classList.add(config.rippleClass)\n\n const radius = this.calcRippleRadius(centerPosition)\n const diameter = radius * 2\n\n // 设置波纹元素的基础样式\n const rippleStyle: CSSProperties = {\n width: `${diameter}px`,\n height: `${diameter}px`,\n left: `${centerPosition.x - radius}px`,\n top: `${centerPosition.y - radius}px`\n }\n\n // 设置自定义动画时长\n if (config?.duration) {\n rippleStyle.transitionDuration = `${config.duration}ms`\n }\n\n setStyles(rippleEl, rippleStyle)\n\n // 监听过渡动画结束事件\n const transitionEndHandler = (e: TransitionEvent) => {\n if (e.propertyName !== 'transform') return\n\n rippleEl.removeEventListener('transitionend', transitionEndHandler)\n this.markTransitionEnd(rippleEl)\n // 尝试移除\n this.removeRippleEl(rippleEl)\n }\n\n rippleEl.addEventListener('transitionend', transitionEndHandler)\n\n this.container.appendChild(rippleEl)\n this.amount++\n\n // 如果配置了自动移除,标记为可移除\n if (config?.autoRemove) {\n this.markRemovable(rippleEl)\n }\n\n // 触发缩放动画\n nextFrame(() => {\n setStyles(rippleEl, { transform: 'scale3d(1, 1, 1)' })\n })\n }\n\n /**\n * 移除波纹元素\n * 检查元素状态,符合条件时执行淡出动画并移除DOM\n * @param rippleEl 要移除的波纹元素\n */\n private removeRippleEl(rippleEl: HTMLElement): void {\n const { transitionend, removable } = rippleEl.dataset\n\n // 只有在过渡结束且标记为可移除时才执行移除\n if (transitionend !== 'true' || removable !== 'true') return\n\n const transitionEndOrCancelHandler = (e: TransitionEvent) => {\n if (e.propertyName !== 'opacity') return\n\n rippleEl.removeEventListener('transitionend', transitionEndOrCancelHandler)\n rippleEl.removeEventListener('transitioncancel', transitionEndOrCancelHandler)\n rippleEl.remove()\n this.amount--\n }\n\n rippleEl.addEventListener('transitionend', transitionEndOrCancelHandler)\n rippleEl.addEventListener('transitioncancel', transitionEndOrCancelHandler)\n rippleEl.classList.add(bem.is('removing'))\n }\n\n /**\n * 显示波纹\n * 根据指定位置创建波纹效果\n * @param centerPosition 波纹圆心位置\n */\n show(centerPosition: RipplePosition): void {\n this.createRipple(centerPosition)\n }\n\n /**\n * 根据事件对象显示波纹\n * 从鼠标或触摸事件中提取位置信息并创建波纹\n * @param e 鼠标或触摸事件对象\n */\n showByEvent(e: MouseEvent | TouchEvent): void {\n const centerPosition = this.getRippleCenterPosition(e instanceof MouseEvent ? e : e.touches[0]!)\n this.createRipple(centerPosition)\n }\n\n /**\n * 移除波纹\n * 手动移除当前活跃的波纹元素\n * 注意:如果已经在Ripple配置中增加了autoRemove属性,则不需要调用此方法\n */\n remove(): void {\n let el = this.currentRippleEl\n if (el) {\n this.markRemovable(el)\n this.removeRippleEl(el)\n el = undefined\n this.currentRippleEl = undefined\n }\n }\n\n /**\n * 重置容器矩形\n * 当容器大小发生变化时,需要重置容器矩形缓存\n * 否则计算的波纹半径不准确\n * 注意:大部分情况下不需要调用此方法\n */\n resetContainerRect(): void {\n this.containerRect = undefined\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veltra/directives",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "files": [
5
5
  "dist",
6
6
  "src"
@@ -25,8 +25,8 @@
25
25
  "check-types": "tsc -p tsconfig.json --noEmit"
26
26
  },
27
27
  "dependencies": {
28
- "@veltra/styles": "1.0.9",
29
- "@veltra/utils": "1.0.9"
28
+ "@veltra/styles": "1.0.11",
29
+ "@veltra/utils": "1.0.11"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "vue": "^3.5.33"