[docs] Use a simpler demo for the first actions tutorial (#5014) (#6962)

* Change actions tutorial

* Rename files containing action functions

* Move old pannable example to separate directory

* Add new tutorial to examples

* Update title of the pannable example

* Add thumbnail for pannable action example

* I can't remember all css properties, okay?

* Fix order of style tag in new example

* Inline outclick handlers

* Rename pannable example

* Fix formatting

Co-authored-by: Nayan Gautam <50981692+698969@users.noreply.github.com>
pull/6974/head
gtmnayan 3 years ago committed by GitHub
parent 81fc3f898a
commit 6ff1aed8d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,39 +1,15 @@
<script>
import { spring } from 'svelte/motion';
import { pannable } from './pannable.js';
import { clickOutside } from "./click_outside.js";
const coords = spring({ x: 0, y: 0 }, {
stiffness: 0.2,
damping: 0.4
});
function handlePanStart() {
coords.stiffness = coords.damping = 1;
}
function handlePanMove(event) {
coords.update($coords => ({
x: $coords.x + event.detail.dx,
y: $coords.y + event.detail.dy
}));
}
function handlePanEnd(event) {
coords.stiffness = 0.2;
coords.damping = 0.4;
coords.set({ x: 0, y: 0 });
}
let showModal = true;
</script>
<div class="box"
use:pannable
on:panstart={handlePanStart}
on:panmove={handlePanMove}
on:panend={handlePanEnd}
style="transform:
translate({$coords.x}px,{$coords.y}px)
rotate({$coords.x * 0.2}deg)"
></div>
<button on:click={() => (showModal = true)}>Show Modal</button>
{#if showModal}
<div class="box" use:clickOutside on:outclick={() => (showModal = false)}>
Click outside me!
</div>
{/if}
<style>
.box {
@ -46,6 +22,8 @@
top: calc(50% - var(--height) / 2);
border-radius: 4px;
background-color: #ff3e00;
cursor: move;
color: #fff;
text-align: center;
font-weight: bold;
}
</style>
</style>

@ -0,0 +1,15 @@
export function clickOutside(node) {
const handleClick = (event) => {
if (!node.contains(event.target)) {
node.dispatchEvent(new CustomEvent("outclick"));
}
};
document.addEventListener("click", handleClick, true);
return {
destroy() {
document.removeEventListener("click", handleClick, true);
}
};
}

@ -0,0 +1,51 @@
<script>
import { spring } from 'svelte/motion';
import { pannable } from './pannable.js';
const coords = spring({ x: 0, y: 0 }, {
stiffness: 0.2,
damping: 0.4
});
function handlePanStart() {
coords.stiffness = coords.damping = 1;
}
function handlePanMove(event) {
coords.update($coords => ({
x: $coords.x + event.detail.dx,
y: $coords.y + event.detail.dy
}));
}
function handlePanEnd(event) {
coords.stiffness = 0.2;
coords.damping = 0.4;
coords.set({ x: 0, y: 0 });
}
</script>
<div class="box"
use:pannable
on:panstart={handlePanStart}
on:panmove={handlePanMove}
on:panend={handlePanEnd}
style="transform:
translate({$coords.x}px,{$coords.y}px)
rotate({$coords.x * 0.2}deg)"
></div>
<style>
.box {
--width: 100px;
--height: 100px;
position: absolute;
width: var(--width);
height: var(--height);
left: calc(50% - var(--width) / 2);
top: calc(50% - var(--height) / 2);
border-radius: 4px;
background-color: #ff3e00;
cursor: move;
}
</style>

@ -0,0 +1,3 @@
{
"title": "A more complex action"
}

@ -1,29 +1,16 @@
<script>
import { spring } from 'svelte/motion';
const coords = spring({ x: 0, y: 0 }, {
stiffness: 0.2,
damping: 0.4
});
function handlePanStart() {
coords.stiffness = coords.damping = 1;
}
function handlePanMove(event) {
coords.update($coords => ({
x: $coords.x + event.detail.dx,
y: $coords.y + event.detail.dy
}));
}
function handlePanEnd(event) {
coords.stiffness = 0.2;
coords.damping = 0.4;
coords.set({ x: 0, y: 0 });
}
let showModal = true;
</script>
<button on:click={() => (showModal = true)}>Show Modal</button>
{#if showModal}
<div class="box" on:outclick={() => (showModal = false)}>
Click outside me!
</div>
{/if}
<style>
.box {
--width: 100px;
@ -35,15 +22,8 @@
top: calc(50% - var(--height) / 2);
border-radius: 4px;
background-color: #ff3e00;
cursor: move;
color: #fff;
text-align: center;
font-weight: bold;
}
</style>
<div class="box"
on:panstart={handlePanStart}
on:panmove={handlePanMove}
on:panend={handlePanEnd}
style="transform:
translate({$coords.x}px,{$coords.y}px)
rotate({$coords.x * 0.2}deg)"
></div>

@ -1,4 +1,4 @@
export function pannable(node) {
export function clickOutside(node) {
// setup work goes here...
return {
@ -6,4 +6,4 @@ export function pannable(node) {
// ...cleanup goes here
}
};
}
}

@ -1,30 +1,16 @@
<script>
import { spring } from 'svelte/motion';
import { pannable } from './pannable.js';
import { clickOutside } from "./click_outside.js";
const coords = spring({ x: 0, y: 0 }, {
stiffness: 0.2,
damping: 0.4
});
function handlePanStart() {
coords.stiffness = coords.damping = 1;
}
function handlePanMove(event) {
coords.update($coords => ({
x: $coords.x + event.detail.dx,
y: $coords.y + event.detail.dy
}));
}
function handlePanEnd(event) {
coords.stiffness = 0.2;
coords.damping = 0.4;
coords.set({ x: 0, y: 0 });
}
let showModal = true;
</script>
<button on:click={() => (showModal = true)}>Show Modal</button>
{#if showModal}
<div class="box" use:clickOutside on:outclick={() => (showModal = false)}>
Click outside me!
</div>
{/if}
<style>
.box {
--width: 100px;
@ -36,16 +22,8 @@
top: calc(50% - var(--height) / 2);
border-radius: 4px;
background-color: #ff3e00;
cursor: move;
color: #fff;
text-align: center;
font-weight: bold;
}
</style>
<div class="box"
use:pannable
on:panstart={handlePanStart}
on:panmove={handlePanMove}
on:panend={handlePanEnd}
style="transform:
translate({$coords.x}px,{$coords.y}px)
rotate({$coords.x * 0.2}deg)"
></div>

@ -0,0 +1,15 @@
export function clickOutside(node) {
const handleClick = (event) => {
if (!node.contains(event.target)) {
node.dispatchEvent(new CustomEvent("outclick"));
}
};
document.addEventListener("click", handleClick, true);
return {
destroy() {
document.removeEventListener("click", handleClick, true);
}
};
}

@ -1,47 +0,0 @@
export function pannable(node) {
let x;
let y;
function handleMousedown(event) {
x = event.clientX;
y = event.clientY;
node.dispatchEvent(new CustomEvent('panstart', {
detail: { x, y }
}));
window.addEventListener('mousemove', handleMousemove);
window.addEventListener('mouseup', handleMouseup);
}
function handleMousemove(event) {
const dx = event.clientX - x;
const dy = event.clientY - y;
x = event.clientX;
y = event.clientY;
node.dispatchEvent(new CustomEvent('panmove', {
detail: { x, y, dx, dy }
}));
}
function handleMouseup(event) {
x = event.clientX;
y = event.clientY;
node.dispatchEvent(new CustomEvent('panend', {
detail: { x, y }
}));
window.removeEventListener('mousemove', handleMousemove);
window.removeEventListener('mouseup', handleMouseup);
}
node.addEventListener('mousedown', handleMousedown);
return {
destroy() {
node.removeEventListener('mousedown', handleMousedown);
}
};
}

@ -4,85 +4,45 @@ title: The use directive
Actions are essentially element-level lifecycle functions. They're useful for things like:
* interfacing with third-party libraries
* lazy-loaded images
* tooltips
* adding custom event handlers
- interfacing with third-party libraries
- lazy-loaded images
- tooltips
- adding custom event handlers
In this app, we want to make the orange box 'pannable'. It has event handlers for the `panstart`, `panmove` and `panend` events, but these aren't native DOM events. We have to dispatch them ourselves. First, import the `pannable` function...
In this app, we want to make the orange modal close when the user clicks outside it. It has an event handler for the `outclick` event, but it isn't a native DOM event. We have to dispatch it ourselves. First, import the `clickOutside` function...
```js
import { pannable } from './pannable.js';
import { clickOutside } from "./click_outside.js";
```
...then use it with the element:
```html
<div class="box"
use:pannable
on:panstart={handlePanStart}
on:panmove={handlePanMove}
on:panend={handlePanEnd}
style="transform:
translate({$coords.x}px,{$coords.y}px)
rotate({$coords.x * 0.2}deg)"
></div>
<div class="box" use:clickOutside on:outclick="{() => (showModal = false)}">
Click outside me!
</div>
```
Open the `pannable.js` file. Like transition functions, an action function receives a `node` and some optional parameters, and returns an action object. That object can have a `destroy` function, which is called when the element is unmounted.
Open the `click_outside.js` file. Like transition functions, an action function receives a `node` (which is the element that the action is applied to) and some optional parameters, and returns an action object. That object can have a `destroy` function, which is called when the element is unmounted.
We want to fire `panstart` event when the user mouses down on the element, `panmove` events (with `dx` and `dy` properties showing how far the mouse moved) when they drag it, and `panend` events when they mouse up. One possible implementation looks like this:
We want to fire the `outclick` event when the user clicks outside the orange box. One possible implementation looks like this:
```js
export function pannable(node) {
let x;
let y;
function handleMousedown(event) {
x = event.clientX;
y = event.clientY;
node.dispatchEvent(new CustomEvent('panstart', {
detail: { x, y }
}));
window.addEventListener('mousemove', handleMousemove);
window.addEventListener('mouseup', handleMouseup);
}
function handleMousemove(event) {
const dx = event.clientX - x;
const dy = event.clientY - y;
x = event.clientX;
y = event.clientY;
node.dispatchEvent(new CustomEvent('panmove', {
detail: { x, y, dx, dy }
}));
}
function handleMouseup(event) {
x = event.clientX;
y = event.clientY;
node.dispatchEvent(new CustomEvent('panend', {
detail: { x, y }
}));
window.removeEventListener('mousemove', handleMousemove);
window.removeEventListener('mouseup', handleMouseup);
}
export function clickOutside(node) {
const handleClick = (event) => {
if (!node.contains(event.target)) {
node.dispatchEvent(new CustomEvent("outclick"));
}
};
node.addEventListener('mousedown', handleMousedown);
document.addEventListener("click", handleClick, true);
return {
destroy() {
node.removeEventListener('mousedown', handleMousedown);
}
document.removeEventListener("click", handleClick, true);
},
};
}
```
Update the `pannable` function and try moving the box around.
> This implementation is for demonstration purposes — a more complete one would also consider touch events.
Update the `clickOutside` function, click the button to show the modal and then click outside it to close it.

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Loading…
Cancel
Save