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

@passportauth/elements

v0.1.0

Published

PassportAuth Elements — drop-in embeddable UI components for access control

Downloads

88

Readme

@passportauth/elements

Embeddable React UI components for PassportAuth authorization.

Drop these components into any React app to add permission-aware UI, user profile management, and access control panels — without building auth logic from scratch. Each component talks directly to the PassportAuth API; no Redux, no context provider required.

Security note: PermissionGuard performs client-side permission checks and is intended for UI feedback only. For security-critical decisions, enforce permissions server-side using the PassportAuth Check API.


Installation

npm install @passportauth/elements

Peer dependencies

npm install react@^18

Configuration

Every component accepts a config prop of type ElementsConfig:

import type { ElementsConfig } from '@passportauth/elements';

const elementsConfig: ElementsConfig = {
  apiUrl: 'https://auth.passportauth.com',
  tenantId: 'ten_your_tenant_id',
  // serviceToken is optional — omit for public (user-facing) components,
  // include for components embedded in admin surfaces.
  serviceToken: process.env.NEXT_PUBLIC_PA_SERVICE_TOKEN,
};

You can create this object once and share it across all components on a page.


Quick start

Settings page with UserProfile

// src/pages/settings.tsx
import { UserProfile } from '@passportauth/elements';

const elementsConfig = {
  apiUrl: 'https://auth.passportauth.com',
  tenantId: 'ten_acme',
};

export default function SettingsPage({ userId }: { userId: string }) {
  return (
    <div className="max-w-lg mx-auto py-8">
      <h1 className="text-xl font-semibold mb-6">Your profile</h1>
      <UserProfile
        userId={userId}
        config={elementsConfig}
        editable
        onSave={async (updated) => {
          console.log('Profile saved:', updated);
        }}
      />
    </div>
  );
}

Conditionally showing UI with PermissionGuard

import { PermissionGuard } from '@passportauth/elements';

// Only show the "Delete" button to users with the `owner` relation on the document.
function DocumentActions({ userId, documentId }: { userId: string; documentId: string }) {
  return (
    <div>
      <button>View</button>

      <PermissionGuard
        user={userId}
        relation="editor"
        object={`document:${documentId}`}
        config={elementsConfig}
        fallback={null}
        loadingFallback={<span>Checking permissions…</span>}
      >
        <button>Edit</button>
      </PermissionGuard>

      <PermissionGuard
        user={userId}
        relation="owner"
        object={`document:${documentId}`}
        config={elementsConfig}
      >
        <button className="text-red-600">Delete</button>
      </PermissionGuard>
    </div>
  );
}

Sharing a resource with ResourceSharing

import { ResourceSharing } from '@passportauth/elements';

function ShareDialog({ currentUserId, documentId }: { currentUserId: string; documentId: string }) {
  return (
    <ResourceSharing
      object={`document:${documentId}`}
      currentUser={currentUserId}
      config={elementsConfig}
      availableRelations={['viewer', 'editor', 'owner']}
      title="Share document"
      onChange={() => {
        // Refetch your own data after membership changes
        console.log('Membership updated');
      }}
    />
  );
}

Components

UserProfile

Displays a user's profile — avatar, name, email, verification status, and account state. Set editable to show an inline edit form.

<UserProfile
  userId="usr_abc123"
  config={elementsConfig}
  editable={true}
  onSave={async (data) => { /* Partial<UserProfileData> */ }}
  className="my-custom-class"
/>

Props:

| Prop | Type | Default | Description | |---|---|---|---| | userId | string | required | PassportAuth user ID | | config | ElementsConfig | required | API config | | editable | boolean | false | Show edit form | | onSave | (data: Partial<UserProfileData>) => Promise<void> | — | Called after a successful save | | className | string | — | CSS class for the outer element |


PermissionGuard

Renders children when the specified permission check passes, fallback otherwise. Calls POST /authz/check on the PassportAuth API.

<PermissionGuard
  user="usr_abc123"
  relation="write"
  object="document:doc_xyz"
  config={elementsConfig}
  fallback={<p>Read-only</p>}
  loadingFallback={<Spinner />}
  context={{ resource_owner: 'org_acme' }}
