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.
The Angular-first package in this repo is now:
@sumanthnagireddi/atlas-angular
That package is the recommended consumer entrypoint.
It gives Angular teams:
- Angular components as the public API
- React kept internal
- packaged runtime loading by default
- an
assetBaseUrlescape hatch when you want to self-host or override the runtime assets
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.
From this repo:
npm ci
npm run buildIf you only need the standalone bundle output:
npm run build:bundleIf you only need the Angular wrapper package output:
npm run build:angular-libThis is the supported Angular-first approach:
- build and publish
@sumanthnagireddi/atlas-angular - install that package in the consumer Angular app
- use the Angular components directly
- let the wrappers load the packaged runtime automatically
You do not need to:
- copy wrapper files into the consumer app
- add
<script>tags toindex.html - manage React directly
The package source lives here:
- C:\Users\HP\Desktop\code\atlas-editor\packages\angular
Build it with:
npm run build:angular-libThat 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.
CI also publishes the Angular package automatically after the main workspace build passes on pushes to master or main.
To make that work in GitHub Actions, configure:
NPM_TOKENas a repository secret with publish permission for npm
The publish job checks whether the current packages/angular/package.json version already exists on npm. If it does, the workflow skips publish cleanly, so version bumps are what trigger new package releases.
The wrappers support both selector styles:
- editor:
app-atlaskit-editorapp-atlaskit-editor-host
- side nav:
app-atlaskit-side-navapp-atlaskit-side-nav-host
For new consumers, prefer:
app-atlaskit-editorapp-atlaskit-side-nav
In the consumer app, import from @sumanthnagireddi/atlas-angular:
import {
AtlaskitEditorComponent,
AtlaskitSideNavComponent
} from '@sumanthnagireddi/atlas-angular';These are exported as real standalone Angular component classes, so they can be used directly in:
imports: [CommonModule, AtlaskitEditorComponent, AtlaskitSideNavComponent]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
[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
[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 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);
}
}assetBaseUrlvaluepagereadOnlymodedarkModedebounceMsplaceholder
valueChangechangepageChangepageSubmitpageCanceleditModeChangereadyeditorError
assetBaseUrlmodeldarkMode
itemInvokeactionInvokeexpandChangeflyoutOpenChangereadysideNavError
@sumanthnagireddi/atlas-angular defaults to the packaged runtime bundle that ships inside the npm library itself.
That means the simplest Angular consumer often does not need to pass assetBaseUrl at all.
If you want to override the runtime location, pass the folder URL, not an individual loader file. Internally:
- editor wrapper loads
atlas-editor.js - side-nav wrapper loads
atlas-side-nav.js atlas-editor.jsloads./atlaskit-editor/atlas-atlaskit-editor.jsatlas-side-nav.jsloads./atlaskit-navigation/atlas-atlaskit-navigation.js
If you want to be explicit, or you want to swap environments, pass your base URL to:
[assetBaseUrl]onapp-atlaskit-editor[assetBaseUrl]onapp-atlaskit-side-nav
No index.html script tags are required in either mode.
If you prefer to host the runtime assets yourself, copy:
- C:\Users\HP\Desktop\code\atlas-editor\dist\web-components
into your own static hosting path and point assetBaseUrl there, for example:
bundleBaseUrl = '/assets/atlas';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.
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
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.
In this repo:
npm ci
npm run build
npm run startIf the consumer app still shows stale behavior after a bundle update:
- rebuild the bundle
- restart
ng serve - hard refresh the browser
This matters because the Angular wrappers load generated runtime assets from assetBaseUrl.
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/...
Pass a valid ADF doc object into [value], for example:
{
"version": 1,
"type": "doc",
"content": []
}Do not pass HTML and expect automatic conversion.
Set:
darkMode = true;and avoid global CSS overrides that restyle Atlaskit internals.
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.
- Angular package entrypoint: C:\Users\HP\Desktop\code\atlas-editor\packages\angular\src\public-api.ts
- editor wrapper source: C:\Users\HP\Desktop\code\atlas-editor\packages\angular\src\lib\atlaskit-editor.component.ts
- side-nav wrapper source: C:\Users\HP\Desktop\code\atlas-editor\packages\angular\src\lib\atlaskit-side-nav.component.ts
- generated assets: C:\Users\HP\Desktop\code\atlas-editor\dist\web-components
- bundle builder: C:\Users\HP\Desktop\code\atlas-editor\scripts\build-web-components.mjs