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

react-json-logic

v3.0.0

Published

Build and evaluate JsonLogic rules with React components.

Readme

react-json-logic

Build and evaluate JsonLogic rules with React components.

Headless. No CSS shipped — bring your own. Built on Base UI primitives. Style with Tailwind, CSS modules, vanilla CSS, or whatever you like.

Install

pnpm add react-json-logic react react-dom

Usage

import { useState } from "react";
import JsonLogicBuilder, { applyLogic, type JsonLogicValue } from "react-json-logic";

function Example() {
  const [rule, setRule] = useState<JsonLogicValue>("");
  const data = { user: { age: 21 } };

  return (
    <>
      <JsonLogicBuilder value={rule} data={data} onChange={setRule} />
      <p>Result: {String(applyLogic(rule, data))}</p>
    </>
  );
}

Props

| Prop | Type | Default | Description | | ------------- | ------------------------------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------- | | onChange | (value: JsonLogicValue) => void | — | Called with the updated rule whenever the builder changes. | | value | JsonLogicValue | "" | Current rule (controlled). | | data | JsonLogicData \| string | {} | Sample data — used by accessor (var) field suggestions. Pass an object/array directly or a JSON string (parsed for you). | | onDataError | (err: unknown, raw: string) => void | console.warn | Called when data is a string and JSON.parse fails. De-duplicated by raw value, fires once per malformed input. |

JsonLogicValue is the recursive any-shape type for rules and primitive values. JsonLogicData = Record<string, unknown> | unknown[] is the narrower shape the data prop accepts (objects or arrays — primitives make no sense as accessor data).

Named exports: applyLogic, rule, validate, OPERATORS, FIELD_TYPES, types FieldType, Operator, JsonLogicValue, JsonLogicData, ValidationError, ValidationResult.

Building rules in code

rule is a typed factory you can use to construct JsonLogic rules without writing the JSON shape by hand:

import { applyLogic, rule, validate } from "react-json-logic";

const r = rule.and(rule.eq(rule.var("user.age"), 21), rule.gt(rule.var("score"), 100));

applyLogic(r, { user: { age: 21 }, score: 150 }); // → true
validate(r); // → { ok: true }

Each factory returns a JsonLogicValue shaped per the canonical JsonLogic spec — the <JsonLogicBuilder /> UI, applyLogic, and validate all consume the same shape. Arity is enforced at the function signature level (no runtime schema overhead).

| Group | Factories | | ------------ | -------------------------------------------------------------------- | | Equality | eq, looseEq, notEq, looseNotEq | | Logical | and, or, not, if(...args) | | Comparison | lt, lte, gt, gte | | Arithmetic | add, sub, mul, div, mod, min, max | | Accessor | var(path, fallback?), missing(...keys), missingSome(min, keys) | | String/Array | in(needle, haystack), cat(...args), merge(...args) | | Higher-order | some, all, none, map, filter |

validate(rule) walks a rule against the operator table and reports structural problems (multi-key operator objects, arity violations, etc.) as { ok: false, errors: [{ path, message }] }. Custom operators (registered via json-logic-js's add_operation) are tolerated — only known operators get arity-checked.

Styling

Components render unstyled. Target the rendered DOM via stable data-rjl-* attributes:

| Attribute | What it marks | | ------------------------------- | -------------------------------------------------- | | data-rjl-builder | Outermost wrapper | | data-rjl-any | Recursive operator container | | data-rjl-children | Wrapper around an operator's child fields | | data-rjl-field | A single child field row | | data-rjl-add | "Add field" button | | data-rjl-remove | "Remove field" button | | data-rjl-operator-trigger | Operator dropdown trigger | | data-rjl-operator-popup | Operator dropdown popup (portaled) | | data-rjl-input | Value-input wrapper | | data-rjl-input-type-trigger | Type select trigger (text / number) | | data-rjl-input-type-popup | Type select popup (portaled) | | data-rjl-input-value | The actual <input> element | | data-rjl-accessor | Accessor (var) wrapper | | data-rjl-accessor-level | One level of an accessor path | | data-rjl-accessor-level-index | The level's index ("0", "1", …) | | data-rjl-accessor-input | Accessor input element | | data-rjl-accessor-popup | Accessor suggestion popup (portaled) | | data-rjl-higher-order | some / all / none / map / filter wrapper | | data-rjl-higher-order-arrow | The => glyph | | data-rjl-higher-order-child | The inner expression of a higher-order op |

Example with Tailwind:

[data-rjl-operator-trigger] {
  @apply inline-flex h-8 items-center rounded border px-2;
}
[data-rjl-operator-popup] {
  @apply rounded border bg-white shadow;
}
[data-rjl-add],
[data-rjl-remove] {
  @apply h-6 w-6 rounded border bg-white text-sm;
}

Development

This repo runs on Vite+. All workflows go through vp:

vp install        # install deps
vp check          # format + lint + typecheck
vp test           # run tests
vp test --coverage  # with coverage report
vp pack           # build the library
pnpm verify       # the full gate (check + test --coverage + pack)

See AGENTS.md for project layout and contributor notes.

License

MIT