@schema-render/core-react
Version:
Through a set of simple JSON Schema, efficiently build a set of forms.
88 lines (87 loc) • 3.72 kB
JavaScript
import { useImperativeHandle } from "react";
import { EValidationStatus } from "../constants";
import { isArray, isString } from "../utils/checking";
import { positionedOffset } from "../utils/dom";
import { stringifyPath } from "../utils/misc";
import { pick } from "../utils/tinyLodash";
import { validateRootSchema } from "../utils/validator";
import useMemoizedFn from "./useMemoizedFn";
/**
* 内部滚动到指定表单项位置方法
* @param formItemElement 表单项 DOM 元素
* @param coreRootElement 内核根节点元素
* @param options 参数
*/ function internalScrollTo(formItemElement, coreRootElement, options = {}) {
if (!formItemElement) {
return;
}
// 解构参数,并赋予默认值
const { positionedElement, xAxis, yAxis, behavior = 'smooth', gap = 0 } = options;
// 表单内部滚动,取根节点元素,否则取用户指定的 “定位元素”
const scrollElement = positionedElement || coreRootElement;
if (scrollElement) {
// 获取指定表单项元素到滚动祖先元素的距离
const offset = positionedOffset(formItemElement, scrollElement);
// 滚动到指定位置
scrollElement.scrollTo({
left: xAxis === false ? undefined : offset.left + gap,
top: yAxis === false ? undefined : offset.top + gap,
behavior
});
}
}
/**
* 开放 API
*/ export default function useOpenApi({ ref, rootElementRef, rootContextRef, getValue, setValue, resetValue }) {
const validate = useMemoizedFn(()=>{
return validateRootSchema(pick(rootContextRef.current, 'rootSchema', 'rootValue', 'locale', 'disabled', 'readonly', 'renderers', 'rendererStorage', 'validators', 'userCtx'));
});
/**
* 查找指定表单项
*/ const findItem = useMemoizedFn((paths)=>{
var _rootContextRef_current;
const renderers = (_rootContextRef_current = rootContextRef.current) === null || _rootContextRef_current === void 0 ? void 0 : _rootContextRef_current.rendererStorage;
if (renderers && paths) {
const sPath = isArray(paths) ? stringifyPath(paths) : paths;
return renderers[sPath];
}
});
/**
* 重置错误与警告
*/ const resetError = useMemoizedFn((paths)=>{
var _rootContextRef_current;
const renderers = (_rootContextRef_current = rootContextRef.current) === null || _rootContextRef_current === void 0 ? void 0 : _rootContextRef_current.rendererStorage;
if (renderers) {
const pathList = !paths ? Object.keys(renderers) : isString(paths) ? [
paths
] : paths;
pathList.forEach((pathKey)=>{
var _renderers_pathKey;
(_renderers_pathKey = renderers[pathKey]) === null || _renderers_pathKey === void 0 ? void 0 : _renderers_pathKey.setValidatorState({
status: EValidationStatus.success
});
});
}
});
/**
* 获取 Core 根节点元素
*/ const getRootElement = useMemoizedFn(()=>rootElementRef.current);
/**
* 滚动到指定位置
*/ const scrollTo = useMemoizedFn((paths, options)=>{
var _findItem;
return internalScrollTo((_findItem = findItem(paths)) === null || _findItem === void 0 ? void 0 : _findItem.getRootElement(), getRootElement(), options);
});
// 暴露开放 API
useImperativeHandle(ref, ()=>({
validate,
resetError,
setValue,
resetValue,
getValue,
getRootElement,
scrollTo,
findItem
}), // eslint-disable-next-line react-hooks/exhaustive-deps
[]);
}