Socket
Socket
Sign inDemoInstall

svelte-actions

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

svelte-actions - npm Package Compare versions

Comparing version 0.2.1 to 0.2.2

16

dist/clickOutside.d.ts
import { Action } from './types';
export interface ClickOutsideConfig {
enabled: boolean;
cb: (node: HTMLElement) => void;
}
/**
*
* Call callback when user clicks outside a given element
*
* Usage:
* @example
* ```svelte
* <div use:clickOutside={{ enabled: open, cb: () => open = false }}>
*
* ```
* Demo: https://svelte.dev/repl/dae848c2157e48ab932106779960f5d5?version=3.19.2
*
*/
export declare function clickOutside(node: HTMLElement, params: {
enabled: boolean;
cb: Function;
}): ReturnType<Action>;
export declare const clickOutside: Action<ClickOutsideConfig>;

@@ -1,38 +0,27 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.clickOutside = void 0;
/**
*
* Call callback when user clicks outside a given element
*
* Usage:
* @example
* ```svelte
* <div use:clickOutside={{ enabled: open, cb: () => open = false }}>
*
* ```
* Demo: https://svelte.dev/repl/dae848c2157e48ab932106779960f5d5?version=3.19.2
*
*/
function clickOutside(node, params) {
var initialEnabled = params.enabled, cb = params.cb;
var handleOutsideClick = function (_a) {
var target = _a.target;
if (!node.contains(target))
cb(node); // typescript hack, not sure how to solve without asserting as Node
};
function update(_a) {
var enabled = _a.enabled;
if (enabled) {
window.addEventListener('click', handleOutsideClick);
}
else {
window.removeEventListener('click', handleOutsideClick);
}
export var clickOutside = function (node, config) {
function handler(e) {
if (!node.contains(e.target))
config.cb(node);
}
update({ enabled: initialEnabled });
function set_handler(enabled) {
(enabled ? window.addEventListener : window.removeEventListener)('click', handler);
}
set_handler(config.enabled);
return {
update: update,
update: function (params) {
set_handler((config = params).enabled);
},
destroy: function () {
window.removeEventListener('click', handleOutsideClick);
}
set_handler(false);
},
};
}
exports.clickOutside = clickOutside;
};

@@ -1,18 +0,6 @@

"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./clickOutside"), exports);
__exportStar(require("./longpress"), exports);
__exportStar(require("./pannable"), exports);
__exportStar(require("./lazyload"), exports);
__exportStar(require("./preventTabClose"), exports);
__exportStar(require("./shortcut"), exports);
export * from './clickOutside';
export * from './longpress';
export * from './pannable';
export * from './lazyload';
export * from './preventTabClose';
export * from './shortcut';
import { Action } from './types';
export declare function lazyload(node: HTMLElement, attributes: Object): ReturnType<Action>;
/**
* Set attributes on an element when it is visible in the viewport.
*@example
*```svelte
* <img use:lazyLoad={{src:"/myimage"}} alt="">
*```
* Demo: https://svelte.dev/repl/f12988de576b4bf9b541a2a59eb838f6?version=3.23.2
*
*/
export declare const lazyload: Action<object>;

@@ -1,41 +0,32 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.lazyload = void 0;
var node_attributes_map = new WeakMap();
var intersection_handler = function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting && entry.target instanceof HTMLElement) {
var node = entry.target;
Object.assign(node, node_attributes_map.get(node));
lazy_load_observer.unobserve(node);
}
});
};
var lazy_load_observer;
function observer() {
return (lazy_load_observer !== null && lazy_load_observer !== void 0 ? lazy_load_observer : (lazy_load_observer = new IntersectionObserver(intersection_handler)));
}
/**
* Attach onto any image to lazy load it
*
* Set attributes on an element when it is visible in the viewport.
*@example
*```svelte
* <img use:lazyLoad={{src:"/myimage"}} alt="">
*
*```
* Demo: https://svelte.dev/repl/f12988de576b4bf9b541a2a59eb838f6?version=3.23.2
*
*/
var lazyLoadHandleIntersection = function (entries) {
entries.forEach(function (entry) {
var _a;
if (!entry.isIntersecting) {
return;
}
if (!(entry.target instanceof HTMLElement)) {
return;
}
var node = entry.target;
var attributes = (_a = lazyLoadNodeAttributes.find(function (item) { return item.node === node; })) === null || _a === void 0 ? void 0 : _a.attributes;
Object.assign(node, attributes);
lazyLoadObserver.unobserve(node);
});
};
var lazyLoadObserver;
var lazyLoadNodeAttributes = [];
function lazyload(node, attributes) {
if (!lazyLoadObserver) {
lazyLoadObserver = new IntersectionObserver(lazyLoadHandleIntersection);
}
lazyLoadNodeAttributes.push({ node: node, attributes: attributes });
lazyLoadObserver.observe(node);
export var lazyload = function (node, attributes) {
node_attributes_map.set(node, attributes);
observer().observe(node);
return {
destroy: function () {
lazyLoadObserver.unobserve(node);
}
observer().unobserve(node);
},
};
}
exports.lazyload = lazyload;
};

