Merge branch 'master' into site-headings-level-4

pull/2373/head
Rich Harris 6 years ago committed by GitHub
commit 9a0b847455
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -267,21 +267,21 @@ const time = readable(new Date(), set => {
#### `derive`
* `store = derive(a, callback: (a: any) => any)`
* `store = derive(a, callback: (a: any, set: (value: any) => void) => void)`
* `store = derive([a, ...b], callback: ([a: any, ...b: any[]]) => any)`
* `store = derive([a, ...b], callback: ([a: any, ...b: any[]], set: (value: any) => void) => void)`
* `store = derived(a, callback: (a: any) => any)`
* `store = derived(a, callback: (a: any, set: (value: any) => void) => void)`
* `store = derived([a, ...b], callback: ([a: any, ...b: any[]]) => any)`
* `store = derived([a, ...b], callback: ([a: any, ...b: any[]], set: (value: any) => void) => void)`
---
Derives a store from one or more other stores. Whenever those dependencies change, the callback runs.
In the simplest version, `derive` takes a single store, and the callback returns a derived value.
In the simplest version, `derived` takes a single store, and the callback returns a derived value.
```js
import { derive } from 'svelte/store';
import { derived } from 'svelte/store';
const doubled = derive(a, $a => $a * 2);
const doubled = derived(a, $a => $a * 2);
```
---
@ -289,9 +289,9 @@ const doubled = derive(a, $a => $a * 2);
The callback can set a value asynchronously by accepting a second argument, `set`, and calling it when appropriate.
```js
import { derive } from 'svelte/store';
import { derived } from 'svelte/store';
const delayed = derive(a, ($a, set) => {
const delayed = derived(a, ($a, set) => {
setTimeout(() => set($a), 1000);
});
```
@ -301,11 +301,11 @@ const delayed = derive(a, ($a, set) => {
In both cases, an array of arguments can be passed as the first argument instead of a single store.
```js
import { derive } from 'svelte/store';
import { derived } from 'svelte/store';
const summed = derive([a, b], ([$a, $b]) => $a + $b);
const summed = derived([a, b], ([$a, $b]) => $a + $b);
const delayed = derive([a, b], ([$a, $b], set) => {
const delayed = derived([a, b], ([$a, $b], set) => {
setTimeout(() => set($a + $b), 1000);
});
```
@ -434,7 +434,7 @@ As with [`tweened`](#tweened) stores, `set` and `update` return a Promise that r
TODO
* fade, fly, slide, draw
* fade, fly, slide, scale, draw
* crossfade...
### `svelte/animation`

@ -1,4 +1,4 @@
import { readable, derive } from 'svelte/store';
import { readable, derived } from 'svelte/store';
export const time = readable(new Date(), function start(set) {
const interval = setInterval(() => {
@ -12,7 +12,7 @@ export const time = readable(new Date(), function start(set) {
const start = new Date();
export const elapsed = derive(
export const elapsed = derived(
time,
$time => Math.round(($time - start) / 1000)
);

@ -1,4 +1,4 @@
import { readable, derive } from 'svelte/store';
import { readable, derived } from 'svelte/store';
export const time = readable(new Date(), function start(set) {
const interval = setInterval(() => {
@ -12,7 +12,7 @@ export const time = readable(new Date(), function start(set) {
const start = new Date();
export const elapsed = derive(
export const elapsed = derived(
time,
$time => {}
);

@ -1,4 +1,4 @@
import { readable, derive } from 'svelte/store';
import { readable, derived } from 'svelte/store';
export const time = readable(new Date(), function start(set) {
const interval = setInterval(() => {
@ -12,7 +12,7 @@ export const time = readable(new Date(), function start(set) {
const start = new Date();
export const elapsed = derive(
export const elapsed = derived(
time,
$time => Math.round(($time - start) / 1000)
);

@ -2,10 +2,10 @@
title: Derived stores
---
You can create a store whose value is based on the value of one or more *other* stores with `derive`. Building on our previous example, we can create a store that derives the time the page has been open:
You can create a store whose value is based on the value of one or more *other* stores with `derived`. Building on our previous example, we can create a store that derives the time the page has been open:
```js
export const elapsed = derive(
export const elapsed = derived(
time,
$time => Math.round(($time - start) / 1000)
);

@ -0,0 +1,166 @@
<style>
.container {
position: relative;
display: grid;
margin: 10rem auto;
padding: 0 var(--side-nav);
max-width: 120rem;
grid-row-gap: 1em;
grid-template-areas:
"one"
"two"
"three"
"what"
"start";
}
.box {
padding: 1em;
display: flex;
flex-direction: column;
}
h2 {
padding: 0;
margin: 0 0 0.5em 0;
font-size: var(--h2);
color: white;
text-align: left;
}
p {
font-size: var(--h5);
}
.box a {
position: relative;
text-align: right;
margin-top: auto;
padding: 0 1.2em 0 0;
font-family: Roboto, sans-serif;
font-size: 1.6rem;
}
.box a:hover {
color: white;
text-decoration: underline;
}
.box a::after, .cta a::after {
content: '';
position: absolute;
display: block;
right: 0;
top: 0.35em;
width: 1em;
height: 1em;
background: url(/icons/arrow-right.svg);
}
.cta a {
display: inline-block;
text-align: right;
background-color: var(--prime);
padding: 0.5em 1.8em 0.5em 1em;
border-radius: var(--border-r);
color: white;
position: relative;
}
.cta a::after {
right: 0.5em;
top: 0.75em;
}
.description {
margin: 2em 0 0 0;
}
.cta {
margin: 0;
}
@media (min-width: 900px) {
.container {
grid-column-gap: 1em;
grid-row-gap: 1em;
grid-template-columns: repeat(2, 1fr);
grid-template-areas:
"one two"
"three start"
"what what";
}
.box {
padding: 2em;
}
.cta {
text-align: right;
}
}
@media (min-width: 1200px) {
.container {
grid-column-gap: 1em;
grid-row-gap: 5em;
grid-template-columns: repeat(6, 1fr);
grid-template-areas:
"one one two two three three"
"what what what start start start";
}
.description {
margin: 0;
}
.cta {
text-align: left;
}
}
</style>
<section class='container'>
<div class='box bg-prime white' style="grid-area: one">
<h2 style='padding:2.4rem 0 0 0'>Write less code</h2>
<p>Build boilerplate-free components using languages you already know — HTML, CSS and JavaScript</p>
<a href="TODO-blog-post-on-loc">learn more</a>
</div>
<div class='box bg-flash white' style="grid-area: two">
<h2 style='padding:2.4rem 0 0 0'>No virtual DOM</h2>
<p>Svelte compiles your code to tiny, framework-less vanilla JS — your app starts fast and stays fast</p>
<a href="TODO-blog-post-on-vdom-overhead">learn more</a>
</div>
<div class='box bg-second white' style="grid-area: three">
<h2 style='padding:2.4rem 0 0 0'>Truly reactive</h2>
<p>No more complex state management libraries — Svelte brings reactivity to JavaScript itself</p>
<a href="TODO-blog-post-on-reactivity">learn more</a>
</div>
<div class="linkify description" style="grid-area: what;">
<p>Svelte is a radical new approach to building user interfaces. Whereas traditional frameworks like React and Vue do the bulk of their work in the <em>browser</em>, Svelte shifts that work into a <em>compile step</em> that happens when you build your app.</p>
<p>Instead of using techniques like virtual DOM diffing, Svelte writes code that surgically updates the DOM when the state of your app changes.</p>
<p><a href="TODO-svelte-3-blog-post">Read the introductory blog post</a> to learn more.</p>
</div>
<div style="grid-area: start; display: flex; flex-direction: column">
<pre class="language-bash" style="margin: 0 0 1em 0">
npx degit sveltejs/template my-svelte-project
cd my-svelte-project
npm install
npm run dev & open http://localhost:5000
</pre>
<p class="linkify" style="flex: 1">See the <a href="blog/the-easiest-way-to-get-started">quickstart guide</a> for more information.</p>
<p class="cta"><a rel="prefetch" href="tutorial">Learn Svelte</a></p>
</div>
</section>

@ -1,7 +1,8 @@
<script>
import Icon from '../components/Icon.svelte';
import Logo from '../components/Logo.svelte';
import WhosUsingSvelte from '../components/WhosUsingSvelte/index.svelte';
import Blurb from './_components/Blurb.svelte';
import WhosUsingSvelte from './_components/WhosUsingSvelte.svelte';
import IntersectionObserver from '../components/IntersectionObserver.svelte';
// import Lazy from '../components/Lazy.svelte';
import ReplWidget from '../components/Repl/ReplWidget.svelte';
@ -70,54 +71,6 @@
opacity: 0.7;
}
.box {
padding: 2em;
display: flex;
flex-direction: column;
}
.box > h2 {
padding: 0;
margin: 0 0 0.5em 0;
font-size: var(--h2);
color: white;
text-align: left;
}
.box > p {
font-size: var(--h5);
}
.box a {
position: relative;
text-align: right;
margin-top: auto;
padding: 0 1.2em 0 0;
font-family: Roboto, sans-serif;
font-size: 1.6rem;
}
.box a:hover {
color: white;
text-decoration: underline;
}
.box a::after, .cta::after {
content: '';
position: absolute;
display: block;
right: 0;
top: 0.25em;
width: 1em;
height: 1em;
background: url(/icons/arrow-right.svg);
}
.cta::after {
right: 0.5em;
top: 0.6em;
}
.examples {
background: var(--second);
color: white;
@ -145,14 +98,6 @@
/* padding: 0.8rem; */
}
a.cta {
background-color: var(--prime);
padding: 0.5em 1.8em 0.5em 1em;
border-radius: var(--border-r);
color: white;
position: relative;
}
.contributor {
width: 2.4em;
height: 2.4em;
@ -197,54 +142,7 @@
<h1>Svelte</h1>
</section>
<section class='container'>
<ul class='grid stretch'>
<li class='box bg-prime white'>
<h2 style='padding:2.4rem 0 0 0'>Write less code</h2>
<p>Build boilerplate-free components using languages you already know — HTML, CSS and JavaScript</p>
<a href="TODO-blog-post-on-loc">learn more</a>
</li>
<li class='box bg-flash white'>
<h2 style='padding:2.4rem 0 0 0'>No virtual DOM</h2>
<p>Svelte compiles your code to tiny, framework-less vanilla JS — your app starts fast and stays fast</p>
<a href="TODO-blog-post-on-vdom-overhead">learn more</a>
</li>
<li class='box bg-second white'>
<h2 style='padding:2.4rem 0 0 0'>Truly reactive</h2>
<p>No more complex state management libraries — Svelte brings reactivity to JavaScript itself</p>
<a href="TODO-blog-post-on-reactivity">learn more</a>
</li>
</ul>
</section>
<section class="container grid half">
<div class="linkify">
<p>Svelte is a radical new approach to building user interfaces. Whereas traditional frameworks like React and Vue do the bulk of their work in the <em>browser</em>, Svelte shifts that work into a <em>compile step</em> that happens when you build your app.</p>
<p>Instead of using techniques like virtual DOM diffing, Svelte writes code that surgically updates the DOM when the state of your app changes.</p>
<p><a href="TODO-svelte-3-blog-post">Read the introductory blog post</a> to learn more.</p>
</div>
<div>
<pre class="language-bash">
npx degit sveltejs/template my-svelte-project
cd my-svelte-project
npm install
npm run dev & open http://localhost:5000
</pre>
<p class="linkify">See the <a href="blog/the-easiest-way-to-get-started">quickstart guide</a> for more information.</p>
<p><a rel="prefetch" class="cta" href="tutorial">Learn Svelte</a></p>
</div>
</section>
<Blurb/>
<div class="examples">
<section class="container example linkify">

@ -28,7 +28,7 @@
a {
display: block;
padding: 0.7em 0;
padding: 0.75em 0;
text-align: center;
opacity: 0.7;
}
@ -54,6 +54,7 @@
height: 100%;
opacity: 0.0001;
cursor: pointer;
-webkit-appearance: none;
}
</style>
@ -63,7 +64,13 @@
</a>
<div>
<span><strong>{selected.section.title} /</strong> {selected.chapter.title}</span>
<span>
<strong>
<span style="position: relative; top: -0.1em; margin: 0 0.5em 0 0"><Icon name="menu"/></span>
{selected.section.title} /
</strong>
{selected.chapter.title}
</span>
<select value={slug} on:change={navigate}>
{#each sections as section, i}

@ -16,7 +16,7 @@ import list from '../../utils/list';
import Let from './Let';
import TemplateScope from './shared/TemplateScope';
const svg = /^(?:altGlyph|altGlyphDef|altGlyphItem|animate|animateColor|animateMotion|animateTransform|circle|clipPath|color-profile|cursor|defs|desc|discard|ellipse|feBlend|feColorMatrix|feComponentTransfer|feComposite|feConvolveMatrix|feDiffuseLighting|feDisplacementMap|feDistantLight|feDropShadow|feFlood|feFuncA|feFuncB|feFuncG|feFuncR|feGaussianBlur|feImage|feMerge|feMergeNode|feMorphology|feOffset|fePointLight|feSpecularLighting|feSpotLight|feTile|feTurbulence|filter|font|font-face|font-face-format|font-face-name|font-face-src|font-face-uri|foreignObject|g|glyph|glyphRef|hatch|hatchpath|hkern|image|line|linearGradient|marker|mask|mesh|meshgradient|meshpatch|meshrow|metadata|missing-glyph|mpath|path|pattern|polygon|polyline|radialGradient|rect|set|solidcolor|stop|switch|symbol|text|textPath|tref|tspan|unknown|use|view|vkern)$/;
const svg = /^(?:altGlyph|altGlyphDef|altGlyphItem|animate|animateColor|animateMotion|animateTransform|circle|clipPath|color-profile|cursor|defs|desc|discard|ellipse|feBlend|feColorMatrix|feComponentTransfer|feComposite|feConvolveMatrix|feDiffuseLighting|feDisplacementMap|feDistantLight|feDropShadow|feFlood|feFuncA|feFuncB|feFuncG|feFuncR|feGaussianBlur|feImage|feMerge|feMergeNode|feMorphology|feOffset|fePointLight|feSpecularLighting|feSpotLight|feTile|feTurbulence|filter|font|font-face|font-face-format|font-face-name|font-face-src|font-face-uri|foreignObject|g|glyph|glyphRef|hatch|hatchpath|hkern|image|line|linearGradient|marker|mask|mesh|meshgradient|meshpatch|meshrow|metadata|missing-glyph|mpath|path|pattern|polygon|polyline|radialGradient|rect|set|solidcolor|stop|svg|switch|symbol|text|textPath|tref|tspan|unknown|use|view|vkern)$/;
const aria_attributes = 'activedescendant atomic autocomplete busy checked colindex controls current describedby details disabled dropeffect errormessage expanded flowto grabbed haspopup hidden invalid keyshortcuts label labelledby level live modal multiline multiselectable orientation owns placeholder posinset pressed readonly relevant required roledescription rowindex selected setsize sort valuemax valuemin valuenow valuetext'.split(' ');
const aria_attribute_set = new Set(aria_attributes);
@ -73,6 +73,21 @@ const passive_events = new Set([
'touchcancel'
]);
function get_namespace(parent: Element, element: Element, explicit_namespace: string) {
const parent_element = parent.find_nearest(/^Element/);
if (!parent_element) {
return explicit_namespace || (svg.test(element.name)
? namespaces.svg
: null);
}
if (element.name.toLowerCase() === 'svg') return namespaces.svg;
if (parent_element.name.toLowerCase() === 'foreignobject') return null;
return parent_element.namespace;
}
export default class Element extends Node {
type: 'Element';
name: string;
@ -93,12 +108,7 @@ export default class Element extends Node {
super(component, parent, scope, info);
this.name = info.name;
const parent_element = parent.find_nearest(/^Element/);
this.namespace = this.name === 'svg' || (!parent_element && svg.test(this.name))
? namespaces.svg
: this.name === 'foreignObject'
? namespaces.html
: parent_element ? parent_element.namespace : this.component.namespace;
this.namespace = get_namespace(parent, this, component.namespace);
if (this.name === 'textarea') {
if (info.children.length > 0) {

@ -39,7 +39,7 @@ export function writable(value, start = noop) {
return { set, update, subscribe };
}
export function derive(stores, fn) {
export function derived(stores, fn) {
const single = !Array.isArray(stores);
if (single) stores = [stores];

@ -1,9 +1,9 @@
<script>
import { derive } from 'svelte/store';
import { derived } from 'svelte/store';
export let count;
const doubled = derive(count, $count => $count * 2);
const doubled = derived(count, $count => $count * 2);
</script>
<button on:click="{() => $count += 1}">count {$count}</button>

@ -8,6 +8,9 @@ export default {
`,
test({ assert, target }) {
const foreignObject = target.querySelector('foreignObject');
assert.equal(foreignObject.namespaceURI, 'http://www.w3.org/2000/svg');
const p = target.querySelector('p');
assert.equal(p.namespaceURI, 'http://www.w3.org/1999/xhtml');
}

@ -1,5 +1,5 @@
import * as assert from 'assert';
import { readable, writable, derive, get } from '../../store.js';
import { readable, writable, derived, get } from '../../store.js';
describe('store', () => {
describe('writable', () => {
@ -100,10 +100,10 @@ describe('store', () => {
});
});
describe('derive', () => {
describe('derived', () => {
it('maps a single store', () => {
const a = writable(1);
const b = derive(a, n => n * 2);
const b = derived(a, n => n * 2);
const values = [];
@ -123,7 +123,7 @@ describe('store', () => {
it('maps multiple stores', () => {
const a = writable(2);
const b = writable(3);
const c = derive(([a, b]), ([a, b]) => a * b);
const c = derived(([a, b]), ([a, b]) => a * b);
const values = [];
@ -143,7 +143,7 @@ describe('store', () => {
it('passes optional set function', () => {
const number = writable(0);
const evens = derive(number, (n, set) => {
const evens = derived(number, (n, set) => {
if (n % 2 === 0) set(n);
});
@ -169,9 +169,9 @@ describe('store', () => {
it('prevents glitches', () => {
const lastname = writable('Jekyll');
const firstname = derive(lastname, n => n === 'Jekyll' ? 'Henry' : 'Edward');
const firstname = derived(lastname, n => n === 'Jekyll' ? 'Henry' : 'Edward');
const fullname = derive([firstname, lastname], names => names.join(' '));
const fullname = derived([firstname, lastname], names => names.join(' '));
const values = [];

@ -66,6 +66,32 @@ export function slide(node, {
};
}
export function scale(node, {
delay = 0,
duration = 400,
easing = cubicOut,
start = 0,
opacity = 0
}) {
const sd = 1 - start;
const od = 1 - opacity;
const transform = (
node.style.transform ||
getComputedStyle(node).transform
).replace('none', '');
return {
delay,
duration,
easing,
css: (t, u) => `
transform: ${transform} scale(${1 - (sd * u)});
opacity: ${1 - (od * u)}
`
};
}
export function draw(node, {
delay = 0,
duration = 800,

Loading…
Cancel
Save