UNPKG

@pmwcs/base

Version:
343 lines (284 loc) 13.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useFoundation = exports.FoundationElement = void 0; var _hooks = require("preact/hooks"); var _classnames = _interopRequireDefault(require("classnames")); var _eventsMap = require("./utils/events-map"); var _strings = require("./utils/strings"); var _component = require("./component"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } var reactPropFromEventName = function reactPropFromEventName(evtName) { return _eventsMap.eventsMap[evtName] || evtName; }; var FoundationElement = /*#__PURE__*/function () { function FoundationElement() { var onChange = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; _classCallCheck(this, FoundationElement); this._classes = new Set(); this._events = {}; this._style = {}; this._props = {}; this._ref = null; this._onChange = onChange; this.onChange = this.onChange.bind(this); this.addClass = this.addClass.bind(this); this.removeClass = this.removeClass.bind(this); this.hasClass = this.hasClass.bind(this); this.setProp = this.setProp.bind(this); this.getProp = this.getProp.bind(this); this.removeProp = this.removeProp.bind(this); this.setStyle = this.setStyle.bind(this); this.addEventListener = this.addEventListener.bind(this); this.removeEventListener = this.removeEventListener.bind(this); this.setRef = this.setRef.bind(this); } _createClass(FoundationElement, [{ key: "onChange", value: function onChange() { this._onChange && this._onChange(); } }, { key: "destroy", value: function destroy() { var _this = this; this._onChange = null; this._events = {}; this._style = {}; this._props = {}; this._classes = new Set(); setTimeout(function () { _this._ref = null; }); } /************************************************** * Classes **************************************************/ }, { key: "addClass", value: function addClass(className) { if (!this._classes.has(className)) { this._classes.add(className); this.onChange(); } } }, { key: "removeClass", value: function removeClass(className) { if (this._classes.has(className)) { this._classes.delete(className); this.onChange(); } } }, { key: "hasClass", value: function hasClass(className) { return this._classes.has(className); } /************************************************** * Props **************************************************/ }, { key: "setProp", value: function setProp(propName, value) { var silent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; if (this._props[propName] !== value) { this._props[propName] = value; !silent && this.onChange(); } } }, { key: "getProp", value: function getProp(propName) { return this._props[propName]; } }, { key: "removeProp", value: function removeProp(propName) { if (this._props[propName] !== undefined) { delete this._props[propName]; this.onChange(); } } }, { key: "props", value: function props(propsToMerge) { var _this2 = this; var _propsToMerge$classNa = propsToMerge.className, className = _propsToMerge$classNa === void 0 ? '' : _propsToMerge$classNa, _propsToMerge$style = propsToMerge.style, style = _propsToMerge$style === void 0 ? {} : _propsToMerge$style; // handle merging events // the foundation should be able to pass something onClick as well as a user // This wraps them in a function that calls both var mergedEvents = Object.entries(propsToMerge).reduce(function (acc, _ref) { var _ref2 = _slicedToArray(_ref, 2), key = _ref2[0], possibleCallback = _ref2[1]; var existingCallback = _this2._events[key]; if (typeof possibleCallback === 'function' && typeof existingCallback === 'function') { var wrappedCallback = function wrappedCallback(evt) { existingCallback(evt); return possibleCallback(evt); }; acc[key] = wrappedCallback; } return acc; }, _objectSpread({}, this._events)); // handle className var mergedClasses = (0, _classnames.default)(className, _toConsumableArray(this._classes)); // handle styles var mergedStyles = _objectSpread(_objectSpread({}, this._style), style); return _objectSpread(_objectSpread(_objectSpread(_objectSpread({}, propsToMerge), this._props), mergedEvents), {}, { style: mergedStyles, className: mergedClasses }); } /************************************************** * Styles **************************************************/ }, { key: "setStyle", value: function setStyle(propertyName, value) { propertyName = propertyName.startsWith('--') ? propertyName : (0, _strings.toCamel)(propertyName); if (this._style[propertyName] !== value) { this._style[propertyName] = value; this.onChange(); } } /************************************************** * Events **************************************************/ }, { key: "addEventListener", value: function addEventListener(evtName, callback) { var propName = reactPropFromEventName(evtName); if (this._events[propName] !== callback) { this._events[propName] = callback; this.onChange(); } } }, { key: "removeEventListener", value: function removeEventListener(evtName /*, callback */ ) { var propName = reactPropFromEventName(evtName); if (this._events[propName]) { delete this._events[propName]; this.onChange(); } } /************************************************** * Refs **************************************************/ }, { key: "setRef", value: function setRef(el) { if (el) { this._ref = el; } } }, { key: "ref", get: function get() { return this._ref; } }]); return FoundationElement; }(); exports.FoundationElement = FoundationElement; var emitFactory = function emitFactory(props) { return function (evtType, evtData) { var shouldBubble = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; var evt = new CustomEvent(evtType, { detail: evtData, bubbles: shouldBubble }); // bugfix for events coming from form elements // and also fits with reacts form pattern better... // This should always otherwise be null since there is no target // for Custom Events Object.defineProperty(evt, 'target', { value: evtData, writable: false }); Object.defineProperty(evt, 'currentTarget', { value: evtData, writable: false }); // Custom handling for React var propName = evtType; props[propName] && props[propName](evt); return evt; }; }; var useFoundation = function useFoundation(_ref3) { var foundationFactory = _ref3.foundation, inputProps = _ref3.props, elementsInput = _ref3.elements, api = _ref3.api; var _useState = (0, _hooks.useState)(0), _useState2 = _slicedToArray(_useState, 2), setIteration = _useState2[1]; var props = (0, _hooks.useRef)(inputProps); props.current = inputProps; var elements = (0, _hooks.useMemo)(function () { return Object.keys(elementsInput).reduce(function (acc, key) { acc[key] = new FoundationElement(function () { setIteration(function (val) { return val + 1; }); }); return acc; }, {}); }, []); var foundation = (0, _hooks.useMemo)(function () { // init foundation var f = foundationFactory(_objectSpread(_objectSpread({}, elements), {}, { getProps: function getProps() { return props.current; }, emit: function emit() { return emitFactory(props.current).apply(void 0, arguments); } })); // handle apiRefs api && (0, _component.handleRef)(props.current.apiRef, api(_objectSpread({ foundation: f }, elements))); return f; }, []); (0, _hooks.useEffect)(function () { var f = foundation; f.init(); api && (0, _component.handleRef)(props.current.apiRef, api(_objectSpread({ foundation: f }, elements))); (0, _component.handleRef)(props.current.foundationRef, f); return function () { f.destroy(); (0, _component.handleRef)(props.current.apiRef, null); (0, _component.handleRef)(props.current.foundationRef, null); Object.values(elements).map(function (element) { return element.destroy(); }); props.current = {}; }; }, [foundation, elements]); return _objectSpread({ foundation: foundation }, elements); }; exports.useFoundation = useFoundation;