@handsontable/react-wrapper
Version:
Best Data Grid for React with Spreadsheet Look and Feel.
1,134 lines (1,112 loc) • 45.4 kB
JavaScript
/*!
* 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