UNPKG

@handsontable/react-wrapper

Version:

Best Data Grid for React with Spreadsheet Look and Feel.

1,134 lines (1,112 loc) 45.4 kB
/*! * Copyright (c) HANDSONCODE sp. z o. o. * * HANDSONTABLE is a software distributed by HANDSONCODE sp. z o. o., a Polish corporation based in * Gdynia, Poland, at Aleja Zwyciestwa 96-98, registered by the District Court in Gdansk under number * 538651, EU tax ID number: PL5862294002, share capital: PLN 62,800.00. * * This software is protected by applicable copyright laws, including international treaties, and dual- * licensed - depending on whether your use for commercial purposes, meaning intended for or * resulting in commercial advantage or monetary compensation, or not. * * If your use is strictly personal or solely for evaluation purposes, meaning for the purposes of testing * the suitability, performance, and usefulness of this software outside the production environment, * you agree to be bound by the terms included in the "handsontable-non-commercial-license.pdf" file. * * Your use of this software for commercial purposes is subject to the terms included in an applicable * license agreement. * * In any case, you must not make any such use of this software as to develop software which may be * considered competitive with this software. * * UNLESS EXPRESSLY AGREED OTHERWISE, HANDSONCODE PROVIDES THIS SOFTWARE ON AN "AS IS" * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, AND IN NO EVENT AND UNDER NO * LEGAL THEORY, SHALL HANDSONCODE BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY DIRECT, * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER ARISING FROM * USE OR INABILITY TO USE THIS SOFTWARE. * * Version: 16.1.1 (built at Tue Sep 23 2025 14:17:52 GMT+0200 (Central European Summer Time)) */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('react-dom'), require('handsontable/base'), require('handsontable/renderers/registry'), require('handsontable/editors/registry')) : typeof define === 'function' && define.amd ? define(['exports', 'react', 'react-dom', 'handsontable/base', 'handsontable/renderers/registry', 'handsontable/editors/registry'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.Handsontable = global.Handsontable || {}, global.Handsontable.react = {}), global.React, global.ReactDOM, global.Handsontable, global.Handsontable.renderers, global.Handsontable.editors)); })(this, (function (exports, React, ReactDOM, Handsontable, registry, registry$1) { 'use strict'; function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; } var React__default = /*#__PURE__*/_interopDefaultCompat(React); var ReactDOM__default = /*#__PURE__*/_interopDefaultCompat(ReactDOM); var Handsontable__default = /*#__PURE__*/_interopDefaultCompat(Handsontable); var bulkComponentContainer = null; /** * Warning message for the `autoRowSize`/`autoColumnSize` compatibility check. */ var AUTOSIZE_WARNING = 'Your `HotTable` configuration includes `autoRowSize`/`autoColumnSize` options, which are not compatible with ' + ' the component-based renderers`. Disable `autoRowSize` and `autoColumnSize` to prevent row and column misalignment.'; /** * Warning message for the `hot-renderer` obsolete renderer passing method. */ var OBSOLETE_HOTRENDERER_WARNING = 'Providing a component-based renderer using `hot-renderer`-annotated component is no longer supported. ' + 'Pass your component using `renderer` prop of the `HotTable` or `HotColumn` component instead.'; /** * Warning message for the `hot-editor` obsolete editor passing method. */ var OBSOLETE_HOTEDITOR_WARNING = 'Providing a component-based editor using `hot-editor`-annotated component is no longer supported. ' + 'Pass your component using `editor` prop of the `HotTable` or `HotColumn` component instead.'; /** * Warning message for the unexpected children of HotTable component. */ var UNEXPECTED_HOTTABLE_CHILDREN_WARNING = 'Unexpected children nodes found in HotTable component. ' + 'Only HotColumn components are allowed.'; /** * Warning message for the unexpected children of HotColumn component. */ var UNEXPECTED_HOTCOLUMN_CHILDREN_WARNING = 'Unexpected children nodes found in HotColumn component. ' + 'HotColumn components do not support any children.'; /** * Message for the warning thrown if the Handsontable instance has been destroyed. */ var HOT_DESTROYED_WARNING = 'The Handsontable instance bound to this component was destroyed and cannot be' + ' used properly.'; /** * Default classname given to the wrapper container. */ var DEFAULT_CLASSNAME = 'hot-wrapper-editor-container'; /** * Logs warn to the console if the `console` object is exposed. * * @param {...*} args Values which will be logged. */ function warn() { if (typeof console !== 'undefined') { var _console; (_console = console).warn.apply(_console, arguments); } } /** * Detect if `hot-renderer` or `hot-editor` is defined, and if so, throw an incompatibility warning. * * @returns {boolean} 'true' if the warning was issued */ function displayObsoleteRenderersEditorsWarning(children) { if (hasChildElementOfType(children, 'hot-renderer')) { warn(OBSOLETE_HOTRENDERER_WARNING); return true; } if (hasChildElementOfType(children, 'hot-editor')) { warn(OBSOLETE_HOTEDITOR_WARNING); return true; } return false; } /** * Detect if children of specified type are defined, and if so, throw an incompatibility warning. * * @param {ReactNode} children Component children nodes * @param {ComponentType} Component Component type to check * @returns {boolean} 'true' if the warning was issued */ function displayChildrenOfTypeWarning(children, Component) { var childrenArray = React__default["default"].Children.toArray(children); if (childrenArray.some(function (child) { return child.type !== Component; })) { warn(UNEXPECTED_HOTTABLE_CHILDREN_WARNING); return true; } return false; } /** * Detect if children is defined, and if so, throw an incompatibility warning. * * @param {ReactNode} children Component children nodes * @returns {boolean} 'true' if the warning was issued */ function displayAnyChildrenWarning(children) { var childrenArray = React__default["default"].Children.toArray(children); if (childrenArray.length) { warn(UNEXPECTED_HOTCOLUMN_CHILDREN_WARNING); return true; } return false; } /** * Check the existence of elements of the provided `type` from the `HotColumn` component's children. * * @param {ReactNode} children HotTable children array. * @param {String} type Either `'hot-renderer'` or `'hot-editor'`. * @returns {boolean} `true` if the child of that type was found, `false` otherwise. */ function hasChildElementOfType(children, type) { var childrenArray = React__default["default"].Children.toArray(children); return childrenArray.some(function (child) { return child.props[type] !== void 0; }); } /** * Create an editor portal. * * @param {Document} doc Document to be used. * @param {ComponentType} Editor Editor component or render function. * @returns {ReactPortal} The portal for the editor. */ function createEditorPortal(doc, Editor) { if (!doc || !Editor || typeof Editor === 'boolean') { return null; } var editorElement = React__default["default"].createElement(Editor, null); var containerProps = getContainerAttributesProps({}, false); containerProps.className = "".concat(DEFAULT_CLASSNAME, " ").concat(containerProps.className); return ReactDOM__default["default"].createPortal(React__default["default"].createElement("div", Object.assign({}, containerProps), editorElement), doc.body); } /** * Render a cell component to an external DOM node. * * @param {React.ReactElement} rElement React element to be used as a base for the component. * @param {Document} [ownerDocument] The owner document to set the portal up into. * @param {String} portalKey The key to be used for the portal. * @param {HTMLElement} [cachedContainer] The cached container to be used for the portal. * @returns {{portal: ReactPortal, portalContainer: HTMLElement}} An object containing the portal and its container. */ function createPortal(rElement) { var ownerDocument = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : document; var portalKey = arguments.length > 2 ? arguments[2] : undefined; var cachedContainer = arguments.length > 3 ? arguments[3] : undefined; if (!ownerDocument) { ownerDocument = document; } if (!bulkComponentContainer) { bulkComponentContainer = ownerDocument.createDocumentFragment(); } var portalContainer = cachedContainer !== null && cachedContainer !== void 0 ? cachedContainer : ownerDocument.createElement('DIV'); bulkComponentContainer.appendChild(portalContainer); return { portal: ReactDOM__default["default"].createPortal(rElement, portalContainer, portalKey), portalContainer: portalContainer }; } /** * Get an object containing the `id`, `className` and `style` keys, representing the corresponding props passed to the * component. * * @param {HotTableProps} props Object containing the React element props. * @param {Boolean} randomizeId If set to `true`, the function will randomize the `id` property when no `id` was present in the `prop` object. * @returns An object containing the `id`, `className` and `style` keys, representing the corresponding props passed to the * component. */ function getContainerAttributesProps(props) { var randomizeId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; return { id: props.id || (randomizeId ? 'hot-' + Math.random().toString(36).substring(5) : undefined), className: props.className || '', style: props.style || {} }; } /** * Checks if the environment that the code runs in is a browser. * * @returns {boolean} */ function isCSR() { return typeof window !== 'undefined'; } /** * A variant of useEffect hook that does not trigger on initial mount, only updates * * @param effect Effect function * @param deps Effect dependencies */ function useUpdateEffect(effect, deps) { var notInitialRender = React__default["default"].useRef(false); React.useEffect(function () { if (notInitialRender.current) { return effect(); } else { notInitialRender.current = true; } }, deps); } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); } function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; } function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || false, o.configurable = true, "value" in o && (o.writable = true), Object.defineProperty(e, _toPropertyKey(o.key), o); } } function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: false }), e; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e; } function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); } function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: true, configurable: true } }), Object.defineProperty(t, "prototype", { writable: false }), e && _setPrototypeOf(t, e); } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function () { return !!t; })(); } function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); } function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = true, o = false; try { if (i = (t = t.call(r)).next, 0 === l) ; else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = true, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } 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 _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 ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread2(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; } function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; } function _possibleConstructorReturn(t, e) { if (e && ("object" == typeof e || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); } function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); } function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); } function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return (String )(t); } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } var SettingsMapper = /*#__PURE__*/function () { function SettingsMapper() { _classCallCheck(this, SettingsMapper); } return _createClass(SettingsMapper, null, [{ key: "getSettings", value: /** * Parse component settings into Handsontable-compatible settings. * * @param {Object} properties Object containing properties from the HotTable object. * @param {Object} additionalSettings Additional settings. * @param {boolean} additionalSettings.isInit Flag determining whether the settings are being set during initialization. * @param {string[]} additionalSettings.initOnlySettingKeys Array of keys that can be set only during initialization. * @returns {Object} Handsontable-compatible settings object. */ function getSettings(properties) { var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, _ref$prevProps = _ref.prevProps, prevProps = _ref$prevProps === void 0 ? {} : _ref$prevProps, _ref$isInit = _ref.isInit, isInit = _ref$isInit === void 0 ? false : _ref$isInit, _ref$initOnlySettingK = _ref.initOnlySettingKeys, initOnlySettingKeys = _ref$initOnlySettingK === void 0 ? [] : _ref$initOnlySettingK; var shouldSkipProp = function shouldSkipProp(key) { // Omit settings that can be set only during initialization and are intentionally modified. if (!isInit && initOnlySettingKeys.includes(key)) { return prevProps[key] === properties[key]; } return false; }; var newSettings = {}; for (var key in properties) { if (key !== 'children' && !shouldSkipProp(key) && properties.hasOwnProperty(key)) { newSettings[key] = properties[key]; } } return newSettings; } }]); }(); var HotTableContext = React.createContext(undefined); var HotTableContextProvider = function HotTableContextProvider(_ref) { var children = _ref.children; var columnsSettings = React.useRef([]); var setHotColumnSettings = React.useCallback(function (columnSettings, columnIndex) { columnsSettings.current[columnIndex] = columnSettings; }, []); var componentRendererColumns = React.useRef(new Map()); var renderedCellCache = React.useRef(new Map()); var clearRenderedCellCache = React.useCallback(function () { return renderedCellCache.current.clear(); }, []); var portalCache = React.useRef(new Map()); var clearPortalCache = React.useCallback(function () { return portalCache.current.clear(); }, []); var portalContainerCache = React.useRef(new Map()); var getRendererWrapper = React.useCallback(function (Renderer) { return function __internalRenderer(instance, TD, row, col, prop, value, cellProperties) { var key = "".concat(row, "-").concat(col); // Handsontable.Core type is missing guid var instanceGuid = instance.guid; var portalContainerKey = "".concat(instanceGuid, "-").concat(key); var portalKey = "".concat(key, "-").concat(instanceGuid); if (renderedCellCache.current.has(key)) { TD.innerHTML = renderedCellCache.current.get(key).innerHTML; } if (TD && !TD.getAttribute('ghost-table')) { var cachedPortal = portalCache.current.get(portalKey); var cachedPortalContainer = portalContainerCache.current.get(portalContainerKey); while (TD.firstChild) { TD.removeChild(TD.firstChild); } // if portal already exists, do not recreate if (cachedPortal && cachedPortalContainer) { TD.appendChild(cachedPortalContainer); } else { var rendererElement = React__default["default"].createElement(Renderer, { instance: instance, TD: TD, row: row, col: col, prop: prop, value: value, cellProperties: cellProperties }); var _createPortal = createPortal(rendererElement, TD.ownerDocument, portalKey, cachedPortalContainer), portal = _createPortal.portal, portalContainer = _createPortal.portalContainer; portalContainerCache.current.set(portalContainerKey, portalContainer); TD.appendChild(portalContainer); portalCache.current.set(portalKey, portal); } } renderedCellCache.current.set("".concat(row, "-").concat(col), TD); return TD; }; }, []); var renderersPortalManager = React.useRef(function () { return undefined; }); var setRenderersPortalManagerRef = React.useCallback(function (pmComponent) { renderersPortalManager.current = pmComponent; }, []); var pushCellPortalsIntoPortalManager = React.useCallback(function () { renderersPortalManager.current(_toConsumableArray(portalCache.current.values())); }, []); var contextImpl = React.useMemo(function () { return { componentRendererColumns: componentRendererColumns.current, columnsSettings: columnsSettings.current, emitColumnSettings: setHotColumnSettings, getRendererWrapper: getRendererWrapper, clearPortalCache: clearPortalCache, clearRenderedCellCache: clearRenderedCellCache, setRenderersPortalManagerRef: setRenderersPortalManagerRef, pushCellPortalsIntoPortalManager: pushCellPortalsIntoPortalManager }; }, [setHotColumnSettings, getRendererWrapper, clearRenderedCellCache, setRenderersPortalManagerRef, pushCellPortalsIntoPortalManager]); return React__default["default"].createElement(HotTableContext.Provider, { value: contextImpl }, children); }; /** * Exposes the table context object to components * * @returns HotTableContext */ function useHotTableContext() { return React.useContext(HotTableContext); } var HotColumnContext = React.createContext(undefined); var HotColumnContextProvider = function HotColumnContextProvider(_ref) { var columnIndex = _ref.columnIndex, getOwnerDocument = _ref.getOwnerDocument, children = _ref.children; var contextImpl = React.useMemo(function () { return { columnIndex: columnIndex, getOwnerDocument: getOwnerDocument }; }, [columnIndex, getOwnerDocument]); return React__default["default"].createElement(HotColumnContext.Provider, { value: contextImpl }, children); }; var useHotColumnContext = function useHotColumnContext() { return React.useContext(HotColumnContext); }; var AbstractMethods = ['close', 'focus', 'open']; var ExcludedMethods = ['getValue', 'setValue']; var MethodsMap = { open: 'onOpen', close: 'onClose', prepare: 'onPrepare', focus: 'onFocus' }; /** * Create a class to be passed to the Handsontable's settings. * * @param {RefObject<HotEditorHooks>} hooksRef Reference to component-based editor overridden hooks object. * @param {RefObject} instanceRef Reference to Handsontable-native custom editor class instance. * @returns {Function} A class to be passed to the Handsontable editor settings. */ function makeEditorClass(hooksRef, instanceRef) { return /*#__PURE__*/function (_Handsontable$editors) { function CustomEditor(hotInstance) { var _this; _classCallCheck(this, CustomEditor); _this = _callSuper(this, CustomEditor, [hotInstance]); instanceRef.current = _this; Object.getOwnPropertyNames(Handsontable__default["default"].editors.BaseEditor.prototype).forEach(function (propName) { if (propName === 'constructor' || ExcludedMethods.includes(propName)) { return; } var baseMethod = Handsontable__default["default"].editors.BaseEditor.prototype[propName]; CustomEditor.prototype[propName] = function () { var _hooksRef$current; var result; for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } if (!AbstractMethods.includes(propName)) { result = baseMethod.call.apply(baseMethod, [this].concat(args)); // call super } if (MethodsMap[propName] && (_hooksRef$current = hooksRef.current) !== null && _hooksRef$current !== void 0 && _hooksRef$current[MethodsMap[propName]]) { var _hooksRef$current$Met; result = (_hooksRef$current$Met = hooksRef.current[MethodsMap[propName]]).call.apply(_hooksRef$current$Met, [this].concat(args)); } return result; }.bind(_this); }); return _this; } _inherits(CustomEditor, _Handsontable$editors); return _createClass(CustomEditor, [{ key: "focus", value: function focus() {} }, { key: "getValue", value: function getValue() { return this.value; } }, { key: "setValue", value: function setValue(newValue) { this.value = newValue; } }, { key: "open", value: function open() {} }, { key: "close", value: function close() {} }]); }(Handsontable__default["default"].editors.BaseEditor); } /** * Context to provide Handsontable-native custom editor class instance to overridden hooks object. */ var EditorContext = React.createContext(undefined); /** * Provider of the context that exposes Handsontable-native editor instance and passes hooks object * for custom editor components. * * @param {Ref} hooksRef Reference for component-based editor overridden hooks object. * @param {RefObject} hotCustomEditorInstanceRef Reference to Handsontable-native editor instance. */ var EditorContextProvider = function EditorContextProvider(_ref) { var hooksRef = _ref.hooksRef, hotCustomEditorInstanceRef = _ref.hotCustomEditorInstanceRef, children = _ref.children; return React__default["default"].createElement(EditorContext.Provider, { value: { hooksRef: hooksRef, hotCustomEditorInstanceRef: hotCustomEditorInstanceRef } }, children); }; /** * Hook that allows encapsulating custom behaviours of component-based editor by customizing passed ref with overridden hooks object. * * @param {HotEditorHooks} overriddenHooks Overrides specific for the custom editor. * @param {DependencyList} deps Overridden hooks object React dependency list. * @returns {UseHotEditorImpl} Editor API methods */ function useHotEditor(overriddenHooks, deps) { var _useContext = React.useContext(EditorContext), hooksRef = _useContext.hooksRef, hotCustomEditorInstanceRef = _useContext.hotCustomEditorInstanceRef; var _useState = React.useState(0), _useState2 = _slicedToArray(_useState, 2), rerenderTrigger = _useState2[0], setRerenderTrigger = _useState2[1]; var _useState3 = React.useState(), _useState4 = _slicedToArray(_useState3, 2), editorValue = _useState4[0], setEditorValue = _useState4[1]; // return a deferred value that allows for optimizing performance by delaying the update of a value until the next render. var deferredValue = React.useDeferredValue(editorValue); React.useImperativeHandle(hooksRef, function () { return _objectSpread2(_objectSpread2({}, overriddenHooks), {}, { onOpen: function onOpen() { var _hotCustomEditorInsta, _overriddenHooks$onOp; setEditorValue((_hotCustomEditorInsta = hotCustomEditorInstanceRef.current) === null || _hotCustomEditorInsta === void 0 ? void 0 : _hotCustomEditorInsta.getValue()); overriddenHooks === null || overriddenHooks === void 0 || (_overriddenHooks$onOp = overriddenHooks.onOpen) === null || _overriddenHooks$onOp === void 0 || _overriddenHooks$onOp.call(overriddenHooks); setRerenderTrigger(function (t) { return t + 1; }); } }); }, deps); return React.useMemo(function () { return { get value() { return deferredValue; }, setValue: function setValue(newValue) { var _hotCustomEditorInsta2; setEditorValue(newValue); (_hotCustomEditorInsta2 = hotCustomEditorInstanceRef.current) === null || _hotCustomEditorInsta2 === void 0 || _hotCustomEditorInsta2.setValue(newValue); }, get isOpen() { var _hotCustomEditorInsta3, _hotCustomEditorInsta4; return (_hotCustomEditorInsta3 = (_hotCustomEditorInsta4 = hotCustomEditorInstanceRef.current) === null || _hotCustomEditorInsta4 === void 0 ? void 0 : _hotCustomEditorInsta4.isOpened()) !== null && _hotCustomEditorInsta3 !== void 0 ? _hotCustomEditorInsta3 : false; }, finishEditing: function finishEditing() { var _hotCustomEditorInsta5; (_hotCustomEditorInsta5 = hotCustomEditorInstanceRef.current) === null || _hotCustomEditorInsta5 === void 0 || _hotCustomEditorInsta5.finishEditing(); }, get row() { var _hotCustomEditorInsta6; return (_hotCustomEditorInsta6 = hotCustomEditorInstanceRef.current) === null || _hotCustomEditorInsta6 === void 0 ? void 0 : _hotCustomEditorInsta6.row; }, get col() { var _hotCustomEditorInsta7; return (_hotCustomEditorInsta7 = hotCustomEditorInstanceRef.current) === null || _hotCustomEditorInsta7 === void 0 ? void 0 : _hotCustomEditorInsta7.col; } }; }, [rerenderTrigger, hotCustomEditorInstanceRef, deferredValue]); } var isHotColumn = function isHotColumn(childNode) { return childNode.type === HotColumn; }; var internalProps = ['_columnIndex', '_getOwnerDocument', 'children']; var HotColumn = function HotColumn(props) { var _useHotTableContext = useHotTableContext(), componentRendererColumns = _useHotTableContext.componentRendererColumns, emitColumnSettings = _useHotTableContext.emitColumnSettings, getRendererWrapper = _useHotTableContext.getRendererWrapper; var _useHotColumnContext = useHotColumnContext(), columnIndex = _useHotColumnContext.columnIndex, getOwnerDocument = _useHotColumnContext.getOwnerDocument; /** * Reference to component-based editor overridden hooks object. */ var localEditorHooksRef = React.useRef(null); /** * Reference to HOT-native custom editor class instance. */ var localEditorClassInstance = React.useRef(null); /** * Logic performed after mounting & updating of the HotColumn component. */ React.useEffect(function () { /** * Filter out all the internal properties and return an object with just the Handsontable-related props. * * @returns {Object} */ var getSettingsProps = function getSettingsProps() { return Object.keys(props).filter(function (key) { return !internalProps.includes(key); }).reduce(function (obj, key) { obj[key] = props[key]; return obj; }, {}); }; /** * Create the column settings based on the data provided to the `HotColumn` component and its child components. */ var createColumnSettings = function createColumnSettings() { var columnSettings = SettingsMapper.getSettings(getSettingsProps()); if (props.renderer) { columnSettings.renderer = getRendererWrapper(props.renderer); componentRendererColumns.set(columnIndex, true); } else if (props.hotRenderer) { columnSettings.renderer = props.hotRenderer; } if (props.editor) { columnSettings.editor = makeEditorClass(localEditorHooksRef, localEditorClassInstance); } else if (props.hotEditor) { columnSettings.editor = props.hotEditor; } return columnSettings; }; var columnSettings = createColumnSettings(); emitColumnSettings(columnSettings, columnIndex); if (!displayObsoleteRenderersEditorsWarning(props.children)) { displayAnyChildrenWarning(props.children); } }); var editorPortal = createEditorPortal(getOwnerDocument(), props.editor); /** * Render the portals of the editors, if there are any. * * @returns {ReactElement} */ return React__default["default"].createElement(EditorContextProvider, { hooksRef: localEditorHooksRef, hotCustomEditorInstanceRef: localEditorClassInstance }, editorPortal); }; var version="16.1.1"; /** * Component used to manage the renderer component portals. */ var RenderersPortalManager = React.forwardRef(function (_, ref) { var _useState = React.useState([]), _useState2 = _slicedToArray(_useState, 2), portals = _useState2[0], setPortals = _useState2[1]; React.useImperativeHandle(ref, function () { return setPortals; }); return React__default["default"].createElement(React.Fragment, null, portals); }); function getDefaultExportFromCjs (x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; } var propTypes = {exports: {}}; /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var ReactPropTypesSecret_1; var hasRequiredReactPropTypesSecret; function requireReactPropTypesSecret() { if (hasRequiredReactPropTypesSecret) return ReactPropTypesSecret_1; hasRequiredReactPropTypesSecret = 1; var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED'; ReactPropTypesSecret_1 = ReactPropTypesSecret; return ReactPropTypesSecret_1; } /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var factoryWithThrowingShims; var hasRequiredFactoryWithThrowingShims; function requireFactoryWithThrowingShims() { if (hasRequiredFactoryWithThrowingShims) return factoryWithThrowingShims; hasRequiredFactoryWithThrowingShims = 1; var ReactPropTypesSecret = requireReactPropTypesSecret(); function emptyFunction() {} function emptyFunctionWithReset() {} emptyFunctionWithReset.resetWarningCache = emptyFunction; factoryWithThrowingShims = function factoryWithThrowingShims() { function shim(props, propName, componentName, location, propFullName, secret) { if (secret === ReactPropTypesSecret) { // It is still safe when called from React. return; } var err = new Error('Calling PropTypes validators directly is not supported by the `prop-types` package. ' + 'Use PropTypes.checkPropTypes() to call them. ' + 'Read more at http://fb.me/use-check-prop-types'); err.name = 'Invariant Violation'; throw err; } shim.isRequired = shim; function getShim() { return shim; } // Important! // Keep this list in sync with production version in `./factoryWithTypeCheckers.js`. var ReactPropTypes = { array: shim, bigint: shim, bool: shim, func: shim, number: shim, object: shim, string: shim, symbol: shim, any: shim, arrayOf: getShim, element: shim, elementType: shim, instanceOf: getShim, node: shim, objectOf: getShim, oneOf: getShim, oneOfType: getShim, shape: getShim, exact: getShim, checkPropTypes: emptyFunctionWithReset, resetWarningCache: emptyFunction }; ReactPropTypes.PropTypes = ReactPropTypes; return ReactPropTypes; }; return factoryWithThrowingShims; } /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ { // By explicitly using `prop-types` you are opting into new production behavior. // http://fb.me/prop-types-in-prod propTypes.exports = requireFactoryWithThrowingShims()(); } var propTypesExports = propTypes.exports; var PropTypes = /*@__PURE__*/getDefaultExportFromCjs(propTypesExports); var HotTableInner = React.forwardRef(function (props, ref) { /** * Reference to the Handsontable instance. */ var __hotInstance = React.useRef(null); /** * Reference to the main Handsontable DOM element. */ var hotElementRef = React.useRef(null); /** * Reference to component-based editor overridden hooks object. */ var globalEditorHooksRef = React.useRef(null); /** * Reference to HOT-native custom editor class instance. */ var globalEditorClassInstance = React.useRef(null); /** * Reference to the previous props object. */ var prevProps = React.useRef(); /** * HotTable context exposing helper functions. */ var context = useHotTableContext(); /** * Getter for the property storing the Handsontable instance. */ var getHotInstance = React.useCallback(function () { if (!__hotInstance.current || !__hotInstance.current.isDestroyed) { // Will return the Handsontable instance or `null` if it's not yet been created. return __hotInstance.current; } else { console.warn(HOT_DESTROYED_WARNING); return null; } }, [__hotInstance]); var isHotInstanceDestroyed = React.useCallback(function () { return !__hotInstance.current || __hotInstance.current.isDestroyed; }, [__hotInstance]); /** * Clear both the editor and the renderer cache. */ var clearCache = React.useCallback(function () { context.clearRenderedCellCache(); context.componentRendererColumns.clear(); }, [context]); /** * Get the `Document` object corresponding to the main component element. * * @returns The `Document` object used by the component. */ var getOwnerDocument = React.useCallback(function () { if (isCSR()) { return hotElementRef.current ? hotElementRef.current.ownerDocument : document; } return null; }, [hotElementRef]); /** * Create a new settings object containing the column settings and global editors and renderers. * * @returns {Handsontable.GridSettings} New global set of settings for Handsontable. */ var createNewGlobalSettings = function createNewGlobalSettings() { var _getHotInstance; var init = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; var prevProps = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var initOnlySettingKeys = !isHotInstanceDestroyed() ? // Needed for React's double-rendering. ((_getHotInstance = getHotInstance()) === null || _getHotInstance === void 0 || (_getHotInstance = _getHotInstance.getSettings()) === null || _getHotInstance === void 0 ? void 0 : _getHotInstance._initOnlySettings) || [] : []; var newSettings = SettingsMapper.getSettings(props, { prevProps: prevProps, isInit: init, initOnlySettingKeys: initOnlySettingKeys }); newSettings.columns = context.columnsSettings.length ? context.columnsSettings : newSettings.columns; if (props.renderer) { newSettings.renderer = context.getRendererWrapper(props.renderer); context.componentRendererColumns.set('global', true); } else { newSettings.renderer = props.hotRenderer || registry.getRenderer('text'); } if (props.editor) { newSettings.editor = makeEditorClass(globalEditorHooksRef, globalEditorClassInstance); } else { newSettings.editor = props.hotEditor || registry$1.getEditor('text'); } return newSettings; }; /** * Detect if `autoRowSize` or `autoColumnSize` is defined, and if so, throw an incompatibility warning. */ var displayAutoSizeWarning = function displayAutoSizeWarning(hotInstance) { var _hotInstance$getPlugi, _hotInstance$getPlugi2; if (hotInstance && ((_hotInstance$getPlugi = hotInstance.getPlugin('autoRowSize')) !== null && _hotInstance$getPlugi !== void 0 && _hotInstance$getPlugi.enabled || (_hotInstance$getPlugi2 = hotInstance.getPlugin('autoColumnSize')) !== null && _hotInstance$getPlugi2 !== void 0 && _hotInstance$getPlugi2.enabled)) { if (context.componentRendererColumns.size > 0) { warn(AUTOSIZE_WARNING); } } }; /** * Initialize Handsontable after the component has mounted. */ React.useEffect(function () { var newGlobalSettings = createNewGlobalSettings(true); // Update prevProps with the current props prevProps.current = props; __hotInstance.current = new Handsontable__default["default"].Core(hotElementRef.current, newGlobalSettings); /** * Handsontable's `beforeViewRender` hook callback. */ __hotInstance.current.addHook('beforeViewRender', function () { context.clearPortalCache(); context.clearRenderedCellCache(); }); /** * Handsontable's `afterViewRender` hook callback. */ __hotInstance.current.addHook('afterViewRender', function () { context.pushCellPortalsIntoPortalManager(); }); __hotInstance.current.init(); displayAutoSizeWarning(__hotInstance.current); if (!displayObsoleteRenderersEditorsWarning(props.children)) { displayChildrenOfTypeWarning(props.children, HotColumn); } /** * Destroy the Handsontable instance when the parent component unmounts. */ return function () { var _getHotInstance2; clearCache(); (_getHotInstance2 = getHotInstance()) === null || _getHotInstance2 === void 0 || _getHotInstance2.destroy(); }; }, []); /** * Logic performed after the component update. */ useUpdateEffect(function () { clearCache(); var hotInstance = getHotInstance(); var newGlobalSettings = createNewGlobalSettings(false, prevProps.current); // Update prevProps with the current props prevProps.current = props; hotInstance === null || hotInstance === void 0 || hotInstance.updateSettings(newGlobalSettings, false); displayAutoSizeWarning(hotInstance); displayObsoleteRenderersEditorsWarning(props.children); }); /** * Interface exposed to parent components by HotTable instance via React ref */ React.useImperativeHandle(ref, function () { return { get hotElementRef() { return hotElementRef.current; }, get hotInstance() { return getHotInstance(); } }; }); /** * Render the component. */ var hotColumnWrapped = React.Children.toArray(props.children).filter(isHotColumn).map(function (childNode, columnIndex) { return React__default["default"].createElement(HotColumnContextProvider, { columnIndex: columnIndex, getOwnerDocument: getOwnerDocument, key: columnIndex }, childNode); }); var containerProps = getContainerAttributesProps(props); var editorPortal = createEditorPortal(getOwnerDocument(), props.editor); return React__default["default"].createElement(React.Fragment, null, React__default["default"].createElement("div", Object.assign({ ref: hotElementRef }, containerProps), hotColumnWrapped), React__default["default"].createElement(RenderersPortalManager, { ref: context.setRenderersPortalManagerRef }), React__default["default"].createElement(EditorContextProvider, { hooksRef: globalEditorHooksRef, hotCustomEditorInstanceRef: globalEditorClassInstance }, editorPortal)); }); /** * Prop types to be checked at runtime. */ HotTableInner.propTypes = { style: PropTypes.object, id: PropTypes.string, className: PropTypes.string }; var _excluded = ["children"]; /** * A Handsontable-ReactJS wrapper. * * To implement, use the `HotTable` tag with properties corresponding to Handsontable options. * For example: * * ```js * <HotTable id="hot" data={dataObject} contextMenu={true} colHeaders={true} width={600} height={300} stretchH="all" /> * * // is analogous to * let hot = new Handsontable(document.getElementById('hot'), { * data: dataObject, * contextMenu: true, * colHeaders: true, * width: 600 * height: 300 * }); * * ``` */ var HotTable = React.forwardRef(function (_ref, ref) { var _props$id; var children = _ref.children, props = _objectWithoutProperties(_ref, _excluded); var componentId = (_props$id = props.id) !== null && _props$id !== void 0 ? _props$id : React.useId(); return React__default["default"].createElement(HotTableContextProvider, null, React__default["default"].createElement(HotTableInner, Object.assign({ id: componentId }, props, { ref: ref }), children)); }); /** * Package version. * * @returns The version number of the package. */ HotTable.version = version; exports.HotColumn = HotColumn; exports.HotTable = HotTable; exports["default"] = HotTable; exports.isHotColumn = isHotColumn; exports.useHotEditor = useHotEditor; Object.defineProperty(exports, '__esModule', { value: true }); })); //# sourceMappingURL=react-handsontable.js.map