UNPKG

@layr/react-integration

Version:
118 lines 5.56 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.layout = exports.page = exports.view = void 0; const component_1 = require("@layr/component"); const routable_1 = require("@layr/routable"); const core_helpers_1 = require("core-helpers"); const hooks_1 = require("./hooks"); /** * Decorates a method of a Layr [component](https://layrjs.com/docs/v2/reference/component) so it be can used as a React component. * * Like any React component, the method can receive some properties as first parameter and return some React elements to render. * * The decorator binds the method to a specific component, so when the method is executed by React (via, for example, a reference included in a [JSX expression](https://reactjs.org/docs/introducing-jsx.html)), it has access to the bound component through `this`. * * Also, the decorator observes the attributes of the bound component, so when the value of an attribute changes, the React component is automatically re-rendered. * * @example * ``` * import {Component, attribute} from '﹫layr/component'; * import React from 'react'; * import ReactDOM from 'react-dom'; * import {view} from '﹫layr/react-integration'; * * class Person extends Component { * ﹫attribute('string') firstName = ''; * * ﹫attribute('string') lastName = ''; * * ﹫view() FullName() { * return <span>{`${this.firstName} ${this.fullName}`}</span>; * } * } * * const person = new Person({firstName: 'Alan', lastName: 'Turing'}); * * ReactDOM.render(<person.FullName />, document.getElementById('root')); * ``` * * @category Decorators * @decorator */ function view(options = {}) { const { observe = true } = options; return function (target, name, descriptor) { const { value: ReactComponent, configurable, enumerable } = descriptor; if (!((0, component_1.isComponentClassOrInstance)(target) && typeof ReactComponent === 'function' && enumerable === false)) { throw new Error(`@view() should be used to decorate a component method (property: '${name}')`); } return { configurable, enumerable, get() { if (!(0, core_helpers_1.hasOwnProperty)(this, '__boundReactComponents')) { Object.defineProperty(this, '__boundReactComponents', { value: Object.create(null) }); } let BoundReactComponent = this.__boundReactComponents[name]; if (BoundReactComponent === undefined) { BoundReactComponent = (...args) => { if (observe) { (0, hooks_1.useObserve)(this); } return ReactComponent.apply(this, args); }; BoundReactComponent.displayName = this.describeComponentProperty(name); Object.defineProperty(BoundReactComponent, '__isView', { value: true }); this.__boundReactComponents[name] = BoundReactComponent; } return BoundReactComponent; } }; }; } exports.view = view; /** * A convenience decorator that combines the [`@route()`](https://layrjs.com/docs/v2/reference/routable#route-decorator) and [`@view()`](https://layrjs.com/docs/v2/reference/react-integration#view-decorator) decorators. * * Typically, you should use this decorator to implement the pages of your app. * * @param pattern The canonical [URL pattern](https://layrjs.com/docs/v2/reference/addressable#url-pattern-type) of the route. * @param [options] An object specifying the options to pass to the `Route`'s [constructor](https://layrjs.com/docs/v2/reference/addressable#constructor) when the route is created. * * @examplelink See an example of use in the [`BrowserNavigatorView`](https://layrjs.com/docs/v2/reference/react-integration#browser-navigator-view-react-component) React component. * * @category Decorators * @decorator */ function page(pattern, options = {}) { return function (target, name, descriptor) { descriptor = view(options)(target, name, descriptor); descriptor = (0, routable_1.route)(pattern, options)(target, name, descriptor); return descriptor; }; } exports.page = page; /** * A convenience decorator that combines the [`@wrapper()`](https://layrjs.com/docs/v2/reference/routable#wrapper-decorator) and [`@view()`](https://layrjs.com/docs/v2/reference/react-integration#view-decorator) decorators. * * Typically, you should use this decorator to implement the layouts of your app. * * @param pattern The canonical [URL pattern](https://layrjs.com/docs/v2/reference/addressable#url-pattern-type) of the wrapper. * @param [options] An object specifying the options to pass to the `Wrapper`'s [constructor](https://layrjs.com/docs/v2/reference/addressable#constructor) when the wrapper is created. * * @examplelink See an example of use in the [`BrowserNavigatorView`](https://layrjs.com/docs/v2/reference/react-integration#browser-navigator-view-react-component) React component. * * @category Decorators * @decorator */ function layout(pattern, options = {}) { return function (target, name, descriptor) { descriptor = view(options)(target, name, descriptor); descriptor = (0, routable_1.wrapper)(pattern, options)(target, name, descriptor); return descriptor; }; } exports.layout = layout; //# sourceMappingURL=decorators.js.map