>
  <EditButton />
</PermissionGuard>

Props:

| Prop | Type | Default | Description | |---|---|---|---| | user | string | required | User URN or ID | | relation | string | required | Permission / relation name | | object | string | required | Object in <type>:<id> format | | config | ElementsConfig | required | API config | | children | ReactNode | required | Rendered when allowed | | fallback | ReactNode | null | Rendered when denied or error | | loadingFallback | ReactNode | null | Rendered while checking | | context | Record<string, unknown> | — | ABAC evaluation context |


ResourceSharing

Panel that lists who has access to a resource and lets owners add or remove members. Calls /authz/list-users, /authz/check, and /management/tuples.

<ResourceSharing
  object="project:proj_123"
  currentUser="usr_admin"
  config={elementsConfig}
  availableRelations={['viewer', 'editor', 'owner']}
  title="Manage access"
  onChange={() => refetch()}
  className="shadow-md"
/>

Props:

| Prop | Type | Default | Description | |---|---|---|---| | object | string | required | Resource in <type>:<id> format | | currentUser | string | required | Authenticated user ID | | config | ElementsConfig | required | API config | | availableRelations | string[] | ['viewer', 'editor', 'owner'] | Relations to display and assign | | title | string | 'Share' | Panel heading | | onChange | () => void | — | Called after any membership change | | className | string | — | CSS class for the outer element |

The component automatically checks whether currentUser has the owner relation before showing add/remove controls.


AccessRequest

Lets a user submit a request to access a resource. Calls POST /management/access-requests.

<AccessRequest
  requesterUser="usr_abc123"
  object="document:doc_xyz"
  relation="editor"
  config={elementsConfig}
  onSubmit={async (request) => {
    console.log('Request submitted:', request.id);
  }}
/>

Props:

| Prop | Type | Default | Description | |---|---|---|---| | requesterUser | string | required | User requesting access | | object | string | required | Resource in <type>:<id> format | | relation | string | required | Requested permission level | | config | ElementsConfig | required | API config | | onSubmit | (data: AccessRequestData) => Promise<void> | — | Called after successful submission |


UserRolesPanel

Displays and manages the roles assigned to a user across one or more objects. Calls /management/tuples to list and modify role assignments.

<UserRolesPanel
  userId="usr_abc123"
  config={elementsConfig}
  editable={isAdmin}
  onChange={() => refetch()}
/>

Props:

| Prop | Type | Default | Description | |---|---|---|---| | userId | string | required | User whose roles to display | | config | ElementsConfig | required | API config | | editable | boolean | false | Allow adding/removing roles | | onChange | () => void | — | Called after any role change | | className | string | — | CSS class for the outer element |


Types

import type {
  ElementsConfig,
  ElementsTheme,
  UserProfileData,
  RoleAssignment,
  AccessRequestData,
} from '@passportauth/elements';

interface ElementsConfig {
  apiUrl: string;
  tenantId: string;
  serviceToken?: string;
}

interface ElementsTheme {
  primaryColor?: string;
  fontFamily?: string;
  borderRadius?: string;
  colorScheme?: 'light' | 'dark' | 'auto';
}

interface UserProfileData {
  id: string;
  email: string;
  name?: string;
  avatar_url?: string;
  email_verified: boolean;
  is_active: boolean;
}

interface RoleAssignment {
  user: string;
  relation: string;
  object: string;
}

interface AccessRequestData {
  id?: string;
  requester_user: string;
  relation: string;
  object: string;
  status: 'pending' | 'approved' | 'denied';
  requested_at?: string;
}

Styling

All components render unstyled inline styles by default — no CSS file to import. Pass a className prop to override the outer container. Component internals use inline styles built with system-ui as the base font and a neutral palette that works in both light and dark contexts.

Custom theming via ElementsTheme is planned for a future release.


License

Apache 2.0 — see LICENSE.

Full documentation

docs.passportauth.com/sdks/elements