@v-c/util 0.0.4 → 0.0.6

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 (66) hide show
  1. package/dist/props-util/index.cjs +1 -1
  2. package/dist/props-util/index.d.ts +2 -3
  3. package/dist/props-util/index.js +18 -20
  4. package/package.json +5 -1
  5. package/dist/props-util/initDefaultProps.cjs +0 -1
  6. package/dist/props-util/initDefaultProps.d.ts +0 -8
  7. package/dist/props-util/initDefaultProps.js +0 -13
  8. package/src/Children/isFragment.ts +0 -6
  9. package/src/Children/tests/isFragment.test.tsx +0 -15
  10. package/src/Children/tests/toArray.test.tsx +0 -101
  11. package/src/Children/toArray.ts +0 -27
  12. package/src/Dom/addEventListener.ts +0 -20
  13. package/src/Dom/canUseDom.ts +0 -7
  14. package/src/Dom/class.ts +0 -29
  15. package/src/Dom/contains.ts +0 -19
  16. package/src/Dom/css.ts +0 -113
  17. package/src/Dom/dynamicCSS.ts +0 -173
  18. package/src/Dom/findDOMNode.ts +0 -23
  19. package/src/Dom/focus.ts +0 -96
  20. package/src/Dom/isVisible.ts +0 -23
  21. package/src/Dom/scrollLocker.ts +0 -144
  22. package/src/Dom/shadow.ts +0 -17
  23. package/src/Dom/styleChecker.ts +0 -31
  24. package/src/Dom/support.ts +0 -27
  25. package/src/EventInterface.ts +0 -19
  26. package/src/KeyCode.ts +0 -517
  27. package/src/Portal.tsx +0 -50
  28. package/src/PortalWrapper.tsx +0 -217
  29. package/src/composeProps.ts +0 -23
  30. package/src/createRef.ts +0 -32
  31. package/src/debug/diff.ts +0 -66
  32. package/src/deprecated.ts +0 -8
  33. package/src/getScrollBarSize.tsx +0 -57
  34. package/src/guid.ts +0 -4
  35. package/src/hooks/useEvent.ts +0 -3
  36. package/src/hooks/useId.ts +0 -20
  37. package/src/hooks/useLayoutEffect.ts +0 -61
  38. package/src/hooks/useMemo.ts +0 -21
  39. package/src/hooks/useMergedState.ts +0 -44
  40. package/src/hooks/useMobile.ts +0 -16
  41. package/src/hooks/useState.ts +0 -17
  42. package/src/index.ts +0 -3
  43. package/src/isEqual.ts +0 -50
  44. package/src/isMobile.ts +0 -15
  45. package/src/isValid.ts +0 -4
  46. package/src/omit.ts +0 -14
  47. package/src/pickAttrs.ts +0 -79
  48. package/src/props-util/index.ts +0 -57
  49. package/src/props-util/initDefaultProps.ts +0 -34
  50. package/src/raf.ts +0 -55
  51. package/src/setStyle.ts +0 -38
  52. package/src/switchScrollingEffect.ts +0 -48
  53. package/src/test/domHook.ts +0 -66
  54. package/src/type.ts +0 -94
  55. package/src/utils/checkSlotProp.ts +0 -10
  56. package/src/utils/get.ts +0 -15
  57. package/src/utils/omit.ts +0 -9
  58. package/src/utils/set.ts +0 -110
  59. package/src/utils/transition.ts +0 -128
  60. package/src/vnode.ts +0 -86
  61. package/src/vueuse/unref-element.ts +0 -13
  62. package/src/warning.ts +0 -79
  63. package/tests/Portal.spec.tsx +0 -199
  64. package/tsconfig.json +0 -8
  65. package/vite.config.ts +0 -18
  66. package/vitest.config.ts +0 -11
