From e73f2ebea9cb81fcb369beb7e9a2e6423532e052 Mon Sep 17 00:00:00 2001 From: Frank Wilkerson Date: Mon, 19 Feb 2018 23:58:03 -0700 Subject: [PATCH 1/2] split slot content by key, key onChange, render multiple children in a slot --- src/slot-content.js | 17 +++++++++-------- src/slot-provider.js | 2 +- src/slot.js | 15 ++++++++------- test/slot-content.test.js | 4 ++-- test/slot-provider.test.js | 2 +- test/slot.test.js | 12 ++++++------ test/with-slot.test.js | 8 ++++---- 7 files changed, 31 insertions(+), 29 deletions(-) diff --git a/src/slot-content.js b/src/slot-content.js index 477fc5c..ec0f685 100644 --- a/src/slot-content.js +++ b/src/slot-content.js @@ -4,24 +4,25 @@ export class SlotContent { if (slot) { slots.named[slot] = content; if (fireChange) { - for (let i=0; i { - let content = this.context.slots.named[this.props.name]; - if (content!=this.state.content) { - this.setState({ content }); + const {props, state} = this; + let content = this.context.slots.named[props.name]; + if (!state.content || content != state.content[props.name]) { + this.setState({ content: Object.assign({}, state.content, {[props.name]: content}) }); } }; this.componentDidMount = () => { - this.context.slots.onChange.push(update); + this.context.slots.onChange[this.props.name] = update; }; this.componentWillUnmount = () => { - this.context.slots.onChange.push(update); + this.context.slots.onChange[this.props.name] = update; }; update(); } (Slot.prototype = new Component()).constructor = Slot; -Slot.prototype.render = function(props, state) { +Slot.prototype.render = function(props, { content = {} }) { let child = props.children[0]; - return typeof child==='function' ? child(state.content) : (state.content || child); + return typeof child==='function' ? child(content[props.name]) : (content[props.name][0]) || child; }; diff --git a/test/slot-content.test.js b/test/slot-content.test.js index 807956c..e53b91e 100644 --- a/test/slot-content.test.js +++ b/test/slot-content.test.js @@ -18,9 +18,9 @@ describe('Slot', () => { expect(Spy).toHaveBeenCalledWith(jasmine.any(Object), { slots: { named: { - foo: 'bar' + foo: ['bar'] }, - onChange: [] + onChange: {} } }); }); diff --git a/test/slot-provider.test.js b/test/slot-provider.test.js index 4f4acd5..ae721cd 100644 --- a/test/slot-provider.test.js +++ b/test/slot-provider.test.js @@ -14,7 +14,7 @@ describe('SlotProvider', () => { expect(Spy).toHaveBeenCalledWith(jasmine.any(Object), { slots: { named: {}, - onChange: [] + onChange: {} } }); }); diff --git a/test/slot.test.js b/test/slot.test.js index e3afccb..8527cff 100644 --- a/test/slot.test.js +++ b/test/slot.test.js @@ -25,7 +25,7 @@ describe('Slot', () => { named: { foo: 'bar' }, - onChange: [] + onChange: {} }; render(( @@ -43,7 +43,7 @@ describe('Slot', () => { const slots = { named: {}, - onChange: [] + onChange: {} }; render(( @@ -52,13 +52,13 @@ describe('Slot', () => { ), document.createElement('x-root')); - expect(slots.onChange).toContain(jasmine.any(Function)); + expect(slots.onChange.foo).toEqual(jasmine.any(Function)); expect(spy).toHaveBeenCalledTimes(1); expect(spy).toHaveBeenCalledWith(undefined); slots.named.foo = 'bar'; - slots.onChange[0](); + slots.onChange['foo'](); await tick(); expect(spy).toHaveBeenCalledTimes(2); @@ -72,7 +72,7 @@ describe('Slot', () => { named: { foo: 'bar' }, - onChange: [] + onChange: {} }; render(( @@ -84,7 +84,7 @@ describe('Slot', () => { expect(spy).toHaveBeenCalledTimes(1); expect(spy).toHaveBeenCalledWith('bar'); - slots.onChange[0](); + slots.onChange['foo'](); await tick(); expect(spy).toHaveBeenCalledTimes(1); diff --git a/test/with-slot.test.js b/test/with-slot.test.js index 4b43ad0..743fe93 100644 --- a/test/with-slot.test.js +++ b/test/with-slot.test.js @@ -12,7 +12,7 @@ describe('withSlot()', () => { named: { foo: 'bar' }, - onChange: [] + onChange: {} }; const Child = withSlot('foo')(Spy); @@ -32,7 +32,7 @@ describe('withSlot()', () => { const slots = { named: {}, - onChange: [] + onChange: {} }; const Child = withSlot('foo')(Spy); @@ -46,10 +46,10 @@ describe('withSlot()', () => { expect(Spy).toHaveBeenCalledTimes(1); expect(Spy).toHaveBeenCalledWith({ foo: undefined, children: [] }, jasmine.anything()); - expect(slots.onChange).toContain(jasmine.any(Function)); + expect(slots.onChange.foo).toEqual(jasmine.any(Function)); slots.named.foo = 'bar'; - slots.onChange[0](); + slots.onChange['foo'](); await tick(); expect(Spy).toHaveBeenCalledTimes(2); From f1aa1983ef062deb778769950b8565e1b0663380 Mon Sep 17 00:00:00 2001 From: Frank Wilkerson Date: Tue, 20 Feb 2018 00:06:35 -0700 Subject: [PATCH 2/2] null check keyed content --- src/slot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slot.js b/src/slot.js index cc45e3d..a3f4057 100644 --- a/src/slot.js +++ b/src/slot.js @@ -20,5 +20,5 @@ export function Slot(props, context) { (Slot.prototype = new Component()).constructor = Slot; Slot.prototype.render = function(props, { content = {} }) { let child = props.children[0]; - return typeof child==='function' ? child(content[props.name]) : (content[props.name][0]) || child; + return typeof child==='function' ? child(content[props.name]) : (content[props.name] && content[props.name][0]) || child; };