@@ -5,11 +5,10 @@ import { Action } from './types';

*
* Usage:
*
*<button use:longpress={duration}
on:longpress="{() => pressed = true}"
on:mouseenter="{() => pressed = false}"
>press and hold</button>
*
* @example
* ```svelte
* <button use:longpress={duration} on:longpress={() => alert("longpress")}>
* press and hold
* </button>
*```
* Demo: https://svelte.dev/tutorial/adding-parameters-to-actions
*/
export declare function longpress(node: HTMLElement, duration: number): ReturnType<Action>;
export declare const longpress: Action<number>;

@@ -1,38 +0,35 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.longpress = void 0;
/**
* Creates `longpress` event when mousedown above `duration` milliseconds.
*
* Usage:
*
*<button use:longpress={duration}
on:longpress="{() => pressed = true}"
on:mouseenter="{() => pressed = false}"
>press and hold</button>
*
* @example
* ```svelte
* <button use:longpress={duration} on:longpress={() => alert("longpress")}>
* press and hold
* </button>
*```
* Demo: https://svelte.dev/tutorial/adding-parameters-to-actions
*/
function longpress(node, duration) {
export var longpress = function (node, duration) {
var timer;
var handleMousedown = function () {
function handle_mouse_down() {
timer = window.setTimeout(function () {
node.dispatchEvent(new CustomEvent('longpress'));
}, duration);
};
var handleMouseup = function () {
}
function handle_mouse_up() {
clearTimeout(timer);
};
node.addEventListener('mousedown', handleMousedown);
node.addEventListener('mouseup', handleMouseup);
}
node.addEventListener('mousedown', handle_mouse_down);
node.addEventListener('mouseup', handle_mouse_up);
return {
update: function (newDuration) {
handle_mouse_up();
duration = newDuration;
},
destroy: function () {
node.removeEventListener('mousedown', handleMousedown);
node.removeEventListener('mouseup', handleMouseup);
}
handle_mouse_up();
node.removeEventListener('mousedown', handle_mouse_down);
node.removeEventListener('mouseup', handle_mouse_up);
},
};
}
exports.longpress = longpress;
};

@@ -7,3 +7,7 @@ import { Action } from './types';

*
* @example
* ```svelte
* <div use:pannable={true} on:panstart on:panmove on:panend>
* ```
*/
export declare function pannable(node: HTMLElement): ReturnType<Action>;
export declare const pannable: Action;