package/src/omit.ts DELETED
@@ -1,14 +0,0 @@
1
- export default function omit<T extends object, K extends keyof T>(
2
- obj: T,
3
- fields: K[] | readonly K[],
4
- ): Omit<T, K> {
5
- const clone = { ...obj }
6
-
7
- if (Array.isArray(fields)) {
8
- fields.forEach((key) => {
9
- delete clone[key]
10
- })
11
- }
12
-
13
- return clone
14
- }
package/src/pickAttrs.ts DELETED
@@ -1,79 +0,0 @@
1
- const attributes = `accept acceptCharset accessKey action allowFullScreen allowTransparency
2
- alt async autoComplete autoFocus autoPlay capture cellPadding cellSpacing challenge
3
- charSet checked classID className colSpan cols content contentEditable contextMenu
4
- controls coords crossOrigin data dateTime default defer dir disabled download draggable
5
- encType form formAction formEncType formMethod formNoValidate formTarget frameBorder
6
- headers height hidden high href hrefLang htmlFor httpEquiv icon id inputMode integrity
7
- is keyParams keyType kind label lang list loop low manifest marginHeight marginWidth max maxLength media
8
- mediaGroup method min minLength multiple muted name noValidate nonce open
9
- optimum pattern placeholder poster preload radioGroup readOnly rel required
10
- reversed role rowSpan rows sandbox scope scoped scrolling seamless selected
11
- shape size sizes span spellCheck src srcDoc srcLang srcSet start step style
12
- summary tabIndex target title type useMap value width wmode wrap`
13
-
14
- const eventsName = `onCopy onCut onPaste onCompositionEnd onCompositionStart onCompositionUpdate onKeyDown
15
- onKeyPress onKeyUp onFocus onBlur onChange onInput onSubmit onClick onContextMenu onDoubleClick
16
- onDrag onDragEnd onDragEnter onDragExit onDragLeave onDragOver onDragStart onDrop onMouseDown
17
- onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp onSelect onTouchCancel
18
- onTouchEnd onTouchMove onTouchStart onScroll onWheel onAbort onCanPlay onCanPlayThrough
19
- onDurationChange onEmptied onEncrypted onEnded onError onLoadedData onLoadedMetadata
20
- onLoadStart onPause onPlay onPlaying onProgress onRateChange onSeeked onSeeking onStalled onSuspend onTimeUpdate onVolumeChange onWaiting onLoad onError`
21
-
22
- const propList = `${attributes} ${eventsName}`.split(/\s+/)
23
-
24
- const ariaPrefix = 'aria-'
25
- const dataPrefix = 'data-'
26
-
27
- function match(key: string, prefix: string) {
28
- return key.indexOf(prefix) === 0
29
- }
30
-
31
- export interface PickConfig {
32
- aria?: boolean
33
- data?: boolean
34
- attr?: boolean
35
- }
36
-
37
- /**
38
- * Picker props from exist props with filter
39
- * @param props Passed props
40
- * @param ariaOnly boolean | { aria?: boolean; data?: boolean; attr?: boolean; } filter config
41
- */
42
- export default function pickAttrs(
43
- props: object,
44
- ariaOnly: boolean | PickConfig = false,
45
- ) {
46
- let mergedConfig: PickConfig
47
- if (ariaOnly === false) {
48
- mergedConfig = {
49
- aria: true,
50
- data: true,
51
- attr: true,
52
- }
53
- }
54
- else if (ariaOnly === true) {
55
- mergedConfig = {
56
- aria: true,
57
- }
58
- }
59
- else {
60
- mergedConfig = {
61
- ...ariaOnly,
62
- }
63
- }
64
-
65
- const attrs: Record<string, any> = {}
66
- Object.keys(props).forEach((key) => {
67
- if (
68
- // Aria
69
- (mergedConfig.aria && (key === 'role' || match(key, ariaPrefix)))
70
- // Data
71
- || (mergedConfig.data && match(key, dataPrefix))
72
- // Attr
73
- || (mergedConfig.attr && propList.includes(key))
74
- ) {
75
- attrs[key] = (props as any)[key]
76
- }
77
- })
78
- return attrs
79
- }
@@ -1,57 +0,0 @@
1
- import type { VNode, VNodeNormalizedChildren } from 'vue'
2
- import { Comment, Fragment, isVNode, Text } from 'vue'
3
- import isValid from '../isValid'
4
- import initDefaultProps from './initDefaultProps'
5
-
6
- export function isEmptyElement(c: any) {
7
- return (
8
- c
9
- && (c.type === Comment
10
- || (c.type === Fragment && c.children.length === 0)
11
- || (c.type === Text && c.children.trim() === ''))
12
- )
13
- }
14
- export function filterEmpty(children: any[] = []) {
15
- const res: any[] = []
16
- children.forEach((child: any) => {
17
- if (Array.isArray(child))
18
- res.push(...child)
19
- else if (child?.type === Fragment)
20
- res.push(...filterEmpty(child.children))
21
- else res.push(child)
22
- })
23
- return res.filter(c => !isEmptyElement(c))
24
- }
25
-
26
- export const skipFlattenKey = Symbol('skipFlatten')
27
- function flattenChildren(children?: VNode | VNodeNormalizedChildren, filterEmpty = true) {
28
- const temp = Array.isArray(children) ? children : [children]
29
- const res = []
30
- temp.forEach((child) => {
31
- if (Array.isArray(child)) {
32
- res.push(...flattenChildren(child, filterEmpty))
33
- }
34
- else if (isValid(child)) {
35
- res.push(child)
36
- }
37
- else if (child && typeof child === 'object' && child.type === Fragment) {
38
- if (child.key === skipFlattenKey) {
39
- res.push(child)
40
- }
41
- else {
42
- res.push(...flattenChildren(child.children, filterEmpty))
43
- }
44
- }
45
- else if (child && isVNode(child)) {
46
- if (filterEmpty && !isEmptyElement(child)) {
47
- res.push(child)
48
- }
49
- else if (!filterEmpty) {
50
- res.push(child)
51
- }
52
- }
53
- })
54
- return res
55
- }
56
-
57
- export { flattenChildren, initDefaultProps }
@@ -1,34 +0,0 @@
1
- import type { PropType } from 'vue'
2
- import type { VueTypeDef, VueTypeValidableDef } from 'vue-types'
3
-
4
- function initDefaultProps<T>(types: T, defaultProps: {
5
- [K in keyof T]?: T[K] extends VueTypeValidableDef<infer U>
6
- ? U
7
- : T[K] extends VueTypeDef<infer U>
8
- ? U
9
- : T[K] extends { type: PropType<infer U> }
10
- ? U
11
- : any;
12
- }): T {
13
- const propTypes: T = { ...types }
14
- Object.keys(defaultProps).forEach((k) => {
15
- const prop = propTypes[k] as VueTypeValidableDef
16
- if (prop) {
17
- if (prop.type || prop.default) {
18
- prop.default = defaultProps[k]
19
- }
20
- else if (prop.def) {
21
- prop.def(defaultProps[k])
22
- }
23
- else {
24
- propTypes[k] = { type: prop, default: defaultProps[k] }
25
- }
26
- }
27
- else {
28
- throw new Error(`not have ${k} prop`)
29
- }
30
- })
31
- return propTypes
32
- }
33
-
34
- export default initDefaultProps
package/src/raf.ts DELETED
@@ -1,55 +0,0 @@
1
- let raf = (callback: FrameRequestCallback) => +setTimeout(callback, 16)
2
- let caf = (num: number) => clearTimeout(num)
3
-
4
- if (typeof window !== 'undefined' && 'requestAnimationFrame' in window) {
5
- raf = (callback: FrameRequestCallback) =>
6
- window.requestAnimationFrame(callback)
7
- caf = (handle: number) => window.cancelAnimationFrame(handle)
8
- }
9
-
10
- let rafUUID = 0
11
-
12
- const rafIds = new Map<number, number>()
13
-
14
- function cleanup(id: number) {
15
- rafIds.delete(id)
16
- }
17
-
18
- function wrapperRaf(callback: () => void, times = 1): number {
19
- rafUUID += 1
20
- const id = rafUUID
21
-
22
- function callRef(leftTimes: number) {
23
- if (leftTimes === 0) {
24
- // Clean up
25
- cleanup(id)
26
-
27
- // Trigger
28
- callback()
29
- }
30
- else {
31
- // Next raf
32
- const realId = raf(() => {
33
- callRef(leftTimes - 1)
34
- })
35
-
36
- // Bind real raf id
37
- rafIds.set(id, realId)
38
- }
39
- }
40
-
41
- callRef(times)
42
-
43
- return id
44
- }
45
-
46
- wrapperRaf.cancel = (id: number) => {
47
- const realId = rafIds.get(id)
48
- cleanup(id)
49
- return caf(realId!)
50
- }
51
-
52
- if (process.env.NODE_ENV !== 'production')
53
- wrapperRaf.ids = () => rafIds
54
-
55
- export default wrapperRaf
package/src/setStyle.ts DELETED
@@ -1,38 +0,0 @@
1
- import type { CSSProperties } from 'vue'
2
-
3
- export interface SetStyleOptions {
4
- element?: HTMLElement
5
- }
6
-
7
- /**
8
- * Easy to set element style, return previous style
9
- * IE browser compatible(IE browser doesn't merge overflow style, need to set it separately)
10
- * https://github.com/ant-design/ant-design/issues/19393
11
- *
12
- */
13
-
14
- function setStyle(
15
- style: CSSProperties,
16
- options: SetStyleOptions = {},
17
- ): CSSProperties {
18
- if (!style)
19
- return {}
20
-
21
- const { element = document.body } = options
22
- const oldStyle: CSSProperties = {}
23
-
24
- const styleKeys = Object.keys(style)
25
-
26
- // IE browser compatible
27
- styleKeys.forEach((key: any) => {
28
- oldStyle[key] = element.style[key]
29
- })
30
-
31
- styleKeys.forEach((key: any) => {
32
- (element as any).style[key] = style[key]
33
- })
34
-
35
- return oldStyle
36
- }
37
-
38
- export default setStyle
@@ -1,48 +0,0 @@
1
- import getScrollBarSize from './getScrollBarSize'
2
- import setStyle from './setStyle'
3
-
4
- function isBodyOverflowing() {
5
- return (
6
- document.body.scrollHeight
7
- > (window.innerHeight || document.documentElement.clientHeight)
8
- && window.innerWidth > document.body.offsetWidth
9
- )
10
- }
11
-
12
- let cacheStyle = {}
13
-
14
- export default (close: any) => {
15
- if (!isBodyOverflowing() && !close)
16
- return
17
-
18
- // https://github.com/ant-design/ant-design/issues/19729
19
- const scrollingEffectClassName = 'ant-scrolling-effect'
20
- const scrollingEffectClassNameReg = new RegExp(
21
- `${scrollingEffectClassName}`,
22
- 'g',
23
- )
24
- const bodyClassName = document.body.className
25
-
26
- if (close) {
27
- if (!scrollingEffectClassNameReg.test(bodyClassName))
28
- return
29
- setStyle(cacheStyle)
30
- cacheStyle = {}
31
- document.body.className = bodyClassName
32
- .replace(scrollingEffectClassNameReg, '')
33
- .trim()
34
- return
35
- }
36
-
37
- const scrollBarSize = getScrollBarSize()
38
- if (scrollBarSize) {
39
- cacheStyle = setStyle({
40
- position: 'relative',
41
- width: `calc(100% - ${scrollBarSize}px)`,
42
- })
43
- if (!scrollingEffectClassNameReg.test(bodyClassName)) {
44
- const addClassName = `${bodyClassName} ${scrollingEffectClassName}`
45
- document.body.className = addClassName.trim()
46
- }
47
- }
48
- }
@@ -1,66 +0,0 @@
1
- const NO_EXIST = { __NOT_EXIST: true }
2
-
3
- export type ElementClass = Function
4
-
5
- export type Property = PropertyDescriptor | Function
6
-
7
- export function spyElementPrototypes<T extends ElementClass>(
8
- elementClass: T,
9
- properties: Record<string, Property>,
10
- ) {
11
- const propNames = Object.keys(properties)
12
- const originDescriptors: any = {}
13
-
14
- propNames.forEach((propName) => {
15
- const originDescriptor: any = Object.getOwnPropertyDescriptor(elementClass.prototype, propName)
16
- originDescriptors[propName] = originDescriptor || NO_EXIST
17
-
18
- const spyProp: any = properties[propName]
19
-
20
- if (typeof spyProp === 'function') {
21
- // If is a function
22
- elementClass.prototype[propName] = function spyFunc(...args: any[]) {
23
- return spyProp.call(this, originDescriptor, ...args)
24
- }
25
- }
26
- else {
27
- // Otherwise tread as a property
28
- Object.defineProperty(elementClass.prototype, propName, {
29
- ...spyProp,
30
- set(value) {
31
- if (spyProp.set)
32
- return (spyProp as any).set.call(this, originDescriptor, value)
33
-
34
- return originDescriptor.set(value)
35
- },
36
- get() {
37
- if (spyProp.get)
38
- return spyProp.get.call(this, originDescriptor)
39
-
40
- return originDescriptor.get()
41
- },
42
- configurable: true,
43
- })
44
- }
45
- })
46
-
47
- return {
48
- mockRestore() {
49
- propNames.forEach((propName) => {
50
- const originDescriptor = originDescriptors[propName]
51
- if (originDescriptor === NO_EXIST)
52
- delete elementClass.prototype[propName]
53
- else if (typeof originDescriptor === 'function')
54
- elementClass.prototype[propName] = originDescriptor
55
- else
56
- Object.defineProperty(elementClass.prototype, propName, originDescriptor)
57
- })
58
- },
59
- }
60
- }
61
-
62
- export function spyElementPrototype(Element: ElementClass, propName: string, property: Property) {
63
- return spyElementPrototypes(Element, {
64
- [propName]: property,
65
- })
66
- }
package/src/type.ts DELETED
@@ -1,94 +0,0 @@
1
- import type { App, Component, Plugin, PropType, Ref, SlotsType, VNode } from 'vue'
2
-
3
- // https://stackoverflow.com/questions/46176165/ways-to-get-string-literal-type-of-array-values-without-enum-overhead
4
- export const tuple = <T extends string[]>(...args: T) => args
5
-
6
- export const tupleNum = <T extends number[]>(...args: T) => args
7
-
8
- /**
9
- * https://stackoverflow.com/a/59187769
10
- * Extract the type of an element of an array/tuple without performing indexing
11
- */
12
- export type ElementOf<T> = T extends (infer E)[] ? E : T extends readonly (infer F)[] ? F : never
13
-
14
- /**
15
- * https://github.com/Microsoft/TypeScript/issues/29729
16
- */
17
- export type LiteralUnion<T extends string> = T | (string & {})
18
-
19
- export type Data = Record<string, unknown>
20
-
21
- export type Key = string | number
22
-
23
- type DefaultFactory<T> = (props: Data) => T | null | undefined
24
-
25
- export interface PropOptions<T = any, D = T> {
26
- type?: PropType<T> | true | null
27
- required?: boolean
28
- default?: D | DefaultFactory<D> | null | undefined | object
29
- validator?: (value: unknown) => boolean
30
- }
31
-
32
- declare type VNodeChildAtom = Component | VNode | string | number | null | undefined | void
33
-
34
- export type VueNode = VNodeChildAtom | VNodeChildAtom[] | VNode
35
-
36
- export function withInstall<T>(comp: T) {
37
- const c = comp as any
38
- c.install = function (app: App) {
39
- app.component(c.displayName || c.name, comp as any)
40
- }
41
-
42
- return comp as T & Plugin
43
- }
44
-
45
- export type MaybeRef<T> = T | Ref<T>
46
-
47
- export function eventType<T>() {
48
- return { type: [Function, Array] as PropType<T | T[]> }
49
- }
50
-
51
- export function objectType<T = object>(defaultVal?: T) {
52
- return { type: Object as PropType<T>, default: defaultVal as T }
53
- }
54
-
55
- export function booleanType(defaultVal?: boolean) {
56
- return { type: Boolean, default: defaultVal as boolean }
57
- }
58
-
59
- export function functionType<T = () => object>(defaultVal?: T) {
60
- return { type: Function as PropType<T>, default: defaultVal as T }
61
- }
62
-
63
- export function anyType<T = any>(defaultVal?: T, required?: boolean) {
64
- const type = { validator: () => true, default: defaultVal as T } as unknown
65
- return required
66
- ? (type as {
67
- type: PropType<T>
68
- default: T
69
- required: true
70
- })
71
- : (type as {
72
- default: T
73
- type: PropType<T>
74
- })
75
- }
76
- export function vNodeType<T = VueNode>() {
77
- return { validator: () => true } as unknown as { type: PropType<T> }
78
- }
79
-
80
- export function arrayType<T extends any[]>(defaultVal?: T) {
81
- return { type: Array as unknown as PropType<T>, default: defaultVal as T }
82
- }
83
-
84
- export function stringType<T extends string = string>(defaultVal?: T) {
85
- return { type: String as unknown as PropType<T>, default: defaultVal as T }
86
- }
87
-
88
- export function someType<T>(types?: any[], defaultVal?: T) {
89
- return types ? { type: types as PropType<T>, default: defaultVal as T } : anyType<T>(defaultVal)
90
- }
91
-
92
- export type CustomSlotsType<T extends Record<string, any>> = SlotsType<T>
93
-
94
- export type AnyObject = Record<PropertyKey, any>
@@ -1,10 +0,0 @@
1
- export function checkSlotProp(props: Record<string, any>, slots: Record<string, any>, name: string, ...args: any[]) {
2
- if (slots[name])
3
- return slots[name]?.(...args)
4
- if (name in props) {
5
- if (typeof props[name] === 'function')
6
- return props[name]?.(...args)
7
- return props[name]
8
- }
9
- return null
10
- }
package/src/utils/get.ts DELETED
@@ -1,15 +0,0 @@
1
- export default function get(
2
- entity: any,
3
- path: (string | number | symbol)[] | readonly (string | number | symbol)[],
4
- ) {
5
- let current = entity
6
-
7
- for (let i = 0; i < path.length; i += 1) {
8
- if (current === null || current === undefined)
9
- return undefined
10
-
11
- current = current[path[i]]
12
- }
13
-
14
- return current
15
- }
package/src/utils/omit.ts DELETED
@@ -1,9 +0,0 @@
1
- export function omit<T, K extends keyof T>(obj: T, keys: K[]): Omit<T, K> {
2
- const result = { ...obj }
3
-
4
- keys.forEach((key) => {
5
- delete result[key]
6
- })
7
-
8
- return result
9
- }
package/src/utils/set.ts DELETED
@@ -1,110 +0,0 @@
1
- import get from './get'
2
-
3
- export type Path = (string | number | symbol)[]
4
-
5
- function internalSet<Entity = any, Output = Entity, Value = any>(
6
- entity: Entity,
7
- paths: Path,
8
- value: Value,
9
- removeIfUndefined: boolean,
10
- ): Output {
11
- if (!paths.length)
12
- return (value as unknown) as Output
13
-
14
- const [path, ...restPath] = paths
15
-
16
- let clone: Output
17
- if (!entity && typeof path === 'number')
18
- clone = ([] as unknown) as Output
19
- else if (Array.isArray(entity))
20
- clone = ([...entity] as unknown) as Output
21
- else
22
- clone = ({ ...entity } as unknown) as Output
23
-
24
- // Delete prop if `removeIfUndefined` and value is undefined
25
- if (removeIfUndefined && value === undefined && restPath.length === 1)
26
- delete (clone as any)[path][restPath[0]]
27
- else
28
- (clone as any)[path] = internalSet((clone as any)[path], restPath, value, removeIfUndefined)
29
-
30
- return clone
31
- }
32
-
33
- export default function set<Entity = any, Output = Entity, Value = any>(
34
- entity: Entity,
35
- paths: Path,
36
- value: Value,
37
- removeIfUndefined: boolean = false,
38
- ): Output {
39
- // Do nothing if `removeIfUndefined` and parent object not exist
40
- if (
41
- paths.length
42
- && removeIfUndefined
43
- && value === undefined
44
- && !get(entity, paths.slice(0, -1))
45
- ) {
46
- return (entity as unknown) as Output
47
- }
48
-
49
- return internalSet(entity, paths, value, removeIfUndefined)
50
- }
51
-
52
- export function isObject(obj: any) {
53
- return (
54
- typeof obj === 'object'
55
- && obj !== null
56
- && Object.getPrototypeOf(obj) === Object.prototype
57
- )
58
- }
59
-
60
- function createEmpty<T>(source: T) {
61
- return (Array.isArray(source) ? [] : {}) as T
62
- }
63
-
64
- const keys = typeof Reflect === 'undefined' ? Object.keys : Reflect.ownKeys
65
-
66
- /**
67
- * Merge objects which will create
68
- */
69
- export function merge<T extends object>(...sources: T[]) {
70
- let clone = createEmpty(sources[0])
71
-
72
- sources.forEach((src) => {
73
- function internalMerge(path: Path, parentLoopSet?: Set<object>) {
74
- const loopSet = new Set(parentLoopSet)
75
-
76
- const value = get(src, path)
77
-
78
- const isArr = Array.isArray(value)
79
-
80
- if (isArr || isObject(value)) {
81
- // Only add not loop obj
82
- if (!loopSet.has(value)) {
83
- loopSet.add(value)
84
-
85
- const originValue = get(clone, path)
86
-
87
- if (isArr) {
88
- // Array will always be overridden
89
- clone = set(clone, path, [])
90
- }
91
- else if (!originValue || typeof originValue !== 'object') {
92
- // Init container if not exist
93
- clone = set(clone, path, createEmpty(value))
94
- }
95
-
96
- keys(value).forEach((key) => {
97
- internalMerge([...path, key], loopSet)
98
- })
99
- }
100
- }
101
- else {
102
- clone = set(clone, path, value)
103
- }
104
- }
105
-
106
- internalMerge([])
107
- })
108
-
109
- return clone
110
- }