Comments and fix recording selectors for some components (and add one for VueComponent)

This commit is contained in:
Samuel Elliott 2019-05-02 18:10:39 +01:00
parent 9c4653ffd4
commit cc1be34263
No known key found for this signature in database
GPG Key ID: 8420C7CDE43DC4D6
2 changed files with 55 additions and 17 deletions

View File

@ -190,15 +190,34 @@ class ReactComponent {
} }
} }
ReactComponent.important = Symbol('BD.ReactComponent.important');
export class ReactComponents { export class ReactComponents {
/** @type {ReactComponent[]} */
static get components() { return this._components || (this._components = []) } static get components() { return this._components || (this._components = []) }
/** @type {Reflection.modules.React.Component[]} */
static get unknownComponents() { return this._unknownComponents || (this._unknownComponents = []) } static get unknownComponents() { return this._unknownComponents || (this._unknownComponents = []) }
/** @type {{id: string, listeners: function[]}[]} */
static get listeners() { return this._listeners || (this._listeners = []) } static get listeners() { return this._listeners || (this._listeners = []) }
/** @type {<{name: string, filter: function}[]>} */
static get nameSetters() { return this._nameSetters || (this._nameSetters = []) } static get nameSetters() { return this._nameSetters || (this._nameSetters = []) }
static get componentAliases() { return this._componentAliases || (this._componentAliases = []) }
/** @type {Object.<string, string>} */
static get componentAliases() { return this._componentAliases || (this._componentAliases = {}) }
static get ReactComponent() { return ReactComponent } static get ReactComponent() { return ReactComponent }
/**
* Processes a React component.
* @param {Reflection.modules.React.Component} component The React component class
* @param {object} retVal
* @param {object} important
* @param {string} important.selector A query selector the component will render elements matching (used to select all component instances to force them to rerender)
* @return {ReactComponent}
*/
static push(component, retVal, important) { static push(component, retVal, important) {
if (!(component instanceof Function)) return null; if (!(component instanceof Function)) return null;
const { displayName } = component; const { displayName } = component;
@ -212,6 +231,8 @@ export class ReactComponents {
return component; return component;
} }
if (!important) important = component[ReactComponent.important];
const c = new ReactComponent(displayName, component, retVal, important); const c = new ReactComponent(displayName, component, retVal, important);
this.components.push(c); this.components.push(c);
@ -226,16 +247,19 @@ export class ReactComponents {
/** /**
* Finds a component from the components array or by waiting for it to be mounted. * Finds a component from the components array or by waiting for it to be mounted.
* @param {String} name The component's name * @param {string} name The component's name
* @param {Object} important An object containing a selector to look for * @param {object} important An object containing a selector to look for
* @param {Function} filter A function to filter components if a single element is rendered by multiple components * @param {function} filter A function to filter components if a single element is rendered by multiple components
* @return {Promise => ReactComponent} * @return {Promise<ReactComponent>}
*/ */
static async getComponent(name, important, filter) { static async getComponent(name, important, filter) {
name = this.getComponentName(name); name = this.getComponentName(name);
const have = this.components.find(c => c.id === name); const have = this.components.find(c => c.id === name);
if (have) return have; if (have) {
if (!have.important) have.important = important;
return have;
}
if (important) { if (important) {
const callback = () => { const callback = () => {
@ -321,6 +345,11 @@ export class ReactComponents {
return this.nameSetters.push({ name, filter }); return this.nameSetters.push({ name, filter });
} }
/**
* Processes a React component that isn't known.
* @param {Reflection.modules.React.Component} component
* @param {} retVal
*/
static processUnknown(component, retVal) { static processUnknown(component, retVal) {
for (const [fi, filter] of this.nameSetters.entries()) { for (const [fi, filter] of this.nameSetters.entries()) {
if (filter.filter.filter(component)) { if (filter.filter.filter(component)) {

View File

@ -8,7 +8,7 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import { Reflection } from 'modules'; import { Reflection, ReactComponents } from 'modules';
import Vue from 'vue'; import Vue from 'vue';
export default class { export default class {
@ -16,12 +16,12 @@ export default class {
/** /**
* Creates a new Vue object and mounts it in the passed element. * Creates a new Vue object and mounts it in the passed element.
* @param {HTMLElement} root The element to mount the new Vue object at * @param {HTMLElement} root The element to mount the new Vue object at
* @param {Object} options Options to pass to Vue * @param {Object} options Options to pass to Vue (see https://vuejs.org/v2/api/#Options-Data)
* @param {BdNode} bdnode The element to append * @param {BdNode} bdnode The element to append
* @return {Vue} * @return {Vue}
*/ */
static inject(root, options, bdnode) { static inject(root, options, bdnode) {
if(bdnode) bdnode.appendTo(root); if (bdnode) bdnode.appendTo(root);
const vue = new Vue(options); const vue = new Vue(options);
@ -37,18 +37,18 @@ export default class {
* @return {React.Element} * @return {React.Element}
*/ */
static createReactElement(component, props, mountAtTop) { static createReactElement(component, props, mountAtTop) {
const { React } = Reflection.modules; return Reflection.modules.React.createElement(this.ReactCompatibility, {component, mountAtTop, props});
return React.createElement(this.ReactCompatibility, {component, mountAtTop, props});
} }
static get ReactCompatibility() { static get ReactCompatibility() {
if (this._ReactCompatibility) return this._ReactCompatibility; const { React, ReactDOM } = Reflection.modules;
const { React, ReactDOM} = Reflection.modules; /**
* A React component that renders a Vue component.
return this._ReactCompatibility = class VueComponent extends React.Component { */
const ReactCompatibility = class VueComponent extends React.Component {
render() { render() {
return React.createElement('span'); return React.createElement('span', {className: 'bd-reactVueComponent'});
} }
componentDidMount() { componentDidMount() {
@ -89,7 +89,13 @@ export default class {
} }
})); }));
} }
} };
// Add a name for ReactComponents
ReactCompatibility.displayName = 'BD.VueComponent';
ReactCompatibility[ReactComponents.ReactComponent.important] = {selector: '.bd-reactVueComponent'};
return Object.defineProperty(this, 'ReactCompatibility', {value: ReactCompatibility}).ReactCompatibility;
} }
static install(Vue) { static install(Vue) {
@ -98,6 +104,9 @@ export default class {
} }
/**
* A Vue component that renders a React component.
*/
export const ReactComponent = { export const ReactComponent = {
props: ['component', 'component-props', 'component-children', 'react-element'], props: ['component', 'component-props', 'component-children', 'react-element'],
render(createElement) { render(createElement) {