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

atlas-editor-workspace

v1.0.0

Published

Angular application hosting a React Atlaskit editor through a production custom element boundary.

Readme

Atlas Angular Integration Guide

This repo ships two Atlaskit-based UI runtimes:

  • an editor
  • a side navigation

They are implemented with React internally, but the recommended consumer API is Angular.

The Angular app should use these wrapper components:

<app-atlaskit-editor></app-atlaskit-editor>
<app-atlaskit-side-nav></app-atlaskit-side-nav>

Those wrappers lazy-load the generated web-component bundles for you, so the consumer app does not need to manage React directly.

Recommended distribution model

The Angular-first package in this repo is now:

@sumanthnagireddi/atlas-angular

That package is the recommended consumer entrypoint.

It gives Angular teams:

  1. Angular components as the public API
  2. React kept internal
  3. hosted bundle loading by default
  4. an assetBaseUrl escape hatch when you want to self-host the runtime assets

What gets built

Running the workspace build produces this folder:

dist/web-components/
  atlas-editor.js
  atlas-side-nav.js
  atlaskit-editor/
    atlas-atlaskit-editor.js
    atlas-atlaskit-editor.css
    ...many chunk files...
  atlaskit-navigation/
    atlas-atlaskit-navigation.js
    atlas-atlaskit-navigation.css
    ...many chunk files...

Important: keep the full folder structure intact. Do not publish only the top-level atlas-editor.js or atlas-side-nav.js files.

Build the bundle

From this repo:

npm ci
npm run build

If you only need the standalone bundle output:

npm run build:bundle

If you only need the Angular wrapper package output:

npm run build:angular-lib

Recommended integration model

This is the supported Angular-first approach:

  1. build and publish @sumanthnagireddi/atlas-angular
  2. install that package in the consumer Angular app
  3. use the Angular components directly
  4. let the wrappers load the hosted runtime automatically

You do not need to:

  • copy wrapper files into the consumer app
  • add <script> tags to index.html
  • manage React directly

Publish or consume the Angular package

The package source lives here:

Build it with:

npm run build:angular-lib

That produces:

packages/angular/dist/
  public-api.js
  public-api.d.ts
  lib/
    atlaskit-editor.component.js
    atlaskit-editor.component.d.ts
    atlaskit-side-nav.component.js
    atlaskit-side-nav.component.d.ts

If you want to publish to npm, publish the @sumanthnagireddi/atlas-angular package from packages/angular.

If you want to consume it before publishing, you can install it from a packed tarball or a git dependency after building it.

Wrapper selectors

The wrappers support both selector styles:

  • editor:
    • app-atlaskit-editor
    • app-atlaskit-editor-host
  • side nav:
    • app-atlaskit-side-nav
    • app-atlaskit-side-nav-host

For new consumers, prefer:

  • app-atlaskit-editor
  • app-atlaskit-side-nav

Angular import surface

In the consumer app, import from @sumanthnagireddi/atlas-angular:

import {
  AtlaskitEditorComponent,
  AtlaskitSideNavComponent
} from '@sumanthnagireddi/atlas-angular';

Ready-to-paste Angular consumer page

This is the recommended standalone Angular usage pattern.

import { CommonModule } from '@angular/common';
import { Component, signal } from '@angular/core';
import {
  AtlaskitEditorComponent,
  AtlaskitSideNavComponent,
  type ADFDoc,
  type AtlasEditorPage,
  type AtlasSideNavModel
} from '@sumanthnagireddi/atlas-angular';

