UNPKG

drip-table

Version:

A tiny and powerful enterprise-class solution for building tables.

446 lines (370 loc) 19.8 kB
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } /* * This file is part of the drip-table project. * @link : https://drip-table.jd.com/ * @author : Emil Zhai (root@derzh.com) * @modifier : Emil Zhai (root@derzh.com) * @copyright: Copyright (c) 2021 JD Network Technology Co., Ltd. */ import "./index.less"; import get from 'lodash/get'; import React from 'react'; import { v4 as uuidv4 } from 'uuid'; import { getDripTableValidatePropsKeys, validateDripTableColumnSchema, validateDripTableProp, validateDripTableRequiredProps } from "../utils/ajv"; import { useState } from "../utils/hooks"; import { createEvaluator as defaultCreateExecutor } from "../utils/sandbox"; import DripTableBuiltInComponents from "../components/cell-components"; import { createTableComponentState, DripTableComponentContext } from "../components/cell-components/hooks"; import { stringify } from "../components/cell-components/utils"; import { createTableState, DripTableContext } from "../hooks"; import { indexValue } from "./.."; import DripTableLayout from "../layouts"; /** * 暴露给外部直接操作实例的接口 */ var DripTableWrapper = /*#__PURE__*/React.forwardRef(function (props, ref) { var _props$createEvaluato; // 旧版参数兼容 var tablePropsMigrated = React.useMemo(function () { var _rtp$schema, _rtp$schema$columns; var rtp = props; // 兼容旧版本数据 if ((_rtp$schema = rtp.schema) !== null && _rtp$schema !== void 0 && (_rtp$schema$columns = _rtp$schema.columns) !== null && _rtp$schema$columns !== void 0 && _rtp$schema$columns.some(function (c) { return c['ui:type'] || c['ui:props']; })) { var _rtp$schema2, _rtp$schema2$columns; rtp = _objectSpread(_objectSpread({}, rtp), {}, { schema: Object.assign({}, rtp.schema, { columns: (_rtp$schema2 = rtp.schema) === null || _rtp$schema2 === void 0 ? void 0 : (_rtp$schema2$columns = _rtp$schema2.columns) === null || _rtp$schema2$columns === void 0 ? void 0 : _rtp$schema2$columns.map(function (c) { var column = c; if ('ui:type' in column || 'ui:props' in column) { var key = column.key; if ('ui:type' in column) { console.warn("[DripTable] Column ".concat(key, " \"ui:type\" is deprecated, please use \"component\" instead.")); } if ('ui:props' in column) { console.warn("[DripTable] Column ".concat(key, " \"ui:props\" is deprecated, please use \"options\" instead.")); } return _objectSpread(_objectSpread({}, Object.fromEntries(Object.entries(column).filter(function (_ref) { var _ref2 = _slicedToArray(_ref, 1), k = _ref2[0]; return k !== 'ui:type' && k !== 'ui:props'; }))), {}, { options: column['ui:props'] || column.options || void 0, component: column['ui:type'] || column.component }); } return column; }) }) }); } return rtp; }, [props]); // 列 ajv 校验 var tableProps = React.useMemo(function () { var rtp = tablePropsMigrated; var ajv = rtp.ajv; if (ajv !== false) { var _rtp$schema3, _rtp$schema3$columns; var validateColumnSchema = function validateColumnSchema(column) { var path = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'column'; var errorMessage = null; var schema; var BuiltInComponent = rtp.defaultComponentLib ? null : DripTableBuiltInComponents[column === null || column === void 0 ? void 0 : column.component]; if (BuiltInComponent) { schema = BuiltInComponent.schema; if (!schema) { errorMessage = "Built-in component must contains a valid options ajv schema! (component: ".concat(column.component, ")"); } } else { var _column$component; var _ref3 = (column === null || column === void 0 ? void 0 : (_column$component = column.component) === null || _column$component === void 0 ? void 0 : _column$component.split('::')) || [], _ref4 = _slicedToArray(_ref3, 2), libName = _ref4[0], componentName = _ref4[1]; if (!componentName && rtp.defaultComponentLib) { componentName = libName; libName = rtp.defaultComponentLib; } if (libName && componentName) { var _rtp$components, _rtp$components$libNa, _rtp$components$libNa2; schema = (_rtp$components = rtp.components) === null || _rtp$components === void 0 ? void 0 : (_rtp$components$libNa = _rtp$components[libName]) === null || _rtp$components$libNa === void 0 ? void 0 : (_rtp$components$libNa2 = _rtp$components$libNa[componentName]) === null || _rtp$components$libNa2 === void 0 ? void 0 : _rtp$components$libNa2.schema; } } if (schema && !errorMessage) { var columnErrorMessage = validateDripTableColumnSchema(column, schema, ajv); if (columnErrorMessage) { errorMessage = columnErrorMessage.replace(/^column/, path); } else if (column.component === 'group') { var items = column.options.items; var _iterator = _createForOfIteratorHelper(items.entries()), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var _step$value = _slicedToArray(_step.value, 2), index = _step$value[0], item = _step$value[1]; var itemSchema = item && 'schema' in item ? item.schema : item; var message = validateColumnSchema(itemSchema, "".concat(path !== null && path !== void 0 ? path : '', "/options/items/").concat(index)); if (message) { errorMessage = message; break; } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } } } return errorMessage; }; rtp = _objectSpread(_objectSpread({}, rtp), {}, { schema: Object.assign({}, rtp.schema, { columns: (_rtp$schema3 = rtp.schema) === null || _rtp$schema3 === void 0 ? void 0 : (_rtp$schema3$columns = _rtp$schema3.columns) === null || _rtp$schema3$columns === void 0 ? void 0 : _rtp$schema3$columns.map(function (column) { var errorMessage = validateColumnSchema(column); if (errorMessage) { return { key: column.key, title: column.title, dataIndex: column.dataIndex, component: 'text', options: { mode: 'static', static: errorMessage, className: 'jfe-drip-table-wrapper-column-ajv-error' } }; } return column; }) }) }); } return rtp; }, [tablePropsMigrated]); // 创建上下文 var _useState = useState(createTableState()), _useState2 = _slicedToArray(_useState, 2), state = _useState2[0], setState = _useState2[1]; var _useState3 = useState(createTableComponentState()), _useState4 = _slicedToArray(_useState3, 2), componentState = _useState4[0], setComponentState = _useState4[1]; var _React$useState = React.useState(uuidv4()), _React$useState2 = _slicedToArray(_React$useState, 1), tableUUID = _React$useState2[0]; var tableInfo = React.useMemo(function () { return { uuid: tableUUID, schema: props.schema, dataSource: props.dataSource, parent: props.__PARENT_INFO__ }; }, [props.schema, props.dataSource, props.__PARENT_INFO__]); var createEvaluator = (_props$createEvaluato = props.createEvaluator) !== null && _props$createEvaluato !== void 0 ? _props$createEvaluato : defaultCreateExecutor; var execute = function execute(script) { var _createEvaluator; var ctx = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; return (_createEvaluator = createEvaluator(script, Object.keys(ctx))) === null || _createEvaluator === void 0 ? void 0 : _createEvaluator.apply(void 0, _toConsumableArray(Object.values(ctx))); }; var safeExecute = function safeExecute(script) { var ctx = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var defaultValue = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : void 0; try { return execute(script, ctx); } catch (error) { console.warn(error); } return defaultValue; }; var finalizeString = function finalizeString(mode, text, record, recordIndex, ext) { var value = ''; if (!mode || mode === 'plain') { value = stringify(text); } else if (mode === 'key') { value = stringify(get(record, text, '')); } else if (mode === 'pattern') { value = stringify(text).replace(/\{\{((?:[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+?)\}\}/gi, function (s, s1) { try { return execute("return ".concat(s1), { props: { record: record, recordIndex: recordIndex, ext: ext }, rec: record }); } catch (error) { return error instanceof Error ? "{{Render Error: ".concat(error.message, "}}") : '{{Unknown Render Error}}'; } }); } else if (mode === 'script') { try { value = stringify(execute(text, { props: { record: record, recordIndex: recordIndex, ext: ext }, rec: record })); } catch (error) { value = error instanceof Error ? "Render Error: ".concat(error.message) : 'Unknown Render Error'; } } return value; }; var context = React.useMemo(function () { return { props: tableProps, info: tableInfo, state: state, setState: setState, createEvaluator: createEvaluator, evaluate: execute, safeEvaluate: safeExecute, finalizeString: finalizeString }; }, [props, tableInfo, state, setState, createEvaluator, execute, safeExecute, finalizeString]); var componentContext = React.useMemo(function () { return { props: tableProps, info: tableInfo, state: componentState, setState: setComponentState }; }, [props, tableInfo, componentState, setComponentState]); // 组件提供给外部的公共接口 React.useImperativeHandle(ref, function () { return { select: function select(selectedRowKeys) { setState({ selectedRowKeys: selectedRowKeys }); }, selectedRowKeys: context.state.selectedRowKeys, setDisplayColumnKeys: function setDisplayColumnKeys(displayColumnKeys) { setState({ displayColumnKeys: displayColumnKeys }); }, displayColumnKeys: context.state.displayColumnKeys, sorter: context.state.sorter, setSorter: function setSorter(sorter) { if (sorter) { var columnSchema = tableInfo.schema.columns.find(function (c) { return c.key === sorter.key; }); if (!(columnSchema !== null && columnSchema !== void 0 && columnSchema.sorter)) { return; } setState({ sorter: { key: sorter.key, direction: sorter.direction, comparer: function comparer(a, b) { var multiply = context.safeEvaluate(columnSchema.sorter || '', { props: { column: columnSchema, leftRecord: a, rightRecord: b, leftValue: indexValue(a, columnSchema.dataIndex), rightValue: indexValue(b, columnSchema.dataIndex), ext: tableProps.ext } }, 1); if (typeof multiply !== 'number') { multiply = 1; } return (sorter.direction === 'ascend' ? 1 : -1) * multiply; } }, sorterChanged: true }); } else { setState({ sorter: { key: null, direction: null, comparer: null }, sorterChanged: true }); } } }; }, [setState, indexValue, context.safeEvaluate, context.state.selectedRowKeys, context.state.displayColumnKeys, context.state.sorter, tableInfo.schema.columns]); // 校验参数 var errorMessage = [props.ajv !== false && validateDripTableRequiredProps(props, props.ajv) || ''].concat(_toConsumableArray(getDripTableValidatePropsKeys(props, props.ajv === false ? void 0 : props.ajv).map(function (k) { return React.useMemo(function () { return props.ajv !== false && validateDripTableProp(k, props[k], props.ajv) || ''; }, [k, props[k], props.ajv]); }))).filter(Boolean).join('\n'); if (errorMessage) { return /*#__PURE__*/React.createElement("pre", { className: "jfe-drip-table-wrapper-column-ajv-error" }, "Props validate failed: ".concat(errorMessage.includes('\n') ? '\n' : '').concat(errorMessage)); } React.useEffect(function () { var _tableProps$component; var sorter = tableInfo.schema.initialSorter; if (sorter) { var columnSchema = tableInfo.schema.columns.find(function (c) { return c.key === sorter.key; }); if (!(columnSchema !== null && columnSchema !== void 0 && columnSchema.sorter)) { return; } setState({ sorter: { key: sorter.key, direction: sorter.direction, comparer: function comparer(a, b) { var multiply = context.safeEvaluate(columnSchema.sorter || '', { props: { column: columnSchema, leftRecord: a, rightRecord: b, leftValue: indexValue(a, columnSchema.dataIndex), rightValue: indexValue(b, columnSchema.dataIndex), ext: tableProps.ext } }, 1); if (typeof multiply !== 'number') { multiply = 1; } return (sorter.direction === 'ascend' ? 1 : -1) * multiply; } }, sorterChanged: true }); } (_tableProps$component = tableProps.componentDidMount) === null || _tableProps$component === void 0 ? void 0 : _tableProps$component.call(tableProps, tableInfo); return function () { var _tableProps$component2; (_tableProps$component2 = tableProps.componentWillUnmount) === null || _tableProps$component2 === void 0 ? void 0 : _tableProps$component2.call(tableProps, tableInfo); }; }, []); React.useEffect(function () { var _tableProps$component3; (_tableProps$component3 = tableProps.componentDidUpdate) === null || _tableProps$component3 === void 0 ? void 0 : _tableProps$component3.call(tableProps, tableInfo); }); return /*#__PURE__*/React.createElement(DripTableContext.Provider, { value: context }, /*#__PURE__*/React.createElement(DripTableComponentContext.Provider, { value: componentContext }, /*#__PURE__*/React.createElement(DripTableLayout, null))); }); export default DripTableWrapper;