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

@aeliqo/react

v0.5.2

Published

Thin React bindings for Aeliqo web elements

Downloads

1,707

Readme

@aeliqo/react

@aeliqo/react provides React 19 bindings over the shared web implementation. It does not add another renderer, data layer, or authorization boundary.

The package requires React 19, react-dom 19, and the matching @aeliqo/runtime package. The runtime peer provides the public app and region state types used by the React app API; @aeliqo/web is installed as a package dependency.

Main entry point

import { AeliqoProvider, AeliqoRegion, useAeliqoRender } from '@aeliqo/react';
import type { AeliqoApp } from '@aeliqo/web/app';

export function PeopleRegion({ app }: { app: AeliqoApp }) {
  return (
    <AeliqoProvider app={app}>
      <AeliqoRegion regionId="people-main" resourceId="people" />
    </AeliqoProvider>
  );
}

Create the AeliqoApp at the application boundary and pass that instance into the provider. The provider exposes the app to its descendants; the host still owns the app's data and authority adapters. Call registerAeliqoReactElements() from the client entry point when the page uses custom elements.

For an advanced, host-created runtime, pass runtime instead of app. The provider accepts exactly one of those values and never disposes either one.

Native React views and headless surfaces

For a small complete array already supplied by the application, the 0.5.0 line has a providerless path with no factory or explicit runtime. The historical 0.5.0-rc.1 came from an earlier source revision and does not include this path:

import { AdaptiveSurface, useDataSurface } from '@aeliqo/react/surface';

type Person = { id: string; name: string; team: string };

export function People({ rows }: { rows: readonly Person[] }) {
  const surface = useDataSurface({ data: rows, getRowId: row => row.id });
  return <AdaptiveSurface surface={surface} />;
}

The hook creates its local runtime and default browse request after React commits. Server rendering exposes meaningful read-only rows before hydration; the client then reads through the same runtime source/evaluator path. Rows must have a bounded consistent scalar shape and one real unique identity field. An initially empty array needs an explicit Zod schema and identity field; without them, the component shows empty-data guidance. This local path never grants remote access. Replace the data prop with a new array to refresh while retaining the controller address; mutate-in-place callers must change the version option to request a fresh snapshot. Unsupported or invalid updates retain the last committed rows and show a diagnostic.

For an advanced host-controlled surface, @aeliqo/react/surface adapts a real, application-owned SurfaceController into the existing React tree. It does not create a React root, add a second data engine, or accept view implementations from a wire payload. The host creates the surface at its runtime boundary and registers trusted local React components explicitly.

import { AeliqoScope, ViewSurface, defineReactViews, useSurfaceState } from '@aeliqo/react/surface';
import type { SurfaceController } from '@aeliqo/runtime/surfaces';

const peopleViews = defineReactViews([
  {
    id: 'people.native-table',
    revision: '1',
    render: ({ snapshot }) => <p>{snapshot.phase}</p>,
  },
]);

export function PeopleNativeView({
  scope,
  surface,
}: {
  scope: import('@aeliqo/runtime/scopes').ScopeController;
  surface: SurfaceController<unknown, { readonly rows: readonly unknown[] }>;
}) {
  const rowCount = useSurfaceState(surface, snapshot => snapshot.state.rows.length);
  return (
    <AeliqoScope scope={scope}>
      <p>{rowCount} rows</p>
      <ViewSurface surface={surface} views={peopleViews} view={{ id: 'people.native-table', revision: '1' }} />
    </AeliqoScope>
  );
}

AeliqoScope attaches and detaches the supplied scope for committed React lifecycle work, but never disposes it. It renders children only for an active, authorized activation. Initial resolution, denied access, forced invalidation, and disposal show a safe status without rendering the scoped children. During a voluntary Save / Discard / Stay guard, the current scope and its React subtree remain mounted; the requested selector is only pending. An accepted switch remounts the scoped subtree under the new activation epoch, including A→B→A. The host must call scope.invalidate(...) on logout or revocation; changing a route prop alone does not fence access. useSurfaceState subscribes to one controller with a selector, so unrelated controller updates do not rely on a global React context broadcast. Advanced AdaptiveSurface requires trusted presentation evidence to make an automatic choice from registered native views. A host selector is treated as a pin through shared eligibility checks; plain registration does not qualify a view. An unknown explicit ViewSurface ref renders an accessible diagnostic instead of silently switching views.

