// Overlay service copy-paste examples.
export /**
*
*/
const OVERLAY_MODAL = `// Centered modal via ModalService. Needs provideAfricaniesUiOverlays() in app.config.
// Built on Angular CDK Overlay (panels attach to body — not clipped by overflow).
// Inject OVERLAY_DATA in the panel, close with AfricaniesOverlayRef.close(result).
// dismissible defaults to false — backdrop/Escape only work when you opt in.
// Close X: put it in a shrink-0 header and scroll the body (host overflow-hidden
// + africanies-overlay-scroll). The pane reserves a scrollbar gutter so the track
// cannot cover the button.
// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideAfricaniesUiOverlays } from '@africanies/africanies-ui';
export const appConfig: ApplicationConfig = {
providers: [
provideAfricaniesUiOverlays(),
],
};
// --- Hosted panel ---
import { Component, inject } from '@angular/core';
import {
AfricaniesOverlayRef,
ButtonComponent,
OVERLAY_DATA,
} from '@africanies/africanies-ui';
export interface EditShipmentData {
shipmentRef: string;
}
export interface EditShipmentResult {
saved: boolean;
note: string;
}
@Component({
selector: 'app-edit-shipment-modal',
standalone: true,
imports: [ButtonComponent],
template: \`
Edit {{ data.shipmentRef }}
\`,
})
export class EditShipmentModalComponent {
protected readonly data = inject(OVERLAY_DATA);
protected readonly ref = inject(AfricaniesOverlayRef);
protected note = '';
}
// --- Caller ---
import { Component, inject } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { ButtonComponent, ModalService } from '@africanies/africanies-ui';
@Component({
selector: 'app-open-modal-demo',
standalone: true,
imports: [ButtonComponent],
template: \`
\`,
})
export class OpenModalDemoComponent {
private readonly modal = inject(ModalService);
protected openLocked(): void {
this.modal
.open(EditShipmentModalComponent, {
data: { shipmentRef: 'SFN-1042' },
// dismissible defaults to false — backdrop / Escape do nothing.
// size defaults to 'md'. Use 'lg' for dense forms, 'xl' for media.
})
.afterClosed()
.pipe(takeUntilDestroyed())
.subscribe((result) => {
if (result?.saved) {
// Apply note locally or invalidate list query — no second GET needed.
}
});
}
protected openDismissible(): void {
this.modal
.open(EditShipmentModalComponent, {
data: { shipmentRef: 'SFN-1042' },
dismissible: true,
size: 'lg',
})
.afterClosed()
.pipe(takeUntilDestroyed())
.subscribe((result) => {
// result undefined when dismissed via backdrop / Escape / Cancel without save.
});
}
}`;
export /**
*
*/
const OVERLAY_DRAWER = `// Right-edge drawer — same OVERLAY_DATA / AfricaniesOverlayRef contract as modals.
// Good for filters and detail chrome. Default is locked; set dismissible: true for abandonable panels.
import { Component, inject } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import {
AfricaniesOverlayRef,
ButtonComponent,
DrawerService,
OVERLAY_DATA,
} from '@africanies/africanies-ui';
export interface FiltersDrawerData {
facet: string;
}
export interface FiltersDrawerResult {
applied: boolean;
}
@Component({
selector: 'app-filters-drawer',
standalone: true,
imports: [ButtonComponent],
template: \`
Filters — {{ data.facet }}
@for (opt of options; track opt) {
}
\`,
})
export class FiltersDrawerComponent {
protected readonly data = inject(OVERLAY_DATA);
protected readonly ref = inject(AfricaniesOverlayRef);
protected readonly options = ['In transit', 'Delivered', 'Pending', 'Exception'] as const;
}
@Component({
selector: 'app-open-drawer-demo',
standalone: true,
imports: [ButtonComponent],
template: \`
\`,
})
export class OpenDrawerDemoComponent {
private readonly drawer = inject(DrawerService);
protected open(dismissible: boolean): void {
this.drawer
.open(FiltersDrawerComponent, {
data: { facet: 'Status' },
dismissible,
})
.afterClosed()
.pipe(takeUntilDestroyed())
.subscribe((result) => {
if (result?.applied) {
// Push facet selections into list query params → refetch.
}
});
}
}`;
export /**
*
*/
const OVERLAY_CONFIRM = `// One-liner confirm via ConfirmService — returns Observable.
// Set danger: true for delete/void. Don't open ConfirmDialogComponent yourself.
import { Component, inject } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { ButtonComponent, ConfirmService } from '@africanies/africanies-ui';
@Component({
selector: 'app-confirm-demo',
standalone: true,
imports: [ButtonComponent],
template: \`
\`,
})
export class ConfirmDemoComponent {
private readonly confirm = inject(ConfirmService);
protected confirmNeutral(): void {
this.confirm
.confirm({
title: 'Mark as delivered?',
message: 'The consignee will be notified that the shipment is complete.',
confirmLabel: 'Mark delivered',
cancelLabel: 'Cancel',
danger: false,
})
.pipe(takeUntilDestroyed())
.subscribe((ok) => {
if (ok) {
this.markDelivered();
}
});
}
protected confirmDestructive(): void {
this.confirm
.confirm({
title: 'Delete shipment?',
message: 'This cannot be undone. Related documents stay in archive.',
confirmLabel: 'Delete',
cancelLabel: 'Cancel',
danger: true,
// Optional: keep the dialog open with a loading Confirm until this
// settles. Errors leave it open so the user can retry or cancel.
// onConfirm: () => this.shipments.delete(id),
})
.pipe(takeUntilDestroyed())
.subscribe((ok) => {
if (ok) {
this.deleteShipment();
}
});
}
protected confirmDismissible(): void {
this.confirm
.confirm({
title: 'Discard unsaved changes?',
message: 'Your draft note will be lost.',
confirmLabel: 'Discard',
cancelLabel: 'Keep editing',
danger: true,
dismissible: true,
// backdrop / Escape → false (same as Cancel) via ConfirmService map.
})
.pipe(takeUntilDestroyed())
.subscribe((ok) => {
if (ok) {
this.discardDraft();
}
});
}
private markDelivered(): void {
// mutation.mutate({ id, status: 'Delivered' })
}
private deleteShipment(): void {
// mutation.mutate({ id })
}
private discardDraft(): void {
// navigate away or ref.close() on parent overlay
}
}`;