Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/baseballyama/svelte-preprocess-delegate-events

You can delegate events by on:* 🎉
https://github.com/baseballyama/svelte-preprocess-delegate-events

preprocessor svelte sveltejs

Last synced: 27 days ago
JSON representation

You can delegate events by on:* 🎉

Awesome Lists containing this project

README

        

[![NPM license](https://img.shields.io/npm/l/svelte-preprocess-delegate-events.svg)](https://www.npmjs.com/package/svelte-preprocess-delegate-events)
[![NPM version](https://img.shields.io/npm/v/svelte-preprocess-delegate-events.svg)](https://www.npmjs.com/package/svelte-preprocess-delegate-events)
[![Code Style: Prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier)
[![Build Status](https://github.com/baseballyama/svelte-preprocess-delegate-events/workflows/CI/badge.svg?branch=main)](https://github.com/baseballyama/svelte-preprocess-delegate-events/actions?query=workflow:ci)
[![Coverage Status](https://coveralls.io/repos/github/baseballyama/svelte-preprocess-delegate-events/badge.svg?branch=main)](https://coveralls.io/github/baseballyama/svelte-preprocess-delegate-events?branch=main)

# Delegate events with `on:*` 🎉

- 💡 Easy to use
- ⚡️ No performance impact
- 🔑 No type errors with [svelte-check](https://github.com/sveltejs/language-tools/tree/master/packages/svelte-check)

## Try it on [Stackblitz](https://stackblitz.com/edit/sveltejs-kit-template-default-rwmhls?file=src%2Froutes%2F%2Bpage.svelte&terminal=dev) 🚀.

# Overview

Since 2019, one popular issue on the Svelte GitHub repository has been delegating all events.

https://github.com/sveltejs/svelte/issues/2837

This repository aims to solve this issue.

# Example

**Component.svelte**

```svelte

```

**App.svelte**

```svelte

import Component from './Component.svelte';

```

# Prerequisites

This library needs Svelte 3 or Svelte 4.

# Installation

```shell
npm install -D svelte-preprocess-delegate-events
```

# Usage

After installation, add this as a Svelte preprocessor.

```js
// svelte.config.js
import delegateEvents from "svelte-preprocess-delegate-events/preprocess";

const config = {
// Add this preprocessor at the end of the array.
preprocess: [delegateEvents()],
};

export default config;
```

# Integration with svelte-check

If you want to use `svelte-check`, create `svelte-jsx.d.ts` at the project root and update `[tj]sconfig.json`.

**svelte-jsx.d.ts**
```ts
declare namespace svelteHTML {
/**
* base: https://github.com/sveltejs/language-tools/blob/651db67858d18ace44d000d263ac57ed5590ea05/packages/svelte2tsx/svelte-jsx.d.ts#L42
*/
type HTMLProps =
Omit<
Omit>> & EventsWithColon>,
keyof Override
> & Override & (Record<'on:*', (event: Event & { currentTarget: EventTarget & EventTarget }) => any | never> | object);
}
```

**[tj]sconfig.json**
```diff
{
+ "include": ["./svelte-jsx.d.ts"]
}
```

# How the Preprocessor Works?

This chapter explains how the preprocessor functions. The preprocessor operates differently for Elements and Components.

## Element

Consider the following simple example:

```svelte

import Child from './Child.svelte';

console.log('clicked!')} />

Click Me
```

Svelte executes events registered in `component.$$.callbacks` when an event is triggered in a child component. In the example above, `component.$$.callbacks` is as follows:
```js
component.$$.callbacks = {
click: () => console.log('clicked!')
}
```

This preprocessor adds a process to listen for events registered in `component.$$.callbacks` for elements with `on:*`. After preprocessing, Child.svelte looks like this:
```svelte

import { boundElements, registerDelegatedEvents } from 'svelte-preprocess-delegate-events/runtime';
import { get_current_component } from 'svelte/internal';
let button = boundElements();
const component = get_current_component();
$: registerDelegatedEvents(button.bounds, component, (handler) => handler, {});

Click Me
```
NOTE: The reason for binding `` to `button.bounds` instead of binding it to the `button` variable is to support cases where multiple elements exist, such as `` in a `{#each}` block.

In this way, only events that are being listened to by the parent component are listened to, thus providing a mechanism with no performance overhead.

## Component

Component uses a different mechanism than Element. Consider the following simple example:
```svelte

import Child from './Child.svelte';

console.log('clicked!')} />

import GrandChild from './GrandChild.svelte';

Click Me
```

If you are using `on:*` in `Child.svelte`, you need to forward all events from `GrandChild` to `Parent`. However, `Child` does not know what events are coming from `GrandChild`, so you need to do something. Specifically, when `GrandChild` triggers an event, it will refer to `component.$$.callbacks` to run its event handlers. By proxying `component.$$.callbacks`, you will know which events have been forwarded. Forwarded events can be communicated to the parent component so that the `Parent` component can handle the event.

After preprocessing, it looks like this:
```svelte

import { boundComponents, proxyCallbacks } from 'svelte-preprocess-delegate-events/runtime';
import { get_current_component } from 'svelte/internal';
import GrandChild from './GrandChild.svelte';

const GrandChild = boundComponents();
const component = get_current_component();
$: proxyCallbacks(component, GrandChild.bounds, false);

```

# Note

`on:*` does not support specifying event handlers directly because a useful use case could not be found. If you have a useful use case, please create a new issue.

```svelte

import Component from './Component.svelte';
const handleEvent = (e) => {
console.log(e);
}

```

# For Svelte 5 Users

For Svelte 5, event forwarding is natively supported.🎉

https://svelte-5-preview.vercel.app/docs/event-handlers#bubbling-events