@@ -1,4 +0,1 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.pannable = void 0;
/**

@@ -9,16 +6,20 @@ * Creates panStart, panMove, panEnd events so you can drag elements.

*
* @example
* ```svelte
* <div use:pannable={true} on:panstart on:panmove on:panend>
* ```
*/
function pannable(node) {
export var pannable = function (node) {
var x;
var y;
function handleMousedown(event) {
function handle_mousedown(event) {
x = event.clientX;
y = event.clientY;
node.dispatchEvent(new CustomEvent('panstart', {
detail: { x: x, y: y }
detail: { x: x, y: y },
}));
window.addEventListener('mousemove', handleMousemove);
window.addEventListener('mouseup', handleMouseup);
window.addEventListener('mousemove', handle_mousemove);
window.addEventListener('mouseup', handle_mouseup);
}
function handleMousemove(event) {
function handle_mousemove(event) {
var dx = event.clientX - x;

@@ -29,21 +30,20 @@ var dy = event.clientY - y;

node.dispatchEvent(new CustomEvent('panmove', {
detail: { x: x, y: y, dx: dx, dy: dy }
detail: { x: x, y: y, dx: dx, dy: dy },
}));
}
function handleMouseup(event) {
function handle_mouseup(event) {
x = event.clientX;
y = event.clientY;
node.dispatchEvent(new CustomEvent('panend', {
detail: { x: x, y: y }
detail: { x: x, y: y },
}));
window.removeEventListener('mousemove', handleMousemove);
window.removeEventListener('mouseup', handleMouseup);
window.removeEventListener('mousemove', handle_mousemove);
window.removeEventListener('mouseup', handle_mouseup);
}
node.addEventListener('mousedown', handleMousedown);
node.addEventListener('mousedown', handle_mousedown);
return {
destroy: function () {
node.removeEventListener('mousedown', handleMousedown);
}
node.removeEventListener('mousedown', handle_mousedown);
},
};
}
exports.pannable = pannable;
};

@@ -6,3 +6,8 @@ import { Action } from './types';

* Demo: https://svelte.dev/repl/a95db12c1b46433baac2817a0963dc93
*
* @example
* ```svelte
* <div use:preventTabClose={true}>
* ```
*/
export declare const preventTabClose: Action;
export declare const preventTabClose: Action<boolean>;

@@ -1,4 +0,1 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.preventTabClose = void 0;
/**

@@ -8,18 +5,23 @@ * Prevent current tab from being closed by user

* Demo: https://svelte.dev/repl/a95db12c1b46433baac2817a0963dc93
*
* @example
* ```svelte
* <div use:preventTabClose={true}>
* ```
*/
var preventTabClose = function (_, enabled) {
var handler = function (e) {
export var preventTabClose = function (_, enabled) {
function handler(e) {
e.preventDefault();
e.returnValue = '';
}, setHandler = function (shouldWork) {
return shouldWork ?
window.addEventListener('beforeunload', handler) :
window.removeEventListener('beforeunload', handler);
};
setHandler(enabled);
}
function set_handler(shouldWork) {
(shouldWork ? window.addEventListener : window.removeEventListener)('beforeunload', handler);
}
set_handler(enabled);
return {
update: setHandler,
destroy: function () { return setHandler(false); },
update: set_handler,
destroy: function () {
set_handler(false);
},
};
};
exports.preventTabClose = preventTabClose;

@@ -1,15 +0,25 @@

import { Action } from './types';
import type { Action } from './types.js';
export declare type ShortcutConfig = {
/**
* The code of the key to listen for.
* {@link https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code}
*/
code: KeyboardEventInit['code'];
/**
* The callback to be called when the shortcut is triggered.
*/
callback?: (node: HTMLElement) => void;
control?: boolean;
shift?: boolean;
alt?: boolean;
};
/**
* Simplest possible way to add a keyboard shortcut to a div or a button.
* Simplest possible way to add a keyboard shortcut to an element.
* It either calls a callback or clicks on the node it was put on.
*
* Demo: https://svelte.dev/repl/acd92c9726634ec7b3d8f5f759824d15
* @example
* ```svelte
* <div use:shortcut={{ code: 'KeyA', callback: () => alert('A') }}>
* ```
*/
export declare type ShortcutSetting = {
control?: boolean;
shift?: boolean;
alt?: boolean;
code: string;
callback?: (node?: HTMLElement) => void;
};
export declare const shortcut: Action;
export declare const shortcut: Action<ShortcutConfig>;

@@ -1,27 +0,33 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.shortcut = void 0;
var shortcut = function (node, params) {
var handler;
var removeHandler = function () { return window.removeEventListener('keydown', handler); }, setHandler = function (params) {
removeHandler();
if (!params)
function default_callback(node) {
node.click();
}
/**
* Simplest possible way to add a keyboard shortcut to an element.
* It either calls a callback or clicks on the node it was put on.
*
* @example
* ```svelte
* <div use:shortcut={{ code: 'KeyA', callback: () => alert('A') }}>
* ```
*/
export var shortcut = function (node, config) {
function handler(event) {
var should_ignore = !(!!config.alt == event.altKey &&
!!config.shift == event.shiftKey &&
!!config.control == (event.ctrlKey || event.metaKey) &&
config.code == event.code);
if (should_ignore)
return;
handler = function (e) {
if ((!!params.alt != e.altKey) ||
(!!params.shift != e.shiftKey) ||
(!!params.control != (e.ctrlKey || e.metaKey)) ||
params.code != e.code)
return;
e.preventDefault();
params.callback ? params.callback(node) : node.click();
};
window.addEventListener('keydown', handler);
};
setHandler(params);
event.preventDefault();
(config.callback || default_callback)(node);
}
window.addEventListener('keydown', handler);
return {
update: setHandler,
destroy: removeHandler,
update: function (params) {
config = params;
},
destroy: function () {
window.removeEventListener('keydown', handler);
},
};
};
exports.shortcut = shortcut;

@@ -1,4 +0,7 @@

export declare type Action = (node: HTMLElement, parameters: any) => {
update?: (parameters: any) => void;
export interface ActionReturn<Parameter> {
update?: (parameter: Parameter) => void;
destroy?: () => void;
};
}
export interface Action<Parameter = void, Return = ActionReturn<Parameter>> {
<Node extends HTMLElement>(node: Node, parameter: Parameter): Return;
}

@@ -1,2 +0,1 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
export {};
{
"name": "svelte-actions",
"version": "0.2.1",
"module": "dist/esm/index.mjs",
"main": "dist/index.js",
"version": "0.2.2",
"type": "module",
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc && npm run build:esm && npm run rename:esm",
"build:esm": "tsc --module es2015 --target es5 --outdir dist/esm",
"rename:esm": "find ./dist/esm -name \"*.js\" -exec bash -c 'mv \"$1\" \"${1%.js}\".mjs' - '{}' \\;",
"copy:esm": "mv ./dist/esm/*.mjs ./dist/",
"build": "tsc",
"preversion": "npm run build",
"version": "auto-changelog -p --template keepachangelog && git add CHANGELOG.md",
"prepublishOnly": "git push && git push --tags && gh-release",
"test": "mocha ./src/test.ts"
"test": "mocha ./src/test.ts",
"format": "prettier --write src/**/*.ts",
"check": "tsc --noEmit"
},

@@ -44,2 +42,3 @@ "keywords": [

"mocha": "^9.2.0",
"prettier": "^2.5.1",
"sinon": "^9.2.3",

@@ -49,3 +48,6 @@ "sucrase": "^3.17.0",

"typescript": "^4.0.5"
},
"exports": {
"import": "./dist/index.js"
}
}

@@ -1,12 +0,11 @@

import { clickOutside } from './clickOutside';
import { Action } from './types';
import * as assert from 'assert';
import * as sinon from 'sinon';
import { clickOutside } from './clickOutside';
describe('clickOutside', function() {
describe('clickOutside', function () {
let element: HTMLElement;
let sibling: HTMLElement;
let action: ReturnType<Action>;
let action: ReturnType<typeof clickOutside>;
before(function() {
before(function () {
element = document.createElement('div');

@@ -18,3 +17,3 @@ sibling = document.createElement('div');

after(function() {
after(function () {
element.remove();

@@ -24,7 +23,7 @@ sibling.remove();

afterEach(function() {
afterEach(function () {
action.destroy!();
});
it('calls callback on outside click', function() {
it('calls callback on outside click', function () {
const cb = sinon.fake();

@@ -37,3 +36,3 @@ action = clickOutside(element, { enabled: true, cb });

it('does not call callback when disabled', function() {
it('does not call callback when disabled', function () {
const cb = sinon.fake();

@@ -46,3 +45,3 @@ action = clickOutside(element, { enabled: false, cb });

it('does not call callback when element clicked', function() {
it('does not call callback when element clicked', function () {
const cb = sinon.fake();

@@ -55,6 +54,7 @@ action = clickOutside(element, { enabled: true, cb });

it('updates parameters', function() {
it('updates parameters', function () {
const cb = sinon.fake();
action = clickOutside(element, { enabled: true, cb });
// @ts-expect-error
action.update!({ enabled: false });

@@ -61,0 +61,0 @@ element.click();

import { Action } from './types';
export interface ClickOutsideConfig {
enabled: boolean;
cb: (node: HTMLElement) => void;
}
/**
*
* Call callback when user clicks outside a given element
*
* Usage:
*
* @example
* ```svelte
* <div use:clickOutside={{ enabled: open, cb: () => open = false }}>
*
* ```
* Demo: https://svelte.dev/repl/dae848c2157e48ab932106779960f5d5?version=3.19.2
*
*/
export function clickOutside(node: HTMLElement, params: {enabled: boolean, cb: Function }): ReturnType<Action> {
const { enabled: initialEnabled, cb } = params
export const clickOutside: Action<ClickOutsideConfig> = (node, config) => {
function handler(e: MouseEvent) {
if (!node.contains(e.target as Node)) config.cb(node);
}
const handleOutsideClick = ({ target }: MouseEvent) => {
if (!node.contains(target as Node)) cb(node); // typescript hack, not sure how to solve without asserting as Node
};
function set_handler(enabled: boolean) {
(enabled ? window.addEventListener : window.removeEventListener)('click', handler);
}
set_handler(config.enabled);
function update({enabled}: {enabled: boolean}) {
if (enabled) {
window.addEventListener('click', handleOutsideClick);
} else {
window.removeEventListener('click', handleOutsideClick);
}
}
update({ enabled: initialEnabled });
return {
update,
destroy() {
window.removeEventListener( 'click', handleOutsideClick );
}
};
}
return {
update(params) {
set_handler((config = params).enabled);
},
destroy() {
set_handler(false);
},
};
};

@@ -1,9 +0,8 @@

import { lazyload } from './lazyload';
import { Action } from './types';
import * as assert from 'assert';
import * as sinon from 'sinon';
import { lazyload } from './lazyload';
describe('lazyload', function() {
describe('lazyload', function () {
let element: HTMLElement;
let action: ReturnType<Action>;
let action: ReturnType<typeof lazyload>;
let intersectionObserverConstructorSpy: sinon.SinonSpy;

@@ -13,6 +12,6 @@ const observeFake = sinon.fake();

before(function() {
before(function () {
setupIntersectionObserverMock({
observe: observeFake,
unobserve: unobserveFake
unobserve: unobserveFake,
});

@@ -22,3 +21,3 @@ intersectionObserverConstructorSpy = sinon.spy(global, 'IntersectionObserver');

beforeEach(function() {
beforeEach(function () {
element = document.createElement('div');

@@ -28,3 +27,3 @@ document.body.appendChild(element);

afterEach(function() {
afterEach(function () {
action.destroy!();

@@ -36,3 +35,3 @@ element.remove();

it('observes node', function() {
it('observes node', function () {
action = lazyload(element, {});

@@ -43,9 +42,11 @@ assert.ok(intersectionObserverConstructorSpy.calledOnce);

it('sets attribute on intersection', function() {
action = lazyload(element, { className: 'test'});
it('sets attribute on intersection', function () {
action = lazyload(element, { className: 'test' });
const intersectionCallback = intersectionObserverConstructorSpy.firstCall.firstArg;
intersectionCallback([{
isIntersecting: true,
target: element
}]);
intersectionCallback([
{
isIntersecting: true,
target: element,
},
]);

@@ -56,9 +57,11 @@ assert.ok(unobserveFake.calledOnce);

it('does not set attribute when no intersection', function() {
action = lazyload(element, { className: 'test'});
it('does not set attribute when no intersection', function () {
action = lazyload(element, { className: 'test' });
const intersectionCallback = intersectionObserverConstructorSpy.firstCall.firstArg;
intersectionCallback([{
isIntersecting: false,
target: element
}]);
intersectionCallback([
{
isIntersecting: false,
target: element,
},
]);

@@ -78,3 +81,3 @@ assert.ok(unobserveFake.notCalled);

takeRecords = () => [],
unobserve = () => null
unobserve = () => null,
} = {}): void {

@@ -94,3 +97,3 @@ class MockIntersectionObserver implements IntersectionObserver {

configurable: true,
value: MockIntersectionObserver
value: MockIntersectionObserver,
});

@@ -101,4 +104,4 @@

configurable: true,
value: MockIntersectionObserver
value: MockIntersectionObserver,
});
}
import { Action } from './types';
const node_attributes_map = new WeakMap<HTMLElement, object>();
const intersection_handler: IntersectionObserverCallback = (entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting && entry.target instanceof HTMLElement) {
const node = entry.target;
Object.assign(node, node_attributes_map.get(node));
lazy_load_observer.unobserve(node);
}
});
};
let lazy_load_observer: IntersectionObserver;
function observer() {
return (lazy_load_observer ??= new IntersectionObserver(intersection_handler));
}
/**
* Attach onto any image to lazy load it
*
* Set attributes on an element when it is visible in the viewport.
*@example
*```svelte
* <img use:lazyLoad={{src:"/myimage"}} alt="">
*
*```
* Demo: https://svelte.dev/repl/f12988de576b4bf9b541a2a59eb838f6?version=3.23.2
*
*
*/
const lazyLoadHandleIntersection: IntersectionObserverCallback = (entries) => {
entries.forEach(
entry => {
if (!entry.isIntersecting) {
return
}
if (!(entry.target instanceof HTMLElement)) {
return;
}
let node = entry.target;
let attributes = lazyLoadNodeAttributes.find(item => item.node === node)?.attributes
Object.assign(node, attributes)
lazyLoadObserver.unobserve(node)
}
)
}
let lazyLoadObserver: IntersectionObserver;
let lazyLoadNodeAttributes: Array<{node: HTMLElement, attributes: Object}> = []
export function lazyload(node: HTMLElement, attributes: Object): ReturnType<Action> {
if (!lazyLoadObserver) {
lazyLoadObserver = new IntersectionObserver(lazyLoadHandleIntersection);
}
lazyLoadNodeAttributes.push({node, attributes})
lazyLoadObserver.observe(node);
export const lazyload: Action<object> = (node, attributes) => {
node_attributes_map.set(node, attributes);
observer().observe(node);
return {
destroy() {
lazyLoadObserver.unobserve(node);
}
observer().unobserve(node);
},
};
}
};

@@ -1,13 +0,12 @@

import { longpress } from './longpress';
import { Action } from './types';
import * as assert from 'assert';
import * as sinon from 'sinon';
import { longpress } from './longpress';
describe('longpress', function() {
describe('longpress', function () {
let element: HTMLElement;
let cb = sinon.fake();
let action: ReturnType<Action>;
let action: ReturnType<typeof longpress>;
let clock: sinon.SinonFakeTimers;
before(function() {
before(function () {
element = document.createElement('div');

@@ -19,3 +18,3 @@ element.addEventListener('longpress', cb);

after(function() {
after(function () {
element.remove();

@@ -25,3 +24,3 @@ clock.restore();

afterEach(function() {
afterEach(function () {
action.destroy!();

@@ -31,3 +30,3 @@ cb.resetHistory();

it('dispatches longpress event when mousedown more than duration', function() {
it('dispatches longpress event when mousedown more than duration', function () {
const duration = 10;

@@ -41,3 +40,3 @@ action = longpress(element, duration);

it('does not dispatch longpress event when mousedown less than duration', function() {
it('does not dispatch longpress event when mousedown less than duration', function () {
action = longpress(element, 100);

@@ -50,3 +49,3 @@ element.dispatchEvent(new window.MouseEvent('mousedown'));

it('updates duration', function() {
it('updates duration', function () {
const newDuration = 10;

@@ -53,0 +52,0 @@ action = longpress(element, 500);

@@ -5,39 +5,38 @@ import { Action } from './types';

* Creates `longpress` event when mousedown above `duration` milliseconds.
*
* Usage:
*
*<button use:longpress={duration}
on:longpress="{() => pressed = true}"
on:mouseenter="{() => pressed = false}"
>press and hold</button>
*
* @example
* ```svelte
* <button use:longpress={duration} on:longpress={() => alert("longpress")}>
* press and hold
* </button>
*```
* Demo: https://svelte.dev/tutorial/adding-parameters-to-actions
*/
export function longpress(node: HTMLElement, duration: number): ReturnType<Action> {
let timer: number;
const handleMousedown = () => {
timer = window.setTimeout(() => {
node.dispatchEvent(
new CustomEvent('longpress')
);
}, duration);
};
const handleMouseup = () => {
clearTimeout(timer);
};
export const longpress: Action<number> = (node, duration) => {
let timer: number;
node.addEventListener('mousedown', handleMousedown);
node.addEventListener('mouseup', handleMouseup);
function handle_mouse_down() {
timer = window.setTimeout(() => {
node.dispatchEvent(new CustomEvent('longpress'));
}, duration);
}
return {
update(newDuration) {
duration = newDuration;
},
destroy() {
node.removeEventListener('mousedown', handleMousedown);
node.removeEventListener('mouseup', handleMouseup);
}
};
}
function handle_mouse_up() {
clearTimeout(timer);
}
node.addEventListener('mousedown', handle_mouse_down);
node.addEventListener('mouseup', handle_mouse_up);
return {
update(newDuration) {
handle_mouse_up();
duration = newDuration;
},
destroy() {
handle_mouse_up();
node.removeEventListener('mousedown', handle_mouse_down);
node.removeEventListener('mouseup', handle_mouse_up);
},
};
};

@@ -1,11 +0,10 @@

import { pannable } from './pannable';
import { Action } from './types';
import * as assert from 'assert';
import * as sinon from 'sinon';
import { pannable } from './pannable';
describe('pannable', function() {
describe('pannable', function () {
let element: HTMLElement;
let action: ReturnType<Action>;
let action: ReturnType<typeof pannable>;
before(function() {
before(function () {
element = document.createElement('div');

@@ -15,11 +14,11 @@ document.body.appendChild(element);

after(function() {
after(function () {
element.remove();
});
afterEach(function() {
afterEach(function () {
action.destroy!();
});
it('dispatches pan events', function() {
it('dispatches pan events', function () {
action = pannable(element);

@@ -33,3 +32,3 @@ const panstartCb = sinon.spy();

element.dispatchEvent(new window.MouseEvent('mousedown', { clientX: 20, clientY: 30}));
element.dispatchEvent(new window.MouseEvent('mousedown', { clientX: 20, clientY: 30 }));
const panstartDetail = panstartCb.firstCall.firstArg.detail;

@@ -36,0 +35,0 @@ assert.deepStrictEqual(panstartDetail, { x: 20, y: 30 });

@@ -5,23 +5,29 @@ import { Action } from './types';

* Creates panStart, panMove, panEnd events so you can drag elements.
*
*
* Demo: https://svelte.dev/tutorial/actions
*
*
* @example
* ```svelte
* <div use:pannable={true} on:panstart on:panmove on:panend>
* ```
*/
export function pannable(node: HTMLElement): ReturnType<Action> {
export const pannable: Action = (node) => {
let x: number;
let y: number;
function handleMousedown(event: MouseEvent) {
function handle_mousedown(event: MouseEvent) {
x = event.clientX;
y = event.clientY;
node.dispatchEvent(new CustomEvent('panstart', {
detail: { x, y }
}));
node.dispatchEvent(
new CustomEvent('panstart', {
detail: { x, y },
})
);
window.addEventListener('mousemove', handleMousemove);
window.addEventListener('mouseup', handleMouseup);
window.addEventListener('mousemove', handle_mousemove);
window.addEventListener('mouseup', handle_mouseup);
}
function handleMousemove(event: MouseEvent) {
function handle_mousemove(event: MouseEvent) {
const dx = event.clientX - x;

@@ -32,26 +38,30 @@ const dy = event.clientY - y;

node.dispatchEvent(new CustomEvent('panmove', {
detail: { x, y, dx, dy }
}));
node.dispatchEvent(
new CustomEvent('panmove', {
detail: { x, y, dx, dy },
})
);
}
function handleMouseup(event: MouseEvent) {
function handle_mouseup(event: MouseEvent) {
x = event.clientX;
y = event.clientY;
node.dispatchEvent(new CustomEvent('panend', {
detail: { x, y }
}));
node.dispatchEvent(
new CustomEvent('panend', {
detail: { x, y },
})
);
window.removeEventListener('mousemove', handleMousemove);
window.removeEventListener('mouseup', handleMouseup);
window.removeEventListener('mousemove', handle_mousemove);
window.removeEventListener('mouseup', handle_mouseup);
}
node.addEventListener('mousedown', handleMousedown);
node.addEventListener('mousedown', handle_mousedown);
return {
destroy() {
node.removeEventListener('mousedown', handleMousedown);
}
node.removeEventListener('mousedown', handle_mousedown);
},
};
}
};
import { preventTabClose } from './preventTabClose';
import { Action } from './types';
import * as assert from 'assert';
import * as sinon from 'sinon';
describe('preventTabClose', function() {
describe('preventTabClose', function () {
let element: HTMLElement;
let action: ReturnType<Action>;
let action: ReturnType<typeof preventTabClose>;
before(function() {
before(function () {
element = document.createElement('div');

@@ -15,11 +14,11 @@ document.body.appendChild(element);

after(function() {
after(function () {
element.remove();
});
afterEach(function() {
afterEach(function () {
action.destroy!();
});
it('cancels beforeunload event when enabled', function() {
it('cancels beforeunload event when enabled', function () {
action = preventTabClose(element, true);

@@ -35,3 +34,3 @@ const event = new window.Event('beforeunload');

it('does not cancel beforeunload event when disabled', function() {
it('does not cancel beforeunload event when disabled', function () {
action = preventTabClose(element, false);

@@ -45,3 +44,3 @@ const event = new window.Event('beforeunload');

it('updates enabled parameter', function() {
it('updates enabled parameter', function () {
action = preventTabClose(element, false);

@@ -48,0 +47,0 @@ const event = new window.Event('beforeunload');

@@ -5,21 +5,28 @@ import { Action } from './types';

* Prevent current tab from being closed by user
*
*
* Demo: https://svelte.dev/repl/a95db12c1b46433baac2817a0963dc93
*
* @example
* ```svelte
* <div use:preventTabClose={true}>
* ```
*/
export const preventTabClose: Action = (_, enabled: boolean) => {
const handler = (e: BeforeUnloadEvent) => {
e.preventDefault();
e.returnValue = '';
},
setHandler = (shouldWork: boolean) =>
shouldWork ?
window.addEventListener('beforeunload', handler) :
window.removeEventListener('beforeunload', handler);
export const preventTabClose: Action<boolean> = (_, enabled: boolean) => {
function handler(e: BeforeUnloadEvent) {
e.preventDefault();
e.returnValue = '';
}
setHandler(enabled);
function set_handler(shouldWork: boolean) {
(shouldWork ? window.addEventListener : window.removeEventListener)('beforeunload', handler);
}
return {
update: setHandler,
destroy: () => setHandler(false),
};
set_handler(enabled);
return {
update: set_handler,
destroy() {
set_handler(false);
},
};
};

@@ -1,13 +0,12 @@

import { shortcut } from './shortcut';
import { Action } from './types';
import * as assert from 'assert';
import * as sinon from 'sinon';
import { shortcut } from './shortcut';
describe('shortcut', function() {
describe('shortcut', function () {
let element: HTMLElement;
let action: ReturnType<Action>;
let action: ReturnType<typeof shortcut>;
const spaceKeyCode = 'Space';
before(function() {
before(function () {
element = document.createElement('div');

@@ -17,11 +16,11 @@ document.body.appendChild(element);

after(function() {
after(function () {
element.remove();
});
afterEach(function() {
afterEach(function () {
action.destroy!();
});
it('calls callback when callback provided', function() {
it('calls callback when callback provided', function () {
const callback = sinon.fake();

@@ -34,3 +33,3 @@ action = shortcut(element, { code: spaceKeyCode, callback });

it('clicks node when callback not provided', function() {
it('clicks node when callback not provided', function () {
const callback = sinon.fake();

@@ -45,3 +44,3 @@ action = shortcut(element, { code: spaceKeyCode });

it('does not call callback when different key pressed', function() {
it('does not call callback when different key pressed', function () {
const callback = sinon.fake();

@@ -54,3 +53,3 @@ action = shortcut(element, { code: spaceKeyCode, callback });

it('handles alt key', function() {
it('handles alt key', function () {
const callback = sinon.fake();

@@ -63,3 +62,3 @@ action = shortcut(element, { code: spaceKeyCode, callback, alt: true });

it('handles shift key', function() {
it('handles shift key', function () {
const callback = sinon.fake();

@@ -72,3 +71,3 @@ action = shortcut(element, { code: spaceKeyCode, callback, shift: true });

it('handles ctrl and meta key', function() {
it('handles ctrl and meta key', function () {
const callback = sinon.fake();

@@ -82,3 +81,3 @@ action = shortcut(element, { code: spaceKeyCode, callback, control: true });

it('updates key code', function() {
it('updates key code', function () {
const callback = sinon.fake();

@@ -91,3 +90,3 @@ action = shortcut(element, { code: spaceKeyCode, callback });

assert.ok(callback.calledOnce);
});
});
});

@@ -94,0 +93,0 @@

@@ -1,49 +0,58 @@

import { Action } from './types';
import type { Action } from './types.js';
/**
* Simplest possible way to add a keyboard shortcut to a div or a button.
* It either calls a callback or clicks on the node it was put on.
*
* Demo: https://svelte.dev/repl/acd92c9726634ec7b3d8f5f759824d15
*/
export type ShortcutConfig = {
/**
* The code of the key to listen for.
* {@link https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code}
*/
code: KeyboardEventInit['code'];
export type ShortcutSetting = {
control?: boolean;
shift?: boolean;
alt?: boolean;
/**
* The callback to be called when the shortcut is triggered.
*/
callback?: (node: HTMLElement) => void;
code: string;
callback?: (node?: HTMLElement) => void;
control?: boolean;
shift?: boolean;
alt?: boolean;
};
export const shortcut: Action = (node, params: ShortcutSetting | undefined) => {
let handler: ((e: KeyboardEvent) => void) | undefined;
const removeHandler = () => window.removeEventListener('keydown', handler!),
setHandler = (params: ShortcutSetting | undefined) => {
removeHandler();
if (!params) return;
function default_callback(node: HTMLElement) {
node.click();
}
/**
* Simplest possible way to add a keyboard shortcut to an element.
* It either calls a callback or clicks on the node it was put on.
*
* @example
* ```svelte
* <div use:shortcut={{ code: 'KeyA', callback: () => alert('A') }}>
* ```
*/
export const shortcut: Action<ShortcutConfig> = (node, config) => {
function handler(event: KeyboardEvent) {
const should_ignore = !(
!!config.alt == event.altKey &&
!!config.shift == event.shiftKey &&
!!config.control == (event.ctrlKey || event.metaKey) &&
config.code == event.code
);
handler = (e: KeyboardEvent) => {
if (
(!!params.alt != e.altKey) ||
(!!params.shift != e.shiftKey) ||
(!!params.control != (e.ctrlKey || e.metaKey)) ||
params.code != e.code
)
return;
if (should_ignore) return;
e.preventDefault();
event.preventDefault();
params.callback ? params.callback(node) : node.click();
};
window.addEventListener('keydown', handler);
};
(config.callback || default_callback)(node);
}
setHandler(params);
window.addEventListener('keydown', handler);
return {
update: setHandler,
destroy: removeHandler,
};
return {
update(params) {
config = params;
},
destroy() {
window.removeEventListener('keydown', handler);
},
};
};

@@ -1,4 +0,8 @@

export type Action = (node: HTMLElement, parameters: any) => {
update?: (parameters: any) => void,
destroy?: () => void
export interface ActionReturn<Parameter> {
update?: (parameter: Parameter) => void;
destroy?: () => void;
}
export interface Action<Parameter = void, Return = ActionReturn<Parameter>> {
<Node extends HTMLElement>(node: Node, parameter: Parameter): Return;
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc