diff --git a/.gitignore b/.gitignore
index 1499a0e697..2c8e89efc2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,8 @@ node_modules
/index.js
/internal.*
/store.js
+/easing.js
+/transition.js
/scratch/
/coverage/
/coverage.lcov/
@@ -21,4 +23,6 @@ _actual*.*
/site/cypress/screenshots/
/site/__sapper__/
/site/.env
-/site/.sessions
\ No newline at end of file
+/site/.sessions
+/site/static/svelte-app.json
+/site/scripts/svelte-app
\ No newline at end of file
diff --git a/easing.mjs b/easing.mjs
new file mode 100644
index 0000000000..855713b03d
--- /dev/null
+++ b/easing.mjs
@@ -0,0 +1,173 @@
+/*
+Adapted from https://github.com/mattdesl
+Distributed under MIT License https://github.com/mattdesl/eases/blob/master/LICENSE.md
+*/
+
+export function backInOut(t) {
+ var s = 1.70158 * 1.525;
+ if ((t *= 2) < 1) return 0.5 * (t * t * ((s + 1) * t - s));
+ return 0.5 * ((t -= 2) * t * ((s + 1) * t + s) + 2);
+}
+
+export function backIn(t) {
+ var s = 1.70158;
+ return t * t * ((s + 1) * t - s);
+}
+
+export function backOut(t) {
+ var s = 1.70158;
+ return --t * t * ((s + 1) * t + s) + 1;
+}
+
+export function bounceOut(t) {
+ var a = 4.0 / 11.0;
+ var b = 8.0 / 11.0;
+ var c = 9.0 / 10.0;
+
+ var ca = 4356.0 / 361.0;
+ var cb = 35442.0 / 1805.0;
+ var cc = 16061.0 / 1805.0;
+
+ var t2 = t * t;
+
+ return t < a
+ ? 7.5625 * t2
+ : t < b
+ ? 9.075 * t2 - 9.9 * t + 3.4
+ : t < c
+ ? ca * t2 - cb * t + cc
+ : 10.8 * t * t - 20.52 * t + 10.72;
+}
+
+export function bounceInOut(t) {
+ return t < 0.5
+ ? 0.5 * (1.0 - bounceOut(1.0 - t * 2.0))
+ : 0.5 * bounceOut(t * 2.0 - 1.0) + 0.5;
+}
+
+export function bounceIn(t) {
+ return 1.0 - bounceOut(1.0 - t);
+}
+
+export function circInOut(t) {
+ if ((t *= 2) < 1) return -0.5 * (Math.sqrt(1 - t * t) - 1);
+ return 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1);
+}
+
+export function circIn(t) {
+ return 1.0 - Math.sqrt(1.0 - t * t);
+}
+
+export function circOut(t) {
+ return Math.sqrt(1 - --t * t);
+}
+
+export function cubicInOut(t) {
+ return t < 0.5 ? 4.0 * t * t * t : 0.5 * Math.pow(2.0 * t - 2.0, 3.0) + 1.0;
+}
+
+export function cubicIn(t) {
+ return t * t * t;
+}
+
+export function cubicOut(t) {
+ var f = t - 1.0;
+ return f * f * f + 1.0;
+}
+
+export function elasticInOut(t) {
+ return t < 0.5
+ ? 0.5 *
+ Math.sin(((+13.0 * Math.PI) / 2) * 2.0 * t) *
+ Math.pow(2.0, 10.0 * (2.0 * t - 1.0))
+ : 0.5 *
+ Math.sin(((-13.0 * Math.PI) / 2) * (2.0 * t - 1.0 + 1.0)) *
+ Math.pow(2.0, -10.0 * (2.0 * t - 1.0)) +
+ 1.0;
+}
+
+export function elasticIn(t) {
+ return Math.sin((13.0 * t * Math.PI) / 2) * Math.pow(2.0, 10.0 * (t - 1.0));
+}
+
+export function elasticOut(t) {
+ return (
+ Math.sin((-13.0 * (t + 1.0) * Math.PI) / 2) * Math.pow(2.0, -10.0 * t) + 1.0
+ );
+}
+
+export function expoInOut(t) {
+ return t === 0.0 || t === 1.0
+ ? t
+ : t < 0.5
+ ? +0.5 * Math.pow(2.0, 20.0 * t - 10.0)
+ : -0.5 * Math.pow(2.0, 10.0 - t * 20.0) + 1.0;
+}
+
+export function expoIn(t) {
+ return t === 0.0 ? t : Math.pow(2.0, 10.0 * (t - 1.0));
+}
+
+export function expoOut(t) {
+ return t === 1.0 ? t : 1.0 - Math.pow(2.0, -10.0 * t);
+}
+
+export function linear(t) {
+ return t;
+}
+
+export function quadInOut(t) {
+ t /= 0.5;
+ if (t < 1) return 0.5 * t * t;
+ t--;
+ return -0.5 * (t * (t - 2) - 1);
+}
+
+export function quadIn(t) {
+ return t * t;
+}
+
+export function quadOut(t) {
+ return -t * (t - 2.0);
+}
+
+export function quartInOut(t) {
+ return t < 0.5
+ ? +8.0 * Math.pow(t, 4.0)
+ : -8.0 * Math.pow(t - 1.0, 4.0) + 1.0;
+}
+
+export function quartIn(t) {
+ return Math.pow(t, 4.0);
+}
+
+export function quartOut(t) {
+ return Math.pow(t - 1.0, 3.0) * (1.0 - t) + 1.0;
+}
+
+export function quintInOut(t) {
+ if ((t *= 2) < 1) return 0.5 * t * t * t * t * t;
+ return 0.5 * ((t -= 2) * t * t * t * t + 2);
+}
+
+export function quintIn(t) {
+ return t * t * t * t * t;
+}
+
+export function quintOut(t) {
+ return --t * t * t * t * t + 1;
+}
+
+export function sineInOut(t) {
+ return -0.5 * (Math.cos(Math.PI * t) - 1);
+}
+
+export function sineIn(t) {
+ var v = Math.cos(t * Math.PI * 0.5);
+ if (Math.abs(v) < 1e-14) return 1;
+ else return 1 - v;
+}
+
+export function sineOut(t) {
+ return Math.sin((t * Math.PI) / 2);
+}
diff --git a/package.json b/package.json
index 0f43ed0019..21234501f6 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "svelte",
- "version": "3.0.0-alpha8",
+ "version": "3.0.0-alpha12",
"description": "The magical disappearing UI framework",
"module": "index.mjs",
"main": "index.js",
@@ -14,6 +14,8 @@
"index.*",
"internal.*",
"store.*",
+ "transition.*",
+ "easing.*",
"svelte",
"README.md"
],
diff --git a/rollup.config.js b/rollup.config.js
index 1bb01c9282..7e1947ec4e 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -52,16 +52,6 @@ export default [
experimentalCodeSplitting: true
},
- /* index.js */
- {
- input: 'index.mjs',
- output: {
- file: 'index.js',
- format: 'cjs'
- },
- external: name => name !== 'index.mjs'
- },
-
/* internal.[m]js */
{
input: 'src/internal/index.js',
@@ -77,13 +67,13 @@ export default [
]
},
- /* store.js */
- {
- input: 'store.mjs',
+ // runtime API
+ ...['index', 'store', 'easing', 'transition'].map(name => ({
+ input: `${name}.mjs`,
output: {
- file: 'store.js',
+ file: `${name}.js`,
format: 'cjs'
},
- external: name => name !== 'store.mjs'
- },
+ external: id => id !== `${name}.mjs`
+ }))
];
diff --git a/site/package-lock.json b/site/package-lock.json
index 27bb28b6b0..653489dcaf 100644
--- a/site/package-lock.json
+++ b/site/package-lock.json
@@ -3804,13 +3804,13 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"sapper": {
- "version": "0.25.0-alpha1",
- "resolved": "https://registry.npmjs.org/sapper/-/sapper-0.25.0-alpha1.tgz",
- "integrity": "sha512-zVD/9T0JRC9HveX06OfC04NLIbM3J834evccRGXhOqB3cI9wJeCESnwu2toYVCKPbS2qRNZIdOtKlKc0BhTXAw==",
+ "version": "0.25.0-alpha2",
+ "resolved": "https://registry.npmjs.org/sapper/-/sapper-0.25.0-alpha2.tgz",
+ "integrity": "sha512-GAYdwyDLo6XYJxJDFtpY1BcHPVjibYY/x/DvUEpH9rsH0fLF67SWAf0RokGs1lvhOMd1O6nxtR7KztwIeNIkZA==",
"dev": true,
"requires": {
"html-minifier": "^3.5.20",
- "shimport": "0.0.11",
+ "shimport": "0.0.14",
"source-map-support": "^0.5.9",
"sourcemap-codec": "^1.4.3",
"string-hash": "^1.1.3",
@@ -3935,9 +3935,9 @@
}
},
"shimport": {
- "version": "0.0.11",
- "resolved": "https://registry.npmjs.org/shimport/-/shimport-0.0.11.tgz",
- "integrity": "sha512-wRlG/wMuV/czrzJEWBUPjydU/Ve0kTrTH8wHLRjuY6S2BDB+qDDXkTY/WrNc/7t5jnd0LPVO1sRIE7Ga6uXTpw==",
+ "version": "0.0.14",
+ "resolved": "https://registry.npmjs.org/shimport/-/shimport-0.0.14.tgz",
+ "integrity": "sha512-JfzpHhyZ6CYuPYUSitFNw2/IxWEABLN1chs9xDHnn4tPXXCmfIn1METCmIl8Vwvm2FZGW7b8WB4zMCKaJEhY6A==",
"dev": true
},
"sirv": {
@@ -4220,9 +4220,9 @@
}
},
"svelte": {
- "version": "3.0.0-alpha7",
- "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.0.0-alpha7.tgz",
- "integrity": "sha512-AIEeZlVKqw7rRss0+1YDJlPJW7uQpHMB3ys730D1AuuPQkZVFoW+KuCi+1HiE9D5AUr1pIAUxc3vD66RYGqoyw==",
+ "version": "3.0.0-alpha10",
+ "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.0.0-alpha10.tgz",
+ "integrity": "sha512-SmEI9Heks28DeBF26GZuViYXBwkqVXiqGbpH1CZ/HowGzTDVib2peWBpwaGjKHg1nX9zicNFTRa9E2Ebb/sWoQ==",
"dev": true
},
"terser": {
diff --git a/site/package.json b/site/package.json
index 62f2537530..5f0a1332e0 100644
--- a/site/package.json
+++ b/site/package.json
@@ -5,13 +5,13 @@
"scripts": {
"dev": "sapper dev",
"sapper": "sapper build --legacy",
- "export": "sapper export --legacy",
+ "update_template": "sh ./scripts/update_template.sh",
"start": "node __sapper__/build",
"cy:run": "cypress run",
"cy:open": "cypress open",
"test": "run-p --race dev cy:run",
"deploy": "npm run stage && now alias",
- "prestage": "npm run sapper",
+ "prestage": "npm run update_template && npm run sapper",
"stage": "now"
},
"dependencies": {
@@ -50,7 +50,7 @@
"rollup-plugin-replace": "^2.0.0",
"rollup-plugin-svelte": "^4.2.1",
"rollup-plugin-terser": "^1.0.1",
- "sapper": "^0.25.0-alpha1",
- "svelte": "^3.0.0-alpha7"
+ "sapper": "^0.25.0-alpha2",
+ "svelte": "^3.0.0-alpha10"
}
}
diff --git a/site/scripts/build-svelte-app-json.js b/site/scripts/build-svelte-app-json.js
new file mode 100644
index 0000000000..59a4b4a07b
--- /dev/null
+++ b/site/scripts/build-svelte-app-json.js
@@ -0,0 +1,11 @@
+const fs = require('fs');
+
+const files = [];
+
+for (const path of process.argv.slice(2)) {
+ if (!path.includes('/.')) {
+ files.push({ path: path.slice(19), data: fs.readFileSync(path).toString() });
+ }
+}
+
+fs.writeFileSync('static/svelte-app.json', JSON.stringify(files));
diff --git a/site/scripts/update_template.sh b/site/scripts/update_template.sh
new file mode 100755
index 0000000000..59ab3cb0cd
--- /dev/null
+++ b/site/scripts/update_template.sh
@@ -0,0 +1,15 @@
+cd `dirname $0`/..
+
+# fetch svelte-app
+rm -rf scripts/svelte-app
+node_modules/.bin/degit sveltejs/template scripts/svelte-app
+
+# update repl-viewer.css based on template
+cp scripts/svelte-app/public/global.css static/repl-viewer.css
+
+# remove src (will be recreated client-side) and node_modules
+rm -rf scripts/svelte-app/src
+rm -rf scripts/svelte-app/node_modules
+
+# build svelte-app.json
+node scripts/build-svelte-app-json.js `find scripts/svelte-app -type f`
diff --git a/site/src/routes/guide/index.html b/site/src/routes/guide/index.html
index ff8bc20d73..09c3603f27 100644
--- a/site/src/routes/guide/index.html
+++ b/site/src/routes/guide/index.html
@@ -83,6 +83,17 @@
overflow: hidden;
}
+ aside::after {
+ content: '';
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ width: 100%;
+ height: var(--top-offset);
+ background: linear-gradient(to bottom, rgba(255,255,255,0) 0%, rgba(255,255,255,0.7) 50%, rgba(255,255,255,1) 100%);
+ pointer-events: none;
+ }
+
.sidebar {
padding: var(--top-offset) 3.2rem var(--top-offset) 0;
font-family: var(--font-ui);
diff --git a/site/src/routes/repl/_components/AppControls/index.html b/site/src/routes/repl/_components/AppControls/index.html
index 381cc93f75..ab439251ac 100644
--- a/site/src/routes/repl/_components/AppControls/index.html
+++ b/site/src/routes/repl/_components/AppControls/index.html
@@ -171,13 +171,15 @@
async function download() {
downloading = true;
+ const { components, imports, values } = repl.toJSON();
+
const files = await (await fetch('/svelte-app.json')).json();
- if (bundle.imports.length > 0) {
+ if (imports.length > 0) {
const idx = files.findIndex(({ path }) => path === 'package.json');
const pkg = JSON.parse(files[idx].data);
const deps = {};
- bundle.imports.forEach(mod => {
+ imports.forEach(mod => {
const match = /^(@[^\/]+\/)?[^@\/]+/.exec(mod);
deps[match[0]] = 'latest';
});
@@ -191,7 +193,7 @@
var app = new App({
target: document.body,
- props: ${JSON.stringify(data, null, '\t').replace(/\n/g, '\n\t')}
+ props: ${JSON.stringify(values, null, '\t').replace(/\n/g, '\n\t')}
});
export default app;` });
diff --git a/site/src/routes/repl/_components/Repl.html b/site/src/routes/repl/_components/Repl.html
index 2f03a8e002..862b584f78 100644
--- a/site/src/routes/repl/_components/Repl.html
+++ b/site/src/routes/repl/_components/Repl.html
@@ -18,6 +18,7 @@
version; // workaround
return {
+ imports: bundle.imports,
components: $component_store,
values: $values_store
};
diff --git a/site/src/user.js b/site/src/user.js
index 665db40bae..0ba4e7716f 100644
--- a/site/src/user.js
+++ b/site/src/user.js
@@ -1,4 +1,4 @@
-import { writable } from 'svelte/store.js';
+import { writable } from 'svelte/store';
export const user = writable(null);
diff --git a/src/compile/render-dom/Block.ts b/src/compile/render-dom/Block.ts
index 8a205e25fd..573a9863d8 100644
--- a/src/compile/render-dom/Block.ts
+++ b/src/compile/render-dom/Block.ts
@@ -409,12 +409,10 @@ export default class Block {
const localKey = this.key && this.getUniqueName('key');
return deindent`
- ${this.comment && `// ${escape(this.comment)}`}
- function ${this.name}(#component, ${this.key ? `${localKey}, ` : ''}ctx) {
+ ${this.comment && `// ${this.comment}`}
+ function ${this.name}(${this.alias('component')}, ${this.key ? `${localKey}, ` : ''}ctx) {
${this.getContents(localKey)}
}
- `.replace(/(#+)(\w*)/g, (match: string, sigil: string, name: string) => {
- return sigil === '#' ? this.alias(name) : sigil.slice(1) + name;
- });
+ `;
}
}
diff --git a/src/compile/render-dom/index.ts b/src/compile/render-dom/index.ts
index ee5344869a..64a219ea6a 100644
--- a/src/compile/render-dom/index.ts
+++ b/src/compile/render-dom/index.ts
@@ -131,10 +131,10 @@ export default function dom(
if (expected.length) {
dev_props_check = deindent`
const { ctx } = this.$$;
+ const props = ${options.customElement ? `this.attributes` : `options.props || {}`};
${expected.map(name => deindent`
-
- if (ctx.${name} === undefined${options.customElement && ` && !('${name}' in this.attributes)`}) {
- console.warn("<${component.tag}> was created without expected data property '${name}'");
+ if (ctx.${name} === undefined && !('${name}' in props)) {
+ console.warn("<${component.tag}> was created without expected prop '${name}'");
}`)}
`;
}
diff --git a/src/compile/render-dom/wrappers/Element/index.ts b/src/compile/render-dom/wrappers/Element/index.ts
index f5092cab88..5f6f94f38b 100644
--- a/src/compile/render-dom/wrappers/Element/index.ts
+++ b/src/compile/render-dom/wrappers/Element/index.ts
@@ -403,7 +403,9 @@ export default class ElementWrapper extends Wrapper {
const groups = events
.map(event => ({
events: event.eventNames,
- bindings: mungedBindings.filter(binding => event.filter(this.node, binding.name))
+ bindings: mungedBindings
+ .filter(binding => binding.name !== 'this')
+ .filter(binding => event.filter(this.node, binding.name))
}))
.filter(group => group.bindings.length);
@@ -494,7 +496,7 @@ export default class ElementWrapper extends Wrapper {
block.addVariable(resize_listener);
block.builders.mount.addLine(
- `${resize_listener} = @addResizeListener(${this.var}, ${callee});`
+ `${resize_listener} = @addResizeListener(${this.var}, ${callee}.bind(${this.var}));`
);
block.builders.destroy.addLine(
@@ -632,7 +634,7 @@ export default class ElementWrapper extends Wrapper {
const fn = component.qualify(intro.name);
- block.builders.intro.addConditional(`@intro.enabled`, deindent`
+ block.builders.intro.addConditional(`@intros.enabled`, deindent`
if (${name}) ${name}.invalidate();
@add_render_callback(() => {
@@ -669,7 +671,7 @@ export default class ElementWrapper extends Wrapper {
`);
}
- block.builders.intro.addConditional(`@intro.enabled`, deindent`
+ block.builders.intro.addConditional(`@intros.enabled`, deindent`
@add_render_callback(() => {
${introName} = @wrapTransition(#component, ${this.var}, ${fn}, ${snippet}, true);
${introName}.run(1);
diff --git a/src/internal/Component.js b/src/internal/Component.js
index e7d3d23d05..5ee644c714 100644
--- a/src/internal/Component.js
+++ b/src/internal/Component.js
@@ -1,4 +1,4 @@
-import { add_render_callback, flush, intro, schedule_update } from './scheduler.js';
+import { add_render_callback, flush, intros, schedule_update } from './scheduler.js';
import { current_component, set_current_component } from './lifecycle.js'
import { is_function, run, run_all, noop } from './utils.js';
import { blankObject } from './utils.js';
@@ -101,7 +101,7 @@ export function init(component, options, instance, create_fragment, not_equal) {
$$.fragment = create_fragment(component, $$.ctx);
if (options.target) {
- intro.enabled = !!options.intro;
+ intros.enabled = !!options.intro;
if (options.hydrate) {
$$.fragment.l(children(options.target));
@@ -111,7 +111,7 @@ export function init(component, options, instance, create_fragment, not_equal) {
mount_component(component, options.target, options.anchor);
flush();
- intro.enabled = true;
+ intros.enabled = true;
}
set_current_component(previous_component);
diff --git a/src/internal/scheduler.js b/src/internal/scheduler.js
index 9f1d5feffc..962c321fd6 100644
--- a/src/internal/scheduler.js
+++ b/src/internal/scheduler.js
@@ -6,7 +6,7 @@ let dirty_components = [];
const binding_callbacks = [];
const render_callbacks = [];
-export const intro = { enabled: false };
+export const intros = { enabled: false };
export function schedule_update(component) {
dirty_components.push(component);
diff --git a/test/custom-elements/samples/no-missing-prop-warnings/test.js b/test/custom-elements/samples/no-missing-prop-warnings/test.js
index 675fa66485..9430e97f3a 100644
--- a/test/custom-elements/samples/no-missing-prop-warnings/test.js
+++ b/test/custom-elements/samples/no-missing-prop-warnings/test.js
@@ -12,7 +12,7 @@ export default function (target) {
target.innerHTML = '';
assert.equal(warnings.length, 1);
- assert.equal(warnings[0], ` was created without expected data property 'bar'`);
+ assert.equal(warnings[0], ` was created without expected prop 'bar'`);
console.warn = warn;
}
\ No newline at end of file
diff --git a/test/js/samples/bind-width-height/expected.js b/test/js/samples/bind-width-height/expected.js
index f97a6d81e5..d1396fe895 100644
--- a/test/js/samples/bind-width-height/expected.js
+++ b/test/js/samples/bind-width-height/expected.js
@@ -13,7 +13,7 @@ function create_fragment(component, ctx) {
m(target, anchor) {
insert(target, div, anchor);
- div_resize_listener = addResizeListener(div, ctx.div_resize_handler);
+ div_resize_listener = addResizeListener(div, ctx.div_resize_handler.bind(div));
current = true;
},
diff --git a/test/js/samples/debug-empty/expected.js b/test/js/samples/debug-empty/expected.js
index 424221040a..9d7d110ca3 100644
--- a/test/js/samples/debug-empty/expected.js
+++ b/test/js/samples/debug-empty/expected.js
@@ -70,8 +70,9 @@ class SvelteComponent extends SvelteComponentDev {
init(this, options, instance, create_fragment, safe_not_equal);
const { ctx } = this.$$;
- if (ctx.name === undefined) {
- console.warn(" was created without expected data property 'name'");
+ const props = options.props || {};
+ if (ctx.name === undefined && !('name' in props)) {
+ console.warn(" was created without expected prop 'name'");
}
}
diff --git a/test/js/samples/debug-foo-bar-baz-things/expected.js b/test/js/samples/debug-foo-bar-baz-things/expected.js
index c53273146e..3a1d6265e3 100644
--- a/test/js/samples/debug-foo-bar-baz-things/expected.js
+++ b/test/js/samples/debug-foo-bar-baz-things/expected.js
@@ -158,17 +158,18 @@ class SvelteComponent extends SvelteComponentDev {
init(this, options, instance, create_fragment, safe_not_equal);
const { ctx } = this.$$;
- if (ctx.things === undefined) {
- console.warn(" was created without expected data property 'things'");
+ const props = options.props || {};
+ if (ctx.things === undefined && !('things' in props)) {
+ console.warn(" was created without expected prop 'things'");
}
- if (ctx.foo === undefined) {
- console.warn(" was created without expected data property 'foo'");
+ if (ctx.foo === undefined && !('foo' in props)) {
+ console.warn(" was created without expected prop 'foo'");
}
- if (ctx.bar === undefined) {
- console.warn(" was created without expected data property 'bar'");
+ if (ctx.bar === undefined && !('bar' in props)) {
+ console.warn(" was created without expected prop 'bar'");
}
- if (ctx.baz === undefined) {
- console.warn(" was created without expected data property 'baz'");
+ if (ctx.baz === undefined && !('baz' in props)) {
+ console.warn(" was created without expected prop 'baz'");
}
}
diff --git a/test/js/samples/debug-foo/expected.js b/test/js/samples/debug-foo/expected.js
index 82df828323..92ca5ab9e1 100644
--- a/test/js/samples/debug-foo/expected.js
+++ b/test/js/samples/debug-foo/expected.js
@@ -156,11 +156,12 @@ class SvelteComponent extends SvelteComponentDev {
init(this, options, instance, create_fragment, safe_not_equal);
const { ctx } = this.$$;
- if (ctx.things === undefined) {
- console.warn(" was created without expected data property 'things'");
+ const props = options.props || {};
+ if (ctx.things === undefined && !('things' in props)) {
+ console.warn(" was created without expected prop 'things'");
}
- if (ctx.foo === undefined) {
- console.warn(" was created without expected data property 'foo'");
+ if (ctx.foo === undefined && !('foo' in props)) {
+ console.warn(" was created without expected prop 'foo'");
}
}
diff --git a/test/js/samples/dev-warning-missing-data-computed/expected.js b/test/js/samples/dev-warning-missing-data-computed/expected.js
index c77cac7174..95e85df1c1 100644
--- a/test/js/samples/dev-warning-missing-data-computed/expected.js
+++ b/test/js/samples/dev-warning-missing-data-computed/expected.js
@@ -76,8 +76,9 @@ class SvelteComponent extends SvelteComponentDev {
init(this, options, instance, create_fragment, safe_not_equal);
const { ctx } = this.$$;
- if (ctx.foo === undefined) {
- console.warn(" was created without expected data property 'foo'");
+ const props = options.props || {};
+ if (ctx.foo === undefined && !('foo' in props)) {
+ console.warn(" was created without expected prop 'foo'");
}
}
diff --git a/test/runtime/samples/binding-this-and-value/_config.js b/test/runtime/samples/binding-this-and-value/_config.js
new file mode 100644
index 0000000000..70cc8d4110
--- /dev/null
+++ b/test/runtime/samples/binding-this-and-value/_config.js
@@ -0,0 +1,24 @@
+export default {
+ html: `
+
+ value: initial
+ `,
+
+ ssrHtml: `
+
+ value: initial
+ `,
+
+ async test({ assert, target, window }) {
+ const input = target.querySelector('input');
+ const event = new window.Event('input');
+
+ input.value = 'changed';
+ await input.dispatchEvent(event);
+
+ assert.htmlEqual(target.innerHTML, `
+
+ value: changed
+ `);
+ }
+};
diff --git a/test/runtime/samples/binding-this-and-value/main.html b/test/runtime/samples/binding-this-and-value/main.html
new file mode 100644
index 0000000000..c56509eb7a
--- /dev/null
+++ b/test/runtime/samples/binding-this-and-value/main.html
@@ -0,0 +1,7 @@
+
+
+
+value: {value}
diff --git a/test/runtime/samples/dev-warning-missing-data-binding/_config.js b/test/runtime/samples/dev-warning-missing-data-binding/_config.js
index e85ee3fbb6..ffe62384a1 100644
--- a/test/runtime/samples/dev-warning-missing-data-binding/_config.js
+++ b/test/runtime/samples/dev-warning-missing-data-binding/_config.js
@@ -4,6 +4,6 @@ export default {
},
warnings: [
- ` was created without expected data property 'value'`
+ ` was created without expected prop 'value'`
]
};
diff --git a/test/runtime/samples/dev-warning-missing-data-component/Foo.html b/test/runtime/samples/dev-warning-missing-data-component/Foo.html
new file mode 100644
index 0000000000..8f26d21baf
--- /dev/null
+++ b/test/runtime/samples/dev-warning-missing-data-component/Foo.html
@@ -0,0 +1 @@
+{x} {y}
\ No newline at end of file
diff --git a/test/runtime/samples/dev-warning-missing-data-component/_config.js b/test/runtime/samples/dev-warning-missing-data-component/_config.js
new file mode 100644
index 0000000000..f3fc130528
--- /dev/null
+++ b/test/runtime/samples/dev-warning-missing-data-component/_config.js
@@ -0,0 +1,9 @@
+export default {
+ compileOptions: {
+ dev: true
+ },
+
+ warnings: [
+ ` was created without expected prop 'y'`
+ ]
+};
diff --git a/test/runtime/samples/dev-warning-missing-data-component/main.html b/test/runtime/samples/dev-warning-missing-data-component/main.html
new file mode 100644
index 0000000000..2bda6e2937
--- /dev/null
+++ b/test/runtime/samples/dev-warning-missing-data-component/main.html
@@ -0,0 +1,5 @@
+
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/dev-warning-missing-data/_config.js b/test/runtime/samples/dev-warning-missing-data/_config.js
index aef14fd572..5bc6c8be1f 100644
--- a/test/runtime/samples/dev-warning-missing-data/_config.js
+++ b/test/runtime/samples/dev-warning-missing-data/_config.js
@@ -4,7 +4,7 @@ export default {
},
warnings: [
- ` was created without expected data property 'foo'`,
- ` was created without expected data property 'bar'`
+ ` was created without expected prop 'foo'`,
+ ` was created without expected prop 'bar'`
]
};
diff --git a/test/runtime/samples/hash-in-attribute/_config.js b/test/runtime/samples/hash-in-attribute/_config.js
new file mode 100644
index 0000000000..5e5726c48f
--- /dev/null
+++ b/test/runtime/samples/hash-in-attribute/_config.js
@@ -0,0 +1,26 @@
+export default {
+ preserveIdentifiers: true,
+
+ props: {
+ links: ['a', 'b', 'c']
+ },
+
+ html: `
+ x#a
+ x#b
+ x#c
+ `,
+
+ test({ assert, component, target }) {
+ component.links = ['d', 'e', 'f'];
+
+ const links = [...target.querySelectorAll('a')];
+ assert.deepEqual(links.map(l => l.href), ['x#d', 'x#e', 'x#f']);
+
+ assert.htmlEqual(target.innerHTML, `
+ x#d
+ x#e
+ x#f
+ `);
+ }
+};
\ No newline at end of file
diff --git a/test/runtime/samples/hash-in-attribute/main.html b/test/runtime/samples/hash-in-attribute/main.html
new file mode 100644
index 0000000000..0d1455b066
--- /dev/null
+++ b/test/runtime/samples/hash-in-attribute/main.html
@@ -0,0 +1,3 @@
+{#each links as link}
+ x#{link}
+{/each}
\ No newline at end of file
diff --git a/transition.mjs b/transition.mjs
new file mode 100644
index 0000000000..1b6fbec605
--- /dev/null
+++ b/transition.mjs
@@ -0,0 +1,82 @@
+import { cubicOut, cubicInOut } from './easing';
+
+export function fade(node, {
+ delay = 0,
+ duration = 400
+}) {
+ const o = +getComputedStyle(node).opacity;
+
+ return {
+ delay,
+ duration,
+ css: t => `opacity: ${t * o}`
+ };
+}
+
+export function fly(node, {
+ delay = 0,
+ duration = 400,
+ easing = cubicOut,
+ x = 0,
+ y = 0
+}) {
+ const style = getComputedStyle(node);
+ const opacity = +style.opacity;
+ const transform = style.transform === 'none' ? '' : style.transform;
+
+ return {
+ delay,
+ duration,
+ easing,
+ css: t => `
+ transform: ${transform} translate(${(1 - t) * x}px, ${(1 - t) * y}px);
+ opacity: ${t * opacity}`
+ };
+}
+
+export function slide(node, {
+ delay = 0,
+ duration = 400,
+ easing = cubicOut
+}) {
+ const style = getComputedStyle(node);
+ const opacity = +style.opacity;
+ const height = parseFloat(style.height);
+ const padding_top = parseFloat(style.paddingTop);
+ const padding_bottom = parseFloat(style.paddingBottom);
+ const margin_top = parseFloat(style.marginTop);
+ const margin_bottom = parseFloat(style.marginBottom);
+ const border_top_width = parseFloat(style.borderTopWidth);
+ const border_bottom_width = parseFloat(style.borderBottomWidth);
+
+ return {
+ delay,
+ duration,
+ easing,
+ css: t =>
+ `overflow: hidden;` +
+ `opacity: ${Math.min(t * 20, 1) * opacity};` +
+ `height: ${t * height}px;` +
+ `padding-top: ${t * padding_top}px;` +
+ `padding-bottom: ${t * padding_bottom}px;` +
+ `margin-top: ${t * margin_top}px;` +
+ `margin-bottom: ${t * margin_bottom}px;` +
+ `border-top-width: ${t * border_top_width}px;` +
+ `border-bottom-width: ${t * border_bottom_width}px;`
+ };
+}
+
+export function draw(node, {
+ delay = 0,
+ duration = 800,
+ easing = cubicInOut
+}) {
+ const len = node.getTotalLength();
+
+ return {
+ delay,
+ duration,
+ easing,
+ css: (t, u) => `stroke-dasharray: ${t * len} ${u * len}`
+ };
+}
\ No newline at end of file