For a route-split native view, register a trusted loader in place of render:

const peopleViews = defineReactViews([
  {
    id: 'people.native-detail',
    revision: '1',
    load: () => import('./PeopleDetail.js').then(module => module.default),
  },
]);

The loader returns a React component and is called after commit, not while defining the registry or rendering on the server. ViewSurface and the resolver-backed native AdaptiveSurface keep the previous authorized view mounted while a new view loads. A failure leaves that view usable and shows a retry control; retry calls the registered loader again. If a dynamic import failure is cached by the host's module loader, supply a retryable loader or a fresh module route. Initial loading shows a status or the supplied fallback. Denial, disposal, a changed activation target, or loss of eligibility removes the old view immediately. The loader is application code; neither a model nor a wire payload may choose its import path. Keep a view definition immutable for one ID and revision; increment the revision when its implementation changes.

For a feature bound to an application scope, mount AeliqoProvider with the host runtime, then AeliqoScope with its host scope. A descendant can use useSurface(feature, { id, bindings }). The hook reads those nearest owners, creates the controller only after commit, makes the first request then, and returns undefined until the controller exists. A data feature starts with browse; a capability feature starts from its typed bindings.initialIntent. Supply a stable surface ID within an activation and bindings for that activation:

import { AeliqoProvider } from '@aeliqo/react/app';
import { AeliqoScope, useSurface } from '@aeliqo/react/surface';
import type { DataFeatureDefinition } from '@aeliqo/core/features';
import type { AeliqoRuntime } from '@aeliqo/runtime/app';
import type { ScopeController } from '@aeliqo/runtime/scopes';
import type { DataSurfaceBindings } from '@aeliqo/runtime/surfaces';

type OrdersState = { readonly rows: readonly { readonly id: string }[] };

function Orders({ feature, bindings }: {
  feature: DataFeatureDefinition;
  bindings: DataSurfaceBindings<OrdersState>;
}) {
  const surface = useSurface(feature, { id: 'orders-main', bindings });
  return <p>{surface?.getSnapshot().phase ?? 'Preparing orders'}</p>;
}

export function OrdersWorkspace({ runtime, scope, feature, bindings }: {
  runtime: AeliqoRuntime;
  scope: ScopeController;
  feature: DataFeatureDefinition;
  bindings: DataSurfaceBindings<OrdersState>;
}) {
  return <AeliqoProvider runtime={runtime}>
    <AeliqoScope scope={scope}><Orders feature={feature} bindings={bindings} /></AeliqoScope>
  </AeliqoProvider>;
}

This example only shows controller creation; use useSurfaceState in a child component to subscribe to changing controller state. Keep feature definitions immutable and create new scope-specific bindings for a new activation. A callback holding an old controller remains bound to its old address and cannot act in a later activation. Changing the binding reference within an activation does not replace the controller; use the runtime's source update contract for data changes. The existing factory overloads of useSurface and useDataSurface remain available for application-authored factories and dispose only the controllers they create. A providerless local hook nested inside an application-owned scope fails visibly instead of creating a parallel authority context.

Component wrappers

React wrappers are available from family subpaths such as @aeliqo/react/foundation, @aeliqo/react/inputs, @aeliqo/react/navigation, @aeliqo/react/feedback, @aeliqo/react/data, @aeliqo/react/plot, @aeliqo/react/visualization, and @aeliqo/react/compound. SSR helpers are available from @aeliqo/react/ssr.

Lifecycle

Keep one app instance per application security context. Mount Regions under the provider and let their React lifecycle release their subscriptions on unmount. Dispose the app from the owner that created it. The root exports provider, Region, and lifecycle hooks; component wrappers stay on family subpaths.