mirror of https://github.com/sveltejs/svelte
feat(site-2): Split docs (#8435)
* Update links * Move blog to site/content * Update site/content/docs/02-component-format.md * Fix docs links * Add global prettierrc * Auto format * Fix git merge artifact * Fix errors * Update html to svelte(remaining ones) * Add 2 blog posts * Modify prettierrc * Minor design fix * Switch package lock to spaces, prettier ignore * Regenerate package lock * prettier format * Push * Remove console.logs * Minor fixes * Fix search * Fix heading <code> style * Fix search some more * Code cleanup * Update deps * Move content around * Allow drafts * Redirect logic * Don't render anything on docs if /docs * Shorten the regex patterns * Fix some more * Hack the build into working * Modernize docs links * Add content to introduction * Modify the content * fix content links * Reduce duplication in redirect regex * Differences from Kit page * Fix link * Make OnThisPage visible on all docs * Misc changes * Move differences page to introduction * Run prettier * Prerender examples api routes * Modify introdution page * replace positions of readonly and get * Minor blog style enhancement --------- Co-authored-by: Rich Harris <richard.a.harris@gmail.com>pull/8453/head
parent
95abaec32a
commit
b569018fef
@ -1,11 +0,0 @@
|
||||
---
|
||||
title: Before we begin
|
||||
---
|
||||
|
||||
This page contains detailed API reference documentation. It's intended to be a resource for people who already have some familiarity with Svelte.
|
||||
|
||||
If that's not you (yet), you may prefer to visit the [interactive tutorial](/tutorial) or the [examples](/examples) before consulting this reference.
|
||||
|
||||
Don't be shy about asking for help in the [Discord chatroom](https://svelte.dev/chat).
|
||||
|
||||
Using an older version of Svelte? Have a look at the [v2 docs](https://v2.svelte.dev).
|
@ -1,24 +0,0 @@
|
||||
---
|
||||
title: Getting started
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
To try Svelte in an interactive online environment you can try [the REPL](https://svelte.dev/repl) or [StackBlitz](https://node.new/svelte).
|
||||
|
||||
To create a project locally we recommend using [SvelteKit](https://kit.svelte.dev/), the official application framework from the Svelte team:
|
||||
|
||||
```
|
||||
npm create svelte@latest myapp
|
||||
cd myapp
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
SvelteKit will handle calling [the Svelte compiler](https://www.npmjs.com/package/svelte) to convert your `.svelte` files into `.js` files that create the DOM and `.css` files that style it. It also provides all the other pieces you need to build a web application such as a development server, routing, and deployment. [SvelteKit](https://kit.svelte.dev/) utilizes [Vite](https://vitejs.dev/) to build your code and handle server-side rendering (SSR). There are [plugins for all the major web bundlers](https://sveltesociety.dev/tools#bundling) to handle Svelte compilation, which will output `.js` and `.css` that you can insert into your HTML, but most others won't handle SSR.
|
||||
|
||||
If you don't need a full-fledged app framework and instead want to build a simple frontend-only site/app, you can also use Svelte (without Kit) with Vite by running `npm init vite` and selecting the `svelte` option. With this, `npm run build` will generate HTML, JS and CSS files inside the `dist` directory.
|
||||
|
||||
The Svelte team maintains a [VS Code extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) and there are integrations with various other [editors](https://sveltesociety.dev/tools#editor-support) and tools as well.
|
||||
|
||||
If you're having trouble, get help on [Discord](https://svelte.dev/chat) or [StackOverflow](https://stackoverflow.com/questions/tagged/svelte).
|
@ -0,0 +1,49 @@
|
||||
---
|
||||
title: Introduction
|
||||
---
|
||||
|
||||
Welcome to Svelte docs. These are for folks who are already familiar with Svelte and want to learn more about the details of how it works.
|
||||
|
||||
If that's not you (yet), you may prefer to visit the [interactive tutorial](/tutorial) or the [examples](/examples) before consulting this reference.
|
||||
|
||||
Don't be shy about asking for help in the [Discord chatroom](https://svelte.dev/chat).
|
||||
|
||||
Using an older version of Svelte? Have a look at the [v2 docs](https://v2.svelte.dev).
|
||||
|
||||
## Start a new project
|
||||
|
||||
To try Svelte in an interactive online environment you can try [the REPL](https://svelte.dev/repl) or [StackBlitz](https://node.new/svelte).
|
||||
|
||||
To create a project locally we recommend using [SvelteKit](https://kit.svelte.dev/), the official application framework from the Svelte team:
|
||||
|
||||
```
|
||||
npm create svelte@latest myapp
|
||||
cd myapp
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
SvelteKit will handle calling [the Svelte compiler](https://www.npmjs.com/package/svelte) to convert your `.svelte` files into `.js` files that create the DOM and `.css` files that style it. It also provides all the other pieces you need to build a web application such as a development server, routing, and deployment. [SvelteKit](https://kit.svelte.dev/) utilizes [Vite](https://vitejs.dev/) to build your code and handle server-side rendering (SSR). There are [plugins for all the major web bundlers](https://sveltesociety.dev/tools#bundling) to handle Svelte compilation, which will output `.js` and `.css` that you can insert into your HTML, but most others won't handle SSR.
|
||||
|
||||
### Alternatives to SvelteKit
|
||||
|
||||
If you don't need a full-fledged app framework and instead want to build a simple frontend-only site/app, you can also use Svelte (without Kit) with Vite by running `npm init vite` and selecting the `svelte` option. With this, `npm run build` will generate HTML, JS and CSS files inside the `dist` directory.
|
||||
|
||||
Notable Mentions:
|
||||
|
||||
- [Routify](https://www.routify.dev/)
|
||||
- [Elder.js](https://elderjs.com/)
|
||||
|
||||
## Differences from SvelteKit
|
||||
|
||||
Svelte renders UI components. You can compose these components and render an entire page with just Svelte, but you need more than just Svelte to write an entire app.
|
||||
|
||||
SvelteKit provides basic functionality like a [router](https://kit.svelte.dev/glossary#routing) — which updates the UI when a link is clicked — and [server-side rendering (SSR)](https://kit.svelte.dev/glossary#ssr). But beyond that, building an app with all the modern best practices is fiendishly complicated. Those practices include [build optimizations](https://vitejs.dev/guide/features.html#build-optimizations), so that you load only the minimal required code; [offline support](https://kit.svelte.devservice-workers); [preloading](https://kit.svelte.dev/link-options#data-sveltekit-preload-data) pages before the user initiates navigation; [configurable rendering](https://kit.svelte.dev/page-options) that allows you to render different parts of your app on the server with [SSR](https://kit.svelte.dev/glossary#ssr), in the browser [client-side rendering](https://kit.svelte.dev/glossary#csr), or at build-time with [prerendering](https://kit.svelte.dev/glossary#prerendering); and many other things. SvelteKit does all the boring stuff for you so that you can get on with the creative part.
|
||||
|
||||
It reflects changes to your code in the browser instantly to provide a lightning-fast and feature-rich development experience by leveraging [Vite](https://vitejs.dev/) with a [Svelte plugin](https://github.com/sveltejs/vite-plugin-svelte) to do [Hot Module Replacement (HMR)](https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/config.md#hot).
|
||||
|
||||
## Editor tooling
|
||||
|
||||
The Svelte team maintains a [VS Code extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) and there are integrations with various other [editors](https://sveltesociety.dev/tools#editor-support) and tools as well.
|
||||
|
||||
If you're having trouble, get help on [Discord](https://svelte.dev/chat) or [StackOverflow](https://stackoverflow.com/questions/tagged/svelte).
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"title": "Getting Started"
|
||||
}
|
@ -0,0 +1,206 @@
|
||||
---
|
||||
title: Logic blocks
|
||||
---
|
||||
|
||||
## {#if ...}
|
||||
|
||||
```svelte
|
||||
{#if expression}...{/if}
|
||||
```
|
||||
|
||||
```svelte
|
||||
{#if expression}...{:else if expression}...{/if}
|
||||
```
|
||||
|
||||
```svelte
|
||||
{#if expression}...{:else}...{/if}
|
||||
```
|
||||
|
||||
Content that is conditionally rendered can be wrapped in an if block.
|
||||
|
||||
```svelte
|
||||
{#if answer === 42}
|
||||
<p>what was the question?</p>
|
||||
{/if}
|
||||
```
|
||||
|
||||
Additional conditions can be added with `{:else if expression}`, optionally ending in an `{:else}` clause.
|
||||
|
||||
```svelte
|
||||
{#if porridge.temperature > 100}
|
||||
<p>too hot!</p>
|
||||
{:else if 80 > porridge.temperature}
|
||||
<p>too cold!</p>
|
||||
{:else}
|
||||
<p>just right!</p>
|
||||
{/if}
|
||||
```
|
||||
|
||||
(Blocks don't have to wrap elements, they can also wrap text within elements!)
|
||||
|
||||
## {#each ...}
|
||||
|
||||
```svelte
|
||||
{#each expression as name}...{/each}
|
||||
```
|
||||
|
||||
```svelte
|
||||
{#each expression as name, index}...{/each}
|
||||
```
|
||||
|
||||
```svelte
|
||||
{#each expression as name (key)}...{/each}
|
||||
```
|
||||
|
||||
```svelte
|
||||
{#each expression as name, index (key)}...{/each}
|
||||
```
|
||||
|
||||
```svelte
|
||||
{#each expression as name}...{:else}...{/each}
|
||||
```
|
||||
|
||||
Iterating over lists of values can be done with an each block.
|
||||
|
||||
```svelte
|
||||
<h1>Shopping list</h1>
|
||||
<ul>
|
||||
{#each items as item}
|
||||
<li>{item.name} x {item.qty}</li>
|
||||
{/each}
|
||||
</ul>
|
||||
```
|
||||
|
||||
You can use each blocks to iterate over any array or array-like value — that is, any object with a `length` property.
|
||||
|
||||
An each block can also specify an _index_, equivalent to the second argument in an `array.map(...)` callback:
|
||||
|
||||
```svelte
|
||||
{#each items as item, i}
|
||||
<li>{i + 1}: {item.name} x {item.qty}</li>
|
||||
{/each}
|
||||
```
|
||||
|
||||
If a _key_ expression is provided — which must uniquely identify each list item — Svelte will use it to diff the list when data changes, rather than adding or removing items at the end. The key can be any object, but strings and numbers are recommended since they allow identity to persist when the objects themselves change.
|
||||
|
||||
```svelte
|
||||
{#each items as item (item.id)}
|
||||
<li>{item.name} x {item.qty}</li>
|
||||
{/each}
|
||||
|
||||
<!-- or with additional index value -->
|
||||
{#each items as item, i (item.id)}
|
||||
<li>{i + 1}: {item.name} x {item.qty}</li>
|
||||
{/each}
|
||||
```
|
||||
|
||||
You can freely use destructuring and rest patterns in each blocks.
|
||||
|
||||
```svelte
|
||||
{#each items as { id, name, qty }, i (id)}
|
||||
<li>{i + 1}: {name} x {qty}</li>
|
||||
{/each}
|
||||
|
||||
{#each objects as { id, ...rest }}
|
||||
<li><span>{id}</span><MyComponent {...rest} /></li>
|
||||
{/each}
|
||||
|
||||
{#each items as [id, ...rest]}
|
||||
<li><span>{id}</span><MyComponent values={rest} /></li>
|
||||
{/each}
|
||||
```
|
||||
|
||||
An each block can also have an `{:else}` clause, which is rendered if the list is empty.
|
||||
|
||||
```svelte
|
||||
{#each todos as todo}
|
||||
<p>{todo.text}</p>
|
||||
{:else}
|
||||
<p>No tasks today!</p>
|
||||
{/each}
|
||||
```
|
||||
|
||||
## {#await ...}
|
||||
|
||||
```svelte
|
||||
{#await expression}...{:then name}...{:catch name}...{/await}
|
||||
```
|
||||
|
||||
```svelte
|
||||
{#await expression}...{:then name}...{/await}
|
||||
```
|
||||
|
||||
```svelte
|
||||
{#await expression then name}...{/await}
|
||||
```
|
||||
|
||||
```svelte
|
||||
{#await expression catch name}...{/await}
|
||||
```
|
||||
|
||||
Await blocks allow you to branch on the three possible states of a Promise — pending, fulfilled or rejected. In SSR mode, only the pending state will be rendered on the server.
|
||||
|
||||
```svelte
|
||||
{#await promise}
|
||||
<!-- promise is pending -->
|
||||
<p>waiting for the promise to resolve...</p>
|
||||
{:then value}
|
||||
<!-- promise was fulfilled -->
|
||||
<p>The value is {value}</p>
|
||||
{:catch error}
|
||||
<!-- promise was rejected -->
|
||||
<p>Something went wrong: {error.message}</p>
|
||||
{/await}
|
||||
```
|
||||
|
||||
The `catch` block can be omitted if you don't need to render anything when the promise rejects (or no error is possible).
|
||||
|
||||
```svelte
|
||||
{#await promise}
|
||||
<!-- promise is pending -->
|
||||
<p>waiting for the promise to resolve...</p>
|
||||
{:then value}
|
||||
<!-- promise was fulfilled -->
|
||||
<p>The value is {value}</p>
|
||||
{/await}
|
||||
```
|
||||
|
||||
If you don't care about the pending state, you can also omit the initial block.
|
||||
|
||||
```svelte
|
||||
{#await promise then value}
|
||||
<p>The value is {value}</p>
|
||||
{/await}
|
||||
```
|
||||
|
||||
Similarly, if you only want to show the error state, you can omit the `then` block.
|
||||
|
||||
```svelte
|
||||
{#await promise catch error}
|
||||
<p>The error is {error}</p>
|
||||
{/await}
|
||||
```
|
||||
|
||||
## {#key ...}
|
||||
|
||||
```svelte
|
||||
{#key expression}...{/key}
|
||||
```
|
||||
|
||||
Key blocks destroy and recreate their contents when the value of an expression changes.
|
||||
|
||||
This is useful if you want an element to play its transition whenever a value changes.
|
||||
|
||||
```svelte
|
||||
{#key value}
|
||||
<div transition:fade>{value}</div>
|
||||
{/key}
|
||||
```
|
||||
|
||||
When used around components, this will cause them to be reinstantiated and reinitialised.
|
||||
|
||||
```svelte
|
||||
{#key value}
|
||||
<Component />
|
||||
{/key}
|
||||
```
|
@ -0,0 +1,84 @@
|
||||
---
|
||||
title: Special tags
|
||||
---
|
||||
|
||||
## {@html ...}
|
||||
|
||||
```svelte
|
||||
{@html expression}
|
||||
```
|
||||
|
||||
In a text expression, characters like `<` and `>` are escaped; however, with HTML expressions, they're not.
|
||||
|
||||
The expression should be valid standalone HTML — `{@html "<div>"}content{@html "</div>"}` will _not_ work, because `</div>` is not valid HTML. It also will _not_ compile Svelte code.
|
||||
|
||||
> Svelte does not sanitize expressions before injecting HTML. If the data comes from an untrusted source, you must sanitize it, or you are exposing your users to an XSS vulnerability.
|
||||
|
||||
```svelte
|
||||
<div class="blog-post">
|
||||
<h1>{post.title}</h1>
|
||||
{@html post.content}
|
||||
</div>
|
||||
```
|
||||
|
||||
## {@debug ...}
|
||||
|
||||
```svelte
|
||||
{@debug}
|
||||
```
|
||||
|
||||
```svelte
|
||||
{@debug var1, var2, ..., varN}
|
||||
```
|
||||
|
||||
The `{@debug ...}` tag offers an alternative to `console.log(...)`. It logs the values of specific variables whenever they change, and pauses code execution if you have devtools open.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
let user = {
|
||||
firstname: 'Ada',
|
||||
lastname: 'Lovelace'
|
||||
};
|
||||
</script>
|
||||
|
||||
{@debug user}
|
||||
|
||||
<h1>Hello {user.firstname}!</h1>
|
||||
```
|
||||
|
||||
`{@debug ...}` accepts a comma-separated list of variable names (not arbitrary expressions).
|
||||
|
||||
```svelte
|
||||
<!-- Compiles -->
|
||||
{@debug user}
|
||||
{@debug user1, user2, user3}
|
||||
|
||||
<!-- WON'T compile -->
|
||||
{@debug user.firstname}
|
||||
{@debug myArray[0]}
|
||||
{@debug !isReady}
|
||||
{@debug typeof user === 'object'}
|
||||
```
|
||||
|
||||
The `{@debug}` tag without any arguments will insert a `debugger` statement that gets triggered when _any_ state changes, as opposed to the specified variables.
|
||||
|
||||
## {@const ...}
|
||||
|
||||
```svelte
|
||||
{@const assignment}
|
||||
```
|
||||
|
||||
The `{@const ...}` tag defines a local constant.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
export let boxes;
|
||||
</script>
|
||||
|
||||
{#each boxes as box}
|
||||
{@const area = box.width * box.height}
|
||||
{box.width} * {box.height} = {area}
|
||||
{/each}
|
||||
```
|
||||
|
||||
`{@const}` is only allowed as direct child of `{#if}`, `{:else if}`, `{:else}`, `{#each}`, `{:then}`, `{:catch}`, `<Component />` or `<svelte:fragment />`.
|
@ -0,0 +1,109 @@
|
||||
---
|
||||
title: Component directives
|
||||
---
|
||||
|
||||
## on:_eventname_
|
||||
|
||||
```svelte
|
||||
on:eventname={handler}
|
||||
```
|
||||
|
||||
Components can emit events using [createEventDispatcher](/docs/svelte#createeventdispatcher), or by forwarding DOM events. Listening for component events looks the same as listening for DOM events:
|
||||
|
||||
```svelte
|
||||
<SomeComponent on:whatever={handler} />
|
||||
```
|
||||
|
||||
As with DOM events, if the `on:` directive is used without a value, the component will _forward_ the event, meaning that a consumer of the component can listen for it.
|
||||
|
||||
```svelte
|
||||
<SomeComponent on:whatever />
|
||||
```
|
||||
|
||||
## --style-props
|
||||
|
||||
```svelte
|
||||
--style-props="anycssvalue"
|
||||
```
|
||||
|
||||
You can also pass styles as props to components for the purposes of theming, using CSS custom properties.
|
||||
|
||||
Svelte's implementation is essentially syntactic sugar for adding a wrapper element. This example:
|
||||
|
||||
```svelte
|
||||
<Slider bind:value min={0} --rail-color="black" --track-color="rgb(0, 0, 255)" />
|
||||
```
|
||||
|
||||
Desugars to this:
|
||||
|
||||
```svelte
|
||||
<div style="display: contents; --rail-color: black; --track-color: rgb(0, 0, 255)">
|
||||
<Slider bind:value min={0} max={100} />
|
||||
</div>
|
||||
```
|
||||
|
||||
**Note**: Since this is an extra `<div>`, beware that your CSS structure might accidentally target this. Be mindful of this added wrapper element when using this feature.
|
||||
|
||||
For SVG namespace, the example above desugars into using `<g>` instead:
|
||||
|
||||
```svelte
|
||||
<g style="--rail-color: black; --track-color: rgb(0, 0, 255)">
|
||||
<Slider bind:value min={0} max={100} />
|
||||
</g>
|
||||
```
|
||||
|
||||
**Note**: Since this is an extra `<g>`, beware that your CSS structure might accidentally target this. Be mindful of this added wrapper element when using this feature.
|
||||
|
||||
Svelte's CSS Variables support allows for easily themeable components:
|
||||
|
||||
```svelte
|
||||
<!-- Slider.svelte -->
|
||||
<style>
|
||||
.potato-slider-rail {
|
||||
background-color: var(--rail-color, var(--theme-color, 'purple'));
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
So you can set a high-level theme color:
|
||||
|
||||
```css
|
||||
/* global.css */
|
||||
html {
|
||||
--theme-color: black;
|
||||
}
|
||||
```
|
||||
|
||||
Or override it at the consumer level:
|
||||
|
||||
```svelte
|
||||
<Slider --rail-color="goldenrod" />
|
||||
```
|
||||
|
||||
## bind:_property_
|
||||
|
||||
```svelte
|
||||
bind:property={variable}
|
||||
```
|
||||
|
||||
You can bind to component props using the same syntax as for elements.
|
||||
|
||||
```svelte
|
||||
<Keypad bind:value={pin} />
|
||||
```
|
||||
|
||||
## bind:this
|
||||
|
||||
```svelte
|
||||
bind:this={component_instance}
|
||||
```
|
||||
|
||||
Components also support `bind:this`, allowing you to interact with component instances programmatically.
|
||||
|
||||
> Note that we can't do `{cart.empty}` since `cart` is `undefined` when the button is first rendered and throws an error.
|
||||
|
||||
```svelte
|
||||
<ShoppingCart bind:this={cart} />
|
||||
|
||||
<button on:click={() => cart.empty()}> Empty shopping cart </button>
|
||||
```
|
@ -0,0 +1,335 @@
|
||||
---
|
||||
title: Special elements
|
||||
---
|
||||
|
||||
## `<slot>`
|
||||
|
||||
```svelte
|
||||
<slot><!-- optional fallback --></slot>
|
||||
```
|
||||
|
||||
```svelte
|
||||
<slot name="x"><!-- optional fallback --></slot>
|
||||
```
|
||||
|
||||
```svelte
|
||||
<slot prop={value} />
|
||||
```
|
||||
|
||||
Components can have child content, in the same way that elements can.
|
||||
|
||||
The content is exposed in the child component using the `<slot>` element, which can contain fallback content that is rendered if no children are provided.
|
||||
|
||||
```svelte
|
||||
<!-- Widget.svelte -->
|
||||
<div>
|
||||
<slot>
|
||||
this fallback content will be rendered when no content is provided, like in the first example
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
<!-- App.svelte -->
|
||||
<Widget />
|
||||
<!-- this component will render the default content -->
|
||||
|
||||
<Widget>
|
||||
<p>this is some child content that will overwrite the default slot content</p>
|
||||
</Widget>
|
||||
```
|
||||
|
||||
Note: If you want to render regular `<slot>` element, You can use `<svelte:element this="slot" />`.
|
||||
|
||||
Note: If you want to render regular `<slot>` element, You can use `<svelte:element this="slot" />`.
|
||||
|
||||
### `<slot name="`_name_`">`
|
||||
|
||||
Named slots allow consumers to target specific areas. They can also have fallback content.
|
||||
|
||||
```svelte
|
||||
<!-- Widget.svelte -->
|
||||
<div>
|
||||
<slot name="header">No header was provided</slot>
|
||||
<p>Some content between header and footer</p>
|
||||
<slot name="footer" />
|
||||
</div>
|
||||
|
||||
<!-- App.svelte -->
|
||||
<Widget>
|
||||
<h1 slot="header">Hello</h1>
|
||||
<p slot="footer">Copyright (c) 2019 Svelte Industries</p>
|
||||
</Widget>
|
||||
```
|
||||
|
||||
Components can be placed in a named slot using the syntax `<Component slot="name" />`.
|
||||
In order to place content in a slot without using a wrapper element, you can use the special element `<svelte:fragment>`.
|
||||
|
||||
```svelte
|
||||
<!-- Widget.svelte -->
|
||||
<div>
|
||||
<slot name="header">No header was provided</slot>
|
||||
<p>Some content between header and footer</p>
|
||||
<slot name="footer" />
|
||||
</div>
|
||||
|
||||
<!-- App.svelte -->
|
||||
<Widget>
|
||||
<HeaderComponent slot="header" />
|
||||
<svelte:fragment slot="footer">
|
||||
<p>All rights reserved.</p>
|
||||
<p>Copyright (c) 2019 Svelte Industries</p>
|
||||
</svelte:fragment>
|
||||
</Widget>
|
||||
```
|
||||
|
||||
### $$slots
|
||||
|
||||
`$$slots` is an object whose keys are the names of the slots passed into the component by the parent. If the parent does not pass in a slot with a particular name, that name will not be present in `$$slots`. This allows components to render a slot (and other elements, like wrappers for styling) only if the parent provides it.
|
||||
|
||||
Note that explicitly passing in an empty named slot will add that slot's name to `$$slots`. For example, if a parent passes `<div slot="title" />` to a child component, `$$slots.title` will be truthy within the child.
|
||||
|
||||
```svelte
|
||||
<!-- Card.svelte -->
|
||||
<div>
|
||||
<slot name="title" />
|
||||
{#if $$slots.description}
|
||||
<!-- This <hr> and slot will render only if a slot named "description" is provided. -->
|
||||
<hr />
|
||||
<slot name="description" />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- App.svelte -->
|
||||
<Card>
|
||||
<h1 slot="title">Blog Post Title</h1>
|
||||
<!-- No slot named "description" was provided so the optional slot will not be rendered. -->
|
||||
</Card>
|
||||
```
|
||||
|
||||
### `<slot key={`_value_`}>`
|
||||
|
||||
Slots can be rendered zero or more times and can pass values _back_ to the parent using props. The parent exposes the values to the slot template using the `let:` directive.
|
||||
|
||||
The usual shorthand rules apply — `let:item` is equivalent to `let:item={item}`, and `<slot {item}>` is equivalent to `<slot item={item}>`.
|
||||
|
||||
```svelte
|
||||
<!-- FancyList.svelte -->
|
||||
<ul>
|
||||
{#each items as item}
|
||||
<li class="fancy">
|
||||
<slot prop={item} />
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
|
||||
<!-- App.svelte -->
|
||||
<FancyList {items} let:prop={thing}>
|
||||
<div>{thing.text}</div>
|
||||
</FancyList>
|
||||
```
|
||||
|
||||
Named slots can also expose values. The `let:` directive goes on the element with the `slot` attribute.
|
||||
|
||||
```svelte
|
||||
<!-- FancyList.svelte -->
|
||||
<ul>
|
||||
{#each items as item}
|
||||
<li class="fancy">
|
||||
<slot name="item" {item} />
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
|
||||
<slot name="footer" />
|
||||
|
||||
<!-- App.svelte -->
|
||||
<FancyList {items}>
|
||||
<div slot="item" let:item>{item.text}</div>
|
||||
<p slot="footer">Copyright (c) 2019 Svelte Industries</p>
|
||||
</FancyList>
|
||||
```
|
||||
|
||||
## `<svelte:self>`
|
||||
|
||||
The `<svelte:self>` element allows a component to include itself, recursively.
|
||||
|
||||
It cannot appear at the top level of your markup; it must be inside an if or each block or passed to a component's slot to prevent an infinite loop.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
export let count;
|
||||
</script>
|
||||
|
||||
{#if count > 0}
|
||||
<p>counting down... {count}</p>
|
||||
<svelte:self count={count - 1} />
|
||||
{:else}
|
||||
<p>lift-off!</p>
|
||||
{/if}
|
||||
```
|
||||
|
||||
## `<svelte:component>`
|
||||
|
||||
```svelte
|
||||
<svelte:component this={expression} />
|
||||
```
|
||||
|
||||
The `<svelte:component>` element renders a component dynamically, using the component constructor specified as the `this` property. When the property changes, the component is destroyed and recreated.
|
||||
|
||||
If `this` is falsy, no component is rendered.
|
||||
|
||||
```svelte
|
||||
<svelte:component this={currentSelection.component} foo={bar} />
|
||||
```
|
||||
|
||||
## `<svelte:element>`
|
||||
|
||||
```svelte
|
||||
<svelte:element this={expression} />
|
||||
```
|
||||
|
||||
The `<svelte:element>` element lets you render an element of a dynamically specified type. This is useful for example when displaying rich text content from a CMS. Any properties and event listeners present will be applied to the element.
|
||||
|
||||
The only supported binding is `bind:this`, since the element type-specific bindings that Svelte does at build time (e.g. `bind:value` for input elements) do not work with a dynamic tag type.
|
||||
|
||||
If `this` has a nullish value, the element and its children will not be rendered.
|
||||
|
||||
If `this` is the name of a [void element](https://developer.mozilla.org/en-US/docs/Glossary/Void_element) (e.g., `br`) and `<svelte:element>` has child elements, a runtime error will be thrown in development mode.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
let tag = 'div';
|
||||
export let handler;
|
||||
</script>
|
||||
|
||||
<svelte:element this={tag} on:click={handler}>Foo</svelte:element>
|
||||
```
|
||||
|
||||
## `<svelte:window>`
|
||||
|
||||
```svelte
|
||||
<svelte:window on:event={handler} />
|
||||
```
|
||||
|
||||
```svelte
|
||||
<svelte:window bind:prop={value} />
|
||||
```
|
||||
|
||||
The `<svelte:window>` element allows you to add event listeners to the `window` object without worrying about removing them when the component is destroyed, or checking for the existence of `window` when server-side rendering.
|
||||
|
||||
Unlike `<svelte:self>`, this element may only appear at the top level of your component and must never be inside a block or element.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
function handleKeydown(event) {
|
||||
alert(`pressed the ${event.key} key`);
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:window on:keydown={handleKeydown} />
|
||||
```
|
||||
|
||||
You can also bind to the following properties:
|
||||
|
||||
- `innerWidth`
|
||||
- `innerHeight`
|
||||
- `outerWidth`
|
||||
- `outerHeight`
|
||||
- `scrollX`
|
||||
- `scrollY`
|
||||
- `online` — an alias for `window.navigator.onLine`
|
||||
|
||||
All except `scrollX` and `scrollY` are readonly.
|
||||
|
||||
```svelte
|
||||
<svelte:window bind:scrollY={y} />
|
||||
```
|
||||
|
||||
> Note that the page will not be scrolled to the initial value to avoid accessibility issues. Only subsequent changes to the bound variable of `scrollX` and `scrollY` will cause scrolling. However, if the scrolling behaviour is desired, call `scrollTo()` in `onMount()`.
|
||||
|
||||
## `<svelte:document>`
|
||||
|
||||
```svelte
|
||||
<svelte:document on:event={handler}/>
|
||||
```
|
||||
|
||||
Similarly to `<svelte:window>`, this element allows you to add listeners to events on `document`, such as `visibilitychange`, which don't fire on `window`. It also lets you use [actions](/docs/element-directives#use-action) on `document`.
|
||||
|
||||
As with `<svelte:window>`, this element may only appear the top level of your component and must never be inside a block or element.
|
||||
|
||||
```svelte
|
||||
<svelte:document
|
||||
on:visibilitychange={handleVisibilityChange}
|
||||
use:someAction
|
||||
/>
|
||||
```
|
||||
|
||||
## `<svelte:body>`
|
||||
|
||||
```svelte
|
||||
<svelte:body on:event={handler} />
|
||||
```
|
||||
|
||||
Similarly to `<svelte:window>`, this element allows you to add listeners to events on `document.body`, such as `mouseenter` and `mouseleave`, which don't fire on `window`. It also lets you use [actions](/docs/element-directives#use-action) on the `<body>` element.
|
||||
|
||||
As with `<svelte:window>` and `<svelte:document>`, this element may only appear the top level of your component and must never be inside a block or element.
|
||||
|
||||
```svelte
|
||||
<svelte:body on:mouseenter={handleMouseenter} on:mouseleave={handleMouseleave} use:someAction />
|
||||
```
|
||||
|
||||
## `<svelte:head>`
|
||||
|
||||
```svelte
|
||||
<svelte:head>...</svelte:head>
|
||||
```
|
||||
|
||||
This element makes it possible to insert elements into `document.head`. During server-side rendering, `head` content is exposed separately to the main `html` content.
|
||||
|
||||
As with `<svelte:window>`, `<svelte:document>` and `<svelte:body>`, this element may only appear at the top level of your component and must never be inside a block or element.
|
||||
|
||||
```svelte
|
||||
<svelte:head>
|
||||
<link rel="stylesheet" href="/tutorial/dark-theme.css" />
|
||||
</svelte:head>
|
||||
```
|
||||
|
||||
## `<svelte:options>`
|
||||
|
||||
```svelte
|
||||
<svelte:options option={value} />
|
||||
```
|
||||
|
||||
The `<svelte:options>` element provides a place to specify per-component compiler options, which are detailed in the [compiler section](/docs/svelte-compiler#svelte-compile). The possible options are:
|
||||
|
||||
- `immutable={true}` — you never use mutable data, so the compiler can do simple referential equality checks to determine if values have changed
|
||||
- `immutable={false}` — the default. Svelte will be more conservative about whether or not mutable objects have changed
|
||||
- `accessors={true}` — adds getters and setters for the component's props
|
||||
- `accessors={false}` — the default
|
||||
- `namespace="..."` — the namespace where this component will be used, most commonly "svg"; use the "foreign" namespace to opt out of case-insensitive attribute names and HTML-specific warnings
|
||||
- `tag="..."` — the name to use when compiling this component as a custom element
|
||||
|
||||
```svelte
|
||||
<svelte:options tag="my-custom-element" />
|
||||
```
|
||||
|
||||
## `<svelte:fragment>`
|
||||
|
||||
The `<svelte:fragment>` element allows you to place content in a [named slot](/docs/special-elements#slot-name-name) without wrapping it in a container DOM element. This keeps the flow layout of your document intact.
|
||||
|
||||
```svelte
|
||||
<!-- Widget.svelte -->
|
||||
<div>
|
||||
<slot name="header">No header was provided</slot>
|
||||
<p>Some content between header and footer</p>
|
||||
<slot name="footer" />
|
||||
</div>
|
||||
|
||||
<!-- App.svelte -->
|
||||
<Widget>
|
||||
<h1 slot="header">Hello</h1>
|
||||
<svelte:fragment slot="footer">
|
||||
<p>All rights reserved.</p>
|
||||
<p>Copyright (c) 2019 Svelte Industries</p>
|
||||
</svelte:fragment>
|
||||
</Widget>
|
||||
```
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"title": "Template Syntax"
|
||||
}
|
@ -0,0 +1,248 @@
|
||||
---
|
||||
title: svelte
|
||||
---
|
||||
|
||||
The `svelte` package exposes [lifecycle functions](/tutorial/onmount) and the [context API](/tutorial/context-api).
|
||||
|
||||
## `onMount`
|
||||
|
||||
```js
|
||||
onMount(callback: () => void)
|
||||
```
|
||||
|
||||
```js
|
||||
onMount(callback: () => () => void)
|
||||
```
|
||||
|
||||
The `onMount` function schedules a callback to run as soon as the component has been mounted to the DOM. It must be called during the component's initialisation (but doesn't need to live _inside_ the component; it can be called from an external module).
|
||||
|
||||
`onMount` does not run inside a [server-side component](/docs/server-side-component-api).
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
onMount(() => {
|
||||
console.log('the component has mounted');
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
If a function is returned from `onMount`, it will be called when the component is unmounted.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
onMount(() => {
|
||||
const interval = setInterval(() => {
|
||||
console.log('beep');
|
||||
}, 1000);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
> This behaviour will only work when the function passed to `onMount` _synchronously_ returns a value. `async` functions always return a `Promise`, and as such cannot _synchronously_ return a function.
|
||||
|
||||
## `beforeUpdate`
|
||||
|
||||
```js
|
||||
beforeUpdate(callback: () => void)
|
||||
```
|
||||
|
||||
Schedules a callback to run immediately before the component is updated after any state change.
|
||||
|
||||
> The first time the callback runs will be before the initial `onMount`
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { beforeUpdate } from 'svelte';
|
||||
|
||||
beforeUpdate(() => {
|
||||
console.log('the component is about to update');
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
## `afterUpdate`
|
||||
|
||||
```js
|
||||
afterUpdate(callback: () => void)
|
||||
```
|
||||
|
||||
Schedules a callback to run immediately after the component has been updated.
|
||||
|
||||
> The first time the callback runs will be after the initial `onMount`
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { afterUpdate } from 'svelte';
|
||||
|
||||
afterUpdate(() => {
|
||||
console.log('the component just updated');
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
## `onDestroy`
|
||||
|
||||
```js
|
||||
onDestroy(callback: () => void)
|
||||
```
|
||||
|
||||
Schedules a callback to run immediately before the component is unmounted.
|
||||
|
||||
Out of `onMount`, `beforeUpdate`, `afterUpdate` and `onDestroy`, this is the only one that runs inside a server-side component.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { onDestroy } from 'svelte';
|
||||
|
||||
onDestroy(() => {
|
||||
console.log('the component is being destroyed');
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
## `tick`
|
||||
|
||||
```js
|
||||
promise: Promise = tick();
|
||||
```
|
||||
|
||||
Returns a promise that resolves once any pending state changes have been applied, or in the next microtask if there are none.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { beforeUpdate, tick } from 'svelte';
|
||||
|
||||
beforeUpdate(async () => {
|
||||
console.log('the component is about to update');
|
||||
await tick();
|
||||
console.log('the component just updated');
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
## `setContext`
|
||||
|
||||
```js
|
||||
setContext(key: any, context: any)
|
||||
```
|
||||
|
||||
Associates an arbitrary `context` object with the current component and the specified `key` and returns that object. The context is then available to children of the component (including slotted content) with `getContext`.
|
||||
|
||||
Like lifecycle functions, this must be called during component initialisation.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { setContext } from 'svelte';
|
||||
|
||||
setContext('answer', 42);
|
||||
</script>
|
||||
```
|
||||
|
||||
> Context is not inherently reactive. If you need reactive values in context then you can pass a store into context, which _will_ be reactive.
|
||||
|
||||
## `getContext`
|
||||
|
||||
```js
|
||||
context: any = getContext(key: any)
|
||||
```
|
||||
|
||||
Retrieves the context that belongs to the closest parent component with the specified `key`. Must be called during component initialisation.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { getContext } from 'svelte';
|
||||
|
||||
const answer = getContext('answer');
|
||||
</script>
|
||||
```
|
||||
|
||||
## `hasContext`
|
||||
|
||||
```js
|
||||
hasContext: boolean = hasContext(key: any)
|
||||
```
|
||||
|
||||
Checks whether a given `key` has been set in the context of a parent component. Must be called during component initialisation.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { hasContext } from 'svelte';
|
||||
|
||||
if (hasContext('answer')) {
|
||||
// do something
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
## `getAllContexts`
|
||||
|
||||
```js
|
||||
contexts: Map<any, any> = getAllContexts()
|
||||
```
|
||||
|
||||
Retrieves the whole context map that belongs to the closest parent component. Must be called during component initialisation. Useful, for example, if you programmatically create a component and want to pass the existing context to it.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { getAllContexts } from 'svelte';
|
||||
|
||||
const contexts = getAllContexts();
|
||||
</script>
|
||||
```
|
||||
|
||||
## `createEventDispatcher`
|
||||
|
||||
```js
|
||||
dispatch: ((name: string, detail?: any, options?: DispatchOptions) => boolean) = createEventDispatcher();
|
||||
```
|
||||
|
||||
Creates an event dispatcher that can be used to dispatch [component events](/docs/component-directives#on-eventname). Event dispatchers are functions that can take two arguments: `name` and `detail`.
|
||||
|
||||
Component events created with `createEventDispatcher` create a [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent). These events do not [bubble](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture). The `detail` argument corresponds to the [CustomEvent.detail](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail) property and can contain any type of data.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
</script>
|
||||
|
||||
<button on:click={() => dispatch('notify', 'detail value')}>Fire Event</button>
|
||||
```
|
||||
|
||||
Events dispatched from child components can be listened to in their parent. Any data provided when the event was dispatched is available on the `detail` property of the event object.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
function callbackFunction(event) {
|
||||
console.log(`Notify fired! Detail: ${event.detail}`);
|
||||
}
|
||||
</script>
|
||||
|
||||
<Child on:notify={callbackFunction} />
|
||||
```
|
||||
|
||||
Events can be cancelable by passing a third parameter to the dispatch function. The function returns `false` if the event is cancelled with `event.preventDefault()`, otherwise it returns `true`.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
function notify() {
|
||||
const shouldContinue = dispatch('notify', 'detail value', { cancelable: true });
|
||||
if (shouldContinue) {
|
||||
// no one called preventDefault
|
||||
} else {
|
||||
// a listener called preventDefault
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
@ -0,0 +1,194 @@
|
||||
---
|
||||
title: 'svelte/store'
|
||||
---
|
||||
|
||||
The `svelte/store` module exports functions for creating [readable](/docs/svelte-store#readable), [writable](/docs/svelte-store#writable) and [derived](/docs/svelte-store#derived) stores.
|
||||
|
||||
Keep in mind that you don't _have_ to use these functions to enjoy the [reactive `$store` syntax](/docs/dot-svelte-files#4-prefix-stores-with-$-to-access-their-values) in your components. Any object that correctly implements `.subscribe`, unsubscribe, and (optionally) `.set` is a valid store, and will work both with the special syntax, and with Svelte's built-in [`derived` stores](/docs/svelte-store#derived).
|
||||
|
||||
This makes it possible to wrap almost any other reactive state handling library for use in Svelte. Read more about the [store contract](/docs/dot-svelte-files#4-prefix-stores-with-$-to-access-their-values) to see what a correct implementation looks like.
|
||||
|
||||
## `writable`
|
||||
|
||||
```js
|
||||
store = writable(value?: any)
|
||||
```
|
||||
|
||||
```js
|
||||
store = writable(value?: any, start?: (set: (value: any) => void) => () => void)
|
||||
```
|
||||
|
||||
Function that creates a store which has values that can be set from 'outside' components. It gets created as an object with additional `set` and `update` methods.
|
||||
|
||||
`set` is a method that takes one argument which is the value to be set. The store value gets set to the value of the argument if the store value is not already equal to it.
|
||||
|
||||
`update` is a method that takes one argument which is a callback. The callback takes the existing store value as its argument and returns the new value to be set to the store.
|
||||
|
||||
```js
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
const count = writable(0);
|
||||
|
||||
count.subscribe((value) => {
|
||||
console.log(value);
|
||||
}); // logs '0'
|
||||
|
||||
count.set(1); // logs '1'
|
||||
|
||||
count.update((n) => n + 1); // logs '2'
|
||||
```
|
||||
|
||||
If a function is passed as the second argument, it will be called when the number of subscribers goes from zero to one (but not from one to two, etc). That function will be passed a `set` function which changes the value of the store. It must return a `stop` function that is called when the subscriber count goes from one to zero.
|
||||
|
||||
```js
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
const count = writable(0, () => {
|
||||
console.log('got a subscriber');
|
||||
return () => console.log('no more subscribers');
|
||||
});
|
||||
|
||||
count.set(1); // does nothing
|
||||
|
||||
const unsubscribe = count.subscribe((value) => {
|
||||
console.log(value);
|
||||
}); // logs 'got a subscriber', then '1'
|
||||
|
||||
unsubscribe(); // logs 'no more subscribers'
|
||||
```
|
||||
|
||||
Note that the value of a `writable` is lost when it is destroyed, for example when the page is refreshed. However, you can write your own logic to sync the value to for example the `localStorage`.
|
||||
|
||||
## `readable`
|
||||
|
||||
```js
|
||||
store = readable(value?: any, start?: (set: (value: any) => void) => () => void)
|
||||
```
|
||||
|
||||
Creates a store whose value cannot be set from 'outside', the first argument is the store's initial value, and the second argument to `readable` is the same as the second argument to `writable`.
|
||||
|
||||
```js
|
||||
import { readable } from 'svelte/store';
|
||||
|
||||
const time = readable(null, (set) => {
|
||||
set(new Date());
|
||||
|
||||
const interval = setInterval(() => {
|
||||
set(new Date());
|
||||
}, 1000);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
});
|
||||
```
|
||||
|
||||
## `derived`
|
||||
|
||||
```js
|
||||
store = derived(a, callback: (a: any) => any)
|
||||
```
|
||||
|
||||
```js
|
||||
store = derived(a, callback: (a: any, set: (value: any) => void) => void | () => void, initial_value: any)
|
||||
```
|
||||
|
||||
```js
|
||||
store = derived([a, ...b], callback: ([a: any, ...b: any[]]) => any)
|
||||
```
|
||||
|
||||
```js
|
||||
store = derived([a, ...b], callback: ([a: any, ...b: any[]], set: (value: any) => void) => void | () => void, initial_value: any)
|
||||
```
|
||||
|
||||
Derives a store from one or more other stores. The callback runs initially when the first subscriber subscribes and then whenever the store dependencies change.
|
||||
|
||||
In the simplest version, `derived` takes a single store, and the callback returns a derived value.
|
||||
|
||||
```js
|
||||
import { derived } from 'svelte/store';
|
||||
|
||||
const doubled = derived(a, ($a) => $a * 2);
|
||||
```
|
||||
|
||||
The callback can set a value asynchronously by accepting a second argument, `set`, and calling it when appropriate.
|
||||
|
||||
In this case, you can also pass a third argument to `derived` — the initial value of the derived store before `set` is first called.
|
||||
|
||||
```js
|
||||
import { derived } from 'svelte/store';
|
||||
|
||||
const delayed = derived(
|
||||
a,
|
||||
($a, set) => {
|
||||
setTimeout(() => set($a), 1000);
|
||||
},
|
||||
'one moment...'
|
||||
);
|
||||
```
|
||||
|
||||
If you return a function from the callback, it will be called when a) the callback runs again, or b) the last subscriber unsubscribes.
|
||||
|
||||
```js
|
||||
import { derived } from 'svelte/store';
|
||||
|
||||
const tick = derived(
|
||||
frequency,
|
||||
($frequency, set) => {
|
||||
const interval = setInterval(() => {
|
||||
set(Date.now());
|
||||
}, 1000 / $frequency);
|
||||
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
};
|
||||
},
|
||||
'one moment...'
|
||||
);
|
||||
```
|
||||
|
||||
In both cases, an array of arguments can be passed as the first argument instead of a single store.
|
||||
|
||||
```js
|
||||
import { derived } from 'svelte/store';
|
||||
|
||||
const summed = derived([a, b], ([$a, $b]) => $a + $b);
|
||||
|
||||
const delayed = derived([a, b], ([$a, $b], set) => {
|
||||
setTimeout(() => set($a + $b), 1000);
|
||||
});
|
||||
```
|
||||
|
||||
## `readonly`
|
||||
|
||||
```js
|
||||
readableStore = readonly(writableStore);
|
||||
```
|
||||
|
||||
This simple helper function makes a store readonly. You can still subscribe to the changes from the original one using this new readable store.
|
||||
|
||||
```js
|
||||
import { readonly } from 'svelte/store';
|
||||
|
||||
const writableStore = writable(1);
|
||||
const readableStore = readonly(writableStore);
|
||||
|
||||
readableStore.subscribe(console.log);
|
||||
|
||||
writableStore.set(2); // console: 2
|
||||
readableStore.set(2); // ERROR
|
||||
```
|
||||
|
||||
## `get`
|
||||
|
||||
```js
|
||||
value: any = get(store);
|
||||
```
|
||||
|
||||
Generally, you should read the value of a store by subscribing to it and using the value as it changes over time. Occasionally, you may need to retrieve the value of a store to which you're not subscribed. `get` allows you to do so.
|
||||
|
||||
> This works by creating a subscription, reading the value, then unsubscribing. It's therefore not recommended in hot code paths.
|
||||
|
||||
```js
|
||||
import { get } from 'svelte/store';
|
||||
|
||||
const value = get(store);
|
||||
```
|
@ -0,0 +1,141 @@
|
||||
---
|
||||
title: 'svelte/motion'
|
||||
---
|
||||
|
||||
The `svelte/motion` module exports two functions, `tweened` and `spring`, for creating writable stores whose values change over time after `set` and `update`, rather than immediately.
|
||||
|
||||
## `tweened`
|
||||
|
||||
```js
|
||||
store = tweened(value: any, options)
|
||||
```
|
||||
|
||||
Tweened stores update their values over a fixed duration. The following options are available:
|
||||
|
||||
- `delay` (`number`, default 0) — milliseconds before starting
|
||||
- `duration` (`number` | `function`, default 400) — milliseconds the tween lasts
|
||||
- `easing` (`function`, default `t => t`) — an [easing function](/docs/svelte-easing)
|
||||
- `interpolate` (`function`) — see below
|
||||
|
||||
`store.set` and `store.update` can accept a second `options` argument that will override the options passed in upon instantiation.
|
||||
|
||||
Both functions return a Promise that resolves when the tween completes. If the tween is interrupted, the promise will never resolve.
|
||||
|
||||
Out of the box, Svelte will interpolate between two numbers, two arrays or two objects (as long as the arrays and objects are the same 'shape', and their 'leaf' properties are also numbers).
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { tweened } from 'svelte/motion';
|
||||
import { cubicOut } from 'svelte/easing';
|
||||
|
||||
const size = tweened(1, {
|
||||
duration: 300,
|
||||
easing: cubicOut
|
||||
});
|
||||
|
||||
function handleClick() {
|
||||
// this is equivalent to size.update(n => n + 1)
|
||||
$size += 1;
|
||||
}
|
||||
</script>
|
||||
|
||||
<button on:click={handleClick} style="transform: scale({$size}); transform-origin: 0 0">
|
||||
embiggen
|
||||
</button>
|
||||
```
|
||||
|
||||
If the initial value is `undefined` or `null`, the first value change will take effect immediately. This is useful when you have tweened values that are based on props, and don't want any motion when the component first renders.
|
||||
|
||||
```js
|
||||
const size = tweened(undefined, {
|
||||
duration: 300,
|
||||
easing: cubicOut
|
||||
});
|
||||
|
||||
$: $size = big ? 100 : 10;
|
||||
```
|
||||
|
||||
The `interpolate` option allows you to tween between _any_ arbitrary values. It must be an `(a, b) => t => value` function, where `a` is the starting value, `b` is the target value, `t` is a number between 0 and 1, and `value` is the result. For example, we can use the [d3-interpolate](https://github.com/d3/d3-interpolate) package to smoothly interpolate between two colours.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { interpolateLab } from 'd3-interpolate';
|
||||
import { tweened } from 'svelte/motion';
|
||||
|
||||
const colors = ['rgb(255, 62, 0)', 'rgb(64, 179, 255)', 'rgb(103, 103, 120)'];
|
||||
|
||||
const color = tweened(colors[0], {
|
||||
duration: 800,
|
||||
interpolate: interpolateLab
|
||||
});
|
||||
</script>
|
||||
|
||||
{#each colors as c}
|
||||
<button style="background-color: {c}; color: white; border: none;" on:click={(e) => color.set(c)}>
|
||||
{c}
|
||||
</button>
|
||||
{/each}
|
||||
|
||||
<h1 style="color: {$color}">{$color}</h1>
|
||||
```
|
||||
|
||||
## `spring`
|
||||
|
||||
```js
|
||||
store = spring(value: any, options)
|
||||
```
|
||||
|
||||
A `spring` store gradually changes to its target value based on its `stiffness` and `damping` parameters. Whereas `tweened` stores change their values over a fixed duration, `spring` stores change over a duration that is determined by their existing velocity, allowing for more natural-seeming motion in many situations. The following options are available:
|
||||
|
||||
- `stiffness` (`number`, default `0.15`) — a value between 0 and 1 where higher means a 'tighter' spring
|
||||
- `damping` (`number`, default `0.8`) — a value between 0 and 1 where lower means a 'springier' spring
|
||||
- `precision` (`number`, default `0.01`) — determines the threshold at which the spring is considered to have 'settled', where lower means more precise
|
||||
|
||||
All of the options above can be changed while the spring is in motion, and will take immediate effect.
|
||||
|
||||
```js
|
||||
const size = spring(100);
|
||||
size.stiffness = 0.3;
|
||||
size.damping = 0.4;
|
||||
size.precision = 0.005;
|
||||
```
|
||||
|
||||
As with [`tweened`](/docs/svelte-motion#tweened) stores, `set` and `update` return a Promise that resolves if the spring settles.
|
||||
|
||||
Both `set` and `update` can take a second argument — an object with `hard` or `soft` properties. `{ hard: true }` sets the target value immediately; `{ soft: n }` preserves existing momentum for `n` seconds before settling. `{ soft: true }` is equivalent to `{ soft: 0.5 }`.
|
||||
|
||||
```js
|
||||
const coords = spring({ x: 50, y: 50 });
|
||||
// updates the value immediately
|
||||
coords.set({ x: 100, y: 200 }, { hard: true });
|
||||
// preserves existing momentum for 1s
|
||||
coords.update(
|
||||
(target_coords, coords) => {
|
||||
return { x: target_coords.x, y: coords.y };
|
||||
},
|
||||
{ soft: 1 }
|
||||
);
|
||||
```
|
||||
|
||||
[See a full example on the spring tutorial.](/tutorial/spring)
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { spring } from 'svelte/motion';
|
||||
|
||||
const coords = spring(
|
||||
{ x: 50, y: 50 },
|
||||
{
|
||||
stiffness: 0.1,
|
||||
damping: 0.25
|
||||
}
|
||||
);
|
||||
</script>
|
||||
```
|
||||
|
||||
If the initial value is `undefined` or `null`, the first value change will take effect immediately, just as with `tweened` values (see above).
|
||||
|
||||
```js
|
||||
const size = spring();
|
||||
$: $size = big ? 100 : 10;
|
||||
```
|
@ -0,0 +1,264 @@
|
||||
---
|
||||
title: 'svelte/transition'
|
||||
---
|
||||
|
||||
The `svelte/transition` module exports seven functions: `fade`, `blur`, `fly`, `slide`, `scale`, `draw` and `crossfade`. They are for use with Svelte [`transitions`](/docs/element-directives#transition-fn).
|
||||
|
||||
## `fade`
|
||||
|
||||
```svelte
|
||||
transition:fade={params}
|
||||
```
|
||||
|
||||
```svelte
|
||||
in:fade={params}
|
||||
```
|
||||
|
||||
```svelte
|
||||
out:fade={params}
|
||||
```
|
||||
|
||||
Animates the opacity of an element from 0 to the current opacity for `in` transitions and from the current opacity to 0 for `out` transitions.
|
||||
|
||||
`fade` accepts the following parameters:
|
||||
|
||||
- `delay` (`number`, default 0) — milliseconds before starting
|
||||
- `duration` (`number`, default 400) — milliseconds the transition lasts
|
||||
- `easing` (`function`, default `linear`) — an [easing function](/docs/svelte-easing)
|
||||
|
||||
You can see the `fade` transition in action in the [transition tutorial](/tutorial/transition).
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { fade } from 'svelte/transition';
|
||||
</script>
|
||||
|
||||
{#if condition}
|
||||
<div transition:fade={{ delay: 250, duration: 300 }}>fades in and out</div>
|
||||
{/if}
|
||||
```
|
||||
|
||||
## `blur`
|
||||
|
||||
```svelte
|
||||
transition:blur={params}
|
||||
```
|
||||
|
||||
```svelte
|
||||
in:blur={params}
|
||||
```
|
||||
|
||||
```svelte
|
||||
out:blur={params}
|
||||
```
|
||||
|
||||
Animates a `blur` filter alongside an element's opacity.
|
||||
|
||||
`blur` accepts the following parameters:
|
||||
|
||||
- `delay` (`number`, default 0) — milliseconds before starting
|
||||
- `duration` (`number`, default 400) — milliseconds the transition lasts
|
||||
- `easing` (`function`, default `cubicInOut`) — an [easing function](/docs/svelte-easing)
|
||||
- `opacity` (`number`, default 0) - the opacity value to animate out to and in from
|
||||
- `amount` (`number | string`, default 5) - the size of the blur. Supports css units (for example: `"4rem"`). The default unit is `px`
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { blur } from 'svelte/transition';
|
||||
</script>
|
||||
|
||||
{#if condition}
|
||||
<div transition:blur={{ amount: 10 }}>fades in and out</div>
|
||||
{/if}
|
||||
```
|
||||
|
||||
## `fly`
|
||||
|
||||
```svelte
|
||||
transition:fly={params}
|
||||
```
|
||||
|
||||
```svelte
|
||||
in:fly={params}
|
||||
```
|
||||
|
||||
```svelte
|
||||
out:fly={params}
|
||||
```
|
||||
|
||||
Animates the x and y positions and the opacity of an element. `in` transitions animate from the provided values, passed as parameters to the element's default values. `out` transitions animate from the element's default values to the provided values.
|
||||
|
||||
`fly` accepts the following parameters:
|
||||
|
||||
- `delay` (`number`, default 0) — milliseconds before starting
|
||||
- `duration` (`number`, default 400) — milliseconds the transition lasts
|
||||
- `easing` (`function`, default `cubicOut`) — an [easing function](/docs/svelte-easing)
|
||||
- `x` (`number | string`, default 0) - the x offset to animate out to and in from
|
||||
- `y` (`number | string`, default 0) - the y offset to animate out to and in from
|
||||
- `opacity` (`number`, default 0) - the opacity value to animate out to and in from
|
||||
|
||||
x and y use `px` by default but support css units, for example `x: '100vw'` or `y: '50%'`.
|
||||
You can see the `fly` transition in action in the [transition tutorial](/tutorial/adding-parameters-to-transitions).
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { fly } from 'svelte/transition';
|
||||
import { quintOut } from 'svelte/easing';
|
||||
</script>
|
||||
|
||||
{#if condition}
|
||||
<div
|
||||
transition:fly={{ delay: 250, duration: 300, x: 100, y: 500, opacity: 0.5, easing: quintOut }}
|
||||
>
|
||||
flies in and out
|
||||
</div>
|
||||
{/if}
|
||||
```
|
||||
|
||||
## `slide`
|
||||
|
||||
```svelte
|
||||
transition:slide={params}
|
||||
```
|
||||
|
||||
```svelte
|
||||
in:slide={params}
|
||||
```
|
||||
|
||||
```svelte
|
||||
out:slide={params}
|
||||
```
|
||||
|
||||
Slides an element in and out.
|
||||
|
||||
`slide` accepts the following parameters:
|
||||
|
||||
- `delay` (`number`, default 0) — milliseconds before starting
|
||||
- `duration` (`number`, default 400) — milliseconds the transition lasts
|
||||
- `easing` (`function`, default `cubicOut`) — an [easing function](/docs/svelte-easing)
|
||||
|
||||
* `axis` (`x` | `y`, default `y`) — the axis of motion along which the transition occurs
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { slide } from 'svelte/transition';
|
||||
import { quintOut } from 'svelte/easing';
|
||||
</script>
|
||||
|
||||
{#if condition}
|
||||
<div transition:slide={{ delay: 250, duration: 300, easing: quintOut, axis: 'x' }}>
|
||||
slides in and out horizontally
|
||||
</div>
|
||||
{/if}
|
||||
```
|
||||
|
||||
## `scale`
|
||||
|
||||
```svelte
|
||||
transition:scale={params}
|
||||
```
|
||||
|
||||
```svelte
|
||||
in:scale={params}
|
||||
```
|
||||
|
||||
```svelte
|
||||
out:scale={params}
|
||||
```
|
||||
|
||||
Animates the opacity and scale of an element. `in` transitions animate from an element's current (default) values to the provided values, passed as parameters. `out` transitions animate from the provided values to an element's default values.
|
||||
|
||||
`scale` accepts the following parameters:
|
||||
|
||||
- `delay` (`number`, default 0) — milliseconds before starting
|
||||
- `duration` (`number`, default 400) — milliseconds the transition lasts
|
||||
- `easing` (`function`, default `cubicOut`) — an [easing function](/docs/svelte-easing)
|
||||
- `start` (`number`, default 0) - the scale value to animate out to and in from
|
||||
- `opacity` (`number`, default 0) - the opacity value to animate out to and in from
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { scale } from 'svelte/transition';
|
||||
import { quintOut } from 'svelte/easing';
|
||||
</script>
|
||||
|
||||
{#if condition}
|
||||
<div transition:scale={{ duration: 500, delay: 500, opacity: 0.5, start: 0.5, easing: quintOut }}>
|
||||
scales in and out
|
||||
</div>
|
||||
{/if}
|
||||
```
|
||||
|
||||
## `draw`
|
||||
|
||||
```svelte
|
||||
transition:draw={params}
|
||||
```
|
||||
|
||||
```svelte
|
||||
in:draw={params}
|
||||
```
|
||||
|
||||
```svelte
|
||||
out:draw={params}
|
||||
```
|
||||
|
||||
Animates the stroke of an SVG element, like a snake in a tube. `in` transitions begin with the path invisible and draw the path to the screen over time. `out` transitions start in a visible state and gradually erase the path. `draw` only works with elements that have a `getTotalLength` method, like `<path>` and `<polyline>`.
|
||||
|
||||
`draw` accepts the following parameters:
|
||||
|
||||
- `delay` (`number`, default 0) — milliseconds before starting
|
||||
- `speed` (`number`, default undefined) - the speed of the animation, see below.
|
||||
- `duration` (`number` | `function`, default 800) — milliseconds the transition lasts
|
||||
- `easing` (`function`, default `cubicInOut`) — an [easing function](/docs/svelte-easing)
|
||||
|
||||
The `speed` parameter is a means of setting the duration of the transition relative to the path's length. It is a modifier that is applied to the length of the path: `duration = length / speed`. A path that is 1000 pixels with a speed of 1 will have a duration of `1000ms`, setting the speed to `0.5` will double that duration and setting it to `2` will halve it.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { draw } from 'svelte/transition';
|
||||
import { quintOut } from 'svelte/easing';
|
||||
</script>
|
||||
|
||||
<svg viewBox="0 0 5 5" xmlns="http://www.w3.org/2000/svg">
|
||||
{#if condition}
|
||||
<path
|
||||
transition:draw={{ duration: 5000, delay: 500, easing: quintOut }}
|
||||
d="M2 1 h1 v1 h1 v1 h-1 v1 h-1 v-1 h-1 v-1 h1 z"
|
||||
fill="none"
|
||||
stroke="cornflowerblue"
|
||||
stroke-width="0.1px"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
{/if}
|
||||
</svg>
|
||||
```
|
||||
|
||||
## `crossfade`
|
||||
|
||||
The `crossfade` function creates a pair of [transitions](/docs/element-directives#transition-fn) called `send` and `receive`. When an element is 'sent', it looks for a corresponding element being 'received', and generates a transition that transforms the element to its counterpart's position and fades it out. When an element is 'received', the reverse happens. If there is no counterpart, the `fallback` transition is used.
|
||||
|
||||
`crossfade` accepts the following parameters:
|
||||
|
||||
- `delay` (`number`, default 0) — milliseconds before starting
|
||||
- `duration` (`number` | `function`, default 800) — milliseconds the transition lasts
|
||||
- `easing` (`function`, default `cubicOut`) — an [easing function](/docs/svelte-easing)
|
||||
- `fallback` (`function`) — A fallback [transition](/docs/element-directives#transition-fn) to use for send when there is no matching element being received, and for receive when there is no element being sent.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { crossfade } from 'svelte/transition';
|
||||
import { quintOut } from 'svelte/easing';
|
||||
|
||||
const [send, receive] = crossfade({
|
||||
duration: 1500,
|
||||
easing: quintOut
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if condition}
|
||||
<h1 in:send={{ key }} out:receive={{ key }}>BIG ELEM</h1>
|
||||
{:else}
|
||||
<small in:send={{ key }} out:receive={{ key }}>small elem</small>
|
||||
{/if}
|
||||
```
|
@ -0,0 +1,41 @@
|
||||
---
|
||||
title: 'svelte/animate'
|
||||
---
|
||||
|
||||
The `svelte/animate` module exports one function for use with Svelte [animations](/docs/element-directives#animate-fn).
|
||||
|
||||
## `flip`
|
||||
|
||||
```svelte
|
||||
animate:flip={params}
|
||||
```
|
||||
|
||||
The `flip` function calculates the start and end position of an element and animates between them, translating the `x` and `y` values. `flip` stands for [First, Last, Invert, Play](https://aerotwist.com/blog/flip-your-animations/).
|
||||
|
||||
`flip` accepts the following parameters:
|
||||
|
||||
- `delay` (`number`, default 0) — milliseconds before starting
|
||||
- `duration` (`number` | `function`, default `d => Math.sqrt(d) * 120`) — see below
|
||||
- `easing` (`function`, default `cubicOut`) — an [easing function](/docs/svelte-easing)
|
||||
|
||||
`duration` can be provided as either:
|
||||
|
||||
- a `number`, in milliseconds.
|
||||
- a function, `distance: number => duration: number`, receiving the distance the element will travel in pixels and returning the duration in milliseconds. This allows you to assign a duration that is relative to the distance travelled by each element.
|
||||
|
||||
You can see a full example on the [animations tutorial](/tutorial/animate)
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { flip } from 'svelte/animate';
|
||||
import { quintOut } from 'svelte/easing';
|
||||
|
||||
let list = [1, 2, 3];
|
||||
</script>
|
||||
|
||||
{#each list as n (n)}
|
||||
<div animate:flip={{ delay: 250, duration: 250, easing: quintOut }}>
|
||||
{n}
|
||||
</div>
|
||||
{/each}
|
||||
```
|
@ -0,0 +1,31 @@
|
||||
---
|
||||
title: 'svelte/easing'
|
||||
---
|
||||
|
||||
Easing functions specify the rate of change over time and are useful when working with Svelte's built-in transitions and animations as well as the tweened and spring utilities. `svelte/easing` contains 31 named exports, a `linear` ease and 3 variants of 10 different easing functions: `in`, `out` and `inOut`.
|
||||
|
||||
You can explore the various eases using the [ease visualiser](/examples/easing) in the [examples section](/examples).
|
||||
|
||||
| ease | in | out | inOut |
|
||||
| ----------- | ----------- | ------------ | -------------- |
|
||||
| **back** | `backIn` | `backOut` | `backInOut` |
|
||||
| **bounce** | `bounceIn` | `bounceOut` | `bounceInOut` |
|
||||
| **circ** | `circIn` | `circOut` | `circInOut` |
|
||||
| **cubic** | `cubicIn` | `cubicOut` | `cubicInOut` |
|
||||
| **elastic** | `elasticIn` | `elasticOut` | `elasticInOut` |
|
||||
| **expo** | `expoIn` | `expoOut` | `expoInOut` |
|
||||
| **quad** | `quadIn` | `quadOut` | `quadInOut` |
|
||||
| **quart** | `quartIn` | `quartOut` | `quartInOut` |
|
||||
| **quint** | `quintIn` | `quintOut` | `quintInOut` |
|
||||
| **sine** | `sineIn` | `sineOut` | `sineInOut` |
|
||||
|
||||
<!-- TODO -->
|
||||
|
||||
<!--
|
||||
<div class="max">
|
||||
<iframe
|
||||
title="Aphrodite example"
|
||||
src="/repl/easing"
|
||||
scrolling="no"
|
||||
></iframe>
|
||||
</div> -->
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
title: Actions
|
||||
draft: true
|
||||
---
|
||||
|
||||
TODO
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"title": "Runtime"
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,47 @@
|
||||
---
|
||||
title: 'Server-side component API'
|
||||
---
|
||||
|
||||
```js
|
||||
const result = Component.render(...)
|
||||
```
|
||||
|
||||
Unlike client-side components, server-side components don't have a lifespan after you render them — their whole job is to create some HTML and CSS. For that reason, the API is somewhat different.
|
||||
|
||||
A server-side component exposes a `render` method that can be called with optional props. It returns an object with `head`, `html`, and `css` properties, where `head` contains the contents of any `<svelte:head>` elements encountered.
|
||||
|
||||
You can import a Svelte component directly into Node using [`svelte/register`](/docs/svelte-register).
|
||||
|
||||
```js
|
||||
require('svelte/register');
|
||||
|
||||
const App = require('./App.svelte').default;
|
||||
|
||||
const { head, html, css } = App.render({
|
||||
answer: 42
|
||||
});
|
||||
```
|
||||
|
||||
The `.render()` method accepts the following parameters:
|
||||
|
||||
| parameter | default | description |
|
||||
| --------- | ------- | -------------------------------------------------- |
|
||||
| `props` | `{}` | An object of properties to supply to the component |
|
||||
| `options` | `{}` | An object of options |
|
||||
|
||||
The `options` object takes in the following options:
|
||||
|
||||
| option | default | description |
|
||||
| --------- | ----------- | ------------------------------------------------------------------------ |
|
||||
| `context` | `new Map()` | A `Map` of root-level context key-value pairs to supply to the component |
|
||||
|
||||
```js
|
||||
const { head, html, css } = App.render(
|
||||
// props
|
||||
{ answer: 42 },
|
||||
// options
|
||||
{
|
||||
context: new Map([['context-key', 'context-value']])
|
||||
}
|
||||
);
|
||||
```
|
@ -0,0 +1,57 @@
|
||||
---
|
||||
title: 'Custom elements API'
|
||||
---
|
||||
|
||||
Svelte components can also be compiled to custom elements (aka web components) using the `customElement: true` compiler option. You should specify a tag name for the component using the `<svelte:options>` [element](/docs/special-elements#svelte-options).
|
||||
|
||||
```svelte
|
||||
<svelte:options tag="my-element" />
|
||||
|
||||
<script>
|
||||
export let name = 'world';
|
||||
</script>
|
||||
|
||||
<h1>Hello {name}!</h1>
|
||||
<slot />
|
||||
```
|
||||
|
||||
Alternatively, use `tag={null}` to indicate that the consumer of the custom element should name it.
|
||||
|
||||
```js
|
||||
import MyElement from './MyElement.svelte';
|
||||
|
||||
customElements.define('my-element', MyElement);
|
||||
```
|
||||
|
||||
Once a custom element has been defined, it can be used as a regular DOM element:
|
||||
|
||||
```js
|
||||
document.body.innerHTML = `
|
||||
<my-element>
|
||||
<p>This is some slotted content</p>
|
||||
</my-element>
|
||||
`;
|
||||
```
|
||||
|
||||
By default, custom elements are compiled with `accessors: true`, which means that any [props](/docs/dot-svelte-files#attributes-and-props) are exposed as properties of the DOM element (as well as being readable/writable as attributes, where possible).
|
||||
|
||||
To prevent this, add `accessors={false}` to `<svelte:options>`.
|
||||
|
||||
```js
|
||||
const el = document.querySelector('my-element');
|
||||
|
||||
// get the current value of the 'name' prop
|
||||
console.log(el.name);
|
||||
|
||||
// set a new value, updating the shadow DOM
|
||||
el.name = 'everybody';
|
||||
```
|
||||
|
||||
Custom elements can be a useful way to package components for consumption in a non-Svelte app, as they will work with vanilla HTML and JavaScript as well as [most frameworks](https://custom-elements-everywhere.com/). There are, however, some important differences to be aware of:
|
||||
|
||||
- Styles are _encapsulated_, rather than merely _scoped_. This means that any non-component styles (such as you might have in a `global.css` file) will not apply to the custom element, including styles with the `:global(...)` modifier
|
||||
- Instead of being extracted out as a separate .css file, styles are inlined into the component as a JavaScript string
|
||||
- Custom elements are not generally suitable for server-side rendering, as the shadow DOM is invisible until JavaScript loads
|
||||
- In Svelte, slotted content renders _lazily_. In the DOM, it renders _eagerly_. In other words, it will always be created even if the component's `<slot>` element is inside an `{#if ...}` block. Similarly, including a `<slot>` in an `{#each ...}` block will not cause the slotted content to be rendered multiple times
|
||||
- The `let:` directive has no effect
|
||||
- Polyfills are required to support older browsers
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"title": "Compiler and API"
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,6 @@
|
||||
---
|
||||
title: TypeScript
|
||||
draft: true
|
||||
---
|
||||
|
||||
TODO
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
title: Migrating from v3 to v4
|
||||
---
|
||||
|
||||
TODO
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"title": "Misc"
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
---
|
||||
title: 'svelte/register'
|
||||
---
|
||||
|
||||
To render Svelte components in Node.js without bundling, use `require('svelte/register')`. After that, you can use `require` to include any `.svelte` file.
|
||||
|
||||
```js
|
||||
require('svelte/register');
|
||||
|
||||
const App = require('./App.svelte').default;
|
||||
|
||||
...
|
||||
|
||||
const { html, css, head } = App.render({ answer: 42 });
|
||||
```
|
||||
|
||||
> The `.default` is necessary because we're converting from native JavaScript modules to the CommonJS modules recognised by Node. Note that if your component imports JavaScript modules, they will fail to load in Node and you will need to use a bundler instead.
|
||||
|
||||
To set compile options, or to use a custom file extension, call the `register` hook as a function:
|
||||
|
||||
```js
|
||||
require('svelte/register')({
|
||||
extensions: ['.customextension'], // defaults to ['.html', '.svelte']
|
||||
preserveComments: true
|
||||
});
|
||||
```
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"title": "Legacy"
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
// @ts-check
|
||||
import { base as app_base } from '$app/paths';
|
||||
import fs from 'fs';
|
||||
import {
|
||||
escape,
|
||||
extract_frontmatter,
|
||||
normalizeSlugify,
|
||||
removeMarkdown,
|
||||
transform
|
||||
} from '../markdown';
|
||||
|
||||
const BASE = '../../site/content/docs/';
|
||||
|
||||
/** @return {import('./types').DocsData} */
|
||||
export function get_docs_data(base = BASE) {
|
||||
/** @type {import('./types').DocsData} */
|
||||
const docs_data = [];
|
||||
|
||||
for (const category_dir of fs.readdirSync(base)) {
|
||||
const match = /\d{2}-(.+)/.exec(category_dir);
|
||||
if (!match) continue;
|
||||
|
||||
const category_slug = match[1];
|
||||
|
||||
// Read the meta.json
|
||||
const { title: category_title, draft = 'false' } = JSON.parse(
|
||||
fs.readFileSync(`${base}/${category_dir}/meta.json`, 'utf-8')
|
||||
);
|
||||
|
||||
if (draft === 'true') continue;
|
||||
|
||||
/** @type {import('./types').Category} */
|
||||
const category = {
|
||||
title: category_title,
|
||||
slug: category_slug,
|
||||
pages: []
|
||||
};
|
||||
|
||||
for (const page_md of fs
|
||||
.readdirSync(`${base}/${category_dir}`)
|
||||
.filter((filename) => filename !== 'meta.json')) {
|
||||
const match = /\d{2}-(.+)/.exec(page_md);
|
||||
if (!match) continue;
|
||||
|
||||
const page_slug = match[1].replace('.md', '');
|
||||
|
||||
const page_data = extract_frontmatter(
|
||||
fs.readFileSync(`${base}/${category_dir}/${page_md}`, 'utf-8')
|
||||
);
|
||||
|
||||
if (page_data.metadata.draft === 'true') continue;
|
||||
|
||||
const page_title = page_data.metadata.title;
|
||||
const page_content = page_data.body;
|
||||
|
||||
category.pages.push({
|
||||
title: page_title,
|
||||
slug: page_slug,
|
||||
content: page_content,
|
||||
sections: get_sections(page_content),
|
||||
path: `${app_base}/docs/${page_slug}`,
|
||||
file: `${category_dir}/${page_md}`
|
||||
});
|
||||
}
|
||||
|
||||
docs_data.push(category);
|
||||
}
|
||||
|
||||
return docs_data;
|
||||
}
|
||||
|
||||
/** @param {import('./types').DocsData} docs_data */
|
||||
export function get_docs_list(docs_data) {
|
||||
return docs_data.map((category) => ({
|
||||
title: category.title,
|
||||
pages: category.pages.map((page) => ({
|
||||
title: page.title,
|
||||
path: page.path
|
||||
}))
|
||||
}));
|
||||
}
|
||||
|
||||
/** @param {string} markdown */
|
||||
function get_sections(markdown) {
|
||||
const headingRegex = /^##\s+(.*)$/gm;
|
||||
/** @type {import('./types').Section[]} */
|
||||
const secondLevelHeadings = [];
|
||||
let match;
|
||||
|
||||
while ((match = headingRegex.exec(markdown)) !== null) {
|
||||
secondLevelHeadings.push({
|
||||
title: removeMarkdown(
|
||||
escape(transform(match[1], { paragraph: (txt) => txt }))
|
||||
.replace(/<\/?code>/g, '')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/<(\/)?(em|b|strong|code)>/g, '')
|
||||
),
|
||||
slug: normalizeSlugify(match[1])
|
||||
});
|
||||
}
|
||||
|
||||
return secondLevelHeadings;
|
||||
}
|
@ -1,22 +1,9 @@
|
||||
import { extract_frontmatter } from '$lib/server/markdown';
|
||||
import fs from 'fs';
|
||||
import { base } from '$app/paths';
|
||||
import { get_docs_data, get_docs_list } from '$lib/server/docs/get-docs';
|
||||
|
||||
export const prerender = true;
|
||||
|
||||
const base_dir = '../../site/content/docs/';
|
||||
|
||||
export function load() {
|
||||
const sections = fs.readdirSync(base_dir).map((file) => {
|
||||
const { title } = extract_frontmatter(fs.readFileSync(`${base_dir}/${file}`, 'utf-8')).metadata;
|
||||
|
||||
return {
|
||||
title,
|
||||
path: `${base}/docs/${file.slice(3, -3)}`
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
sections
|
||||
sections: get_docs_list(get_docs_data())
|
||||
};
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
export const prerender = true;
|
@ -1,24 +1,13 @@
|
||||
import fs from 'fs';
|
||||
// import { read_file } from '$lib/server/docs';
|
||||
import { get_parsed_docs } from '$lib/server/docs';
|
||||
import { get_docs_data } from '$lib/server/docs/get-docs';
|
||||
import { error } from '@sveltejs/kit';
|
||||
import { read_file } from '$lib/server/docs';
|
||||
|
||||
export const prerender = true;
|
||||
|
||||
const base = '../../site/content/docs/';
|
||||
|
||||
/**
|
||||
* ASSUMPTION FOR FUTURE: This assumes the directory structure of docs is flat. AKA, no nested folders
|
||||
*/
|
||||
/** @type {import('./$types').PageServerLoad} */
|
||||
export async function load({ params }) {
|
||||
for (const file of fs.readdirSync(`${base}`)) {
|
||||
if (file.slice(3, -3) === params.slug) {
|
||||
return {
|
||||
page: await read_file(file)
|
||||
};
|
||||
}
|
||||
}
|
||||
const processed_page = get_parsed_docs(get_docs_data(), params.slug);
|
||||
|
||||
if (!processed_page) throw error(404);
|
||||
|
||||
throw error(404);
|
||||
return { page: processed_page };
|
||||
}
|
||||
|
Loading…
Reference in new issue