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

@middag-io/react

v0.18.0

Published

MIDDAG shared React UI library for Moodle, WordPress and other Inertia hosts

Downloads

4,693

Readme

@middag-io/react

Shared React UI library for the MIDDAG ecosystem. Consumed by Moodle (local_middag) and WordPress host plugins via Inertia.js.

Live Demo | Documentation

Stack

  • React 19, TypeScript, Tailwind CSS v4
  • Inertia.js (peer dependency — all hosts use Inertia)
  • ReUI components (Radix-based)
  • TanStack Table, @xyflow/react, @dnd-kit

Install

Quick start (recommended)

# Community (no auth needed)
npx create-middag-ui

# PRO (source maps, mock SPA, full exports)
npx @middag-io/create-middag-ui

The wizard detects your host platform (Moodle/WordPress), configures authentication, and scaffolds a ui/ directory with a working mock build.

Manual install

npm public (no auth needed):

npm install @middag-io/react react react-dom @inertiajs/react @inertiajs/core

GitHub Packages (includes TypeScript source for IDE navigation):

# Add to global ~/.npmrc
echo "@middag-io:registry=https://npm.pkg.github.com" >> ~/.npmrc
echo "//npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN" >> ~/.npmrc

npm install @middag-io/react react react-dom @inertiajs/react @inertiajs/core

Create a token at github.com/settings/tokens with read:packages scope. See Authentication for details.

GitHub Packages access requires: membership in the middag-io organization on GitHub. The token alone is not sufficient — you must have read access to the middag-io/middag-react repository.

Community vs PRO

| Content | Community | PRO | |------------------------------------|-----------|-----| | ESM bundle (dist-lib/) | Yes | Yes | | TypeScript declarations (.d.ts) | Yes | Yes | | Declaration maps (.d.ts.map) | Yes | Yes | | TypeScript source (src/) | No | Yes | | Mock SPA extensible (mock/) | No | Yes | | IDE "go to definition" into source | No | Yes | | Authentication required | No | Yes |

Both editions deliver the same runtime code. Community is sufficient for building plugins. PRO additionally includes TypeScript source for IDE navigation and the extensible mock SPA.

Usage

import { ContractPage, registerDefaults } from '@middag-io/react';
import type { PageContract } from '@middag-io/react';

// Register core shells, layouts, and all 17 blocks (5 lazy-loaded)
registerDefaults();

// Render a contract-driven page
<ContractPage contract={myContract} />

Selective registration (IIFE consumers)

WordPress and other IIFE consumers should import only the blocks they need to avoid bundling heavy dependencies (@xyflow/react, @dnd-kit, zod, react-hook-form) via inlineDynamicImports:

import {
  registerShell, registerLayout, registerBlock,
  ProductShell, StackLayout, SidebarLayout, DashboardLayout,
  DenseTableBlock, MetricCardBlock, EmptyStateBlock,
} from '@middag-io/react';

registerShell('product', ProductShell);
registerLayout('stack', StackLayout);
registerLayout('sidebar', SidebarLayout);
registerLayout('dashboard', DashboardLayout);
registerBlock('dense_table', DenseTableBlock);
registerBlock('metric_card', MetricCardBlock);
registerBlock('empty_state', EmptyStateBlock);

Lazy block loading

Blocks can defer data loading until they mount (useful for tabbed pages):

// PHP sends block with empty data + lazyProp metadata:
{
  type: 'dense_table',
  key: 'invoices',
  data: {},
  meta: { lazyProp: 'invoices' }
}

// PHP also sends a top-level Inertia prop (initially null):
// 'invoices' => null

// When the block mounts, it auto-fetches via router.reload({ only: ['invoices'] })
// Radix Tabs unmounts inactive tabs, so lazy blocks only fetch when their tab activates

ReUI components

Consumers can import ReUI primitives for custom components:

import { Tabs, TabsList, TabsTrigger, TabsContent } from '@middag-io/react/reui/tabs.tsx';
import { Button } from '@middag-io/react/reui/button.tsx';

Custom blocks

import { registerBlock, type BlockProps } from '@middag-io/react';

function ChartBlock({ block }: BlockProps<{ labels: string[]; values: number[] }>) {
  return <div>{/* your chart */}</div>;
}

registerBlock('chart', ChartBlock);

Contract validation

import { validatePageContract } from '@middag-io/react';

const errors = validatePageContract(contractFromBackend);
if (errors) {
  console.error('Invalid contract:', errors);
}

Zod schemas are exported for consumers who want to extend validation or generate JSON Schema for PHP consumers.

i18n with host-specific resolver

import { I18nProvider } from '@middag-io/react';

// Moodle: inject Moodle string resolver
<I18nProvider asyncResolver={moodleGetStrings}>
  <App />
</I18nProvider>

// WordPress: inject WP i18n resolver
<I18nProvider asyncResolver={wpGetStrings}>
  <App />
</I18nProvider>

Architecture

src/
  app/           # ContractPage, registries (shell/layout/block), providers, LazyBlock
  base/          # Shells, layouts, blocks, hooks, theme, form, partials, registries (field/icon/cell)
  components/
    reui/        # ReUI primitives (Radix-based, source of truth)
    examples/    # ReUI component examples (synced from registry)
  contracts/     # TypeScript types (PageContract, BlockData, etc.)
  lib/           # Generic utilities and hooks
  assets/        # Fonts, lottie animations
  index.ts       # Barrel export
mock/            # Dev playground (standalone SPA, no server needed)
scripts/         # Tooling (sync, doctor)
.githooks/       # Git hooks (pre-commit, commit-msg, pre-push)
.changeset/      # Changesets config for automated versioning