@Component({
  selector: 'app-atlas-consumer-page',
  standalone: true,
  imports: [CommonModule, AtlaskitEditorComponent, AtlaskitSideNavComponent],
  template: `
    <div class="shell">
      <aside class="shell__nav">
        <app-atlaskit-side-nav
          [assetBaseUrl]="bundleBaseUrl()"
          [model]="model()"
          [darkMode]="darkMode()"
          (ready)="handleNavReady()"
          (itemInvoke)="handleItemInvoke($event)"
          (actionInvoke)="handleActionInvoke($event)"
          (expandChange)="handleExpandChange($event)"
          (flyoutOpenChange)="handleFlyoutOpenChange($event)">
        </app-atlaskit-side-nav>
      </aside>

      <main class="shell__content">
        <app-atlaskit-editor
          [assetBaseUrl]="bundleBaseUrl()"
          [value]="document()"
          [page]="page()"
          [readOnly]="readOnly()"
          [mode]="mode()"
          [darkMode]="darkMode()"
          [debounceMs]="debounceMs()"
          [placeholder]="placeholder()"
          (valueChange)="handleValueChange($event)"
          (change)="handleChange($event)"
          (pageChange)="handlePageChange($event)"
          (pageSubmit)="handlePageSubmit($event)"
          (pageCancel)="handlePageCancel($event)"
          (editModeChange)="handleEditModeChange($event)"
          (ready)="handleEditorReady()"
          (editorError)="handleEditorError($event)">
        </app-atlaskit-editor>
      </main>
    </div>
  `,
  styles: [
    `
      :host {
        display: block;
        min-height: 100vh;
        background: #101214;
      }

      .shell {
        display: grid;
        grid-template-columns: 320px minmax(0, 1fr);
        min-height: 100vh;
      }

      .shell__nav {
        min-width: 0;
        border-right: 1px solid rgba(255, 255, 255, 0.08);
      }

      .shell__content {
        min-width: 0;
      }
    `
  ]
})
export class AtlasConsumerPageComponent {
  readonly bundleBaseUrl = signal('https://sumanthnagireddi.github.io/atlas-editor/web-components');
  readonly darkMode = signal(true);
  readonly readOnly = signal(false);
  readonly mode = signal<'editor' | 'renderer'>('editor');
  readonly debounceMs = signal(250);
  readonly placeholder = signal('Give this page a title...');

  readonly document = signal<ADFDoc>({
    version: 1,
    type: 'doc',
    content: [
      {
        type: 'paragraph',
        content: [{ type: 'text', text: 'Hello from another Angular app.' }]
      }
    ]
  });

  readonly page = signal<AtlasEditorPage>({
    title: 'OSI (Open Systems Interconnection)',
    authorName: 'Sumanth',
    authorInitials: 'S',
    updatedText: 'Updated 1h ago',
    metaItems: ['5 min', 'See views', 'Add a reaction'],
    statusText: 'Verified',
    statusAppearance: 'success',
    widthMode: 'centered',
    titleAlignment: 'left'
  });

  readonly model = signal<AtlasSideNavModel>({
    label: 'Workspace navigation',
    header: {
      title: 'Atlas workspace',
      description: 'Angular consumer app',
      icon: 'apps'
    },
    sections: [
      {
        id: 'primary',
        title: 'Main',
        items: [
          {
            id: 'home',
            kind: 'link',
            label: 'Home',
            href: '/home',
            icon: 'home',
            isSelected: true
          },
          {
            id: 'create-page',
            kind: 'button',
            label: 'Create page',
            icon: 'add'
          },
          {
            id: 'projects',
            kind: 'expandable',
            variant: 'button',
            label: 'Projects',
            icon: 'project',
            isOpen: true,
            children: [
              {
                id: 'kanban',
                kind: 'link',
                label: 'My Kanban Project',
                description: 'Board',
                href: '/projects/kanban',
                icon: 'board'
              },
              {
                id: 'analytics',
                kind: 'link',
                label: 'Analytics workspace',
                description: 'Dashboard',
                href: '/projects/analytics',
                icon: 'dashboard'
              }
            ]
          },
          {
            id: 'recent',
            kind: 'flyout',
            label: 'Recent',
            icon: 'recent',
            flyout: {
              title: 'Recent',
              searchPlaceholder: 'Search recent items',
              footerLabel: 'View all recent items',
              sections: [
                {
                  id: 'recent-this-week',
                  title: 'This week',
                  items: [
                    {
                      id: 'kanban-recent',
                      kind: 'link',
                      label: 'My Kanban Project',
                      description: '5 days ago',
                      href: '/recent/kanban',
                      icon: 'board'
                    }
                  ]
                }
              ]
            }
          }
        ]
      }
    ]
  });

  handleValueChange(nextDoc: ADFDoc): void {
    this.document.set(nextDoc);
  }

  handleChange(nextDoc: ADFDoc): void {
    console.log('Editor change', nextDoc);
  }

  handlePageChange(nextPage: AtlasEditorPage): void {
    this.page.set(nextPage);
  }

  handlePageSubmit(payload: unknown): void {
    console.log('Page submit', payload);
  }

  handlePageCancel(payload: unknown): void {
    console.log('Page cancel', payload);
  }

  handleEditModeChange(isEditing: boolean): void {
    console.log('Edit mode', isEditing);
  }

  handleEditorReady(): void {
    console.log('Editor ready');
  }

  handleEditorError(error: unknown): void {
    console.error('Editor error', error);
  }

  handleNavReady(): void {
    console.log('Side nav ready');
  }

  handleItemInvoke(detail: unknown): void {
    console.log('Item invoke', detail);
  }

