From abd2b42307270a314bef6ac1cd49af6e0ae174dc Mon Sep 17 00:00:00 2001 From: Samuel Degueldre Date: Mon, 9 Jan 2023 10:50:57 +0100 Subject: [PATCH] [IMP] slots: make defaultContent of slot available to slot as `zero` In some cases, it is useful for a slot to be able to keep the default content of the slot it is supposed to replace and simply add extra content instead of simply replacing it entirely. This commit makes the default content of a slot available in the context as `zero` similar to how t-call can access the content that was inside the t-call. --- src/runtime/template_helpers.ts | 7 ++++ .../__snapshots__/slots.test.ts.snap | 36 +++++++++++++++++++ tests/components/slots.test.ts | 13 +++++++ 3 files changed, 56 insertions(+) diff --git a/src/runtime/template_helpers.ts b/src/runtime/template_helpers.ts index 82a68e1a..600b9ab3 100644 --- a/src/runtime/template_helpers.ts +++ b/src/runtime/template_helpers.ts @@ -29,6 +29,13 @@ function callSlot( const slots = ctx.props.slots || {}; const { __render, __ctx, __scope } = slots[name] || {}; const slotScope = ObjectCreate(__ctx || {}); + if (defaultContent) { + Object.defineProperty(slotScope, helpers.zero, { + get() { + return defaultContent(ctx, parent, key); + }, + }); + } if (__scope) { slotScope[__scope] = extra; } diff --git a/tests/components/__snapshots__/slots.test.ts.snap b/tests/components/__snapshots__/slots.test.ts.snap index 4eab0079..0e93fa1e 100644 --- a/tests/components/__snapshots__/slots.test.ts.snap +++ b/tests/components/__snapshots__/slots.test.ts.snap @@ -349,6 +349,42 @@ exports[`slots content is the default slot 2`] = ` }" `; +exports[`slots default content is available as 0 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { zero, markRaw } = helpers; + const comp1 = app.createComponent(\`Dialog\`, true, true, false, true); + + function slot1(ctx, node, key = \\"\\") { + const b2 = text(\`Before - \`); + const b3 = ctx[zero]; + const b4 = text(\` - After\`); + return multi([b2, b3, b4]); + } + + return function template(ctx, node, key = \\"\\") { + return comp1({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx}})}, key + \`__1\`, node, this, null); + } +}" +`; + +exports[`slots default content is available as 0 2`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { callSlot } = helpers; + + function defaultContent1(ctx, node, key = \\"\\") { + return text(\`default content\`); + } + + return function template(ctx, node, key = \\"\\") { + return callSlot(ctx, node, key, 'default', false, {}, defaultContent1.bind(this)); + } +}" +`; + exports[`slots default content is not rendered if named slot is provided 1`] = ` "function anonymous(app, bdom, helpers ) { diff --git a/tests/components/slots.test.ts b/tests/components/slots.test.ts index f36ef6d0..0c3f549a 100644 --- a/tests/components/slots.test.ts +++ b/tests/components/slots.test.ts @@ -1933,4 +1933,17 @@ describe("slots", () => { "

1 hello

child

2 hello

child

" ); }); + + test("default content is available as 0", async () => { + class Dialog extends Component { + static template = xml`default content`; + } + class Parent extends Component { + static template = xml`Before - - After`; + static components = { Dialog }; + } + + await mount(Parent, fixture); + expect(fixture.innerHTML).toBe("Before - default content - After"); + }); });