mirror of
https://github.com/withastro/astro.git
synced 2024-12-16 21:46:22 -05:00
Expose slots to components (#1368)
* Expose slots to components via Astro.slots * test: Add Astro.slots API tests * docs: Document Astro.slots API * docs: Duplicate Astro.slots documentation to other api-reference markdown * Update proposal to use booleans, based upon RFC feedback * update implementation & tests based on request * changeset
This commit is contained in:
parent
8f727647af
commit
98d785af1d
10 changed files with 169 additions and 0 deletions
5
.changeset/pink-toes-shake.md
Normal file
5
.changeset/pink-toes-shake.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Expose slots to components
|
|
@ -49,6 +49,17 @@ const data = Astro.fetchContent('../pages/post/*.md'); // returns an array of po
|
|||
}[]
|
||||
```
|
||||
|
||||
### `Astro.slots`
|
||||
|
||||
`Astro.slots` returns an object with any slotted regions passed into the current Astro file.
|
||||
|
||||
```js
|
||||
const {
|
||||
heading as headingSlot, // true or undefined, based on whether `<* slot="heading">` was used.
|
||||
default as defaultSlot, // true or undefined, based on whether `<* slot>` or `<* default>` was used.
|
||||
} = Astro.slots;
|
||||
```
|
||||
|
||||
### `Astro.request`
|
||||
|
||||
`Astro.request` returns an object with the following properties:
|
||||
|
|
|
@ -86,6 +86,17 @@ const path = Astro.site.pathname;
|
|||
<h1>Welcome to {path}</h1>
|
||||
```
|
||||
|
||||
### `Astro.slots`
|
||||
|
||||
`Astro.slots` returns an object with any slotted regions passed into the current Astro file.
|
||||
|
||||
```js
|
||||
const {
|
||||
heading as headingSlot, // true or undefined, based on whether `<* slot="heading">` was used.
|
||||
default as defaultSlot, // true or undefined, based on whether `<* slot>` or `<* default>` was used.
|
||||
} = Astro.slots;
|
||||
```
|
||||
|
||||
## `getStaticPaths()`
|
||||
|
||||
If a page uses dynamic params in the filename, that component will need to export a `getStaticPaths()` function.
|
||||
|
|
|
@ -158,12 +158,25 @@ import { __astro_hoisted_scripts } from 'astro/dist/internal/__astro_hoisted_scr
|
|||
const __astroScripts = __astro_hoisted_scripts([${result.components.map((n) => `typeof ${n} !== 'undefined' && ${n}`)}], ${JSON.stringify(result.hoistedScripts)});
|
||||
const __astroInternal = Symbol('astro.internal');
|
||||
const __astroContext = Symbol.for('astro.context');
|
||||
const __astroSlotted = Symbol.for('astro.slotted');
|
||||
async function __render(props, ...children) {
|
||||
const Astro = Object.create(__TopLevelAstro, {
|
||||
props: {
|
||||
value: props,
|
||||
enumerable: true
|
||||
},
|
||||
slots: {
|
||||
value: children.reduce(
|
||||
(slots, child) => {
|
||||
for (let name in child.$slots) {
|
||||
slots[name] = Boolean(child.$slots[name])
|
||||
}
|
||||
return slots
|
||||
},
|
||||
{}
|
||||
),
|
||||
enumerable: true
|
||||
},
|
||||
pageCSS: {
|
||||
value: (props[__astroContext] && props[__astroContext].pageCSS) || [],
|
||||
enumerable: true
|
||||
|
|
|
@ -74,4 +74,60 @@ Slots('Slots work on Components', async ({ runtime }) => {
|
|||
assert.equal($('#default').children('astro-component').length, 1, 'Slotted component into default slot');
|
||||
});
|
||||
|
||||
Slots('Slots API work on Components', async ({ runtime }) => {
|
||||
// IDs will exist whether the slots are filled or not
|
||||
{
|
||||
const result = await runtime.load('/slottedapi-default');
|
||||
assert.ok(!result.error, `build error: ${result.error}`);
|
||||
|
||||
const $ = doc(result.contents);
|
||||
|
||||
assert.equal($('#a').length, 1);
|
||||
assert.equal($('#b').length, 1);
|
||||
assert.equal($('#c').length, 1);
|
||||
assert.equal($('#default').length, 1);
|
||||
}
|
||||
|
||||
// IDs will not exist because the slots are not filled
|
||||
{
|
||||
const result = await runtime.load('/slottedapi-empty');
|
||||
assert.ok(!result.error, `build error: ${result.error}`);
|
||||
|
||||
const $ = doc(result.contents);
|
||||
|
||||
assert.equal($('#a').length, 0);
|
||||
assert.equal($('#b').length, 0);
|
||||
assert.equal($('#c').length, 0);
|
||||
assert.equal($('#default').length, 0);
|
||||
}
|
||||
|
||||
// IDs will exist because the slots are filled
|
||||
{
|
||||
const result = await runtime.load('/slottedapi-filled');
|
||||
assert.ok(!result.error, `build error: ${result.error}`);
|
||||
|
||||
const $ = doc(result.contents);
|
||||
|
||||
assert.equal($('#a').length, 1);
|
||||
assert.equal($('#b').length, 1);
|
||||
assert.equal($('#c').length, 1);
|
||||
|
||||
assert.equal($('#default').length, 0); // the default slot is not filled
|
||||
}
|
||||
|
||||
// Default ID will exist because the default slot is filled
|
||||
{
|
||||
const result = await runtime.load('/slottedapi-default-filled');
|
||||
assert.ok(!result.error, `build error: ${result.error}`);
|
||||
|
||||
const $ = doc(result.contents);
|
||||
|
||||
assert.equal($('#a').length, 0);
|
||||
assert.equal($('#b').length, 0);
|
||||
assert.equal($('#c').length, 0);
|
||||
|
||||
assert.equal($('#default').length, 1); // the default slot is filled
|
||||
}
|
||||
});
|
||||
|
||||
Slots.run();
|
||||
|
|
15
packages/astro/test/fixtures/astro-slots/src/components/SlottedAPI.astro
vendored
Normal file
15
packages/astro/test/fixtures/astro-slots/src/components/SlottedAPI.astro
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
{Astro.slots.a && <div id="a">
|
||||
<slot name="a" />
|
||||
</div>}
|
||||
|
||||
{Astro.slots.b && <div id="b">
|
||||
<slot name="b" />
|
||||
</div>}
|
||||
|
||||
{Astro.slots.c && <div id="c">
|
||||
<slot name="c" />
|
||||
</div>}
|
||||
|
||||
{Astro.slots.default && <div id="default">
|
||||
<slot />
|
||||
</div>}
|
15
packages/astro/test/fixtures/astro-slots/src/pages/slottedapi-default-filled.astro
vendored
Normal file
15
packages/astro/test/fixtures/astro-slots/src/pages/slottedapi-default-filled.astro
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
import Slotted from '../components/SlottedAPI.astro';
|
||||
---
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<!-- Test Astro.slots behavior. -->
|
||||
<!-- IDs will exist because the slots are filled -->
|
||||
</head>
|
||||
<body>
|
||||
<Slotted>
|
||||
Default
|
||||
</Slotted>
|
||||
</body>
|
||||
</html>
|
13
packages/astro/test/fixtures/astro-slots/src/pages/slottedapi-default.astro
vendored
Normal file
13
packages/astro/test/fixtures/astro-slots/src/pages/slottedapi-default.astro
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
import Slotted from '../components/Slotted.astro';
|
||||
---
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<!-- Test default slots behavior. -->
|
||||
<!-- IDs will exist whether the slots are filled or not -->
|
||||
</head>
|
||||
<body>
|
||||
<Slotted />
|
||||
</body>
|
||||
</html>
|
13
packages/astro/test/fixtures/astro-slots/src/pages/slottedapi-empty.astro
vendored
Normal file
13
packages/astro/test/fixtures/astro-slots/src/pages/slottedapi-empty.astro
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
import Slotted from '../components/SlottedAPI.astro';
|
||||
---
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<!-- Test Astro.slots behavior. -->
|
||||
<!-- IDs will not exist because the slots are not filled -->
|
||||
</head>
|
||||
<body>
|
||||
<Slotted />
|
||||
</body>
|
||||
</html>
|
17
packages/astro/test/fixtures/astro-slots/src/pages/slottedapi-filled.astro
vendored
Normal file
17
packages/astro/test/fixtures/astro-slots/src/pages/slottedapi-filled.astro
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
import Slotted from '../components/SlottedAPI.astro';
|
||||
---
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<!-- Test Astro.slots behavior. -->
|
||||
<!-- IDs will exist because the slots are filled -->
|
||||
</head>
|
||||
<body>
|
||||
<Slotted>
|
||||
<span slot="a">A</span>
|
||||
<span slot="b">B</span>
|
||||
<span slot="c">C</span>
|
||||
</Slotted>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue