Skip to content

@presencelearning/ui

Angular component library for Presence Learning. Provides reusable UI components built on Angular Material and @presencelearning/styles.

Current version: 1.2.2. Single flat entry point — everything is imported from @presencelearning/ui.

Terminal window
npm install @presencelearning/ui

Declared in package.json:

  • @angular/core >=18.0.0 <22.0.0
  • @angular/common >=18.0.0 <22.0.0
  • @angular/cdk >=18.0.0 <22.0.0
  • @angular/material >=18.0.0 <22.0.0
  • @presencelearning/styles ^1.0.0

Also imported by the library but not currently declared as peers — your app needs them installed: @angular/forms (rich text editor), @angular/router (NavigationLinkComponent), @angular/animations (NavigationComponent), and rxjs.

The rich text editor bundles its own runtime dependencies (17 @tiptap/* packages, dompurify, unicode-emoji-json), so they install transitively rather than as peers.

Note that the exported class names have no Pl prefix — the pl- prefix appears only on the selectors.

| Component | Selector | Description | | ------------------------- | --------------------- | ---------------------------------------------------------------------- | | NavigationComponent | pl-navigation | Main navigation with expandable/collapsible sidebar | | NavigationLinkComponent | pl-navigation-link | Navigation link with icon and label | | HelpMenuComponent | pl-help-menu | Help menu dropdown | | BannerComponent | pl-banner | Inline info/success banner with optional link and action buttons | | RichTextEditorComponent | pl-rich-text-editor | Tiptap-based rich text editor with mentions, emoji, tables, and images | | PlaceholderComponent | pl-placeholder | Dashed-border box for verifying that the library is wired up correctly |

NavigationTriggerDirective ([plNavigationTrigger], exportAs: 'plNavigationTrigger') is also exported, for toggling the sidebar from outside it.

| Input | Type | Default | Description | | -------------- | ----------- | ------- | ------------------------------------ | | pages | NavLink[] | [] | Primary navigation links | | resources | NavLink[] | [] | Secondary/resource links | | hiddenRoutes | string[] | [] | Routes on which the nav hides itself | | currentUrl | string | '' | Drives active-link highlighting |

Outputs: linkClicked: NavLink, navigationToggled: boolean. Public methods: toggle(skipSave = false), open(), close(), toggleHelpMenu(). Project help menu content via a #helpMenuContent template.

NavLink resolution priority is routerLinkhref → plain button. Collapsed state persists through the PL_NAVIGATION_STORAGE injection token, which defaults to defaultNavigationStorage (localStorage under the key pl-navigation). Override the token to change or disable persistence.

| Input | Type | Default | Description | | ---------------------- | ------------------------------------ | -------- | ------------------------------------- | | type | BannerType ('info' \| 'success') | 'info' | Visual treatment | | title | string | — | Banner heading | | body | string | — | Banner body text | | bodyLinkLabel | string | — | Label for an inline link in the body | | bodyLinkHref | string | — | Href for the inline body link | | primaryButtonLabel | string | — | Renders the primary action when set | | secondaryButtonLabel | string | — | Renders the secondary action when set | | showCloseButton | boolean | false | Renders a close affordance |

Outputs: primaryClicked, secondaryClicked, bodyLinkClicked, closeClicked (all void).

Implements ControlValueAccessor, so it works with formControl/ngModel as well as with the value/valueChange pair.

| Input | Type | Default | Description | | --------------- | ----------------------- | ------- | ------------------------------- | | value | string | '' | Editor HTML | | readonly | boolean | false | Renders read-only | | placeholder | string | '' | Empty-state placeholder | | mentionsFetch | MentionsFetch \| null | null | Supplies @-mention candidates |

Output: valueChange: string. Public method: print(): void.

Register the editor engine once at app level:

app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideRichTextEditor } from '@presencelearning/ui';
export const appConfig: ApplicationConfig = {
providers: [provideRichTextEditor()],
};

| Export | Kind | Description | | -------------------------- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------- | | BannerType | type | 'info' \| 'success' | | NavLink | type | Navigation entry — label, optional icon, href, routerLink, external, active, children, enabled | | HelpMenuLink | type | Help menu entry — title, subtitle, optional icon, href, external, local | | HelpMenuEmail | type | Help menu email entry — address, label | | PL_NAVIGATION_STORAGE | InjectionToken<NavigationStorage> | Persistence for the sidebar collapsed state | | defaultNavigationStorage | const | localStorage adapter used by default | | NavigationStorage | interface | Contract for a custom storage adapter | | provideRichTextEditor | function | () => EnvironmentProviders — registers the Tiptap engine | | ActiveState | interface | Current editor formatting state | | MentionItem | interface | A single mention candidate | | MentionsFetch | type | Mention lookup callback | | HeadingLevel | type | Heading levels the editor supports |

Stories exist for BannerComponent, NavigationComponent, PlaceholderComponent, and RichTextEditorComponent. Run locally:

Terminal window
npm run storybook --workspace=@presencelearning/ui

Source: packages/ui