diff --git a/client/coral-embed-stream/src/tabs/stream/components/Comment.js b/client/coral-embed-stream/src/tabs/stream/components/Comment.js index 521b28742..f0dcc1017 100644 --- a/client/coral-embed-stream/src/tabs/stream/components/Comment.js +++ b/client/coral-embed-stream/src/tabs/stream/components/Comment.js @@ -604,6 +604,7 @@ export default class Comment extends React.Component { defaultComponent={CommentContent} {...slotProps} queryData={queryData} + slotSize={1} /> )} diff --git a/client/coral-framework/components/Slot.js b/client/coral-framework/components/Slot.js index fe63b4f30..dfe2d80d5 100644 --- a/client/coral-framework/components/Slot.js +++ b/client/coral-framework/components/Slot.js @@ -7,6 +7,7 @@ import PropTypes from 'prop-types'; import isEqual from 'lodash/isEqual'; import get from 'lodash/get'; import { getShallowChanges } from 'coral-framework/utils'; +import omit from 'lodash/omit'; const emptyConfig = {}; @@ -32,27 +33,29 @@ class Slot extends React.Component { } getSlotProps(props = this.props) { - const { - fill: _a, - inline: _b, - className: _c, - reduxState: _d, - defaultComponent_: _e, - queryData: _f, - childFactory: _g, - component: _h, - ...rest - } = props; - return rest; + return omit(props, [ + 'fill', + 'inline', + 'className', + 'reduxState', + 'slotSize', + 'defaultComponent', + 'queryData', + 'childFactory', + 'component', + ]); } getChildren(props = this.props) { + const { slotSize = 0 } = props; const { plugins } = this.context; + return plugins.getSlotElements( props.fill, props.reduxState, this.getSlotProps(props), - props.queryData + props.queryData, + { slotSize } ); } @@ -109,6 +112,11 @@ Slot.propTypes = { reduxState: PropTypes.object, defaultComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), + /** + * Specifies the number of children that can fill the slot. + */ + slotSize: PropTypes.number, + /** * You may specify the component to use as the root wrapper. * Defaults to 'div'. diff --git a/client/coral-framework/services/plugins.js b/client/coral-framework/services/plugins.js index 6f99a2291..222cc1b42 100644 --- a/client/coral-framework/services/plugins.js +++ b/client/coral-framework/services/plugins.js @@ -97,8 +97,9 @@ class PluginsService { /** * Returns React Elements for given slot. */ - getSlotElements(slot, reduxState, props = {}, queryData = {}) { + getSlotElements(slot, reduxState, props = {}, queryData = {}, options = {}) { const pluginConfig = get(reduxState, 'config.plugin_config') || emptyConfig; + const { slotSize = 0 } = options; const isDisabled = component => { if ( @@ -129,11 +130,21 @@ class PluginsService { return false; }; - return flatten( + const slots = flatten( this.plugins .filter(o => o.module.slots && o.module.slots[slot]) .map(o => o.module.slots[slot]) - ) + ); + + if (slotSize > 0 && slots.length > slotSize) { + console.warn( + `Slot[${slot}] supports a maximum of ${slotSize} plugins providing slots, got ${ + slots.length + }, will only use the first ${slotSize}` + ); + } + + return (slotSize > 0 ? slots.slice(0, slotSize) : slots) .map((component, i) => ({ component, disabled: isDisabled(component),