UNPKG

dockview

Version:

Zero dependency layout manager supporting tabs, grids and splitviews with ReactJS support

182 lines 7.86 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.isReactElement = exports.usePortalsLifecycle = exports.ReactPart = exports.ReactPartContext = void 0; var React = __importStar(require("react")); var ReactDOM = __importStar(require("react-dom")); var math_1 = require("../math"); /** * This component is intended to interface between vanilla-js and React hence we need to be * creative in how we update props. * A ref of the component is exposed with an update method; which when called stores the props * as a ref within this component and forcefully triggers a re-render of the component using * the ref of props we just set on the renderered component as the props passed to the inner * component */ var ReactComponentBridge = function (props, ref) { var _a = __read(React.useState(), 2), _ = _a[0], triggerRender = _a[1]; var _props = React.useRef(props.componentProps); React.useImperativeHandle(ref, function () { return ({ update: function (componentProps) { _props.current = __assign(__assign({}, _props.current), componentProps); /** * setting a arbitrary piece of state within this component will * trigger a re-render. * we use this rather than updating through a prop since we can * pass a ref into the vanilla-js world. */ triggerRender(Date.now()); }, }); }, []); return React.createElement(props.component, _props.current); }; ReactComponentBridge.displayName = 'DockviewReactJsBridge'; /** * Since we are storing the React.Portal references in a rendered array they * require a key property like any other React element rendered in an array * to prevent excessive re-rendering */ var uniquePortalKeyGenerator = (0, math_1.sequentialNumberGenerator)(); exports.ReactPartContext = React.createContext({}); var ReactPart = /** @class */ (function () { function ReactPart(parent, portalStore, component, parameters, context) { this.parent = parent; this.portalStore = portalStore; this.component = component; this.parameters = parameters; this.context = context; this.disposed = false; this.createPortal(); } ReactPart.prototype.update = function (props) { var _a; if (this.disposed) { throw new Error('invalid operation: resource is already disposed'); } (_a = this.componentInstance) === null || _a === void 0 ? void 0 : _a.update(props); }; ReactPart.prototype.createPortal = function () { var _this = this; if (this.disposed) { throw new Error('invalid operation: resource is already disposed'); } // TODO use a better check for isReactFunctionalComponent if (typeof this.component !== 'function') { /** * we know this isn't a React.FunctionComponent so throw an error here. * if we do not intercept this the React library will throw a very obsure error * for the same reason, at least at this point we will emit a sensible stacktrace. */ throw new Error('invalid operation: only functional components are supported'); } var bridgeComponent = React.createElement(React.forwardRef(ReactComponentBridge), { component: this .component, componentProps: this.parameters, ref: function (element) { _this.componentInstance = element; }, }); var node = this.context ? React.createElement(exports.ReactPartContext.Provider, { value: this.context }, bridgeComponent) : bridgeComponent; var portal = ReactDOM.createPortal(node, this.parent, uniquePortalKeyGenerator.next()); this.ref = { portal: portal, disposable: this.portalStore.addPortal(portal), }; }; ReactPart.prototype.dispose = function () { var _a; (_a = this.ref) === null || _a === void 0 ? void 0 : _a.disposable.dispose(); this.disposed = true; }; return ReactPart; }()); exports.ReactPart = ReactPart; /** * A React Hook that returns an array of portals to be rendered by the user of this hook * and a disposable function to add a portal. Calling dispose removes this portal from the * portal array */ var usePortalsLifecycle = function () { var _a = __read(React.useState([]), 2), portals = _a[0], setPortals = _a[1]; React.useDebugValue("Portal count: ".concat(portals.length)); var addPortal = React.useCallback(function (portal) { setPortals(function (existingPortals) { return __spreadArray(__spreadArray([], __read(existingPortals), false), [portal], false); }); var disposed = false; return { dispose: function () { if (disposed) { throw new Error('invalid operation: resource already disposed'); } disposed = true; setPortals(function (existingPortals) { return existingPortals.filter(function (p) { return p !== portal; }); }); }, }; }, []); return [portals, addPortal]; }; exports.usePortalsLifecycle = usePortalsLifecycle; // it does the job... function isReactElement(element) { return element === null || element === void 0 ? void 0 : element.type; } exports.isReactElement = isReactElement; //# sourceMappingURL=react.js.map