What belongs here vs host plugins

| Here (@middag-io/react) | Host plugin (Moodle/WP) | |-----------------------------|-------------------------------------| | Shells, layouts, blocks | Extensions with host-specific pages | | ContractPage renderer | Inertia server-side adapter | | Theme system | License validation (server-side) | | i18n provider (generic) | i18n resolver (host-specific) | | Type contracts | API endpoints, DB queries | | ReUI examples (reference) | Custom components | | Mock build (dev playground) | AMD build (Moodle), ESM bundle (WP) |

Extension model

Extensions implement ExtensionPage (extends PageContract) for licensed features. The build gate excludes unlicensed extensions at compile time. Host plugins handle server-side license checks and only send contracts for active extensions.

Development

# Check environment
npm run doctor

# Mock build -- standalone SPA, no server needed
npm run dev:mock        # http://localhost:5174

# Typecheck
npm run typecheck

# Lint
npm run lint:fix

# Build ESM lib
npm run build

Host switching (mock only)

The mock build includes a host switcher (M/W button in sidebar footer) to preview the UI inside Moodle Boost header or WordPress admin chrome.

ReUI component examples

Examples from the ReUI registry are synced to src/components/examples/. They serve as reference for component usage and are excluded from the published NPM package.

# Sync all examples from ReUI registry (auto-discovers new components)
npm run sync:examples

# Preview what would be synced
npm run sync:examples -- --dry-run

# Check if new examples are available (used by CI)
npm run sync:examples -- --check

A GitHub Action runs weekly (Mondays 8:00 UTC) to check for new examples and opens a PR automatically if updates are available.

Git Hooks

Configured via .githooks/ (activated by npm run prepare):

| Hook | Trigger | Protection | |--------------|--------------|--------------------------------------| | pre-commit | git commit | Typecheck + lint on staged files | | commit-msg | git commit | Enforces Conventional Commits format | | pre-push | git push | Full typecheck + lib build |

Versioning

Uses Changesets for automated versioning and changelog with GitHub-linked entries.

# After finishing a feature:
npx changeset           # select patch/minor/major, write summary
git add . && git commit  # include the .changeset/*.md file

# On merge to main:
# GitHub Action opens "Version Packages" PR
# Merge that PR to publish to GitHub Packages

CLI

The package includes a CLI for bootstrapping and maintaining the UI layer in consumer projects:

| Command | Description | |-----------------------------------------|------------------------------------------------------------| | npx create-middag-ui | Bootstrap ui/ (Community) | | npx @middag-io/create-middag-ui | Bootstrap ui/ (PRO) | | npx @middag-io/react doctor | Validate consumer project setup (deps, configs, peer deps) | | npx @middag-io/react dev | Start mock dev server from consumer project | | npx @middag-io/react add-block <type> | Scaffold a new block type with component + mock factory | | npx @middag-io/react upgrade | Check for updates and run codemods |

Scripts

| Command | Description | |-------------------------|---------------------------------------| | npm run doctor | Validate development environment | | npm run dev:mock | Dev server with hot reload (mock SPA) | | npm run build | Build ESM lib to dist-lib/ | | npm run build:mock | Build mock SPA to dist-mock/ | | npm run typecheck | TypeScript type check | | npm run lint | ESLint check | | npm run lint:fix | ESLint auto-fix | | npm run format | Prettier format | | npm run format:check | Prettier check | | npm run sync:examples | Sync ReUI examples from registry | | npm run changeset | Create a changeset for versioning | | npm run release | Build + publish (used by CI) |

Peer Dependencies

  • react ^19.0.0
  • react-dom ^19.0.0
  • @inertiajs/react ^2.0.0
  • @inertiajs/core ^2.0.0

Mock Build Deployment (Cloudflare Pages)

The mock SPA is deployed automatically to Cloudflare Pages on every push to main.

Live URL: https://ui-demo.middag.io

First-time setup

  1. Create the Cloudflare Pages project:

    npx wrangler pages project create middag-react-mock --production-branch main
  2. Add repository secrets in GitHub (Settings > Secrets and variables > Actions):

    • CLOUDFLARE_API_TOKEN — API token with "Cloudflare Pages: Edit" permission
    • CLOUDFLARE_ACCOUNT_ID — your Cloudflare account ID (found in dashboard URL or Workers & Pages overview)
  3. Push to main — the deploy-mock.yml workflow runs automatically.

Manual deploy (local)

npm run build:mock
npx wrangler pages deploy dist-mock --project-name=middag-react-mock

CI/CD

| Workflow | Trigger | What it does | |--------------------------------|-------------------------------------------|----------------------------------------------------------------| | publish.yml | Push to main | Typecheck + Changesets publish to GitHub Packages + npm public | | publish-create-middag-ui.yml | Push to main (packages/create-middag-ui/) | Publish to npm (Community) + GitHub Packages (PRO) | | deploy-mock.yml | Push to main / manual | Build mock + deploy to Cloudflare Pages | | sync-examples.yml | Monday 8:00 UTC / manual | Sync ReUI examples, opens PR if updates |

Required secrets

| Secret | Registry | Purpose | |-------------------------|------------------|-------------------------------------------------| | GITHUB_TOKEN | GitHub Packages | Publish @middag-io/react (auto-provided) | | NPM_TOKEN | npm (public) | Publish @middag-io/react + create-middag-ui | | CLOUDFLARE_API_TOKEN | Cloudflare Pages | Deploy mock SPA | | CLOUDFLARE_ACCOUNT_ID | Cloudflare Pages | Account identifier |

License

Private — MIDDAG proprietary.