@handsontable/vue3
Version:
Best Data Grid for Vue with Spreadsheet Look and Feel.
385 lines (370 loc) • 13.8 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var vue = require('vue');
var Handsontable = require('handsontable/base');
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
var Handsontable__default = /*#__PURE__*/_interopDefaultCompat(Handsontable);
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 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 _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" === r ? String : Number)(t);
}
function _toPropertyKey(t) {
var i = _toPrimitive(t, "string");
return "symbol" == typeof i ? i : i + "";
}
function _typeof(o) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
} : function (o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof(o);
}
var unassignedPropSymbol = Symbol('unassigned');
/**
* 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.';
/**
* Check if at specified `key` there is any value for `object`.
*
* @param {object} object Object to search value at specyfic key.
* @param {string} key String key to check.
* @returns {boolean}
*/
function hasOwnProperty(object, key) {
return Object.prototype.hasOwnProperty.call(object, key);
}
/**
* Generate an object containing all the available Handsontable properties and plugin hooks.
*
* @param {string} source Source for the factory (either 'HotTable' or 'HotColumn').
* @returns {object}
*/
function propFactory(source) {
var registeredHooks = Handsontable__default["default"].hooks.getRegistered();
var propSchema = {};
Object.assign(propSchema, Handsontable__default["default"].DefaultSettings);
// eslint-disable-next-line no-restricted-syntax, guard-for-in
for (var prop in propSchema) {
propSchema[prop] = {
"default": unassignedPropSymbol
};
}
for (var i = 0; i < registeredHooks.length; i++) {
propSchema[registeredHooks[i]] = {
"default": unassignedPropSymbol
};
}
propSchema.settings = {
"default": unassignedPropSymbol
};
if (source === 'HotTable') {
propSchema.id = {
type: String,
"default": "hot-".concat(Math.random().toString(36).substring(5))
};
}
return propSchema;
}
/**
* Filter out all of the unassigned props, and return only the one passed to the component.
*
* @param {object} props Object containing all the possible props.
* @returns {object} Object containing only used props.
*/
function filterPassedProps(props) {
var filteredProps = {};
var columnSettingsProp = props.settings;
if (columnSettingsProp !== unassignedPropSymbol) {
// eslint-disable-next-line no-restricted-syntax
for (var propName in columnSettingsProp) {
if (hasOwnProperty(columnSettingsProp, propName) && columnSettingsProp[propName] !== unassignedPropSymbol) {
filteredProps[propName] = columnSettingsProp[propName];
}
}
}
// eslint-disable-next-line no-restricted-syntax
for (var _propName in props) {
if (hasOwnProperty(props, _propName) && _propName !== 'settings' && props[_propName] !== unassignedPropSymbol) {
filteredProps[_propName] = props[_propName];
}
}
return filteredProps;
}
/**
* Prepare the settings object to be used as the settings for Handsontable, based on the props provided to the component.
*
* @param {HotTableProps} props The props passed to the component.
* @param {Handsontable.GridSettings} currentSettings The current Handsontable settings.
* @returns {Handsontable.GridSettings} An object containing the properties, ready to be used within Handsontable.
*/
function prepareSettings(props, currentSettings) {
var assignedProps = filterPassedProps(props);
var hotSettingsInProps = props.settings ? props.settings : assignedProps;
var additionalHotSettingsInProps = props.settings ? assignedProps : null;
var newSettings = {};
// eslint-disable-next-line no-restricted-syntax
for (var key in hotSettingsInProps) {
if (hasOwnProperty(hotSettingsInProps, key) && hotSettingsInProps[key] !== void 0 && (currentSettings && key !== 'data' ? !simpleEqual(currentSettings[key], hotSettingsInProps[key]) : true)) {
newSettings[key] = hotSettingsInProps[key];
}
}
// eslint-disable-next-line no-restricted-syntax
for (var _key in additionalHotSettingsInProps) {
if (hasOwnProperty(additionalHotSettingsInProps, _key) && _key !== 'id' && _key !== 'settings' && additionalHotSettingsInProps[_key] !== void 0 && (currentSettings && _key !== 'data' ? !simpleEqual(currentSettings[_key], additionalHotSettingsInProps[_key]) : true)) {
newSettings[_key] = additionalHotSettingsInProps[_key];
}
}
return newSettings;
}
/**
* Compare two objects using `JSON.stringify`.
* *Note: * As it's using the stringify function to compare objects, the property order in both objects is
* important. It will return `false` for the same objects, if they're defined in a different order.
*
* @param {object} objectA First object to compare.
* @param {object} objectB Second object to compare.
* @returns {boolean} `true` if they're the same, `false` otherwise.
*/
function simpleEqual(objectA, objectB) {
var stringifyToJSON = function stringifyToJSON(val) {
var circularReplacer = function () {
var seen = new WeakSet();
return function (key, value) {
if (_typeof(value) === 'object' && value !== null) {
if (seen.has(value)) {
return;
}
seen.add(value);
}
return value;
};
}();
return JSON.stringify(val, circularReplacer);
};
if (typeof objectA === 'function' && typeof objectB === 'function') {
return objectA.toString() === objectB.toString();
} else if (_typeof(objectA) !== _typeof(objectB)) {
return false;
} else {
return stringifyToJSON(objectA) === stringifyToJSON(objectB);
}
}
var version="15.3.0";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
var HotTable = vue.defineComponent({
name: 'HotTable',
props: propFactory('HotTable'),
provide: function provide() {
return {
columnsCache: this.columnsCache
};
},
watch: {
$props: {
handler: function handler(props) {
var settings = prepareSettings(props, this.hotInstance ? this.hotInstance.getSettings() : void 0);
if (!this.hotInstance || settings === void 0) {
return;
}
if (settings.data) {
if (this.hotInstance.isColumnModificationAllowed() || !this.hotInstance.isColumnModificationAllowed() && this.hotInstance.countSourceCols() === this.miscCache.currentSourceColumns) {
// If the dataset dimensions change, update the index mappers.
this.matchHotMappersSize();
// Data is automatically synchronized by reference.
delete settings.data;
}
}
// If there are another options changed, update the HOT settings, render the table otherwise.
if (Object.keys(settings).length) {
this.hotInstance.updateSettings(settings);
} else {
this.hotInstance.render();
}
this.miscCache.currentSourceColumns = this.hotInstance.countSourceCols();
},
deep: true,
immediate: true
}
},
data: function data() {
return {
/* eslint-disable vue/no-reserved-keys */
__hotInstance: null,
/* eslint-enable vue/no-reserved-keys */
miscCache: {
currentSourceColumns: null
},
columnSettings: null,
columnsCache: new Map(),
get hotInstance() {
if (!this.__hotInstance || this.__hotInstance && !this.__hotInstance.isDestroyed) {
// Will return the Handsontable instance or `null` if it's not yet been created.
return this.__hotInstance;
} else {
/* eslint-disable-next-line no-console */
console.warn(HOT_DESTROYED_WARNING);
return null;
}
},
set hotInstance(hotInstance) {
this.__hotInstance = hotInstance;
}
};
},
methods: {
/**
* Initialize Handsontable.
*/
hotInit: function hotInit() {
var newSettings = prepareSettings(this.$props);
newSettings.columns = this.columnSettings ? this.columnSettings : newSettings.columns;
this.hotInstance = vue.markRaw(new Handsontable__default["default"].Core(this.$el, newSettings));
this.hotInstance.init();
this.miscCache.currentSourceColumns = this.hotInstance.countSourceCols();
},
matchHotMappersSize: function matchHotMappersSize() {
var _this = this;
if (!this.hotInstance) {
return;
}
var data = this.hotInstance.getSourceData();
var rowsToRemove = [];
var columnsToRemove = [];
var indexMapperRowCount = this.hotInstance.rowIndexMapper.getNumberOfIndexes();
var isColumnModificationAllowed = this.hotInstance.isColumnModificationAllowed();
var indexMapperColumnCount = 0;
if (data && data.length !== indexMapperRowCount) {
if (data.length < indexMapperRowCount) {
for (var r = data.length; r < indexMapperRowCount; r++) {
rowsToRemove.push(r);
}
}
}
if (isColumnModificationAllowed) {
var _data$;
indexMapperColumnCount = this.hotInstance.columnIndexMapper.getNumberOfIndexes();
if (data && data[0] && ((_data$ = data[0]) === null || _data$ === void 0 ? void 0 : _data$.length) !== indexMapperColumnCount) {
if (data[0].length < indexMapperColumnCount) {
for (var c = data[0].length; c < indexMapperColumnCount; c++) {
columnsToRemove.push(c);
}
}
}
}
this.hotInstance.batch(function () {
if (rowsToRemove.length > 0) {
_this.hotInstance.rowIndexMapper.removeIndexes(rowsToRemove);
} else {
_this.hotInstance.rowIndexMapper.insertIndexes(indexMapperRowCount - 1, data.length - indexMapperRowCount);
}
if (isColumnModificationAllowed && data.length !== 0) {
if (columnsToRemove.length > 0) {
_this.hotInstance.columnIndexMapper.removeIndexes(columnsToRemove);
} else {
_this.hotInstance.columnIndexMapper.insertIndexes(indexMapperColumnCount - 1, data[0].length - indexMapperColumnCount);
}
}
});
},
/**
* Get settings for the columns provided in the `hot-column` components.
*
* @returns {HotTableProps[] | undefined}
*/
getColumnSettings: function getColumnSettings() {
var columnSettings = Array.from(this.columnsCache.values());
return columnSettings.length ? columnSettings : void 0;
}
},
mounted: function mounted() {
this.columnSettings = this.getColumnSettings();
this.hotInit();
},
beforeUnmount: function beforeUnmount() {
if (this.hotInstance) {
this.hotInstance.destroy();
}
},
version: version
});
var _hoisted_1 = ["id"];
function render(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createElementBlock("div", {
id: _ctx.id
}, [vue.renderSlot(_ctx.$slots, "default")], 8 /* PROPS */, _hoisted_1);
}
HotTable.render = render;
HotTable.__file = "src/HotTable.vue";
var HotColumn = vue.defineComponent({
name: 'HotColumn',
props: propFactory('HotColumn'),
inject: ['columnsCache'],
methods: {
/**
* Create the column settings based on the data provided to the `hot-column`
* component and it's child components.
*/
createColumnSettings: function createColumnSettings() {
var assignedProps = filterPassedProps(this.$props);
var columnSettings = _objectSpread2({}, assignedProps);
if (assignedProps.renderer) {
columnSettings.renderer = assignedProps.renderer;
}
if (assignedProps.editor) {
columnSettings.editor = assignedProps.editor;
}
this.columnsCache.set(this, columnSettings);
}
},
mounted: function mounted() {
this.createColumnSettings();
},
unmounted: function unmounted() {
this.columnsCache["delete"](this);
},
render: function render() {
return null;
}
});
HotColumn.__file = "src/HotColumn.vue";
exports.HotColumn = HotColumn;
exports.HotTable = HotTable;
exports["default"] = HotTable;