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 {
/** @type {ReactComponent[]} */
static get components() { return this._components || (this._components = []) }
/** @type {Reflection.modules.React.Component[]} */
static get unknownComponents() { return this._unknownComponents || (this._unknownComponents = []) }
/** @type {{id: string, listeners: function[]}[]} */
static get listeners() { return this._listeners || (this._listeners = []) }
/** @type {<{name: string, filter: function}[]>} */
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 }
/**
* 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) {
if (!(component instanceof Function)) return null;
const { displayName } = component;
@ -212,6 +231,8 @@ export class ReactComponents {
return component;
}
if (!important) important = component[ReactComponent.important];
const c = new ReactComponent(displayName, component, retVal, important);
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.
* @param {String} name The component's name
* @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
* @return {Promise => ReactComponent}
* @param {string} name The component's name
* @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
* @return {Promise<ReactComponent>}
*/
static async getComponent(name, important, filter) {
name = this.getComponentName(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) {
const callback = () => {
@ -321,6 +345,11 @@ export class ReactComponents {
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) {
for (const [fi, filter] of this.nameSetters.entries()) {
if (filter.filter.filter(component)) {

View File

@ -8,7 +8,7 @@
* LICENSE file in the root directory of this source tree.
*/
import { Reflection } from 'modules';
import { Reflection, ReactComponents } from 'modules';
import Vue from 'vue';
export default class {
@ -16,12 +16,12 @@ export default class {
/**
* 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 {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
* @return {Vue}
*/
static inject(root, options, bdnode) {
if(bdnode) bdnode.appendTo(root);
if (bdnode) bdnode.appendTo(root);
const vue = new Vue(options);
@ -37,18 +37,18 @@ export default class {
* @return {React.Element}
*/
static createReactElement(component, props, mountAtTop) {
const { React } = Reflection.modules;
return React.createElement(this.ReactCompatibility, {component, mountAtTop, props});
return Reflection.modules.React.createElement(this.ReactCompatibility, {component, mountAtTop, props});
}
static get ReactCompatibility() {
if (this._ReactCompatibility) return this._ReactCompatibility;
const { React, ReactDOM } = Reflection.modules;
const { React, ReactDOM} = Reflection.modules;
return this._ReactCompatibility = class VueComponent extends React.Component {
/**
* A React component that renders a Vue component.
*/
const ReactCompatibility = class VueComponent extends React.Component {
render() {
return React.createElement('span');
return React.createElement('span', {className: 'bd-reactVueComponent'});
}
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) {
@ -98,6 +104,9 @@ export default class {
}
/**
* A Vue component that renders a React component.
*/
export const ReactComponent = {
props: ['component', 'component-props', 'component-children', 'react-element'],
render(createElement) {