svelte-movable
Advanced tools
Comparing version 1.0.4 to 1.1.0
@@ -48,3 +48,3 @@ /** | ||
function input(node, parameters) { | ||
var _a, _b, _c, _d, _e; | ||
var _a, _b, _c, _d; | ||
return { | ||
@@ -54,4 +54,3 @@ enabled: (_a = parameters.enabled) !== null && _a !== void 0 ? _a : true, | ||
normalizedDelta: normalizeDelta((_c = parameters.limit) === null || _c === void 0 ? void 0 : _c.delta), | ||
cache: (_d = parameters.cache) !== null && _d !== void 0 ? _d : 'none', | ||
trigger: (_e = parameters.trigger) !== null && _e !== void 0 ? _e : node, | ||
trigger: (_d = parameters.trigger) !== null && _d !== void 0 ? _d : node, | ||
}; | ||
@@ -80,6 +79,24 @@ } | ||
* | ||
* | ||
* Be aware of side effects: | ||
* | ||
* - element.style.position is set to `relative` (if not already 'absolute' / 'relative') the first time mousedown is triggered | ||
* | ||
* - document.body.userSelect is set to `none` after `mousedown` and restored on `mouseup` | ||
* | ||
* - document.body.cursor is set to `move` after `mousedown` and restored on `mouseup` | ||
* | ||
* @example Typical usage | ||
* | ||
* 1. `mousedown` of the trigger `button` element, a `CustomEvent` `movablestart`is dispatched, | ||
* | ||
* 2. `mousemove` will trigger `div` to move accordingly; | ||
* | ||
* 3. movement will be limited to the border of the `containerNode`, plus and minus 20% of the width & height of the `div` that the action is being used on, | ||
* | ||
* 4. `mouseup` will stop the movement; a `CustomEvent` `movableend` is dispatched. | ||
* | ||
* ```svelte | ||
* <script lang="ts"> | ||
* import { fade } from 'svelte/transition' | ||
* import arrows from 'svelte-awesome/icons/arrows'; | ||
@@ -106,4 +123,4 @@ * import Icon from 'svelte-awesome/components/Icon.svelte'; | ||
* }} | ||
* on:movablestart={() => console.log('movable:start')} | ||
* on:movableend={() => console.log('movable:end')} | ||
* on:movablestart={(event) => console.log('movable:start', event.detail.node, event.detail.position)} | ||
* on:movableend={(event) => console.log('movable:end', event.detail.node, event.detail.position)} | ||
* > | ||
@@ -126,23 +143,23 @@ * <button | ||
function movable(node, parameters) { | ||
if (parameters === void 0) { parameters = { enabled: true, cache: 'none' }; } | ||
if (parameters === void 0) { parameters = { enabled: true }; } | ||
var _a = input(node, parameters), parent = _a.parent, normalizedDelta = _a.normalizedDelta, trigger = _a.trigger, enabled = _a.enabled; | ||
var lastMouseCoordinates = { x: 0, y: 0 }; | ||
var lastNodeCoordinates = { top: 0, left: 0 }; | ||
var lastMousePosition = { x: 0, y: 0 }; | ||
var lastNodePosition = { top: 0, left: 0 }; | ||
var ΣΔx = 0; // total displacement in x-axis | ||
var ΣΔy = 0; // total displacement in y-axis | ||
var updateLastMouseCoordinates = function (event) { | ||
lastMouseCoordinates.x = event.clientX; | ||
lastMouseCoordinates.y = event.clientY; | ||
var updateLastMousePosition = function (event) { | ||
lastMousePosition.x = event.clientX; | ||
lastMousePosition.y = event.clientY; | ||
}; | ||
var updateLastNodeCoordinates = function (_a) { | ||
var updateLastNodePosition = function (_a) { | ||
var top = _a.top, left = _a.left; | ||
lastNodeCoordinates.top = top; | ||
lastNodeCoordinates.left = left; | ||
lastNodePosition.top = top; | ||
lastNodePosition.left = left; | ||
}; | ||
var onMouseMove = function (event) { | ||
var Δx = event.clientX - lastMouseCoordinates.x; | ||
var Δy = event.clientY - lastMouseCoordinates.y; | ||
updateLastMouseCoordinates(event); | ||
var top = lastNodeCoordinates.top + Δy; | ||
var left = lastNodeCoordinates.left + Δx; | ||
var Δx = event.clientX - lastMousePosition.x; | ||
var Δy = event.clientY - lastMousePosition.y; | ||
updateLastMousePosition(event); | ||
var top = lastNodePosition.top + Δy; | ||
var left = lastNodePosition.left + Δx; | ||
var nodeBoundingRect = node.getBoundingClientRect(); | ||
@@ -192,3 +209,3 @@ var boundX = 0; | ||
if (boundX > 0) { | ||
var newΣΔx = ΣΔx + left - lastNodeCoordinates.left; | ||
var newΣΔx = ΣΔx + left - lastNodePosition.left; | ||
if (newΣΔx > boundX) { | ||
@@ -202,3 +219,3 @@ left -= newΣΔx - boundX; | ||
if (boundY > 0) { | ||
var newΣΔy = ΣΔy + top - lastNodeCoordinates.top; | ||
var newΣΔy = ΣΔy + top - lastNodePosition.top; | ||
if (newΣΔy > boundY) { | ||
@@ -214,5 +231,5 @@ top -= newΣΔy - boundY; | ||
node.style.top = "".concat(top, "px"); | ||
ΣΔx += left - lastNodeCoordinates.left; | ||
ΣΔy += top - lastNodeCoordinates.top; | ||
updateLastNodeCoordinates({ top: top, left: left }); | ||
ΣΔx += left - lastNodePosition.left; | ||
ΣΔy += top - lastNodePosition.top; | ||
updateLastNodePosition({ top: top, left: left }); | ||
}; | ||
@@ -224,13 +241,15 @@ var end = function () { | ||
window.removeEventListener('mouseup', end); | ||
node.dispatchEvent(new CustomEvent('movableend', { detail: node })); | ||
var detail = { node: node, position: lastNodePosition }; | ||
node.dispatchEvent(new CustomEvent('movableend', { detail: detail })); | ||
}; | ||
var onMouseDown = function (event) { | ||
var _a, _b, _c, _d; | ||
node.dispatchEvent(new CustomEvent('movablestart', { detail: node })); | ||
var computedStyles = getComputedStyle(node); | ||
// init coordinates | ||
// init position | ||
var regex = '^[-0-9]+'; | ||
var left = parseInt((_b = (_a = computedStyles.getPropertyValue('left').match(regex)) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : '0'); | ||
var top = parseInt((_d = (_c = computedStyles.getPropertyValue('top').match(regex)) === null || _c === void 0 ? void 0 : _c[0]) !== null && _d !== void 0 ? _d : '0'); | ||
updateLastNodeCoordinates({ left: left, top: top }); | ||
updateLastNodePosition({ left: left, top: top }); | ||
var detail = { node: node, position: lastNodePosition }; | ||
node.dispatchEvent(new CustomEvent('movablestart', { detail: detail })); | ||
// init position style | ||
@@ -241,3 +260,3 @@ var position = computedStyles.getPropertyValue('position'); | ||
} | ||
updateLastMouseCoordinates(event); | ||
updateLastMousePosition(event); | ||
document.body.style.userSelect = 'none'; | ||
@@ -244,0 +263,0 @@ document.body.style.cursor = 'move'; |
@@ -22,6 +22,24 @@ import type { MovableParameters } from './types'; | ||
* | ||
* | ||
* Be aware of side effects: | ||
* | ||
* - element.style.position is set to `relative` (if not already 'absolute' / 'relative') the first time mousedown is triggered | ||
* | ||
* - document.body.userSelect is set to `none` after `mousedown` and restored on `mouseup` | ||
* | ||
* - document.body.cursor is set to `move` after `mousedown` and restored on `mouseup` | ||
* | ||
* @example Typical usage | ||
* | ||
* 1. `mousedown` of the trigger `button` element, a `CustomEvent` `movablestart`is dispatched, | ||
* | ||
* 2. `mousemove` will trigger `div` to move accordingly; | ||
* | ||
* 3. movement will be limited to the border of the `containerNode`, plus and minus 20% of the width & height of the `div` that the action is being used on, | ||
* | ||
* 4. `mouseup` will stop the movement; a `CustomEvent` `movableend` is dispatched. | ||
* | ||
* ```svelte | ||
* <script lang="ts"> | ||
* import { fade } from 'svelte/transition' | ||
* import arrows from 'svelte-awesome/icons/arrows'; | ||
@@ -48,4 +66,4 @@ * import Icon from 'svelte-awesome/components/Icon.svelte'; | ||
* }} | ||
* on:movablestart={() => console.log('movable:start')} | ||
* on:movableend={() => console.log('movable:end')} | ||
* on:movablestart={(event) => console.log('movable:start', event.detail.node, event.detail.position)} | ||
* on:movableend={(event) => console.log('movable:end', event.detail.node, event.detail.position)} | ||
* > | ||
@@ -52,0 +70,0 @@ * <button |
/** | ||
* Cache policy for last known position of node | ||
* @public | ||
* | ||
* @remarks | ||
* | ||
* `'session'` & `'local'` mean using session storage & local storage, respectively. | ||
* | ||
* @example | ||
* | ||
* ```svelte | ||
* <div use:movable={{ | ||
* policy: 'session', | ||
* }} /> | ||
* ``` | ||
*/ | ||
export declare type MovableCachePolicy = 'session' | 'local' | 'none'; | ||
/** | ||
* Limit by creating a bounding box of movable area [-delta, +delta] in both axes | ||
@@ -53,9 +36,5 @@ * @public | ||
* The limit within which node can be moved | ||
* | ||
* @remarks | ||
* | ||
* | ||
* @public | ||
*/ | ||
export declare type MovableLimit = { | ||
export interface MovableLimit { | ||
/** | ||
@@ -72,3 +51,3 @@ * Move node within this parent node | ||
} | MovableLimitDelta; | ||
}; | ||
} | ||
/** | ||
@@ -86,11 +65,6 @@ * @public | ||
/** whether to trigger the action */ | ||
enabled: boolean; | ||
enabled?: boolean; | ||
/** Set a limit within which node can be moved */ | ||
limit?: MovableLimit; | ||
/** | ||
* Cache policy for last known position of node | ||
* @alpha | ||
*/ | ||
cache: MovableCachePolicy; | ||
/** | ||
* A node that triggers mousedown event, otherwise the node itself is the trigger | ||
@@ -115,2 +89,35 @@ * | ||
} | ||
/** | ||
* `detail` payload for `movableend` and `movablestart` CustomEvent | ||
* @public | ||
* | ||
* @example | ||
* | ||
* ```svelte | ||
* <script> | ||
* function handler(event) { | ||
* const { position, node } = event.detail; | ||
* console.log('action movable was used on element', node); | ||
* console.log('last known position:', position); | ||
* } | ||
* </script> | ||
* | ||
* <div | ||
* use:movable | ||
* on:movablestart={handler} | ||
* on:movableend={handler} | ||
* /> | ||
* ``` | ||
*/ | ||
export interface MovableEventDetails { | ||
/** the node that the action was placed on */ | ||
node: HTMLElement; | ||
/** last known position, as in styles.position */ | ||
position: { | ||
/** styles.position.left */ | ||
left: number; | ||
/** styles.position.right */ | ||
top: number; | ||
}; | ||
} | ||
//# sourceMappingURL=index.d.ts.map |
@@ -10,3 +10,3 @@ import type { MovableParameters } from '../../types'; | ||
*/ | ||
export declare function input(node: HTMLElement, parameters: Partial<MovableParameters>): { | ||
export declare function input(node: HTMLElement, parameters: MovableParameters): { | ||
enabled: boolean; | ||
@@ -24,5 +24,4 @@ parent: HTMLElement | undefined; | ||
}; | ||
cache: import("../../types").MovableCachePolicy; | ||
trigger: HTMLElement; | ||
}; | ||
//# sourceMappingURL=input.d.ts.map |
{ | ||
"name": "svelte-movable", | ||
"version": "1.0.4", | ||
"description": "Action to move node on mousedown", | ||
"version": "1.1.0", | ||
"description": "Action to move node on mousedown & mousemove", | ||
"main": "lib/index.js", | ||
@@ -17,3 +17,3 @@ "module": "lib/index.js", | ||
"lint:es": "eslint --ignore-path .gitignore .", | ||
"format": "prettier --check --config ./prettierrc.yaml .", | ||
"format": "prettier --check --ignore-path .gitignore --plugin-search-dir=. \"./**/*.{ts,js,cjs,json}\"", | ||
"build": "rollup -c", | ||
@@ -20,0 +20,0 @@ "semantic-release": "semantic-release", |
@@ -5,6 +5,8 @@ # Svelte Action - `use:movable` | ||
[![npm.badge]][npm] [![bundlephobia.badge]][bundlephobia] [![github.release.badge]][github.release] [![semantic-release.badge]][semantic-release] [![MIT][license.badge]][license] | ||
[![npm.badge]][npm] [![bundlephobia.badge]][bundlephobia] [![semantic-release.badge]][semantic-release] [![MIT][license.badge]][license] | ||
[![github.actions.release.badge]][github.actions.release] | ||
[![github.actions.release.badge]][github.actions.release] [![github.release.badge]][github.release] | ||
![demo](./static/images/demo.gif) | ||
</div> | ||
@@ -31,51 +33,4 @@ | ||
<details open> | ||
<summary>Example: show / hide</summary> | ||
See [example for typical usage here][github.api.movable] | ||
While `mousedown` of the trigger `button` element | ||
- `mousemove` will trigger `div` to move accordingly; a `CustomEvent` `movablestart`is dispatched, | ||
- movement will be limited to the border of the `containerNode`, plus and minus 20% of the width & height of the `div` that the action is being used on, | ||
- `mouseup` will stop the movement; a `CustomEvent` `movableend` is dispatched. | ||
```svelte | ||
<script lang="ts"> | ||
import arrows from 'svelte-awesome/icons/arrows'; | ||
import Icon from 'svelte-awesome/components/Icon.svelte'; | ||
let modal = false; | ||
let triggerNode: HTMLElement; | ||
</script> | ||
<container> | ||
<!-- ... some other content ... --> | ||
{#if modal} | ||
<div | ||
transition:fade={{ duration: 200 }} | ||
class="absolute top-1/2 left-1/2 -translate-y-1/2 -translate-x-1/2 w-full max-w-sm" | ||
use:movable={{ | ||
limit: { | ||
delta: '20%', | ||
parent: containerNode, | ||
}, | ||
trigger: triggerNode, | ||
}} | ||
on:movablestart={(node) => console.log('movable:start', node)} | ||
on:movableend={(node) => console.log('movable:end', node)} | ||
> | ||
<button | ||
bind:this={triggerNode} | ||
class="c-btn-icon absolute top-2 right-10 hover:cursor-move" | ||
> | ||
<Icon data={arrows} /> | ||
</button> | ||
<!-- ... some other modal content ... --> | ||
</div> | ||
{/if} | ||
</container> | ||
``` | ||
</details> | ||
@@ -113,3 +68,3 @@ | ||
**Note**: action accepts `Partial<MovableParameters>`. By default you don't need to provide any option. | ||
**Note**: `MovableParameters` has properties that are all optional. By default you don't need to provide any parameter to the action. | ||
@@ -153,2 +108,3 @@ ## Contributing | ||
[github.api.movableparameters]: api/docs/svelte-movable.movableparameters.md | ||
[github.api.movable]: api/docs/svelte-movable.movable.md | ||
@@ -155,0 +111,0 @@ <!-- heading badge --> |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
35112
537
118