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

svelte-writable-with

v0.4.2

Published

[![CI](https://github.com/SaintPepsi/svelte-writable-with/actions/workflows/ci.yml/badge.svg)](https://github.com/SaintPepsi/svelte-writable-with/actions/workflows/ci.yml) # svelte-writable-with

Downloads

1,426

Readme

CI

svelte-writable-with

A Svelte store utility library that allows you to extend the writable.

Working with Svelte's get to retrieve writable values can feel cumbersome, especially with the import clutter from many libraries. withState, inspired by TanStack Store, allows you to access values directly via store.state.

This utility library will evolve to include other useful features.

Why writableWith?

Old way (verbose):

const store = writable('foo');
const value = get(store);
const desiredValue = someRecord[value];

New way (cleaner):

const store = state(writable('foo'));
const desiredValue = someRecord[store.state];

Installation

bun add svelte-writable-with

Features

Composition

writableWith is flexible. You can pass a direct value, a writable, or another writableWith. This keeps writables predictable and avoids introducing unwanted side effects.

Example:

import { state, previous } from 'svelte-writable-with';

type Modes = "paint" | "pan" | "erase";

const baseMode = writable('paint')
const { set, update, subscribe } = baseMode;

const modeWithState = state(baseMode);
const { set, update, subscribe, state } = baseMode;

const modeWithPreviousAndState = previous(modeWithState)
const { set, update, subscribe, state, previous } = baseMode;

Ensure you provide the primary type in the first "withable" to avoid type issues. (Working on improving this 🤓)

✅ Correct types:

state(previous(writable<Record<"foo" | "bar", boolean>>({})))

❌ Invalid types: previous will complain

state<Record<"foo" | "bar", boolean>>(previous(writable({})))

API

Each method can take either a value or a writable.

withState

usage: writableWith.state | withState

Allows access to the store's state directly, without using Svelte's get

this utility returns:

  • [+] property state - Accesses the store state directly, replacing get(store).

Usage:

const {
    state,      // The current state of the writable.
    // ... writable return values
} = withState(writable(1337));

Example:

Property access:

const currentBenefit = withState(writable<"spinach" | "broccoli">("spinach"));

const vegetableBenefits = {
    spinach: "Iron, vitamins, energy",
    broccoli: "Fiber, heart health",
};

function getBenefit() {
    return vegetableBenefits[currentBenefit.state];
}

withPrevious

usage: writableWith.previous | withPrevious

keeps track of the last value.

this utility returns:

  • [+] property previous - Returns the previous value before the store was updated.

  • [%] method subscribe - previous value as second argument (value, previousValue)

  • [%] method set - sets the previous value before setting store state

  • [%] method update - sets the previous value before updating store state

Usage:

const {
    subscribe,      // Modified subscribe with 2 arguments (`value`, `previousValue`)
    set,            // Modified set updates `previous` value
    update,         // Modified update updates `previous` value
    previous,       // The previous value
} = withPrevious(writable(1337));

Example:

setting the writable back to the last value

type States = "paint" | "pan" | "erase"; 
const mode = withPrevious(writable<States>("paint"));

// Some condition to change mode
mode.set("pan");

// Some condition to return
mode.set(mode.previous);

withLocalStorage

usage: writableWith.localStorage | withLocalStorage

Stores the value in localStorage under a specific key prefixed with svelte-writable-with:

If the initialValue is a writable or writableWith, it initializes the store with the value from localStorage (if present).

this utility returns:

  • [+] initialises with the localStorage value for that key or the initialValue

  • [%] method set - sets the value in localStorage - JSON.stringify -> set

  • [%] method update - runs the updater with the value currently in the store and stores the value in localStorage - JSON.stringify -> set

Note: withLocalStorage is still being refined. Here are a few limitations:

⚠️ currently keys are not strongly typed and are just strings.

Keys and values are managed through the WithLocalStorageKeys interface

in your app.d.ts or global.d.ts add the following:

declare module 'svelte-writable-with' {
	interface WithLocalStorageKeys {
		SOME_KEY: number;
	}
}

Features:

  • Typed Keys and values - extendable interface
  • Automatic JSON.parse-ing and JSON.stringify-ing ✅
  • Storage Events
  • Schema Safe Parser ❌ (any?, zod?)

Usage:

const {
    set,            // Modified set updates `localStorage`
    update,         // Modified update updates `localStorage`
    // ... writable return values
} = withLocalStorage('SOME_KEY', writable(1337));

Example:

setting the writable back to the last value

type States = "paint" | "pan" | "erase"; 
const mode = withPrevious(writable<States>("paint"));

// Change the mode
mode.set("pan");

// Revert to the previous mode
mode.set(mode.previous);

withHistory

usage: writableWith.history | withHistory

keeps track of an indefinite history of values.

this utility returns:

  • [+] property history - Returns the history writable (with state).

  • [+] method pop - removes last value from the history object (if it exists), sets the state with the popped value and then returns the popped value

  • [%] method subscribe - history value as second argument (value, history)

  • [%] method set - pushes the value to history before setting store state

  • [%] method update - pushes the value to history before updating store state

Usage:

const {
    subscribe,      // Modified subscribe with 2 arguments (`value`, `history`)
    set,            // Modified set updates `history` value
    update,         // Modified update updates `history` value
    history,		// The history writable
	pop, 			// removes last value from history and returns it (updates main store with returned value)
} = withHistory(writable(1337));

Example:

setting the writable back to the last value

type States = "paint" | "pan" | "erase"; 
const mode = withHistory(writable<States>("paint"));

// Some condition to change mode
mode.set("pan");
// history = ['paint']
mode.set("paint");
// history = ['paint', 'pan']
mode.set("erase");
// history = ['paint', 'pan', 'paint']

// Some code...

const paintValue1 = mode.pop();
// paintValue1 === 'paint'
// history === ['paint', 'pan']
const panValue = mode.pop();
// panValue === 'pan'
// history === ['paint']
const paintValue2 = mode.pop();
// paintValue2 === 'paint'
// history === []

const originalMode = get(mode) // "paint"

Common Issues:

  • Using any writable where a $state rune is expected, i.e. "Type 'WithState<string, Writable<boolean>>' is not assignable to type 'boolean | null | undefined'."

    use fromStore -> import { fromStore } from 'svelte/store'; to create a reactive $state rune .e.g:

    <script lang="ts">
    export let isDebuggerEnabled = withLocalStorage(writable(false), 'DebuggerEnabled');
    export let isChecked = fromStore(isDebuggerEnabled);
    </script>
    <input type="checkbox" id="debugger" name="debugger" bind:checked={isChecked.current} />
    <label for="debugger">Debugger</label>

Goal:

The goal of svelte-writable-with is to offer an intuitive API for extending and enhancing writable stores based on your specific needs.

Possible future extensions include

  • history

License

MIT