  handleActionInvoke(detail: unknown): void {
    console.log('Action invoke', detail);
  }

  handleExpandChange(detail: unknown): void {
    console.log('Expand change', detail);
  }

  handleFlyoutOpenChange(detail: unknown): void {
    console.log('Flyout open change', detail);
  }
}

Inputs and outputs

app-atlaskit-editor inputs

  • assetBaseUrl
  • value
  • page
  • readOnly
  • mode
  • darkMode
  • debounceMs
  • placeholder

app-atlaskit-editor outputs

  • valueChange
  • change
  • pageChange
  • pageSubmit
  • pageCancel
  • editModeChange
  • ready
  • editorError

app-atlaskit-side-nav inputs

  • assetBaseUrl
  • model
  • darkMode

app-atlaskit-side-nav outputs

  • itemInvoke
  • actionInvoke
  • expandChange
  • flyoutOpenChange
  • ready
  • sideNavError

Default runtime location

@sumanthnagireddi/atlas-angular defaults to the hosted runtime bundle:

bundleBaseUrl = 'https://sumanthnagireddi.github.io/atlas-editor/web-components';

That means the simplest Angular consumer often does not need to pass assetBaseUrl at all.

If you want to be explicit, or you want to swap environments, pass that value to:

  • [assetBaseUrl] on app-atlaskit-editor
  • [assetBaseUrl] on app-atlaskit-side-nav

No index.html script tags are required in this mode.

Self-hosting the runtime bundle

If you prefer to host the runtime assets yourself, copy:

into your own static hosting path and point assetBaseUrl there, for example:

bundleBaseUrl = '/assets/atlas';

Dynamic data compatibility

The wrappers are built to support both:

  • initial object input
  • later updates from Angular state

For the side nav specifically, the wrapper also handles in-place JSON mutations by fingerprinting the model during Angular change detection. That means both of these patterns are supported:

this.model.set(nextModel);

and:

const current = this.model();
current.sections[0].items.push({
  id: 'new-item',
  kind: 'link',
  label: 'New item',
  href: '/new-item',
  icon: 'page'
});

As long as Angular change detection runs, the wrapper will push the updated model into the runtime.

Editor page-shell behavior

When a page object is provided, the editor renders in the Confluence-style page shell:

  • top metadata row
  • title area
  • view mode with Edit
  • edit mode with page controls
  • emitted page updates back to the consumer

The consumer remains responsible for:

  • providing the initial page metadata
  • storing updated ADF
  • storing submitted page metadata
  • deciding what to do with pageSubmit

Raw web-component fallback

Only use this section if you do not want the Angular wrappers.

You can still load the generated custom elements directly:

<script type="module" src="https://sumanthnagireddi.github.io/atlas-editor/web-components/atlas-editor.js"></script>
<script type="module" src="https://sumanthnagireddi.github.io/atlas-editor/web-components/atlas-side-nav.js"></script>

<atlas-editor></atlas-editor>
<atlas-side-nav></atlas-side-nav>

Then assign object data as element properties:

const editor = document.querySelector('atlas-editor');
const sideNav = document.querySelector('atlas-side-nav');

editor.value = doc;
editor.page = page;
editor.darkMode = true;

sideNav.model = sideNavModel;
sideNav.darkMode = true;

For Angular consumers, this is a fallback only. The wrapper path above is the preferred integration model.

Local testing

In this repo:

npm ci
npm run build
npm run start

If the consumer app still shows stale behavior after a bundle update:

  1. rebuild the bundle
  2. restart ng serve
  3. hard refresh the browser

This matters because the Angular wrappers load generated runtime assets from assetBaseUrl.

Troubleshooting

The editor never leaves the loading state

Check that the full runtime folder exists under the same base URL:

<assetBaseUrl>/atlas-editor.js
<assetBaseUrl>/atlaskit-editor/...

If you are using the side nav too:

<assetBaseUrl>/atlas-side-nav.js
<assetBaseUrl>/atlaskit-navigation/...

My ADF does not render

Pass a valid ADF doc object into [value], for example:

{
  "version": 1,
  "type": "doc",
  "content": []
}

Do not pass HTML and expect automatic conversion.

Dark mode looks wrong

Set:

darkMode = true;

and avoid global CSS overrides that restyle Atlaskit internals.

Local npm ci fails on Windows with EPERM around esbuild.exe

That usually means a local process is still holding node_modules/@esbuild/win32-x64/esbuild.exe open. This does not indicate a broken CI dependency graph by itself. Close running dev processes and retry locally.

Files in this repo that matter