diff --git a/package.json b/package.json
index cf2cdd1..78f04fe 100644
--- a/package.json
+++ b/package.json
@@ -13,13 +13,16 @@
},
"dependencies": {
"compression": "^1.7.1",
+ "eases-jsnext": "^1.0.10",
"polka": "^0.4.0",
"sapper": "^0.14.0",
- "sirv": "^0.1.1"
+ "sirv": "^0.1.1",
+ "svelte-transitions": "^1.2.0",
+ "yootils": "^0.0.9"
},
"devDependencies": {
"npm-run-all": "^4.1.2",
- "svelte": "^2.0.0",
+ "svelte": "^2.9.0",
"svelte-loader": "^2.9.0",
"webpack": "^4.7.0"
}
diff --git a/routes/blog/[slug].html b/routes/blog/[slug].html
index 27354be..ab22608 100644
--- a/routes/blog/[slug].html
+++ b/routes/blog/[slug].html
@@ -2,13 +2,23 @@
+
{post.title}
-
- {@html post.html}
+
+ {@html post.html}
+
\ No newline at end of file
diff --git a/routes/blog/_crossfade.js b/routes/blog/_crossfade.js
new file mode 100644
index 0000000..81a7efd
--- /dev/null
+++ b/routes/blog/_crossfade.js
@@ -0,0 +1,82 @@
+import * as eases from 'eases-jsnext';
+import * as yootils from 'yootils';
+
+export default function crossfade({ fallback }) {
+ let requested = new Map();
+ let provided = new Map();
+
+ function crossfade(from, node) {
+ const to = node.getBoundingClientRect();
+ console.log({ from, to });
+ const dx = from.left - to.left;
+ const dy = from.top - to.top;
+
+ const dsx = (from.right - from.left) / (to.right - to.left);
+ const dsy = (from.bottom - from.top) / (to.bottom - to.top);
+
+ console.log({ dsx, dsy });
+
+ const sx = yootils.linearScale([0, 1], [dsx, 1]);
+ const sy = yootils.linearScale([0, 1], [dsy, 1]);
+
+ const style = getComputedStyle(node);
+ const transform = style.transform === 'none' ? '' : style.transform;
+
+ return {
+ duration: 4000,
+ easing: eases.quintOut,
+ css: (t, u) => `
+ opacity: ${t};
+ transform-origin: 0 0;
+ transform: ${transform} translate(${u * dx}px,${u * dy}px) scale(${sx(t)}, ${sy(t)});
+ `,
+ tick: (t, u) => {
+ // console.log({
+ // sx: 1 + u * dsx,
+ // sy: 1 + u * dsy,
+ // });
+ }
+ };
+ }
+
+ return {
+ send(node, params) {
+ provided.set(params.key, {
+ rect: node.getBoundingClientRect()
+ });
+
+ return () => {
+ if (requested.has(params.key)) {
+ const { rect } = requested.get(params.key);
+ requested.delete(params.key);
+
+ return crossfade(rect, node);
+ }
+
+ // if the node is disappearing altogether
+ // (i.e. wasn't claimed by the other list)
+ // then we need to supply an outro
+ provided.delete(params.key);
+ return fallback(node, params);
+ };
+ },
+
+ receive(node, params) {
+ requested.set(params.key, {
+ rect: node.getBoundingClientRect()
+ });
+
+ return () => {
+ if (provided.has(params.key)) {
+ const { rect } = provided.get(params.key);
+ provided.delete(params.key);
+
+ return crossfade(rect, node);
+ }
+
+ requested.delete(params.key);
+ return fallback(node, params);
+ };
+ }
+ };
+}
\ No newline at end of file
diff --git a/routes/blog/_move.js b/routes/blog/_move.js
new file mode 100644
index 0000000..3fbd76e
--- /dev/null
+++ b/routes/blog/_move.js
@@ -0,0 +1,75 @@
+import * as eases from 'eases-jsnext';
+import * as yootils from 'yootils';
+
+export default function move({ fallback }) {
+ let requested = new Map();
+ let provided = new Map();
+
+ function move(from, node) {
+ const to = node.getBoundingClientRect();
+ const dx = from.left - to.left;
+ const dy = from.top - to.top;
+
+ const dsx = (from.right - from.left) / (to.right - to.left);
+ const dsy = (from.bottom - from.top) / (to.bottom - to.top);
+
+ const sx = yootils.linearScale([0, 1], [dsx, 1]);
+ const sy = yootils.linearScale([0, 1], [dsy, 1]);
+
+ const style = getComputedStyle(node);
+ const transform = style.transform === 'none' ? '' : style.transform;
+
+ return {
+ duration: 400,
+ easing: eases.quintOut,
+ css: (t, u) => `
+ transform-origin: 0 0;
+ transform: ${transform} translate(${u * dx}px,${u * dy}px) scale(${sx(t)}, ${sy(t)});
+ `
+ };
+ }
+
+ return {
+ send(node, params) {
+ provided.set(params.key, {
+ rect: node.getBoundingClientRect()
+ });
+
+ return () => {
+ if (requested.has(params.key)) {
+ const { rect } = requested.get(params.key);
+ requested.delete(params.key);
+
+ return {
+ duration: 0,
+ css: () => `opacity: 0`
+ };
+ }
+
+ // if the node is disappearing altogether
+ // (i.e. wasn't claimed by the other list)
+ // then we need to supply an outro
+ provided.delete(params.key);
+ return fallback(node, params);
+ };
+ },
+
+ receive(node, params) {
+ requested.set(params.key, {
+ rect: node.getBoundingClientRect()
+ });
+
+ return () => {
+ if (provided.has(params.key)) {
+ const { rect } = provided.get(params.key);
+ provided.delete(params.key);
+
+ return move(rect, node);
+ }
+
+ requested.delete(params.key);
+ return fallback(node, params);
+ };
+ }
+ };
+}
\ No newline at end of file
diff --git a/routes/blog/_transitions.js b/routes/blog/_transitions.js
new file mode 100644
index 0000000..975f227
--- /dev/null
+++ b/routes/blog/_transitions.js
@@ -0,0 +1,12 @@
+import move from './_move.js';
+
+const { send, receive } = move({
+ fallback(node) {
+ return {
+ duration: 0,
+ css: t => `opacity: ${t}`
+ };
+ }
+});
+
+export { send, receive };
\ No newline at end of file
diff --git a/routes/blog/index.html b/routes/blog/index.html
index f1c80ac..d0891f8 100644
--- a/routes/blog/index.html
+++ b/routes/blog/index.html
@@ -2,31 +2,54 @@
Blog
-
Recent posts
+
\ No newline at end of file
diff --git a/webpack/client.config.js b/webpack/client.config.js
index 9e330c5..3190b69 100644
--- a/webpack/client.config.js
+++ b/webpack/client.config.js
@@ -20,7 +20,8 @@ module.exports = {
options: {
dev: isDev,
hydratable: true,
- hotReload: true
+ hotReload: true,
+ nestedTransitions: true
}
}
}