@veltra/utils 1.0.0

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.
Files changed (73) hide show
  1. package/dist/dom/class-name.d.ts +10 -0
  2. package/dist/dom/class-name.js +16 -0
  3. package/dist/dom/class-name.js.map +1 -0
  4. package/dist/dom/highlight.d.ts +14 -0
  5. package/dist/dom/highlight.js +19 -0
  6. package/dist/dom/highlight.js.map +1 -0
  7. package/dist/dom/position.d.ts +28 -0
  8. package/dist/dom/position.js +59 -0
  9. package/dist/dom/position.js.map +1 -0
  10. package/dist/dom/style.d.ts +25 -0
  11. package/dist/dom/style.js +38 -0
  12. package/dist/dom/style.js.map +1 -0
  13. package/dist/dom/z-index.d.ts +9 -0
  14. package/dist/dom/z-index.js +11 -0
  15. package/dist/dom/z-index.js.map +1 -0
  16. package/dist/form/validate.d.ts +33 -0
  17. package/dist/form/validate.js +197 -0
  18. package/dist/form/validate.js.map +1 -0
  19. package/dist/helper/create-increase.d.ts +10 -0
  20. package/dist/helper/create-increase.js +17 -0
  21. package/dist/helper/create-increase.js.map +1 -0
  22. package/dist/helper/create-toggle.d.ts +15 -0
  23. package/dist/helper/create-toggle.js +24 -0
  24. package/dist/helper/create-toggle.js.map +1 -0
  25. package/dist/helper/frame.d.ts +9 -0
  26. package/dist/helper/frame.js +14 -0
  27. package/dist/helper/frame.js.map +1 -0
  28. package/dist/helper/make-bem.d.ts +52 -0
  29. package/dist/helper/make-bem.js +39 -0
  30. package/dist/helper/make-bem.js.map +1 -0
  31. package/dist/helper/tween.d.ts +43 -0
  32. package/dist/helper/tween.js +89 -0
  33. package/dist/helper/tween.js.map +1 -0
  34. package/dist/helper/vue.d.ts +44 -0
  35. package/dist/helper/vue.js +62 -0
  36. package/dist/helper/vue.js.map +1 -0
  37. package/dist/index.d.ts +19 -0
  38. package/dist/index.js +15 -0
  39. package/dist/reactive/proxy.d.ts +19 -0
  40. package/dist/reactive/proxy.js +57 -0
  41. package/dist/reactive/proxy.js.map +1 -0
  42. package/dist/shared/constants.d.ts +10 -0
  43. package/dist/shared/constants.js +11 -0
  44. package/dist/shared/constants.js.map +1 -0
  45. package/dist/types/component-common.d.ts +37 -0
  46. package/dist/types/form-context.d.ts +6 -0
  47. package/dist/types/helper.d.ts +22 -0
  48. package/dist/types/index.d.ts +5 -0
  49. package/dist/types/index.js +0 -0
  50. package/dist/types/utils/form/validate.d.ts +34 -0
  51. package/package.json +47 -0
  52. package/src/dom/class-name.ts +20 -0
  53. package/src/dom/highlight.ts +23 -0
  54. package/src/dom/position.ts +96 -0
  55. package/src/dom/style.ts +60 -0
  56. package/src/dom/z-index.ts +7 -0
  57. package/src/env.d.ts +1 -0
  58. package/src/form/validate.ts +278 -0
  59. package/src/helper/create-increase.ts +14 -0
  60. package/src/helper/create-toggle.ts +29 -0
  61. package/src/helper/frame.ts +9 -0
  62. package/src/helper/make-bem.ts +109 -0
  63. package/src/helper/tween.ts +123 -0
  64. package/src/helper/vue.ts +88 -0
  65. package/src/index.ts +28 -0
  66. package/src/reactive/proxy.ts +90 -0
  67. package/src/shared/constants.ts +8 -0
  68. package/src/shared/index.ts +1 -0
  69. package/src/types/component-common.ts +41 -0
  70. package/src/types/form-context.ts +2 -0
  71. package/src/types/helper.ts +31 -0
  72. package/src/types/index.ts +4 -0
  73. package/src/types/utils/form/validate.ts +33 -0
