Match-id-a177994d0b3fe27dac34cee64bf01b1ba92b9310
This commit is contained in:
parent
e31ed399de
commit
eec4863d61
|
@ -1,7 +1,7 @@
|
||||||
import {throwIfTrue} from '../renderer/utils/throwIfTrue';
|
import { throwIfTrue } from '../renderer/utils/throwIfTrue';
|
||||||
import {TYPE_COMMON_ELEMENT, TYPE_PORTAL} from './JSXElementType';
|
import { TYPE_COMMON_ELEMENT, TYPE_PORTAL } from './JSXElementType';
|
||||||
|
|
||||||
import {isValidElement, JSXElement} from './JSXElement';
|
import { isValidElement, JSXElement } from './JSXElement';
|
||||||
|
|
||||||
// 生成key
|
// 生成key
|
||||||
function getItemKey(item: any, index: number): string {
|
function getItemKey(item: any, index: number): string {
|
||||||
|
@ -12,12 +12,7 @@ function getItemKey(item: any, index: number): string {
|
||||||
return '.' + index.toString(36);
|
return '.' + index.toString(36);
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapChildrenToArray(
|
function mapChildrenToArray(children: any, arr: Array<any>, prefix: string, callback?: Function): number | void {
|
||||||
children: any,
|
|
||||||
arr: Array<any>,
|
|
||||||
prefix: string,
|
|
||||||
callback?: Function,
|
|
||||||
): number | void {
|
|
||||||
const type = typeof children;
|
const type = typeof children;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
// 继承原有规格,undefined和boolean类型按照null处理
|
// 继承原有规格,undefined和boolean类型按照null处理
|
||||||
|
@ -36,44 +31,27 @@ function mapChildrenToArray(
|
||||||
}
|
}
|
||||||
const vtype = children.vtype;
|
const vtype = children.vtype;
|
||||||
if (vtype === TYPE_COMMON_ELEMENT || vtype === TYPE_PORTAL) {
|
if (vtype === TYPE_COMMON_ELEMENT || vtype === TYPE_PORTAL) {
|
||||||
callMapFun(children, arr, prefix, callback) ;
|
callMapFun(children, arr, prefix, callback);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (Array.isArray(children)) {
|
if (Array.isArray(children)) {
|
||||||
processArrayChildren(children, arr, prefix, callback);
|
processArrayChildren(children, arr, prefix, callback);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw new Error(
|
throw new Error('Object is invalid as a Horizon child. ');
|
||||||
'Object is invalid as a Horizon child. '
|
|
||||||
);
|
|
||||||
// No Default
|
// No Default
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function processArrayChildren(
|
function processArrayChildren(children: any, arr: Array<any>, prefix: string, callback: Function) {
|
||||||
children: any,
|
|
||||||
arr: Array<any>,
|
|
||||||
prefix: string,
|
|
||||||
callback: Function,
|
|
||||||
) {
|
|
||||||
for (let i = 0; i < children.length; i++) {
|
for (let i = 0; i < children.length; i++) {
|
||||||
const childItem = children[i];
|
const childItem = children[i];
|
||||||
const nextPrefix = prefix + getItemKey(childItem, i);
|
const nextPrefix = prefix + getItemKey(childItem, i);
|
||||||
mapChildrenToArray(
|
mapChildrenToArray(childItem, arr, nextPrefix, callback);
|
||||||
childItem,
|
|
||||||
arr,
|
|
||||||
nextPrefix,
|
|
||||||
callback,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function callMapFun(
|
function callMapFun(children: any, arr: Array<any>, prefix: string, callback: Function) {
|
||||||
children: any,
|
|
||||||
arr: Array<any>,
|
|
||||||
prefix: string,
|
|
||||||
callback: Function,
|
|
||||||
) {
|
|
||||||
let mappedChild = callback(children);
|
let mappedChild = callback(children);
|
||||||
if (Array.isArray(mappedChild)) {
|
if (Array.isArray(mappedChild)) {
|
||||||
// 维持原有规格,如果callback返回结果是数组,处理函数修改为返回数组item
|
// 维持原有规格,如果callback返回结果是数组,处理函数修改为返回数组item
|
||||||
|
@ -83,9 +61,8 @@ function callMapFun(
|
||||||
if (isValidElement(mappedChild)) {
|
if (isValidElement(mappedChild)) {
|
||||||
const childKey = prefix === '' ? getItemKey(children, 0) : '';
|
const childKey = prefix === '' ? getItemKey(children, 0) : '';
|
||||||
const mappedKey = getItemKey(mappedChild, 0);
|
const mappedKey = getItemKey(mappedChild, 0);
|
||||||
const newKey = prefix + childKey + (mappedChild.key && mappedKey !== getItemKey(children, 0)
|
const newKey =
|
||||||
? '.$' + mappedChild.key
|
prefix + childKey + (mappedChild.key && mappedKey !== getItemKey(children, 0) ? '.$' + mappedChild.key : '');
|
||||||
: '');
|
|
||||||
// 返回一个修改key的children
|
// 返回一个修改key的children
|
||||||
mappedChild = JSXElement(
|
mappedChild = JSXElement(
|
||||||
mappedChild.type,
|
mappedChild.type,
|
||||||
|
@ -93,6 +70,7 @@ function callMapFun(
|
||||||
mappedChild.ref,
|
mappedChild.ref,
|
||||||
mappedChild.belongClassVNode,
|
mappedChild.belongClassVNode,
|
||||||
mappedChild.props,
|
mappedChild.props,
|
||||||
|
mappedChild.source
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
arr.push(mappedChild);
|
arr.push(mappedChild);
|
||||||
|
@ -100,11 +78,7 @@ function callMapFun(
|
||||||
}
|
}
|
||||||
|
|
||||||
// 在 children 里的每个直接子节点上调用一个函数,并将 this 设置为 thisArg
|
// 在 children 里的每个直接子节点上调用一个函数,并将 this 设置为 thisArg
|
||||||
function mapChildren(
|
function mapChildren(children: any, func: Function, context?: any): Array<any> {
|
||||||
children: any,
|
|
||||||
func: Function,
|
|
||||||
context?: any,
|
|
||||||
): Array<any> {
|
|
||||||
if (children === null || children === undefined) {
|
if (children === null || children === undefined) {
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
@ -121,27 +95,22 @@ const Children = {
|
||||||
},
|
},
|
||||||
map: mapChildren,
|
map: mapChildren,
|
||||||
// 并非所有元素都会计数,只计数调用callMapFun函数次数
|
// 并非所有元素都会计数,只计数调用callMapFun函数次数
|
||||||
count: (children) => {
|
count: children => {
|
||||||
let n = 0;
|
let n = 0;
|
||||||
mapChildren(children, () => {
|
mapChildren(children, () => {
|
||||||
n++;
|
n++;
|
||||||
});
|
});
|
||||||
return n;
|
return n;
|
||||||
},
|
},
|
||||||
only: (children) => {
|
only: children => {
|
||||||
throwIfTrue(
|
throwIfTrue(!isValidElement(children), 'Horizon.Children.only function received invalid element.');
|
||||||
!isValidElement(children),
|
|
||||||
'Horizon.Children.only function received invalid element.'
|
|
||||||
);
|
|
||||||
return children;
|
return children;
|
||||||
},
|
},
|
||||||
toArray: (children) => {
|
toArray: children => {
|
||||||
const result = [];
|
const result = [];
|
||||||
mapChildrenToArray(children, result, '', child => child);
|
mapChildrenToArray(children, result, '', child => child);
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
}
|
|
||||||
|
|
||||||
export {
|
|
||||||
Children
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { Children };
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { TYPE_COMMON_ELEMENT } from './JSXElementType';
|
import {TYPE_COMMON_ELEMENT} from './JSXElementType';
|
||||||
import { getProcessingClassVNode } from '../renderer/GlobalVar';
|
import {getProcessingClassVNode} from '../renderer/GlobalVar';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,7 +31,7 @@ function isValidKey(key) {
|
||||||
'key',
|
'key',
|
||||||
'ref',
|
'ref',
|
||||||
'__source',
|
'__source',
|
||||||
'__self'
|
'__self',
|
||||||
];
|
];
|
||||||
return !keyArray.includes(key);
|
return !keyArray.includes(key);
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ function buildElement(isClone, type, setting, children) {
|
||||||
// setting中的值优先级最高,clone情况下从 type 中取值,创建情况下直接赋值为 null
|
// setting中的值优先级最高,clone情况下从 type 中取值,创建情况下直接赋值为 null
|
||||||
const key = (setting && setting.key !== undefined) ? String(setting.key) : (isClone ? type.key : null);
|
const key = (setting && setting.key !== undefined) ? String(setting.key) : (isClone ? type.key : null);
|
||||||
const ref = (setting && setting.ref !== undefined) ? setting.ref : (isClone ? type.ref : null);
|
const ref = (setting && setting.ref !== undefined) ? setting.ref : (isClone ? type.ref : null);
|
||||||
const props = isClone ? { ...type.props } : {};
|
const props = isClone ? {...type.props} : {};
|
||||||
let vNode = isClone ? type.belongClassVNode : getProcessingClassVNode();
|
let vNode = isClone ? type.belongClassVNode : getProcessingClassVNode();
|
||||||
|
|
||||||
if (setting !== null && setting !== undefined) {
|
if (setting !== null && setting !== undefined) {
|
||||||
|
@ -74,9 +74,7 @@ function buildElement(isClone, type, setting, children) {
|
||||||
mergeDefault(props, element.defaultProps);
|
mergeDefault(props, element.defaultProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
const source = setting?.__source === undefined ? null : setting.__source;
|
return JSXElement(element, key, ref, vNode, props, setting?.__source ?? null);
|
||||||
|
|
||||||
return JSXElement(element, key, ref, vNode, props, source);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建Element结构体,供JSX编译时调用
|
// 创建Element结构体,供JSX编译时调用
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { travelVNodeTree } from '../renderer/vnode/VNodeUtils';
|
import {travelVNodeTree} from '../renderer/vnode/VNodeUtils';
|
||||||
import { Hook, Reducer, Ref, Effect, CallBack, Memo } from '../renderer/hooks/HookType';
|
import {Hook, Reducer, Ref, Effect, CallBack, Memo} from '../renderer/hooks/HookType';
|
||||||
import { VNode } from '../renderer/vnode/VNode';
|
import {VNode} from '../renderer/vnode/VNode';
|
||||||
import { launchUpdateFromVNode } from '../renderer/TreeBuilder';
|
import {launchUpdateFromVNode} from '../renderer/TreeBuilder';
|
||||||
import { DomComponent } from '../renderer/vnode/VNodeTags';
|
import {DomComponent} from '../renderer/vnode/VNodeTags';
|
||||||
import { getElementTag } from '../renderer/vnode/VNodeCreator';
|
import {getElementTag} from '../renderer/vnode/VNodeCreator';
|
||||||
import { JSXElement } from '../renderer/Types';
|
import {JSXElement} from '../renderer/Types';
|
||||||
import { EffectConstant } from '../renderer/hooks/EffectConstant';
|
import {EffectConstant} from '../renderer/hooks/EffectConstant';
|
||||||
|
|
||||||
const isEffectHook = (state: any): state is Effect => !!state.effect;
|
const isEffectHook = (state: any): state is Effect => !!state.effect;
|
||||||
const isRefHook = (state: any): state is Ref<any> => Object.prototype.hasOwnProperty.call(state, 'current');
|
const isRefHook = (state: any): state is Ref<any> => Object.prototype.hasOwnProperty.call(state, 'current');
|
||||||
|
@ -28,23 +28,23 @@ export const helper = {
|
||||||
},
|
},
|
||||||
// 获取 hook 名,hIndex值和存储的值
|
// 获取 hook 名,hIndex值和存储的值
|
||||||
getHookInfo: (hook: Hook<any, any>) => {
|
getHookInfo: (hook: Hook<any, any>) => {
|
||||||
const { hIndex, state } = hook;
|
const {hIndex, state} = hook;
|
||||||
if ((state as Reducer<any, any>).trigger) {
|
if ((state as Reducer<any, any>).trigger) {
|
||||||
if ((state as Reducer<any, any>).isUseState) {
|
if ((state as Reducer<any, any>).isUseState) {
|
||||||
return { name: HookName.StateHook, hIndex, value: (state as Reducer<any, any>).stateValue };
|
return {name: HookName.StateHook, hIndex, value: (state as Reducer<any, any>).stateValue};
|
||||||
} else if ((state as Reducer<any, any>).reducer) {
|
} else if ((state as Reducer<any, any>).reducer) {
|
||||||
return { name: HookName.ReducerHook, hIndex, value: (state as Reducer<any, any>).stateValue };
|
return {name: HookName.ReducerHook, hIndex, value: (state as Reducer<any, any>).stateValue};
|
||||||
}
|
}
|
||||||
} else if (isRefHook(state)) {
|
} else if (isRefHook(state)) {
|
||||||
return { name: HookName.RefHook, hIndex, value: (state as Ref<any>).current };
|
return {name: HookName.RefHook, hIndex, value: (state as Ref<any>).current};
|
||||||
} else if (isEffectHook(state)) {
|
} else if (isEffectHook(state)) {
|
||||||
const name =
|
const name =
|
||||||
state.effectConstant == EffectConstant.LayoutEffect ? HookName.LayoutEffectHook : HookName.EffectHook;
|
state.effectConstant == EffectConstant.LayoutEffect ? HookName.LayoutEffectHook : HookName.EffectHook;
|
||||||
return { name, hIndex, value: (state as Effect).effect };
|
return {name, hIndex, value: (state as Effect).effect};
|
||||||
} else if (isCallbackHook(state)) {
|
} else if (isCallbackHook(state)) {
|
||||||
return { name: HookName.CallbackHook, hIndex, value: (state as CallBack<any>).func };
|
return {name: HookName.CallbackHook, hIndex, value: (state as CallBack<any>).func};
|
||||||
} else if (isMemoHook(state)) {
|
} else if (isMemoHook(state)) {
|
||||||
return { name: HookName.MemoHook, hIndex, value: (state as Memo<any>).result };
|
return {name: HookName.MemoHook, hIndex, value: (state as Memo<any>).result};
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
@ -70,7 +70,7 @@ export const helper = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getComponentInfo: (vNode: VNode) => {
|
getComponentInfo: (vNode: VNode) => {
|
||||||
const { props, state, hooks } = vNode;
|
const {props, state, hooks} = vNode;
|
||||||
const info: any = {};
|
const info: any = {};
|
||||||
if (props && Object.keys(props).length !== 0) {
|
if (props && Object.keys(props).length !== 0) {
|
||||||
info['Props'] = props;
|
info['Props'] = props;
|
||||||
|
@ -98,11 +98,7 @@ export const helper = {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
}, null, vNode, null);
|
||||||
null,
|
|
||||||
vNode,
|
|
||||||
null
|
|
||||||
);
|
|
||||||
return info;
|
return info;
|
||||||
},
|
},
|
||||||
getElementTag: (element: JSXElement) => {
|
getElementTag: (element: JSXElement) => {
|
||||||
|
|
|
@ -27,8 +27,8 @@ export type ProviderType<T> = {
|
||||||
|
|
||||||
export type ContextType<T> = {
|
export type ContextType<T> = {
|
||||||
vtype: number;
|
vtype: number;
|
||||||
Consumer: ContextType<T>;
|
Consumer: ContextType<T> | null;
|
||||||
Provider: ProviderType<T>;
|
Provider: ProviderType<T> | null;
|
||||||
value: T;
|
value: T;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ export function captureMemoComponent(
|
||||||
if (type === TYPE_STRICT_MODE || type === TYPE_FRAGMENT || type === TYPE_PROFILER) {
|
if (type === TYPE_STRICT_MODE || type === TYPE_FRAGMENT || type === TYPE_PROFILER) {
|
||||||
newChild = createFragmentVNode(null, newProps.children);
|
newChild = createFragmentVNode(null, newProps.children);
|
||||||
} else {
|
} else {
|
||||||
newChild = createUndeterminedVNode(type, null, newProps);
|
newChild = createUndeterminedVNode(type, null, newProps,processing.src);
|
||||||
}
|
}
|
||||||
newChild.parent = processing;
|
newChild.parent = processing;
|
||||||
newChild.ref = processing.ref;
|
newChild.ref = processing.ref;
|
||||||
|
|
|
@ -17,10 +17,10 @@ import {
|
||||||
Profiler,
|
Profiler,
|
||||||
MemoComponent,
|
MemoComponent,
|
||||||
} from './VNodeTags';
|
} from './VNodeTags';
|
||||||
import type { VNodeTag } from './VNodeTags';
|
import type {VNodeTag} from './VNodeTags';
|
||||||
import type { RefType, ContextType, SuspenseState, Source } from '../Types';
|
import type {RefType, ContextType, SuspenseState, Source} from '../Types';
|
||||||
import type { Hook } from '../hooks/HookType';
|
import type {Hook} from '../hooks/HookType';
|
||||||
import { InitFlag } from './VNodeFlags';
|
import {InitFlag} from './VNodeFlags';
|
||||||
|
|
||||||
export class VNode {
|
export class VNode {
|
||||||
tag: VNodeTag;
|
tag: VNodeTag;
|
||||||
|
@ -77,8 +77,8 @@ export class VNode {
|
||||||
|
|
||||||
// 根节点数据
|
// 根节点数据
|
||||||
toUpdateNodes: Set<VNode> | null; // 保存要更新的节点
|
toUpdateNodes: Set<VNode> | null; // 保存要更新的节点
|
||||||
delegatedEvents: Set<string>
|
delegatedEvents: Set<string>;
|
||||||
delegatedNativeEvents: Set<string>
|
delegatedNativeEvents: Set<string>;
|
||||||
|
|
||||||
belongClassVNode: VNode | null = null; // 记录JSXElement所属class vNode,处理ref的时候使用
|
belongClassVNode: VNode | null = null; // 记录JSXElement所属class vNode,处理ref的时候使用
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ export class VNode {
|
||||||
isStoreChange: boolean;
|
isStoreChange: boolean;
|
||||||
observers: Set<any> | null = null; // 记录这个函数组件/类组件依赖哪些Observer
|
observers: Set<any> | null = null; // 记录这个函数组件/类组件依赖哪些Observer
|
||||||
classComponentWillUnmount: Function | null; // HorizonX会在classComponentWillUnmount中清除对VNode的引入用
|
classComponentWillUnmount: Function | null; // HorizonX会在classComponentWillUnmount中清除对VNode的引入用
|
||||||
source: Source | null; // 节点所在代码位置
|
src: Source | null; // 节点所在代码位置
|
||||||
|
|
||||||
constructor(tag: VNodeTag, props: any, key: null | string, realNode) {
|
constructor(tag: VNodeTag, props: any, key: null | string, realNode) {
|
||||||
this.tag = tag; // 对应组件的类型,比如ClassComponent等
|
this.tag = tag; // 对应组件的类型,比如ClassComponent等
|
||||||
|
@ -117,7 +117,7 @@ export class VNode {
|
||||||
this.isStoreChange = false;
|
this.isStoreChange = false;
|
||||||
this.observers = null;
|
this.observers = null;
|
||||||
this.classComponentWillUnmount = null;
|
this.classComponentWillUnmount = null;
|
||||||
this.source = null;
|
this.src = null;
|
||||||
break;
|
break;
|
||||||
case ClassComponent:
|
case ClassComponent:
|
||||||
this.realNode = null;
|
this.realNode = null;
|
||||||
|
@ -132,18 +132,18 @@ export class VNode {
|
||||||
this.isStoreChange = false;
|
this.isStoreChange = false;
|
||||||
this.observers = null;
|
this.observers = null;
|
||||||
this.classComponentWillUnmount = null;
|
this.classComponentWillUnmount = null;
|
||||||
this.source = null;
|
this.src = null;
|
||||||
break;
|
break;
|
||||||
case DomPortal:
|
case DomPortal:
|
||||||
this.realNode = null;
|
this.realNode = null;
|
||||||
this.context = null;
|
this.context = null;
|
||||||
this.source = null;
|
this.src = null;
|
||||||
break;
|
break;
|
||||||
case DomComponent:
|
case DomComponent:
|
||||||
this.realNode = null;
|
this.realNode = null;
|
||||||
this.changeList = null;
|
this.changeList = null;
|
||||||
this.context = null;
|
this.context = null;
|
||||||
this.source = null;
|
this.src = null;
|
||||||
break;
|
break;
|
||||||
case DomText:
|
case DomText:
|
||||||
this.realNode = null;
|
this.realNode = null;
|
||||||
|
@ -155,17 +155,17 @@ export class VNode {
|
||||||
didCapture: false,
|
didCapture: false,
|
||||||
promiseResolved: false,
|
promiseResolved: false,
|
||||||
oldChildStatus: '',
|
oldChildStatus: '',
|
||||||
childStatus: ''
|
childStatus: '',
|
||||||
};
|
};
|
||||||
this.source = null;
|
this.src = null;
|
||||||
break;
|
break;
|
||||||
case ContextProvider:
|
case ContextProvider:
|
||||||
this.source = null;
|
this.src = null;
|
||||||
this.context = null;
|
this.context = null;
|
||||||
break;
|
break;
|
||||||
case MemoComponent:
|
case MemoComponent:
|
||||||
this.effectList = null;
|
this.effectList = null;
|
||||||
this.source = null;
|
this.src = null;
|
||||||
break;
|
break;
|
||||||
case LazyComponent:
|
case LazyComponent:
|
||||||
this.realNode = null;
|
this.realNode = null;
|
||||||
|
@ -173,7 +173,7 @@ export class VNode {
|
||||||
this.isLazyComponent = true;
|
this.isLazyComponent = true;
|
||||||
this.lazyType = null;
|
this.lazyType = null;
|
||||||
this.updates = null;
|
this.updates = null;
|
||||||
this.source = null;
|
this.src = null;
|
||||||
break;
|
break;
|
||||||
case Fragment:
|
case Fragment:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -132,7 +132,7 @@ export function createUndeterminedVNode(type, key, props, source) {
|
||||||
if (isLazy) {
|
if (isLazy) {
|
||||||
vNode.lazyType = type;
|
vNode.lazyType = type;
|
||||||
}
|
}
|
||||||
vNode.source = source;
|
vNode.src = source;
|
||||||
return vNode;
|
return vNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
"@babel/plugin-transform-shorthand-properties": "7.16.7",
|
"@babel/plugin-transform-shorthand-properties": "7.16.7",
|
||||||
"@babel/plugin-transform-spread": "7.16.7",
|
"@babel/plugin-transform-spread": "7.16.7",
|
||||||
"@babel/plugin-transform-template-literals": "7.16.7",
|
"@babel/plugin-transform-template-literals": "7.16.7",
|
||||||
"@babel/plugin-transform-react-jsx-source": "^7.18.6",
|
"@babel/plugin-transform-react-jsx-source": "^7.16.7",
|
||||||
"@babel/preset-env": "7.16.7",
|
"@babel/preset-env": "7.16.7",
|
||||||
"@babel/preset-react": "7.16.7",
|
"@babel/preset-react": "7.16.7",
|
||||||
"@babel/preset-typescript": "7.16.7",
|
"@babel/preset-typescript": "7.16.7",
|
||||||
|
|
Loading…
Reference in New Issue