@presencelearning/documentation
Angular library for the clinical-documentation workflow shared across Presence frontends — session notes, appointment management, IEP-goal metrics tracking, evaluation recording, and the cross-window pop-out documentation surface.
Features
Section titled “Features”- Standalone Angular components —
DocumentationPanelComponent,DocumentationWindowComponent,DocumentationTabsComponent, session-notes editor, tracked metrics, appointment selection, evaluation recording, session-events timeline - Abstract service contract — Consumer apps provide a concrete
DocumentationServiceimplementation for backend operations (fetch appointments, save records, IEP metric mutations, etc.); the library handles UI state, signal stores, and the NgRx pipeline - Pop-out documentation window — Open a session in its own browser window via
/documentation/window/:instanceId; survives parent-tab refresh and signs off back to the parent viaBroadcastChannel - Signal stores and NgRx —
DocumentationAppointmentStore,DocumentationGlobalStore,DocumentationPolishNotesStore,AppointmentTabsStore,DocumentationAmendmentsStore, plus a full NgRx slice (documentationReducer,DocumentationActions,DocumentationEffects, selectors) - AI note polishing — Polished SOAP-note suggestions surface in
SessionNotesSuggestionComponent; consumers wire up the backend call - Tracked metrics — IEP-goal metrics with score tracking, percent-correct computation, and dropdown/dialog selection UIs
- Evaluations — Evaluation documents, concern areas, assessment components, and report upload/delete, driven by
DocumentationService’s evaluation members - Amendments —
AmendmentsComponentandDocumentationAmendmentsStorefor amending a signed-off note - Cross-window broadcast —
DocumentationBroadcastServiceandSessionEventsBroadcastServicekeep multiple open windows in sync
Installation
Section titled “Installation”npm install @presencelearning/documentationPeer dependencies
Section titled “Peer dependencies”Install these in your application:
npm install @angular/common @angular/core @angular/forms @angular/animations @angular/routernpm install @angular/cdk @angular/materialnpm install @ngrx/store @ngrx/effects @ngrx/signals @ngrx/entitynpm install rxjs @presencelearning/stylesAngular and NgRx peers are >=19.0.0 <22.0.0; @presencelearning/styles is ^1.0.0 and is not optional.
@lottiefiles/dotlottie-web is flagged optional in package.json, but DocumentationPanelComponent imports it statically — so any app rendering the main panel needs it:
npm install @lottiefiles/dotlottie-webQuick Start
Section titled “Quick Start”1. Implement DocumentationService
Section titled “1. Implement DocumentationService”The library requires a concrete implementation of the abstract DocumentationService. This is the bulk of the integration work: the class declares roughly 55 abstract members covering appointments, billing, notes, evaluations, metrics, session events, notifications and dialogs, analytics (trackEvent), URL builders, and the DocumentationState persistence layer, plus the eventStream$ and admissionEventsChanged$ observables. Check the shipped .d.ts for the authoritative list.
import { Injectable, signal } from '@angular/core';import { Observable, of } from 'rxjs';import { DocumentationService, DocumentationAppointment } from '@presencelearning/documentation';
@Injectable({ providedIn: 'root' })export class MyDocumentationService extends DocumentationService { isReady = signal(false); isRefreshing = signal(false); readonlyMode = signal(false);
refreshAppointments(): void { // Your backend call }
loadAppointmentData(appointment: DocumentationAppointment): void { // Your backend call }
// …implement every abstract member}The three abstract signal members are isReady, isRefreshing, and readonlyMode. Recording is a separate contract — see EvaluationRecordingService below.
2. Wire up providers
Section titled “2. Wire up providers”import { ApplicationConfig } from '@angular/core';import { provideStore } from '@ngrx/store';import { provideEffects } from '@ngrx/effects';import { DocumentationEffects, documentationReducer, provideDocumentation,} from '@presencelearning/documentation';import { MyDocumentationService } from './my-documentation.service';
export const appConfig: ApplicationConfig = { providers: [ provideDocumentation(MyDocumentationService, { // Optional — defaults shown: // registerIcons: true, // windowUrlBase: '/documentation/window', // source: 'room', // recordingService: MyEvaluationRecordingService, }), provideStore({ documentation: documentationReducer }), provideEffects(DocumentationEffects), ],};provideDocumentation() wires the abstract DocumentationService binding and registers the library’s SVG icons with MatIconRegistry. ProvideDocumentationOptions:
| Option | Default | Description |
| ------------------ | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| registerIcons | true | Register the library’s SVG icons. Opt out if your app registers its own |
| windowUrlBase | '/documentation/window' | Base path for the pop-out window URL. Must match the route you register in step 4 |
| source | 'room' | Analytics namespace. Composed with the current surface into <namespace>_<surface> for log and tracking values |
| recordingService | — | Concrete EvaluationRecordingService implementation. Without it the recording UI is silently hidden, because the component injects it as optional |
3. Render the panel
Section titled “3. Render the panel”import { Component } from '@angular/core';import { DocumentationPanelComponent } from '@presencelearning/documentation';
@Component({ selector: 'app-session', standalone: true, imports: [DocumentationPanelComponent], template: ` <div #container> <pl-documentation-panel [parentElement]="container" (signOffChange)="onSignOff($event)" /> </div> `,})export class SessionComponent { onSignOff(signedOff: boolean): void { // React to sign-off }}The panel does not take an appointment input — it reads the current selection from the stores. Its inputs are parentElement (required, Element), tabMode, and windowMode. Outputs: openInNew, switchToDrawer, minimize, close, openInTab, signOffChange, closeDrawer, billingCodeChange.
4. (Optional) Add the pop-out window route
Section titled “4. (Optional) Add the pop-out window route”DocumentationWindowComponent is what renders inside a pop-out window when the user opens documentation in its own browser window. Register a route for it so the URL built by DocumentationWindowService.openAppointmentWindow(apptId) resolves.
import { Routes } from '@angular/router';import { DocumentationWindowComponent } from '@presencelearning/documentation';
export const routes: Routes = [ { path: 'documentation/window/:instanceId', component: DocumentationWindowComponent },];Components
Section titled “Components”| Component | Selector | Purpose |
| ------------------------------- | -------------------------- | ----------------------------------------------------------------- |
| DocumentationPanelComponent | pl-documentation-panel | Main documentation panel with tabs for notes, metrics, and events |
| DocumentationWindowComponent | pl-documentation-window | Standalone pop-out window for a single appointment |
| DocumentationTabsComponent | pl-documentation-tabs | Mini-window tab bar for multiple concurrent appointments |
| AppointmentSelectionComponent | pl-appointment-selection | Appointment picker / list |
| SessionNotesComponent | pl-session-notes | SOAP-notes editor (subjective, objective, assessment, plan) |
| TrackedMetricsComponent | pl-tracked-metrics | IEP-goal metrics tracking |
| SessionEventsComponent | pl-session-events | Timeline of session events |
| AppointmentDetailsComponent | pl-appointment-details | Client info, billing code, service selection |
| EvaluationRecordingComponent | pl-evaluation-recording | Evaluation-recording controls |
| TimestampTrackingComponent | pl-timestamp-tracking | Client admission timestamps |
| AmendmentsComponent | pl-amendments | Amend a signed-off note. Input: isNewEvent |
The package exports 26 components in total. The rest are the sub-components those surfaces compose — DocumentationPanelFooterComponent, DocumentationTabsWindowComponent, AppointmentSelectionItemComponent, AppointmentDetailsSelectComponent, AppointmentTabComponent, ClientCardComponent, NoteDictationComponent, SessionEventComponent, SessionNotesDialogComponent, SessionNotesFieldComponent, SessionNotesSuggestionComponent, TrackedMetricsDropdownComponent, TrackedMetricsItemComponent, TrackedMetricsItemScoreComponent, and TrackedMetricsSelectComponent — exported so consumers can compose their own layouts.
Live previews for every component (including states, controls, and design references) live in Storybook.
Services
Section titled “Services”| Service | Purpose |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DocumentationWindowService | Opens, closes, reconnects, and focuses pop-out windows — openAppointmentWindow, openAppointment, closeAppointment, reconnectAppointment, focusAppointmentWindow |
| DocumentationBroadcastService | Cross-window sync for documentation state |
| SessionEventsBroadcastService | Cross-window sync for the session-events timeline |
| ResizeObserverService | Element resize observation used by the drawer |
| BrowserService | Browser capability and window helpers |
| LocalStorageService | Typed localStorage access, keyed by LocalStorageKey |
Stores
Section titled “Stores”Signal stores (NgRx Signals)
Section titled “Signal stores (NgRx Signals)”import { AppointmentTabsStore, DocumentationAmendmentsStore, DocumentationAppointmentStore, DocumentationGlobalStore, DocumentationPolishNotesStore,} from '@presencelearning/documentation';| Store | Holds |
| ------------------------------- | ---------------------------------------------------------- |
| DocumentationAppointmentStore | Appointment entities, selection state |
| DocumentationGlobalStore | Provider info, billing codes, note schemas, surface/source |
| DocumentationPolishNotesStore | AI-generated note suggestions |
| AppointmentTabsStore | Mini-window tab state |
| DocumentationAmendmentsStore | Amendment drafts (AmendmentDraft) |
NgRx slice
Section titled “NgRx slice”import { DocumentationActions, DocumentationEffects, DocumentationState, documentationReducer, initialState, selectCurrentTab, selectCurrentTabForClientId, selectDocumentation, selectDrawerClientIds, selectDrawerWidth, selectTabClientIds, selectTimestampTrackingEnabled,} from '@presencelearning/documentation';Evaluations
Section titled “Evaluations”Evaluation support landed in 1.0.0 and is driven entirely through DocumentationService. The abstract members to implement are getEvaluationDocumentForAppointment, getEvaluationComponentsForAppointment, updateEvaluationComponentForAppointment, updateEvaluationComponentDetailForAppointment, removeEvaluationComponentFromAppointment, updateEvaluationForAppointment, uploadEvaluationReport, deleteEvaluationReport, and saveEvaluationReportForAppointment.
The evaluation UI components themselves are internal to the library — they render inside the panel and are not exported.
Breaking change in 1.0.0:
ClientService.evaluationchanged from an inline{ type; dueDate; provider? }object to theClientEvaluationinterface. Consumers reading evaluation fields must update accordingly.
Compatibility
Section titled “Compatibility”| Angular | Library version | | ------- | --------------- | | 19.x | 1.x | | 20.x | 1.x | | 21.x | 1.x |
Angular, CDK, Material, and NgRx peers are all >=19.0.0 <22.0.0. Node >=20.
The library ships a minimal theme as an asset alongside the JS entry point:
@use '@presencelearning/documentation/styles/theme/theme';The compiled theme.css is available at the same path.
Non-goals
Section titled “Non-goals”- No bundled backend — every persistence call goes through the consumer’s
DocumentationServiceimplementation - No opinionated theming — the library ships a minimal
theme.scss; consumers control palette and typography - No standalone routing — the pop-out window route must be registered by the consumer
Source: packages/documentation