npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

optimistikit

v1.0.2

Published

Optimistic UI is not easy...but it can be easier then ever in SvelteKit with Optimistikit!

Downloads

19

Readme

optimistikit

Optimistic UI is not easy...but it can be easier then ever in SvelteKit with Optimistikit!

Warning

This package is meant to be used with Svelte-Kit as the name suggest. Because it uses api that are only present in Svelte-Kit it will not work in your normal svelte project.

MIT License

npm

npm

GitHub last commit

Contributing

Contributions are always welcome!

For the moment there's no code of conduct neither a contributing guideline but if you found a problem or have an idea feel free to open an issue

If you want the fastest way to open a PR try out Codeflow

Open in Codeflow

Authors

Installation

Install optimistikit with npm

  npm install optimistikit@latest

Usage/Examples

The concept behind optimistikit is quite straightforward. Instead of using the data props from SvelteKit you can call the function optimistikit and get back a function to call whenever data changes and an action to apply to all of your forms.

Basic example

Imagine you have this +page.server.ts

export async function load() {
	const comments = await db.select(comments);
	return {
		comments,
	};
}

export const actions = {
	async add({ request }) {
		const formData = await request.formData();
		const new_comment = formData.get('comment');
		if (new_comment) {
			await db.insert(comments).values({
				content: new_comment,
			});
		}
	},
};

and this +page.svelte

<script lang="ts">
	const { data } = $props();
</script>

<form method="post" action="?/add">
	<input name="comment" />
	<button>Add comment</button>
</form>
<ul>
	{#each data.comments as comment}
		<li>{comment.content}</li>
	{/each}
</ul>

if you want to optimistically add the comment using optimistikit you would need the following updated to +page.svelte

<script lang="ts">
	import { optimistikit } from 'optimistikit';
	const { data } = $props();
	const { enhance, data: optimistic_data } = optimistikit(() => data);
</script>

<form
	use:enhance={(data, { formData }) => {
		const new_comment = formData.get('comment');
		if (new_comment) {
			// just mutate `data`
			data.comments.push({
				content: new_comment,
			});
		}
	}}
	method="post"
	action="?/add"
>
	<input name="comment" />
	<button>Add comment</button>
</form>
<ul>
	<!-- use `optimistic_data` instead of `data` -->
	{#each optimistic_data.comments as comment}
		<li>{comment.content}</li>
	{/each}
</ul>

Keyed forms

Sometimes the resource that you are updating on the server is always the same resource (eg. updating a comment). When that's the case we want to cancel every concurrent request. You can do this by adding an unique data-key attribute to the form.

export async function load() {
	const comments = await db.select(comments);
	return {
		comments,
	};
}

export const actions = {
	// other actions
	async edit({ request }) {
		const formData = await request.formData();
		const new_comment = formData.get('comment');
		const id = formData.get('id');
		if (new_comment && id) {
			await db
				.update(comments)
				.values({
					content: new_comment,
				})
				.where({
					id,
				});
		}
	},
};

and this is the +page.svelte

<script lang="ts">
	import { optimistikit } from 'optimistikit';
	const { data } = $props();

	const { enhance, data: optimistic_data } = optimistikit(() => data);
</script>

<!-- rest of the page -->
<ul>
	<!-- use `optimistic_data` instead of `data` -->
	{#each optimistic_data.comments as comment}
		<li>
			<form
				method="post"
				action="?/edit"
				data-key="edit-comment-{comment.id}"
				use:enhance={(data, { formData }) => {
					const new_comment = formData.get('comment');
					const id = formData.get('id');
					if (new_comment && id) {
						const comment = data.comments.find((comment) => comment.id === id);
						// just mutate `data`
						comment.content = new_comment;
					}
				}}
			>
				<input name="id" type="hidden" value={comment.id} />
				<input name="comment" value={comment.content} />
				<button>Edit</button>
			</form>
		</li>
	{/each}
</ul>

Use in nested components

If you have a form in a nested component it can be tedious to pass either data or the enhance action around. To solver this problem there's another export from optimistikit that allows you to grab the action directly

<script lang="ts">
	import { get_action } from 'optimistikit';
	import type { PageData } from './$types';

	const enhance = get_action<PageData>();
</script>

<form
	use:enhance={(data) => {
		// your logic
	}}
>
	<!-- your form -->
</form>

Options

The function optimistikit can optionally receive an object as argument where you can specify two values:

  • key: a string that allows you to have different actions/stores in the same route. Most of the times you will probably not need this since specifying a key also means that the updates from the forms will involve only the state returned from that specific optimistikit function.
  • enhance: some libraries like superforms provide a custom enhance function that is different from the one provided by SvelteKit. To allow you to use this libraries together with optimistikit you can pass a custom enhance function. It's important for this function to have the same signature as the sveltekit one.

What about svelte 4?

If you are using svelte@4 you really should upgrade to svelte@5...but if you can't you can use the legacy tag of this library that uses a store and has a slightly different and less ergonomic API.

You can install it like this:

npm i optimistikit@legacy

Check the documentation here!