@@ -0,0 +1,123 @@
1
+ /** 自 cat-kit 3.x Tween 行为对齐的轻量动画(原 `cat-kit/fe` 导出) */
2
+
3
+ export interface AnimeConfig<State extends Record<string, number>> {
4
+ duration?: number
5
+ easingFunction?: (progress: number) => number
6
+ onComplete?(state: State): void
7
+ }
8
+
9
+ export interface TweenConfig<State extends Record<string, number>> {
10
+ duration?: number
11
+ onUpdate?(state: State): void
12
+ onComplete?(state: State): void
13
+ easingFunction?: (progress: number) => number
14
+ }
15
+
16
+ export class Tween<State extends Record<string, number> = Record<string, number>> {
17
+ readonly state: State
18
+ protected duration = 300
19
+ protected onUpdate?: (state: State) => void
20
+ protected onComplete?: (state: State) => void
21
+ protected frameId?: number
22
+ protected easingFunction: (progress: number) => number
23
+ private defaultState: State
24
+
25
+ constructor(state: State, config?: TweenConfig<State>) {
26
+ this.state = state
27
+ this.defaultState = { ...state }
28
+ const { duration, onUpdate, onComplete, easingFunction } = config || {}
29
+ if (duration !== undefined) this.duration = duration
30
+ if (onUpdate !== undefined) this.onUpdate = onUpdate
31
+ if (onComplete !== undefined) this.onComplete = onComplete
32
+ this.easingFunction = easingFunction ?? Tween.easing.linear
33
+ }
34
+
35
+ protected raf(options: {
36
+ onComplete: () => void
37
+ duration: number
38
+ tick: (p: number) => void
39
+ }): void {
40
+ const start = performance.now()
41
+ const { onComplete, tick, duration } = options
42
+ const update = (timestamp: number) => {
43
+ const elapsed = timestamp - start
44
+ const progress = Math.min(elapsed / duration, 1)
45
+ tick(progress)
46
+ if (progress < 1) {
47
+ this.frameId = requestAnimationFrame(update)
48
+ } else {
49
+ tick(progress)
50
+ this.stop()
51
+ onComplete()
52
+ }
53
+ }
54
+ this.frameId = requestAnimationFrame(update)
55
+ }
56
+
57
+ to(state: Partial<State>, config?: AnimeConfig<State>): void {
58
+ this.stop()
59
+ const prevState = { ...this.state }
60
+ const stateDistance = Object.keys(state).reduce(
61
+ (acc, key) => {
62
+ const k = key as keyof State
63
+ const sv = state[k] as number
64
+ const pv = prevState[k] as number
65
+ if ((sv || sv === 0) && (pv || pv === 0)) {
66
+ acc[key] = sv - pv
67
+ }
68
+ return acc
69
+ },
70
+ {} as Record<string, number>
71
+ )
72
+ const duration = config?.duration || this.duration
73
+ const easingFunction = config?.easingFunction || this.easingFunction
74
+ const onComplete = config?.onComplete || this.onComplete
75
+ this.raf({
76
+ duration,
77
+ onComplete: () => {
78
+ for (const key in state) {
79
+ if (key in this.state) {
80
+ ;(this.state as Record<string, number>)[key] = state[key as keyof State] as number
81
+ }
82
+ }
83
+ this.onUpdate?.(this.state)
84
+ onComplete?.(this.state)
85
+ },
86
+ tick: (progress) => {
87
+ for (const key in stateDistance) {
88
+ const pk = key as keyof State
89
+ const target = (prevState[pk] as number) + easingFunction(progress) * stateDistance[key]!
90
+ ;(this.state as Record<string, number>)[key] = target
91
+ }
92
+ this.onUpdate?.(this.state)
93
+ }
94
+ })
95
+ }
96
+
97
+ back(config?: AnimeConfig<State>): void {
98
+ this.to(this.defaultState as Partial<State>, config)
99
+ }
100
+
101
+ private stop(): boolean {
102
+ if (!this.frameId) return false
103
+ cancelAnimationFrame(this.frameId)
104
+ this.frameId = undefined
105
+ return true
106
+ }
107
+
108
+ static readonly easing = {
109
+ linear: (p: number) => p,
110
+ easeInQuad: (p: number) => p * p,
111
+ easeOutQuad: (p: number) => p * (2 - p),
112
+ easeInOutQuad: (p: number) => (p < 0.5 ? 2 * p * p : -1 + (4 - 2 * p) * p),
113
+ easeInBack: (p: number) => p * p * ((2.70158 + 1) * p - 1),
114
+ easeOutBack: (p: number) => 1 + 2.70158 * Math.pow(p - 1, 3) + 1.70158 * Math.pow(p - 1, 2),
115
+ easeInOutBack: (p: number) => {
116
+ const c1 = 1.70158
117
+ const c2 = c1 * 1.525
118
+ return p < 0.5
119
+ ? (Math.pow(2 * p, 2) * ((c2 + 1) * 2 * p - c2)) / 2
120
+ : (Math.pow(2 * p - 2, 2) * ((c2 + 1) * (p * 2 - 2) + c2) + 2) / 2
121
+ }
122
+ }
123
+ }
@@ -0,0 +1,88 @@
1
+ import {
2
+ Text,
3
+ Fragment,
4
+ Comment,
5
+ type VNode,
6
+ isVNode,
7
+ createTextVNode,
8
+ type VNodeArrayChildren,
9
+ shallowRef,
10
+ watch,
11
+ type ShallowRef
12
+ } from 'vue'
13
+
14
+ interface TextVNode extends VNode {
15
+ children: string
16
+ }
17
+
18
+ /**
19
+ * 是否为文本
20
+ * @param node
21
+ * @returns
22
+ */
23
+ export function isTextNode(node: VNode): node is TextVNode {
24
+ return node.type === Text
25
+ }
26
+
27
+ /**
28
+ * 是否为片段
29
+ * @param node
30
+ * @returns
31
+ */
32
+ export function isFragment(node: any): node is VNode {
33
+ return node && node.type === Fragment
34
+ }
35
+
36
+ interface CommentVNode extends VNode {
37
+ children: string
38
+ }
39
+
40
+ /**
41
+ * 是否为注释
42
+ * @param node
43
+ * @returns
44
+ */
45
+ export function isComment(node: VNode): node is CommentVNode {
46
+ return node.type === Comment
47
+ }
48
+
49
+ /**
50
+ * 是否为模板
51
+ * @param node
52
+ * @returns
53
+ */
54
+ export function isTemplate(node: unknown): node is VNode {
55
+ return isVNode(node) && node.type === 'template'
56
+ }
57
+
58
+ /**
59
+ * 提取常规虚拟节点(移除type为fragment、template的节点)
60
+ * @param nodes VNodeArrayChildren
61
+ * @param results 虚拟节点
62
+ * @returns
63
+ */
64
+ export function extractNormalVNodes(nodes: VNodeArrayChildren, results: VNode[] = []): VNode[] {
65
+ nodes.forEach((node) => {
66
+ if (!isVNode(node)) {
67
+ if (typeof node === 'string' || typeof node === 'number') {
68
+ results.push(createTextVNode(String(node)))
69
+ }
70
+ return
71
+ }
72
+ if ((isFragment(node) || isTemplate(node)) && Array.isArray(node.children)) {
73
+ extractNormalVNodes(node.children, results)
74
+ } else {
75
+ results.push(node)
76
+ }
77
+ })
78
+ return results
79
+ }
80
+
81
+ export function shallowComputed<T>(getter: () => T): ShallowRef<T> {
82
+ const result = shallowRef<T>(getter())
83
+ watch(getter, (value) => {
84
+ result.value = value
85
+ })
86
+
87
+ return result
88
+ }
package/src/index.ts ADDED
@@ -0,0 +1,28 @@
1
+ export * from './dom/class-name'
2
+
3
+ export * from './dom/highlight'
4
+
5
+ export * from './dom/position'
6
+
7
+ export * from './dom/style'
8
+
9
+ export * from './dom/z-index'
10
+
11
+ export * from './form/validate'
12
+
13
+ export * from './helper/create-increase'
14
+
15
+ export * from './helper/create-toggle'
16
+
17
+ export * from './helper/tween'
18
+
19
+ export * from './helper/frame'
20
+
21
+ export * from './helper/make-bem'
22
+
23
+ export * from './helper/vue'
24
+
25
+ export * from './reactive/proxy'
26
+
27
+ export * from './shared'
28
+ export * from './types'
@@ -0,0 +1,90 @@
1
+ /**
2
+ * 创建一个介于vue的reactive和shallowReactive对象的中间层
3
+ * @description
4
+ * 如果对象含有嵌套对象,则**递归**进行中间代理
5
+ *
6
+ * @param o 代理对象
7
+ * @param handler 处理函数
8
+ * @param options 代理配置
9
+ * @returns 中间代理对象
10
+ */
11
+ function createMiddleProxy(
12
+ o: Record<string, any>,
13
+ handler?: {
14
+ set?: (field: string, val: any) => void
15
+ get?: (field: string) => any
16
+ changed?: (fields: string[]) => void
17
+ },
18
+ options?: {
19
+ weakMap?: WeakMap<Record<string, any>, any>
20
+ parentsField?: string
21
+ changedFields?: string[]
22
+ }
23
+ ) {
24
+ let { weakMap, parentsField, changedFields = [] } = options || {}
25
+ if (!weakMap) {
26
+ weakMap = new WeakMap()
27
+ }
28
+
29
+ return new Proxy(o, {
30
+ set(target, field: string, val) {
31
+ const changedField = parentsField ? `${parentsField}.${field}` : field
32
+ handler?.set?.(changedField, val)
33
+ target[field] = val
34
+
35
+ changedFields.push(changedField)
36
+ Promise.resolve().then(() => {
37
+ if (!changedFields.length) return
38
+ handler?.changed?.([...changedFields])
39
+ changedFields.splice(0)
40
+ })
41
+
42
+ return true
43
+ },
44
+
45
+ get(target, field: string) {
46
+ handler?.get?.(field)
47
+
48
+ const val = target[field]
49
+ if (
50
+ val !== null &&
51
+ typeof val === 'object' &&
52
+ !(val instanceof Date) &&
53
+ !(val instanceof RegExp)
54
+ ) {
55
+ if (weakMap.has(val)) return weakMap.get(val)
56
+ const valProxy = createMiddleProxy(val, handler, {
57
+ weakMap,
58
+ parentsField: parentsField ? `${parentsField}.${field}` : field,
59
+ changedFields
60
+ })
61
+ weakMap.set(val, valProxy)
62
+
63
+ return valProxy
64
+ }
65
+
66
+ return val
67
+ }
68
+ })
69
+ }
70
+
71
+ /**
72
+ * 中间代理, 用于vue的reactive和shallowReactive方法的中间层
73
+ * @param o 代理对象
74
+ * @param config 代理配置
75
+ * @returns
76
+ */
77
+ export function middleProxy<O extends Record<string, any>>(
78
+ o: O,
79
+ handler?: {
80
+ set?: (field: string, val: any) => void
81
+ get?: (field: string) => any
82
+ /**
83
+ * 数值变更回调,传入的参数是本次模型值变更的所有字段
84
+ * @param fields 变更的字段
85
+ */
86
+ changed?: (fields: string[]) => void
87
+ }
88
+ ): O {
89
+ return createMiddleProxy(o, handler) as O
90
+ }
@@ -0,0 +1,8 @@
1
+ /** 命名前缀 */
2
+ export const NAME_SPACE = 'U'
3
+
4
+ /** 类前缀 */
5
+ export const CLS_PREFIX = `${NAME_SPACE.toLowerCase()}-` as 'u-'
6
+
7
+ /** 表单空内容 */
8
+ export const FORM_EMPTY_CONTENT = '-'
@@ -0,0 +1 @@
1
+ export * from './constants'
@@ -0,0 +1,41 @@
1
+ export type ComponentSize = 'small' | 'default' | 'large'
2
+
3
+ export type ColorType = 'primary' | 'info' | 'success' | 'warning' | 'danger'
4
+
5
+ /** 断点名称 */
6
+ export type BreakpointName = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
7
+
8
+ /** 组件通用属性 */
9
+ export interface ComponentProps {
10
+ /** 组件尺寸 */
11
+ size?: ComponentSize
12
+ }
13
+
14
+ /** 表单组件通用属性 */
15
+ export interface FormComponentProps extends ComponentProps {
16
+ /** 在表单控件内时的提示 */
17
+ tips?: string
18
+ /** 所占列的大小 */
19
+ span?:
20
+ | number
21
+ | 'full'
22
+ | ({
23
+ [key in BreakpointName]?: 'full' | number
24
+ } & { default: number | 'full' })
25
+ /** 表单标签文字 */
26
+ label?: string
27
+ /** 表单项字段 */
28
+ field?: string
29
+ /** 是否禁用 */
30
+ disabled?: boolean
31
+ /** 是否只读 */
32
+ readonly?: boolean
33
+ }
34
+
35
+ /** 带有服务端交互功能的组件属性 */
36
+ export interface PropsWithServerQuery {
37
+ /** 请求接口地址 */
38
+ api?: string
39
+ /** 请求查询参数 */
40
+ query?: Record<string, any>
41
+ }
@@ -0,0 +1,2 @@
1
+ /** 表单 provide/inject 上下文(完整 props 见 @veltra/desktop/types/form) */
2
+ export type FormContextInjectProps = Record<string, unknown>
@@ -0,0 +1,31 @@
1
+ import type { VNode } from 'vue'
2
+
3
+ export type Null<T> = null | T
4
+
5
+ export type Undef<T> = undefined | T
6
+
7
+ /** 自定义事件, 可以指定target类型 */
8
+ export interface DefineEvent<T = HTMLElement> extends Omit<Event, 'target'> {
9
+ target: T
10
+ }
11
+
12
+ /** 解构VueExpose中被引用的实例 */
13
+ export type DeconstructValue<E extends Record<string, any>> = {
14
+ [K in keyof E]: E[K] extends { value: infer V } ? V : E[K]
15
+ }
16
+
17
+ /** 索引类型 */
18
+ export type Index<Keys extends string, Val> = {
19
+ [key in Keys]?: Val
20
+ }
21
+
22
+ /**
23
+ * 渲染函数返回内容
24
+ */
25
+ export type RenderReturn =
26
+ | (undefined | VNode | string | null | number)[]
27
+ | undefined
28
+ | VNode
29
+ | string
30
+ | null
31
+ | number
@@ -0,0 +1,4 @@
1
+ export * from './helper'
2
+ export * from './component-common'
3
+ export * from './form-context'
4
+ export * from './utils/form/validate'
@@ -0,0 +1,33 @@
1
+ export type Data = Record<string, any>
2
+
3
+ export type PresetRule = 'email' | 'phone' | 'num' | 'url' | 'idCard'
4
+
5
+ /** 字段校验规则 */
6
+ export interface ValidateRule {
7
+ /** 是否必填 */
8
+ required?: boolean | string
9
+ /** 长度单位 */
10
+ length?: number | [number, string]
11
+ /** 最小值 */
12
+ min?: number | [number, string]
13
+ /** 最大值 */
14
+ max?: number | [number, string]
15
+ /** 最小长度 */
16
+ minLen?: number | [number, string]
17
+ /** 最大长度 */
18
+ maxLen?: number | [number, string]
19
+ /** 匹配 */
20
+ match?: RegExp | [RegExp, string] | string
21
+ /** 预设 */
22
+ preset?: PresetRule
23
+ /** 自定义校验 */
24
+ validator?: (value: any, data: Data) => Promise<string> | string
25
+ }
26
+
27
+ export interface ValidatorConfig {
28
+ /**
29
+ * 是否懒校验,为true时在任意一个字段的的任意规则校验不通过时立马结束校验,性能稍微高一点,但是不能得出所有的错误
30
+ * @default true
31
+ */
32
+ lazy?: boolean
33
+ }