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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sanity-labs/workflow-engine-explore-react

v0.3.1

Published

Sanity App SDK adapter hooks for [`@sanity-labs/workflow-engine-explore`](https://www.npmjs.com/package/@sanity-labs/workflow-engine-explore). Wires `useClient` + `useCurrentUser` from `@sanity/sdk-react` into the engine's call signatures so consumers don

Readme

@sanity-labs/workflow-engine-explore-react

Sanity App SDK adapter hooks for @sanity-labs/workflow-engine-explore. Wires useClient + useCurrentUser from @sanity/sdk-react into the engine's call signatures so consumers don't have to reinvent the same boilerplate per component.

Status: 0.x POC. Minimal first cut — hooks land here as the demo apps need them. The point is to find the right shape, not to ship every variant up front.

npm install @sanity-labs/workflow-engine-explore-react

Peer deps (consumers install themselves):

  • @sanity/sdk-react ^2.11.0
  • react ^18 || ^19

Required: a SanityApp context up the tree (so useClient and useCurrentUser resolve).


Hooks

useFireAction({ tags, onSuccess?, onError? }){ fire, pending, error }

Wrapper around workflow.fireAction. Pulls client + current user from the SDK, manages a pending/error state, calls fire({ instanceId, taskId, action }) to execute.

import { useFireAction } from "@sanity-labs/workflow-engine-explore-react";

function ApproveButton({ instanceId, taskId }: { instanceId: string; taskId: string }) {
  const { fire, pending, error } = useFireAction({
    tags: ["acme-prod"],
    onSuccess: () => toast.success("Approved"),
    onError: (e) => toast.error(e.message),
  });

  return (
    <>
      <button
        disabled={pending}
        onClick={() => fire({ instanceId, taskId, action: "approve" })}
      >
        {pending ? "Approving…" : "Approve"}
      </button>
      {error && <pre className="error">{error.message}</pre>}
    </>
  );
}

The hook uses user?.id ?? "viewer" for the actor — for real apps the SDK supplies a resolved user; the fallback is a placeholder for unauthenticated contexts.

useStartInstance({ tags, onSuccess?, onError? }){ start, pending, error }

Wrapper around workflow.startInstance. Same pattern as useFireAction.

const { start, pending } = useStartInstance({ tags: ["acme-prod"] });

await start({
  workflowId: "article-review",
  subject: { kind: "document", ref: articleId },
  effectsContext: { editor: currentUser.id },
});

useWorkflowInstance(instanceId | null) → live query result

Live read of a single workflow instance. Backed by useQuery from @sanity/sdk-react, so it re-renders on changes.

const { data: instance, isPending } = useWorkflowInstance(instanceId);
if (isPending) return <Spinner />;
if (!instance) return <NotFound />;
return <div>Currently in stage: {instance.currentStageId}</div>;

useWorkflowInstanceForSubject(subjectRef | null) → live query result

Live read of the latest non-completed workflow instance whose subject.ref matches the given doc id. Useful for "is this document under a workflow?" panels.

const { data: instance } = useWorkflowInstanceForSubject(documentId);
return instance
  ? <WorkflowPanel instance={instance} />
  : <StartWorkflowButton documentId={documentId} />;

useWorkflowTaskInbox(){ rows, …queryResult }

Live read of every active task across non-completed instances, flattened to one row per task. Drop-in source for an inbox view; filter by actor at the call site.

const { rows } = useWorkflowTaskInbox();
const mine = rows.filter((r) => isAssignedToMe(r));
return (
  <ul>
    {mine.map((r) => (
      <li key={`${r.instanceId}-${r.taskId}`}>
        {r.workflowId} → {r.currentStageId} → {r.taskId}
      </li>
    ))}
  </ul>
);

Each row is { instanceId, workflowId, currentStageId, subjectRef?, taskId, status, waitUntil? }.


Tag scoping

Every write hook requires a tags: string[] field in its options — same constraint as the underlying engine. See the main engine README for the rules.

The read hooks (useWorkflowInstance, useWorkflowInstanceForSubject, useWorkflowTaskInbox) currently use plain GROQ queries — they're not tag-filtered. If multiple consumers share a workflow resource, filter on the read side too or the inbox will show other tenants' tasks. Future work: tag-aware read hooks.


License

UNLICENSED — internal Sanity labs exploration.