@memberjunction/ng-conversations 6.1.2 → 6.2.0-edge.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/conversation-chat-area.component.js +9 -26
- package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
- package/dist/lib/components/realtime/channels/channel-onboarding-panel.component.d.ts +1 -1
- package/dist/lib/components/realtime/channels/channel-onboarding-panel.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/channels/channel-onboarding-panel.component.js.map +1 -1
- package/dist/lib/components/realtime/channels/client-context-channel.d.ts +1 -1
- package/dist/lib/components/realtime/channels/client-context-channel.d.ts.map +1 -1
- package/dist/lib/components/realtime/channels/client-context-channel.js +1 -1
- package/dist/lib/components/realtime/channels/client-context-channel.js.map +1 -1
- package/dist/lib/components/realtime/channels/realtime-channel-pane.component.d.ts +1 -1
- package/dist/lib/components/realtime/channels/realtime-channel-pane.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/channels/realtime-channel-pane.component.js +3 -0
- package/dist/lib/components/realtime/channels/realtime-channel-pane.component.js.map +1 -1
- package/dist/lib/components/realtime/media/media-channel.d.ts +2 -1
- package/dist/lib/components/realtime/media/media-channel.d.ts.map +1 -1
- package/dist/lib/components/realtime/media/media-channel.js +1 -1
- package/dist/lib/components/realtime/media/media-channel.js.map +1 -1
- package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts +1 -1
- package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-activity-rail.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts +1 -1
- package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-agent-banner.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-composer.component.d.ts +3 -1
- package/dist/lib/components/realtime/realtime-composer.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-composer.component.js +26 -8
- package/dist/lib/components/realtime/realtime-composer.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts +1 -1
- package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-delegation-card.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts +2 -2
- package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-session-overlay.component.js +1 -1
- package/dist/lib/components/realtime/realtime-session-overlay.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-session-state.d.ts +2 -3
- package/dist/lib/components/realtime/realtime-session-state.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-session-state.js +3 -2
- package/dist/lib/components/realtime/realtime-session-state.js.map +1 -1
- package/dist/lib/components/realtime/realtime-session-thread.component.d.ts +17 -1
- package/dist/lib/components/realtime/realtime-session-thread.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-session-thread.component.js +122 -45
- package/dist/lib/components/realtime/realtime-session-thread.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-session-timeline-card.component.d.ts +1 -9
- package/dist/lib/components/realtime/realtime-session-timeline-card.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-session-timeline-card.component.js +13 -43
- package/dist/lib/components/realtime/realtime-session-timeline-card.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts +2 -2
- package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-surface-tabs.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts +1 -1
- package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-surface-tabs.model.js.map +1 -1
- package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts +1 -1
- package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts.map +1 -1
- package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js +1 -1
- package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js.map +1 -1
- package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts +1 -1
- package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts.map +1 -1
- package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js +1 -1
- package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js.map +1 -1
- package/dist/lib/conversations.module.d.ts.map +1 -1
- package/dist/lib/conversations.module.js.map +1 -1
- package/dist/lib/services/browser-realtime-media-host.d.ts +24 -0
- package/dist/lib/services/browser-realtime-media-host.d.ts.map +1 -0
- package/dist/lib/services/browser-realtime-media-host.js +95 -0
- package/dist/lib/services/browser-realtime-media-host.js.map +1 -0
- package/dist/lib/services/conversation-attachment.service.d.ts +24 -2
- package/dist/lib/services/conversation-attachment.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-attachment.service.js +43 -4
- package/dist/lib/services/conversation-attachment.service.js.map +1 -1
- package/dist/lib/services/graphql-attachment-blob-store.d.ts +44 -0
- package/dist/lib/services/graphql-attachment-blob-store.d.ts.map +1 -0
- package/dist/lib/services/graphql-attachment-blob-store.js +113 -0
- package/dist/lib/services/graphql-attachment-blob-store.js.map +1 -0
- package/dist/lib/services/mention-autocomplete.service.d.ts +17 -141
- package/dist/lib/services/mention-autocomplete.service.d.ts.map +1 -1
- package/dist/lib/services/mention-autocomplete.service.js +15 -460
- package/dist/lib/services/mention-autocomplete.service.js.map +1 -1
- package/dist/lib/services/realtime-session-review.service.d.ts +1 -1
- package/dist/lib/services/realtime-session-review.service.d.ts.map +1 -1
- package/dist/lib/services/realtime-session-review.service.js +1 -1
- package/dist/lib/services/realtime-session-review.service.js.map +1 -1
- package/dist/lib/services/realtime-session.service.d.ts +16 -1150
- package/dist/lib/services/realtime-session.service.d.ts.map +1 -1
- package/dist/lib/services/realtime-session.service.js +28 -2430
- package/dist/lib/services/realtime-session.service.js.map +1 -1
- package/dist/lib/utils/realtime-session-timeline.d.ts +8 -79
- package/dist/lib/utils/realtime-session-timeline.d.ts.map +1 -1
- package/dist/lib/utils/realtime-session-timeline.js +8 -89
- package/dist/lib/utils/realtime-session-timeline.js.map +1 -1
- package/dist/public-api.d.ts +2 -2
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +6 -2
- package/dist/public-api.js.map +1 -1
- package/package.json +33 -32
- package/dist/lib/components/realtime/channels/base-realtime-channel-client.d.ts +0 -384
- package/dist/lib/components/realtime/channels/base-realtime-channel-client.d.ts.map +0 -1
- package/dist/lib/components/realtime/channels/base-realtime-channel-client.js +0 -231
- package/dist/lib/components/realtime/channels/base-realtime-channel-client.js.map +0 -1
- package/dist/lib/services/delegation-result-parser.d.ts +0 -50
- package/dist/lib/services/delegation-result-parser.d.ts.map +0 -1
- package/dist/lib/services/delegation-result-parser.js +0 -60
- package/dist/lib/services/delegation-result-parser.js.map +0 -1
- package/dist/lib/services/narration-template.d.ts +0 -42
- package/dist/lib/services/narration-template.d.ts.map +0 -1
- package/dist/lib/services/narration-template.js +0 -73
- package/dist/lib/services/narration-template.js.map +0 -1
- package/dist/lib/services/skill-picker-narrowing.d.ts +0 -13
- package/dist/lib/services/skill-picker-narrowing.d.ts.map +0 -1
- package/dist/lib/services/skill-picker-narrowing.js +0 -13
- package/dist/lib/services/skill-picker-narrowing.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"realtime-session-timeline-card.component.js","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-session-timeline-card.component.ts","../../../../src/lib/components/realtime/realtime-session-timeline-card.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;;;
|
|
1
|
+
{"version":3,"file":"realtime-session-timeline-card.component.js","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-session-timeline-card.component.ts","../../../../src/lib/components/realtime/realtime-session-timeline-card.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, EventEmitter, Input, Output } from '@angular/core';\nimport { DatePipe } from '@angular/common';\nimport {\n RealtimeSessionTimelineGroup,\n RealtimeSessionTimelineMeta,\n SessionCardIsSameDayRange,\n SessionCardStatusChip,\n SessionCardTitle\n} from '../../utils/realtime-session-timeline';\n\n/**\n * The ONE timeline element a realtime session collapses to in the standard conversation\n * message list (see `BuildConversationTimeline`): a visually distinct card at the\n * session's chronological position carrying the session identity (broadcast icon +\n * \"Realtime session · <agent>\"), its time range, a status / close-reason chip when\n * known, the visible-turn count, and a one-line preview of the last turn.\n *\n * The card's **Open** button emits {@link OpenRequested} with the session id; the\n * message list bubbles it up so the chat area can host the existing SESSION REVIEW\n * overlay via `ConversationChatAreaComponent.OpenRealtimeSessionReview` (Resume /\n * Close live inside that overlay, unchanged).\n *\n * Rendered DYNAMICALLY by `MessageListComponent` (same `createComponent` path the\n * message items use) — standalone by design, no module declaration needed.\n */\n@Component({\n standalone: true,\n selector: 'mj-realtime-session-timeline-card',\n imports: [DatePipe],\n templateUrl: './realtime-session-timeline-card.component.html',\n styleUrl: './realtime-session-timeline-card.component.css'\n})\nexport class RealtimeSessionTimelineCardComponent {\n /** The collapsed session block computed from the conversation's stamped detail rows. */\n @Input({ required: true }) Group!: RealtimeSessionTimelineGroup;\n\n /** Optional session-row enrichment (agent name / status / close reason); null degrades gracefully. */\n @Input() Meta: RealtimeSessionTimelineMeta | null = null;\n\n /** Display name of the signed-in user for the last-turn preview (matches the chat's sender names). */\n @Input() UserName = 'You';\n\n /** Emitted with the `MJ: AI Agent Sessions.ID` when the user asks to open the session review. */\n @Output() OpenRequested = new EventEmitter<string>();\n\n /*\n * Title / chip / range derivations live in `@memberjunction/conversations-runtime` alongside the\n * grouping pass, because the React Native thread renders the same card and must not re-decide\n * what \"Timed out\" means. These getters are the Angular binding surface over them, nothing more.\n */\n\n /** Card title: \"Realtime session · <agent>\" when the agent name is known, else the generic label. */\n public get Title(): string {\n return SessionCardTitle(this.Meta);\n }\n\n /** Whether the start and end fall on the same calendar day (drives the end-time format). */\n public get SameDayRange(): boolean {\n return SessionCardIsSameDayRange(this.Group);\n }\n\n /** The status chip label, or null to hide the chip entirely. */\n public get StatusChip(): string | null {\n return SessionCardStatusChip(this.Meta)?.Label ?? null;\n }\n\n /** Whether the chip represents an error close (drives the error chip styling). */\n public get IsErrorChip(): boolean {\n return SessionCardStatusChip(this.Meta)?.Tone === 'error';\n }\n\n /** Whether the chip represents a live session (drives the live chip styling). */\n public get IsLiveChip(): boolean {\n return SessionCardStatusChip(this.Meta)?.Tone === 'live';\n }\n\n /** Emits {@link OpenRequested} for the whole-card / Open-button click. */\n public Open(event?: MouseEvent): void {\n event?.stopPropagation();\n const sessionId = this.Group?.SessionID;\n if (sessionId) {\n this.OpenRequested.emit(sessionId);\n }\n }\n\n}\n","<div class=\"session-card\" role=\"group\" [attr.aria-label]=\"Title\" (click)=\"Open($event)\">\n <div class=\"session-card__icon\" aria-hidden=\"true\">\n <i class=\"fa-solid fa-tower-broadcast\"></i>\n </div>\n\n <div class=\"session-card__body\">\n <div class=\"session-card__head\">\n <span class=\"session-card__title\">{{ Title }}</span>\n @if (StatusChip) {\n <span class=\"session-card__chip\"\n [class.session-card__chip--error]=\"IsErrorChip\"\n [class.session-card__chip--live]=\"IsLiveChip\">{{ StatusChip }}</span>\n }\n </div>\n\n <div class=\"session-card__meta\">\n @if (Group.StartedAt) {\n <span class=\"session-card__range\">\n {{ Group.StartedAt | date:'MMM d, h:mm a' }}\n @if (Group.EndedAt && Group.EndedAt !== Group.StartedAt) {\n <i class=\"fa-solid fa-arrow-right-long session-card__range-arrow\" aria-hidden=\"true\"></i>\n {{ Group.EndedAt | date:(SameDayRange ? 'h:mm a' : 'MMM d, h:mm a') }}\n }\n </span>\n <span class=\"session-card__dot\" aria-hidden=\"true\">·</span>\n }\n <span class=\"session-card__turns\">{{ Group.TurnCount }} {{ Group.TurnCount === 1 ? 'turn' : 'turns' }}</span>\n </div>\n\n @if (Group.LastTurnPreview) {\n <div class=\"session-card__preview\">\n <span class=\"session-card__preview-role\">{{ Group.LastTurnRole === 'User' ? UserName : 'Agent' }}:</span>\n {{ Group.LastTurnPreview }}\n </div>\n }\n </div>\n\n <button type=\"button\" class=\"session-card__open\" (click)=\"Open($event)\"\n title=\"Open this realtime session in review mode\">\n <i class=\"fa-solid fa-up-right-from-square\" aria-hidden=\"true\"></i>\n <span>Open</span>\n </button>\n</div>\n"]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { EventEmitter, OnInit, OnDestroy } from '@angular/core';
|
|
2
2
|
import { UserInfo } from '@memberjunction/core';
|
|
3
3
|
import { RealtimeSessionState } from './realtime-session-state';
|
|
4
|
-
import { ChannelOnboardingDetails } from '
|
|
4
|
+
import { ChannelOnboardingDetails } from '@memberjunction/realtime-runtime';
|
|
5
5
|
import { RealtimeSurfaceTabsModel, RealtimeSurfaceTab, RealtimeChannelTabRegistration } from './realtime-surface-tabs.model';
|
|
6
|
-
import { ParsedDelegationArtifact } from '
|
|
6
|
+
import { ParsedDelegationArtifact } from '@memberjunction/realtime-runtime';
|
|
7
7
|
import * as i0 from "@angular/core";
|
|
8
8
|
/**
|
|
9
9
|
* The call overlay's TABBED SURFACE PANEL (the right panel) — decluttered redesign:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"realtime-surface-tabs.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-surface-tabs.component.ts"],"names":[],"mappings":"AAAA,OAAO,EACM,YAAY,EAAiB,MAAM,EAAE,SAAS,EAC1D,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGhD,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAIhE,OAAO,EAAE,wBAAwB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"realtime-surface-tabs.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-surface-tabs.component.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"realtime-surface-tabs.component.js","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-surface-tabs.component.ts","../../../../src/lib/components/realtime/realtime-surface-tabs.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component, EventEmitter, Input, Output, OnInit, OnDestroy, ChangeDetectorRef, ViewChild, inject\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { Subscription } from 'rxjs';\nimport { UserInfo } from '@memberjunction/core';\nimport { UserInfoEngine } from '@memberjunction/core-entities';\nimport { ArtifactsModule } from '@memberjunction/ng-artifacts';\nimport { RealtimeSessionState } from './realtime-session-state';\nimport { RealtimeActivityRailComponent } from './realtime-activity-rail.component';\nimport { RealtimeChannelPaneComponent } from './channels/realtime-channel-pane.component';\nimport { ChannelOnboardingPanelComponent } from './channels/channel-onboarding-panel.component';\nimport { ChannelOnboardingDetails } from './channels/base-realtime-channel-client';\nimport {\n RealtimeSurfaceTabsModel, RealtimeSurfaceTab, RealtimeChannelTabRegistration\n} from './realtime-surface-tabs.model';\nimport { ParsedDelegationArtifact } from '../../services/delegation-result-parser';\n\n/**\n * User-settings key (NOT localStorage — see `UserInfoEngine`) under which the per-user \"which\n * channel intros have been seen\" map is persisted: a JSON object of `{ [channelName]: true }`,\n * so the first-run onboarding for each interactive channel shows exactly once per user and\n * follows them across devices.\n */\nconst CHANNEL_ONBOARDING_SEEN_SETTING_KEY = 'mj.realtimeChannels.onboardingSeen.v1';\n\n/**\n * The call overlay's TABBED SURFACE PANEL (the right panel) — decluttered redesign:\n *\n * - **Channel tabs** (LEFT cluster) — one per channel that has come into play. The whiteboard\n * tabs immediately at session start; every other channel tabs only once the agent first\n * USES it. Each carries a distinct accent color + its plugin icon. The pane creates the\n * plugin's surface component dynamically (via `mj-realtime-channel-pane`); a placeholder\n * shows the \"coming online…\" state until a plugin/template is supplied.\n * - **Activity** (RIGHT-aligned, pinned LAST) — gated: appears only once ≥1 agent run has\n * occurred (or in review mode). Hosts {@link RealtimeActivityRailComponent}, which now also\n * renders inline artifact previews and a split-pane artifact viewer. Styled distinctly from\n * channel tabs (activity-pulse icon + its own accent) and separated from the channel cluster\n * by a flex spacer.\n *\n * Artifacts NO LONGER get their own tab — they live inside the Activity tab (cleaner than a\n * row of per-artifact tabs).\n *\n * Panes are kept ALIVE while hidden (CSS `display:none`) so switching tabs never reloads a\n * channel surface or resets the rail. The whole panel collapses to a slim strip via the chevron.\n *\n * SIZING IS EXTERNAL: the overlay shell hosts this panel in a fixed-width flex item and owns\n * the width. This panel just fills it and REPORTS the layout signals the shell sizes from:\n * {@link CollapsedChange} (slim-strip toggle) and {@link WideChanged} (a channel tab is focused\n * → the default width tier widens).\n */\n@Component({\n standalone: true,\n selector: 'mj-realtime-surface-tabs',\n imports: [\n CommonModule, ArtifactsModule, RealtimeActivityRailComponent, RealtimeChannelPaneComponent,\n ChannelOnboardingPanelComponent\n ],\n templateUrl: './realtime-surface-tabs.component.html',\n styleUrl: './realtime-surface-tabs.component.css'\n})\nexport class RealtimeSurfaceTabsComponent implements OnInit, OnDestroy {\n /** How long a just-revealed channel tab keeps its flash highlight. */\n private static readonly FlashDurationMs = 1400;\n\n /** Shared live-session state, owned by the overlay shell (feeds the Activity rail). */\n @Input({ required: true }) State!: RealtimeSessionState;\n\n /** Whether developer affordances (\"Open run\" links) are revealed (gear-gated). */\n @Input() DevMode = false;\n\n /**\n * FILL presentation: the panel stretches to the overlay's full width (the board-focus\n * layout, where the main call column is hidden and a channel surface owns the screen).\n * Bound by the overlay shell; overrides the normal / wide width tiers.\n */\n @Input() Fill = false;\n\n /** The signed-in user, threaded to the artifact viewer panel. */\n @Input() CurrentUser: UserInfo | null = null;\n\n /** The active environment id, threaded to the artifact viewer panel. */\n @Input() EnvironmentID = '';\n\n /**\n * Extra (review-carryover) artifacts to surface in the Activity tab, NOT tied to a live\n * activity card. Forwarded to the rail's \"Session artifacts\" group. Empty for a live session.\n */\n @Input() ExtraArtifacts: ParsedDelegationArtifact[] = [];\n\n /**\n * Whether the gated Activity tab should be shown — driven by the overlay shell once ≥1\n * agent run has occurred (or in review mode). A getter/setter so a late \"first run\" flips\n * the tab into the strip reactively.\n */\n private _showActivityTab = false;\n @Input()\n set ShowActivityTab(value: boolean) {\n if (value !== this._showActivityTab) {\n this._showActivityTab = value;\n this.Model.SetShowActivityTab(value);\n this.cdr.markForCheck();\n }\n }\n get ShowActivityTab(): boolean {\n return this._showActivityTab;\n }\n\n /** Re-emitted from the Activity rail's dev \"Open run\" links. */\n @Output() OpenRunRequested = new EventEmitter<string>();\n\n /**\n * Emitted when the panel toggles between expanded and the slim collapsed strip —\n * the overlay shell resizes this panel's split area to the strip width.\n */\n @Output() CollapsedChange = new EventEmitter<boolean>();\n\n /**\n * Emitted when {@link IsWide} flips (a channel tab gained / lost focus) — the\n * overlay shell widens the panel's DEFAULT split-area size while wide (only when\n * the user has never dragged an explicit width).\n */\n @Output() WideChanged = new EventEmitter<boolean>();\n\n /** The panel's tab state (add / focus / dedupe / flash) — see the model for the rules. */\n public readonly Model = new RealtimeSurfaceTabsModel();\n\n /** Whether the panel is collapsed to its slim strip. */\n public Collapsed = false;\n\n /** The embedded Activity rail (owns the inline artifact previews + the split-pane viewer). */\n @ViewChild(RealtimeActivityRailComponent) private activityRail?: RealtimeActivityRailComponent;\n\n private flashTimer: ReturnType<typeof setTimeout> | null = null;\n private subs: Subscription[] = [];\n private lastWide = false;\n private cdr = inject(ChangeDetectorRef);\n\n /**\n * The channel whose first-run intro is currently being shown (its `ChannelName`), or `null`\n * when no intro is up. Set when the user opens a channel tab they've never seen the intro\n * for; cleared on dismiss. Only one intro shows at a time (the active channel's).\n */\n private onboardingChannelName: string | null = null;\n /** The intro content for {@link onboardingChannelName}, mirrored for the template binding. */\n public OnboardingContent: ChannelOnboardingDetails | null = null;\n\n /** The currently focused tab. */\n public get ActiveTab(): RealtimeSurfaceTab {\n return this.Model.ActiveTab;\n }\n\n /** Wide presentation when a channel tab is focused (the Activity tab keeps the normal tier). */\n public get IsWide(): boolean {\n return !this.Collapsed && this.ActiveTab.Kind === 'channel';\n }\n\n ngOnInit(): void {\n this.subs.push(\n this.Model.Changed$.subscribe(() => this.onModelChanged())\n );\n }\n\n ngOnDestroy(): void {\n for (const s of this.subs) {\n s.unsubscribe();\n }\n this.subs = [];\n if (this.flashTimer) {\n clearTimeout(this.flashTimer);\n this.flashTimer = null;\n }\n }\n\n /** Toggle the panel between expanded and slim-collapsed. */\n public ToggleCollapsed(): void {\n this.setCollapsed(!this.Collapsed);\n }\n\n /** Collapse-state transitions funnel through here so the shell always hears about them. */\n private setCollapsed(value: boolean): void {\n if (this.Collapsed !== value) {\n this.Collapsed = value;\n this.CollapsedChange.emit(value);\n this.syncWide();\n }\n }\n\n /** Emits {@link WideChanged} when the wide tier flips (channel tab focus / collapse). */\n private syncWide(): void {\n const wide = this.IsWide;\n if (wide !== this.lastWide) {\n this.lastWide = wide;\n this.WideChanged.emit(wide);\n }\n }\n\n /** track fn for the @for over tabs. */\n public TrackTab(index: number, tab: RealtimeSurfaceTab): string {\n return tab.Key;\n }\n\n /**\n * Focuses the Activity tab and opens the given artifact in the rail's split-pane viewer —\n * the \"View →\" affordance target on done delegation cards / thread entries. Expands the\n * panel if it was collapsed. Replaces the old \"open a tab per artifact\" behavior.\n */\n public FocusArtifact(artifact: ParsedDelegationArtifact): void {\n this.setCollapsed(false);\n // An artifact implies a run happened — ensure the Activity tab is present before focusing it.\n this.Model.SetShowActivityTab(true);\n this.Model.Focus(RealtimeSurfaceTabsModel.ActivityTabKey);\n // The rail may not be created yet (panel just expanded) — defer so it exists.\n if (this.activityRail) {\n this.activityRail.OpenArtifact(artifact);\n } else {\n setTimeout(() => this.activityRail?.OpenArtifact(artifact));\n }\n this.cdr.markForCheck();\n }\n\n /**\n * Registers (or updates) an interactive-channel tab — one per used channel plugin,\n * forwarded from `RealtimeSessionOverlayComponent.RegisterChannelTab`.\n */\n public RegisterChannelTab(registration: RealtimeChannelTabRegistration): void {\n // Microtask defer: the overlay forwards this while handling agent/channel activity, which can\n // land mid change-detection. Adding a tab to Model synchronously then trips NG0100 on the\n // tab-strip bindings (s-tab--active). A microtask lands the mutation in a fresh CD turn —\n // imperceptible for an async reveal, and ordered with any follow-on RevealChannel.\n Promise.resolve().then(() => {\n this.Model.RegisterChannelTab(registration);\n this.cdr.markForCheck();\n });\n }\n\n /**\n * AUTO-REVEALS a channel surface the moment the agent first acts on it: expands the\n * panel if collapsed, focuses the channel's tab and flashes it — so the user discovers\n * the whiteboard (or any channel) exists the instant it comes alive. No-op for unknown keys.\n */\n public RevealChannel(key: string): void {\n // Microtask defer (same NG0100 reason as RegisterChannelTab): the agent-activity reveal mutates\n // ActiveKey/FlashKey, which feed the tab-strip class bindings; doing it mid-CD trips the\n // ExpressionChanged check. Deferring lands it in a fresh CD turn and stays ordered after any\n // RegisterChannelTab queued just before it.\n Promise.resolve().then(() => {\n this.setCollapsed(false);\n this.Model.Focus(key);\n this.Model.FlashTab(key);\n this.cdr.markForCheck();\n });\n }\n\n /**\n * Removes a tab from the panel (Activity is irremovable; focus falls back per the model's\n * rules). Used by the overlay shell on a review→live continuation whose live channel set\n * resolved WITHOUT the channel a stale review tab represents (e.g. no Whiteboard channel →\n * drop the read-only review board tab).\n *\n * @returns `true` when a tab was removed.\n */\n public RemoveTab(key: string): boolean {\n const removed = this.Model.RemoveTab(key);\n if (removed) {\n this.cdr.markForCheck();\n }\n return removed;\n }\n\n /**\n * Registers the reviewed chain's history artifacts so they surface inside the Activity tab.\n * In the redesign there are no per-artifact tabs — the rail picks artifacts up from the\n * session state's cards, so this only needs to ensure the Activity tab is shown (review\n * mode always shows it) and, when `focus` is set, open the artifact in the split viewer.\n */\n public RegisterArtifactTab(artifact: ParsedDelegationArtifact, focus: boolean = false): void {\n this.Model.SetShowActivityTab(true);\n if (focus) {\n this.FocusArtifact(artifact);\n }\n this.cdr.markForCheck();\n }\n\n /** On model changes: schedule the flash clear, report a wide-tier flip, re-render. */\n private onModelChanged(): void {\n this.scheduleFlashClear();\n this.syncWide();\n this.evaluateOnboarding();\n this.cdr.markForCheck();\n }\n\n /**\n * Decides whether the first-run channel intro should be visible for the ACTIVE tab: shows it\n * the first time the user opens (focuses) a channel tab whose plugin supplies onboarding and\n * which this user hasn't dismissed before. Re-runs on every model change so switching away\n * from a channel tab tears the intro down (only the active channel's intro is ever up).\n */\n private evaluateOnboarding(): void {\n const tab = this.ActiveTab;\n const plugin = tab.Kind === 'channel' ? tab.Data?.Plugin ?? null : null;\n const details = plugin?.GetOnboardingDetails() ?? null;\n if (!plugin || !details || this.HasSeenOnboarding(plugin.ChannelName)) {\n this.onboardingChannelName = null;\n this.OnboardingContent = null;\n return;\n }\n this.onboardingChannelName = plugin.ChannelName;\n this.OnboardingContent = details;\n }\n\n /**\n * Dismisses the current channel intro: marks that channel seen for this user (persisted via\n * `UserInfoEngine`, debounced — NOT localStorage) and hides the panel so it never re-appears.\n */\n public DismissOnboarding(): void {\n const channelName = this.onboardingChannelName;\n this.onboardingChannelName = null;\n this.OnboardingContent = null;\n if (channelName) {\n this.markOnboardingSeen(channelName);\n }\n this.cdr.markForCheck();\n }\n\n /** Reads the per-user seen-map and reports whether this channel's intro has been dismissed. */\n private HasSeenOnboarding(channelName: string): boolean {\n return this.readOnboardingSeen()[channelName] === true;\n }\n\n /** Persists `channelName` into the per-user seen-map (merge + debounced save). */\n private markOnboardingSeen(channelName: string): void {\n const map = this.readOnboardingSeen();\n if (map[channelName] === true) {\n return;\n }\n map[channelName] = true;\n UserInfoEngine.Instance.SetSettingDebounced(CHANNEL_ONBOARDING_SEEN_SETTING_KEY, JSON.stringify(map));\n }\n\n /** Reads + parses the per-user seen-map setting (tolerant: malformed / unset → empty map). */\n private readOnboardingSeen(): Record<string, boolean> {\n const raw = UserInfoEngine.Instance.GetSetting(CHANNEL_ONBOARDING_SEEN_SETTING_KEY);\n if (!raw) {\n return {};\n }\n try {\n const parsed: unknown = JSON.parse(raw);\n return parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)\n ? (parsed as Record<string, boolean>)\n : {};\n } catch {\n return {};\n }\n }\n\n /**\n * Focuses the FIRST tab in the strip — channels lead, so a Details peek lands on the\n * marquee surface (e.g. the Whiteboard) when one exists, else on Activity.\n */\n public FocusFirstTab(): void {\n const first = this.Model.Tabs[0];\n if (first) {\n this.Model.Focus(first.Key);\n this.cdr.markForCheck();\n }\n }\n\n /** Clears the model's flash highlight after a beat (one timer; latest flash wins). */\n private scheduleFlashClear(): void {\n if (this.Model.FlashKey === null) {\n return;\n }\n if (this.flashTimer) {\n clearTimeout(this.flashTimer);\n }\n this.flashTimer = setTimeout(() => {\n this.flashTimer = null;\n this.Model.ClearFlash();\n }, RealtimeSurfaceTabsComponent.FlashDurationMs);\n }\n}\n","<!-- SIZING IS EXTERNAL: the overlay hosts this panel inside a fixed-width flex item and\n owns its width (drag, persistence, default tiers) — the panel just fills it. -->\n<aside class=\"surface\"\n [class.surface--collapsed]=\"Collapsed\"\n [class.surface--fill]=\"Fill && !Collapsed\"\n aria-label=\"Session surfaces\">\n\n @if (Collapsed) {\n <!-- Slim strip: the panel's collapse target -->\n <div class=\"surface__strip\">\n <button type=\"button\"\n class=\"surface__toggle\"\n (click)=\"ToggleCollapsed()\"\n title=\"Show session panel\"\n aria-expanded=\"false\">\n <i class=\"fa-solid fa-chevron-left\" aria-hidden=\"true\"></i>\n </button>\n <i class=\"fa-solid fa-wave-square surface__strip-icon\" aria-hidden=\"true\" title=\"Session activity\"></i>\n </div>\n } @else {\n <!-- Tab strip: channel tabs (left cluster) … | spacer | Activity (right-aligned) -->\n <div class=\"surface-tabs\" role=\"tablist\">\n @for (tab of Model.Tabs; track TrackTab($index, tab)) {\n @if (tab.Kind === 'activity') {\n <!-- Flex spacer pushes the Activity tab to the far right -->\n <span class=\"tabs-spacer\" aria-hidden=\"true\"></span>\n }\n <button type=\"button\"\n class=\"s-tab\"\n role=\"tab\"\n [class.s-tab--activity]=\"tab.Kind === 'activity'\"\n [class.s-tab--channel]=\"tab.Kind === 'channel'\"\n [class.s-tab--active]=\"tab.Key === Model.ActiveKey\"\n [class.s-tab--flash]=\"tab.Key === Model.FlashKey\"\n [style.--tab-accent]=\"tab.Color || null\"\n [attr.aria-selected]=\"tab.Key === Model.ActiveKey\"\n [title]=\"tab.Title\"\n (click)=\"Model.Focus(tab.Key)\">\n @if (tab.Kind === 'channel') {\n <span class=\"s-tab__dot\" aria-hidden=\"true\"></span>\n }\n <i [class]=\"tab.Icon\" aria-hidden=\"true\"></i>\n <span class=\"s-tab__title\">{{ tab.Title }}</span>\n @if (tab.Kind === 'activity' && State.Cards.length > 0) {\n <span class=\"s-tab__badge\" aria-hidden=\"true\">{{ State.Cards.length }}</span>\n }\n </button>\n }\n <div class=\"tabs-end\">\n <button type=\"button\"\n class=\"surface__toggle\"\n (click)=\"ToggleCollapsed()\"\n title=\"Hide session panel\"\n aria-expanded=\"true\">\n <i class=\"fa-solid fa-chevron-right\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n\n <!-- Panes: ALL kept alive; only the active one is displayed -->\n @for (tab of Model.Tabs; track TrackTab($index, tab)) {\n <div class=\"s-pane\" [class.s-pane--active]=\"tab.Key === Model.ActiveKey\" role=\"tabpanel\">\n @switch (tab.Kind) {\n @case ('activity') {\n <mj-realtime-activity-rail\n [State]=\"State\"\n [DevMode]=\"DevMode\"\n [Embedded]=\"true\"\n [CurrentUser]=\"CurrentUser\"\n [EnvironmentID]=\"EnvironmentID\"\n [ExtraArtifacts]=\"ExtraArtifacts\"\n (OpenRunRequested)=\"OpenRunRequested.emit($event)\">\n </mj-realtime-activity-rail>\n }\n @case ('channel') {\n @if (tab.Data?.Plugin; as plugin) {\n <!-- Registry-resolved channel: the pane host creates the plugin's surface\n component dynamically and hands the instance back for binding -->\n <mj-realtime-channel-pane [Plugin]=\"plugin\"></mj-realtime-channel-pane>\n <!-- First-run intro: overlaid over the active channel pane the first time this user\n opens it; the pane host renders display:none + a sibling surface, so the overlay\n sits here (inside the positioned .s-pane) rather than inside the pane host. -->\n @if (tab.Key === Model.ActiveKey && OnboardingContent) {\n <mj-channel-onboarding-panel\n [Content]=\"OnboardingContent\"\n (Dismissed)=\"DismissOnboarding()\">\n </mj-channel-onboarding-panel>\n }\n } @else if (tab.Data?.Content; as content) {\n <ng-container [ngTemplateOutlet]=\"content\"></ng-container>\n } @else {\n <!-- Placeholder until the channel registration supplies a plugin / template -->\n <div class=\"channel-placeholder\" role=\"status\">\n <i class=\"fa-solid fa-chalkboard\" aria-hidden=\"true\"></i>\n <span>{{ tab.Title }} coming online…</span>\n </div>\n }\n }\n }\n </div>\n }\n\n @if (Model.Tabs.length === 0) {\n <!-- Nothing in play yet (idle voice-first session): a gentle hint, not an empty grid -->\n <div class=\"surface__empty\" role=\"status\">\n <i class=\"fa-solid fa-wave-square\" aria-hidden=\"true\"></i>\n <span>Surfaces appear here as the call gets going.</span>\n </div>\n }\n }\n</aside>\n"]}
|
|
1
|
+
{"version":3,"file":"realtime-surface-tabs.component.js","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-surface-tabs.component.ts","../../../../src/lib/components/realtime/realtime-surface-tabs.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component, EventEmitter, Input, Output, OnInit, OnDestroy, ChangeDetectorRef, ViewChild, inject\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { Subscription } from 'rxjs';\nimport { UserInfo } from '@memberjunction/core';\nimport { UserInfoEngine } from '@memberjunction/core-entities';\nimport { ArtifactsModule } from '@memberjunction/ng-artifacts';\nimport { RealtimeSessionState } from './realtime-session-state';\nimport { RealtimeActivityRailComponent } from './realtime-activity-rail.component';\nimport { RealtimeChannelPaneComponent } from './channels/realtime-channel-pane.component';\nimport { ChannelOnboardingPanelComponent } from './channels/channel-onboarding-panel.component';\nimport { ChannelOnboardingDetails } from '@memberjunction/realtime-runtime';\nimport {\n RealtimeSurfaceTabsModel, RealtimeSurfaceTab, RealtimeChannelTabRegistration\n} from './realtime-surface-tabs.model';\nimport { ParsedDelegationArtifact } from '@memberjunction/realtime-runtime';\n\n/**\n * User-settings key (NOT localStorage — see `UserInfoEngine`) under which the per-user \"which\n * channel intros have been seen\" map is persisted: a JSON object of `{ [channelName]: true }`,\n * so the first-run onboarding for each interactive channel shows exactly once per user and\n * follows them across devices.\n */\nconst CHANNEL_ONBOARDING_SEEN_SETTING_KEY = 'mj.realtimeChannels.onboardingSeen.v1';\n\n/**\n * The call overlay's TABBED SURFACE PANEL (the right panel) — decluttered redesign:\n *\n * - **Channel tabs** (LEFT cluster) — one per channel that has come into play. The whiteboard\n * tabs immediately at session start; every other channel tabs only once the agent first\n * USES it. Each carries a distinct accent color + its plugin icon. The pane creates the\n * plugin's surface component dynamically (via `mj-realtime-channel-pane`); a placeholder\n * shows the \"coming online…\" state until a plugin/template is supplied.\n * - **Activity** (RIGHT-aligned, pinned LAST) — gated: appears only once ≥1 agent run has\n * occurred (or in review mode). Hosts {@link RealtimeActivityRailComponent}, which now also\n * renders inline artifact previews and a split-pane artifact viewer. Styled distinctly from\n * channel tabs (activity-pulse icon + its own accent) and separated from the channel cluster\n * by a flex spacer.\n *\n * Artifacts NO LONGER get their own tab — they live inside the Activity tab (cleaner than a\n * row of per-artifact tabs).\n *\n * Panes are kept ALIVE while hidden (CSS `display:none`) so switching tabs never reloads a\n * channel surface or resets the rail. The whole panel collapses to a slim strip via the chevron.\n *\n * SIZING IS EXTERNAL: the overlay shell hosts this panel in a fixed-width flex item and owns\n * the width. This panel just fills it and REPORTS the layout signals the shell sizes from:\n * {@link CollapsedChange} (slim-strip toggle) and {@link WideChanged} (a channel tab is focused\n * → the default width tier widens).\n */\n@Component({\n standalone: true,\n selector: 'mj-realtime-surface-tabs',\n imports: [\n CommonModule, ArtifactsModule, RealtimeActivityRailComponent, RealtimeChannelPaneComponent,\n ChannelOnboardingPanelComponent\n ],\n templateUrl: './realtime-surface-tabs.component.html',\n styleUrl: './realtime-surface-tabs.component.css'\n})\nexport class RealtimeSurfaceTabsComponent implements OnInit, OnDestroy {\n /** How long a just-revealed channel tab keeps its flash highlight. */\n private static readonly FlashDurationMs = 1400;\n\n /** Shared live-session state, owned by the overlay shell (feeds the Activity rail). */\n @Input({ required: true }) State!: RealtimeSessionState;\n\n /** Whether developer affordances (\"Open run\" links) are revealed (gear-gated). */\n @Input() DevMode = false;\n\n /**\n * FILL presentation: the panel stretches to the overlay's full width (the board-focus\n * layout, where the main call column is hidden and a channel surface owns the screen).\n * Bound by the overlay shell; overrides the normal / wide width tiers.\n */\n @Input() Fill = false;\n\n /** The signed-in user, threaded to the artifact viewer panel. */\n @Input() CurrentUser: UserInfo | null = null;\n\n /** The active environment id, threaded to the artifact viewer panel. */\n @Input() EnvironmentID = '';\n\n /**\n * Extra (review-carryover) artifacts to surface in the Activity tab, NOT tied to a live\n * activity card. Forwarded to the rail's \"Session artifacts\" group. Empty for a live session.\n */\n @Input() ExtraArtifacts: ParsedDelegationArtifact[] = [];\n\n /**\n * Whether the gated Activity tab should be shown — driven by the overlay shell once ≥1\n * agent run has occurred (or in review mode). A getter/setter so a late \"first run\" flips\n * the tab into the strip reactively.\n */\n private _showActivityTab = false;\n @Input()\n set ShowActivityTab(value: boolean) {\n if (value !== this._showActivityTab) {\n this._showActivityTab = value;\n this.Model.SetShowActivityTab(value);\n this.cdr.markForCheck();\n }\n }\n get ShowActivityTab(): boolean {\n return this._showActivityTab;\n }\n\n /** Re-emitted from the Activity rail's dev \"Open run\" links. */\n @Output() OpenRunRequested = new EventEmitter<string>();\n\n /**\n * Emitted when the panel toggles between expanded and the slim collapsed strip —\n * the overlay shell resizes this panel's split area to the strip width.\n */\n @Output() CollapsedChange = new EventEmitter<boolean>();\n\n /**\n * Emitted when {@link IsWide} flips (a channel tab gained / lost focus) — the\n * overlay shell widens the panel's DEFAULT split-area size while wide (only when\n * the user has never dragged an explicit width).\n */\n @Output() WideChanged = new EventEmitter<boolean>();\n\n /** The panel's tab state (add / focus / dedupe / flash) — see the model for the rules. */\n public readonly Model = new RealtimeSurfaceTabsModel();\n\n /** Whether the panel is collapsed to its slim strip. */\n public Collapsed = false;\n\n /** The embedded Activity rail (owns the inline artifact previews + the split-pane viewer). */\n @ViewChild(RealtimeActivityRailComponent) private activityRail?: RealtimeActivityRailComponent;\n\n private flashTimer: ReturnType<typeof setTimeout> | null = null;\n private subs: Subscription[] = [];\n private lastWide = false;\n private cdr = inject(ChangeDetectorRef);\n\n /**\n * The channel whose first-run intro is currently being shown (its `ChannelName`), or `null`\n * when no intro is up. Set when the user opens a channel tab they've never seen the intro\n * for; cleared on dismiss. Only one intro shows at a time (the active channel's).\n */\n private onboardingChannelName: string | null = null;\n /** The intro content for {@link onboardingChannelName}, mirrored for the template binding. */\n public OnboardingContent: ChannelOnboardingDetails | null = null;\n\n /** The currently focused tab. */\n public get ActiveTab(): RealtimeSurfaceTab {\n return this.Model.ActiveTab;\n }\n\n /** Wide presentation when a channel tab is focused (the Activity tab keeps the normal tier). */\n public get IsWide(): boolean {\n return !this.Collapsed && this.ActiveTab.Kind === 'channel';\n }\n\n ngOnInit(): void {\n this.subs.push(\n this.Model.Changed$.subscribe(() => this.onModelChanged())\n );\n }\n\n ngOnDestroy(): void {\n for (const s of this.subs) {\n s.unsubscribe();\n }\n this.subs = [];\n if (this.flashTimer) {\n clearTimeout(this.flashTimer);\n this.flashTimer = null;\n }\n }\n\n /** Toggle the panel between expanded and slim-collapsed. */\n public ToggleCollapsed(): void {\n this.setCollapsed(!this.Collapsed);\n }\n\n /** Collapse-state transitions funnel through here so the shell always hears about them. */\n private setCollapsed(value: boolean): void {\n if (this.Collapsed !== value) {\n this.Collapsed = value;\n this.CollapsedChange.emit(value);\n this.syncWide();\n }\n }\n\n /** Emits {@link WideChanged} when the wide tier flips (channel tab focus / collapse). */\n private syncWide(): void {\n const wide = this.IsWide;\n if (wide !== this.lastWide) {\n this.lastWide = wide;\n this.WideChanged.emit(wide);\n }\n }\n\n /** track fn for the @for over tabs. */\n public TrackTab(index: number, tab: RealtimeSurfaceTab): string {\n return tab.Key;\n }\n\n /**\n * Focuses the Activity tab and opens the given artifact in the rail's split-pane viewer —\n * the \"View →\" affordance target on done delegation cards / thread entries. Expands the\n * panel if it was collapsed. Replaces the old \"open a tab per artifact\" behavior.\n */\n public FocusArtifact(artifact: ParsedDelegationArtifact): void {\n this.setCollapsed(false);\n // An artifact implies a run happened — ensure the Activity tab is present before focusing it.\n this.Model.SetShowActivityTab(true);\n this.Model.Focus(RealtimeSurfaceTabsModel.ActivityTabKey);\n // The rail may not be created yet (panel just expanded) — defer so it exists.\n if (this.activityRail) {\n this.activityRail.OpenArtifact(artifact);\n } else {\n setTimeout(() => this.activityRail?.OpenArtifact(artifact));\n }\n this.cdr.markForCheck();\n }\n\n /**\n * Registers (or updates) an interactive-channel tab — one per used channel plugin,\n * forwarded from `RealtimeSessionOverlayComponent.RegisterChannelTab`.\n */\n public RegisterChannelTab(registration: RealtimeChannelTabRegistration): void {\n // Microtask defer: the overlay forwards this while handling agent/channel activity, which can\n // land mid change-detection. Adding a tab to Model synchronously then trips NG0100 on the\n // tab-strip bindings (s-tab--active). A microtask lands the mutation in a fresh CD turn —\n // imperceptible for an async reveal, and ordered with any follow-on RevealChannel.\n Promise.resolve().then(() => {\n this.Model.RegisterChannelTab(registration);\n this.cdr.markForCheck();\n });\n }\n\n /**\n * AUTO-REVEALS a channel surface the moment the agent first acts on it: expands the\n * panel if collapsed, focuses the channel's tab and flashes it — so the user discovers\n * the whiteboard (or any channel) exists the instant it comes alive. No-op for unknown keys.\n */\n public RevealChannel(key: string): void {\n // Microtask defer (same NG0100 reason as RegisterChannelTab): the agent-activity reveal mutates\n // ActiveKey/FlashKey, which feed the tab-strip class bindings; doing it mid-CD trips the\n // ExpressionChanged check. Deferring lands it in a fresh CD turn and stays ordered after any\n // RegisterChannelTab queued just before it.\n Promise.resolve().then(() => {\n this.setCollapsed(false);\n this.Model.Focus(key);\n this.Model.FlashTab(key);\n this.cdr.markForCheck();\n });\n }\n\n /**\n * Removes a tab from the panel (Activity is irremovable; focus falls back per the model's\n * rules). Used by the overlay shell on a review→live continuation whose live channel set\n * resolved WITHOUT the channel a stale review tab represents (e.g. no Whiteboard channel →\n * drop the read-only review board tab).\n *\n * @returns `true` when a tab was removed.\n */\n public RemoveTab(key: string): boolean {\n const removed = this.Model.RemoveTab(key);\n if (removed) {\n this.cdr.markForCheck();\n }\n return removed;\n }\n\n /**\n * Registers the reviewed chain's history artifacts so they surface inside the Activity tab.\n * In the redesign there are no per-artifact tabs — the rail picks artifacts up from the\n * session state's cards, so this only needs to ensure the Activity tab is shown (review\n * mode always shows it) and, when `focus` is set, open the artifact in the split viewer.\n */\n public RegisterArtifactTab(artifact: ParsedDelegationArtifact, focus: boolean = false): void {\n this.Model.SetShowActivityTab(true);\n if (focus) {\n this.FocusArtifact(artifact);\n }\n this.cdr.markForCheck();\n }\n\n /** On model changes: schedule the flash clear, report a wide-tier flip, re-render. */\n private onModelChanged(): void {\n this.scheduleFlashClear();\n this.syncWide();\n this.evaluateOnboarding();\n this.cdr.markForCheck();\n }\n\n /**\n * Decides whether the first-run channel intro should be visible for the ACTIVE tab: shows it\n * the first time the user opens (focuses) a channel tab whose plugin supplies onboarding and\n * which this user hasn't dismissed before. Re-runs on every model change so switching away\n * from a channel tab tears the intro down (only the active channel's intro is ever up).\n */\n private evaluateOnboarding(): void {\n const tab = this.ActiveTab;\n const plugin = tab.Kind === 'channel' ? tab.Data?.Plugin ?? null : null;\n const details = plugin?.GetOnboardingDetails() ?? null;\n if (!plugin || !details || this.HasSeenOnboarding(plugin.ChannelName)) {\n this.onboardingChannelName = null;\n this.OnboardingContent = null;\n return;\n }\n this.onboardingChannelName = plugin.ChannelName;\n this.OnboardingContent = details;\n }\n\n /**\n * Dismisses the current channel intro: marks that channel seen for this user (persisted via\n * `UserInfoEngine`, debounced — NOT localStorage) and hides the panel so it never re-appears.\n */\n public DismissOnboarding(): void {\n const channelName = this.onboardingChannelName;\n this.onboardingChannelName = null;\n this.OnboardingContent = null;\n if (channelName) {\n this.markOnboardingSeen(channelName);\n }\n this.cdr.markForCheck();\n }\n\n /** Reads the per-user seen-map and reports whether this channel's intro has been dismissed. */\n private HasSeenOnboarding(channelName: string): boolean {\n return this.readOnboardingSeen()[channelName] === true;\n }\n\n /** Persists `channelName` into the per-user seen-map (merge + debounced save). */\n private markOnboardingSeen(channelName: string): void {\n const map = this.readOnboardingSeen();\n if (map[channelName] === true) {\n return;\n }\n map[channelName] = true;\n UserInfoEngine.Instance.SetSettingDebounced(CHANNEL_ONBOARDING_SEEN_SETTING_KEY, JSON.stringify(map));\n }\n\n /** Reads + parses the per-user seen-map setting (tolerant: malformed / unset → empty map). */\n private readOnboardingSeen(): Record<string, boolean> {\n const raw = UserInfoEngine.Instance.GetSetting(CHANNEL_ONBOARDING_SEEN_SETTING_KEY);\n if (!raw) {\n return {};\n }\n try {\n const parsed: unknown = JSON.parse(raw);\n return parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)\n ? (parsed as Record<string, boolean>)\n : {};\n } catch {\n return {};\n }\n }\n\n /**\n * Focuses the FIRST tab in the strip — channels lead, so a Details peek lands on the\n * marquee surface (e.g. the Whiteboard) when one exists, else on Activity.\n */\n public FocusFirstTab(): void {\n const first = this.Model.Tabs[0];\n if (first) {\n this.Model.Focus(first.Key);\n this.cdr.markForCheck();\n }\n }\n\n /** Clears the model's flash highlight after a beat (one timer; latest flash wins). */\n private scheduleFlashClear(): void {\n if (this.Model.FlashKey === null) {\n return;\n }\n if (this.flashTimer) {\n clearTimeout(this.flashTimer);\n }\n this.flashTimer = setTimeout(() => {\n this.flashTimer = null;\n this.Model.ClearFlash();\n }, RealtimeSurfaceTabsComponent.FlashDurationMs);\n }\n}\n","<!-- SIZING IS EXTERNAL: the overlay hosts this panel inside a fixed-width flex item and\n owns its width (drag, persistence, default tiers) — the panel just fills it. -->\n<aside class=\"surface\"\n [class.surface--collapsed]=\"Collapsed\"\n [class.surface--fill]=\"Fill && !Collapsed\"\n aria-label=\"Session surfaces\">\n\n @if (Collapsed) {\n <!-- Slim strip: the panel's collapse target -->\n <div class=\"surface__strip\">\n <button type=\"button\"\n class=\"surface__toggle\"\n (click)=\"ToggleCollapsed()\"\n title=\"Show session panel\"\n aria-expanded=\"false\">\n <i class=\"fa-solid fa-chevron-left\" aria-hidden=\"true\"></i>\n </button>\n <i class=\"fa-solid fa-wave-square surface__strip-icon\" aria-hidden=\"true\" title=\"Session activity\"></i>\n </div>\n } @else {\n <!-- Tab strip: channel tabs (left cluster) … | spacer | Activity (right-aligned) -->\n <div class=\"surface-tabs\" role=\"tablist\">\n @for (tab of Model.Tabs; track TrackTab($index, tab)) {\n @if (tab.Kind === 'activity') {\n <!-- Flex spacer pushes the Activity tab to the far right -->\n <span class=\"tabs-spacer\" aria-hidden=\"true\"></span>\n }\n <button type=\"button\"\n class=\"s-tab\"\n role=\"tab\"\n [class.s-tab--activity]=\"tab.Kind === 'activity'\"\n [class.s-tab--channel]=\"tab.Kind === 'channel'\"\n [class.s-tab--active]=\"tab.Key === Model.ActiveKey\"\n [class.s-tab--flash]=\"tab.Key === Model.FlashKey\"\n [style.--tab-accent]=\"tab.Color || null\"\n [attr.aria-selected]=\"tab.Key === Model.ActiveKey\"\n [title]=\"tab.Title\"\n (click)=\"Model.Focus(tab.Key)\">\n @if (tab.Kind === 'channel') {\n <span class=\"s-tab__dot\" aria-hidden=\"true\"></span>\n }\n <i [class]=\"tab.Icon\" aria-hidden=\"true\"></i>\n <span class=\"s-tab__title\">{{ tab.Title }}</span>\n @if (tab.Kind === 'activity' && State.Cards.length > 0) {\n <span class=\"s-tab__badge\" aria-hidden=\"true\">{{ State.Cards.length }}</span>\n }\n </button>\n }\n <div class=\"tabs-end\">\n <button type=\"button\"\n class=\"surface__toggle\"\n (click)=\"ToggleCollapsed()\"\n title=\"Hide session panel\"\n aria-expanded=\"true\">\n <i class=\"fa-solid fa-chevron-right\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n\n <!-- Panes: ALL kept alive; only the active one is displayed -->\n @for (tab of Model.Tabs; track TrackTab($index, tab)) {\n <div class=\"s-pane\" [class.s-pane--active]=\"tab.Key === Model.ActiveKey\" role=\"tabpanel\">\n @switch (tab.Kind) {\n @case ('activity') {\n <mj-realtime-activity-rail\n [State]=\"State\"\n [DevMode]=\"DevMode\"\n [Embedded]=\"true\"\n [CurrentUser]=\"CurrentUser\"\n [EnvironmentID]=\"EnvironmentID\"\n [ExtraArtifacts]=\"ExtraArtifacts\"\n (OpenRunRequested)=\"OpenRunRequested.emit($event)\">\n </mj-realtime-activity-rail>\n }\n @case ('channel') {\n @if (tab.Data?.Plugin; as plugin) {\n <!-- Registry-resolved channel: the pane host creates the plugin's surface\n component dynamically and hands the instance back for binding -->\n <mj-realtime-channel-pane [Plugin]=\"plugin\"></mj-realtime-channel-pane>\n <!-- First-run intro: overlaid over the active channel pane the first time this user\n opens it; the pane host renders display:none + a sibling surface, so the overlay\n sits here (inside the positioned .s-pane) rather than inside the pane host. -->\n @if (tab.Key === Model.ActiveKey && OnboardingContent) {\n <mj-channel-onboarding-panel\n [Content]=\"OnboardingContent\"\n (Dismissed)=\"DismissOnboarding()\">\n </mj-channel-onboarding-panel>\n }\n } @else if (tab.Data?.Content; as content) {\n <ng-container [ngTemplateOutlet]=\"content\"></ng-container>\n } @else {\n <!-- Placeholder until the channel registration supplies a plugin / template -->\n <div class=\"channel-placeholder\" role=\"status\">\n <i class=\"fa-solid fa-chalkboard\" aria-hidden=\"true\"></i>\n <span>{{ tab.Title }} coming online…</span>\n </div>\n }\n }\n }\n </div>\n }\n\n @if (Model.Tabs.length === 0) {\n <!-- Nothing in play yet (idle voice-first session): a gentle hint, not an empty grid -->\n <div class=\"surface__empty\" role=\"status\">\n <i class=\"fa-solid fa-wave-square\" aria-hidden=\"true\"></i>\n <span>Surfaces appear here as the call gets going.</span>\n </div>\n }\n }\n</aside>\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Subject } from 'rxjs';
|
|
2
2
|
import type { TemplateRef } from '@angular/core';
|
|
3
|
-
import type { BaseRealtimeChannelClient } from '
|
|
3
|
+
import type { BaseRealtimeChannelClient } from '@memberjunction/realtime-runtime';
|
|
4
4
|
/**
|
|
5
5
|
* The kind of a surface-panel tab:
|
|
6
6
|
* - `activity` — the session-activity tab (pinned LAST, right-aligned). Hosts the activity
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"realtime-surface-tabs.model.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-surface-tabs.model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"realtime-surface-tabs.model.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-surface-tabs.model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAGlF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,sBAAsB,GAAG,UAAU,GAAG,SAAS,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,MAAM,CAAC,EAAE,yBAAyB,CAAC;IACnC;;;;OAIG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;CAChC;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,uEAAuE;IACvE,GAAG,EAAE,MAAM,CAAC;IACZ,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,iFAAiF;IACjF,IAAI,EAAE,MAAM,CAAC;IACb,4BAA4B;IAC5B,IAAI,EAAE,sBAAsB,CAAC;IAC7B;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,IAAI,CAAC,EAAE,sBAAsB,CAAC;CAC/B;AAED;;;;GAIG;AACH,MAAM,WAAW,8BAA8B;IAC7C,uHAAuH;IACvH,GAAG,EAAE,MAAM,CAAC;IACZ,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,iGAAiG;IACjG,MAAM,CAAC,EAAE,yBAAyB,CAAC;IACnC,6GAA6G;IAC7G,OAAO,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IAC/B,sEAAsE;IACtE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,wBAAwB;IACnC,8EAA8E;IAC9E,gBAAuB,cAAc,cAAc;IAEnD,wFAAwF;IACxF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAKjC;IAEF,wFAAwF;IACxF,OAAO,CAAC,WAAW,CAA4B;IAE/C,wFAAwF;IACxF,OAAO,CAAC,YAAY,CAAS;IAE7B,wCAAwC;IACjC,SAAS,EAAE,MAAM,CAA2C;IAEnE;;;;OAIG;IACI,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEtC,iFAAiF;IACjF,SAAgB,QAAQ,gBAAuB;IAE/C;;;OAGG;IACH,IAAW,IAAI,IAAI,kBAAkB,EAAE,CAItC;IAED,+DAA+D;IAC/D,IAAW,eAAe,IAAI,OAAO,CAEpC;IAED;;;;OAIG;IACH,IAAW,SAAS,IAAI,kBAAkB,CAMzC;IAED;;;;;;OAMG;IACI,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAW9C;;;;;;;;;OASG;IACI,kBAAkB,CAAC,YAAY,EAAE,8BAA8B,GAAG,kBAAkB;IAwB3F,qFAAqF;IAC9E,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAQ/B;;;;;OAKG;IACI,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAQlC;;;;;;;;;;OAUG;IACI,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAiBtC,mFAAmF;IAC5E,UAAU,IAAI,IAAI;CAM1B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,+BAA+B,CAC7C,iBAAiB,EAAE,OAAO,EAC1B,6BAA6B,EAAE,OAAO,EACtC,YAAY,EAAE,aAAa,CAAC;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,GACnD,OAAO,CAKT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"realtime-surface-tabs.model.js","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-surface-tabs.model.ts"],"names":[],"mappings":"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","sourcesContent":["import { Subject } from 'rxjs';\nimport type { TemplateRef } from '@angular/core';\nimport type { BaseRealtimeChannelClient } from './channels/base-realtime-channel-client';\nimport { ChannelTabColor } from './realtime-surface-tab-style';\n\n/**\n * The kind of a surface-panel tab:\n * - `activity` — the session-activity tab (pinned LAST, right-aligned). Hosts the activity\n * rail AND, since the artifact redesign, the inline artifact previews + the split-pane\n * artifact viewer. Shown only once ≥1 agent run has occurred (see\n * {@link RealtimeSurfaceTabsModel.SetShowActivityTab}).\n * - `channel` — an interactive-channel surface (e.g. the Whiteboard). Registered per\n * used channel via {@link RealtimeSurfaceTabsModel.RegisterChannelTab}; renders the\n * plugin's dynamically-created surface component (or a registered template for\n * legacy/template-based panes), with the \"coming online…\" placeholder until either\n * is supplied.\n *\n * NOTE: artifacts NO LONGER get their own tab. A delegated run's artifacts now render\n * INSIDE the Activity tab (inline previews + an `as-split` viewer pane) — see\n * `RealtimeActivityRailComponent`.\n */\nexport type RealtimeSurfaceTabKind = 'activity' | 'channel';\n\n/**\n * Per-kind payload carried on a {@link RealtimeSurfaceTab}.\n */\nexport interface RealtimeSurfaceTabData {\n /**\n * For `channel` tabs: the channel PLUGIN whose surface component the pane creates\n * dynamically (and binds back to the plugin) — the registry-driven path every real\n * channel uses. Takes precedence over {@link Content}.\n */\n Plugin?: BaseRealtimeChannelClient;\n /**\n * For `channel` tabs: a TEMPLATE-based pane body. Backward-compatible alternative to\n * {@link Plugin} for hosts that render a bespoke surface without a channel plugin.\n * When BOTH are absent the pane renders the built-in \"coming online…\" placeholder.\n */\n Content?: TemplateRef<unknown>;\n}\n\n/**\n * One tab on the call overlay's tabbed surface panel (the right panel): a channel surface\n * (left cluster) or the session-activity tab (right-aligned).\n */\nexport interface RealtimeSurfaceTab {\n /** Stable unique key (`activity`, or the channel's registered key). */\n Key: string;\n /** Tab strip label (channel name, or \"Activity\"). */\n Title: string;\n /** Font Awesome icon class for the tab strip (e.g. `fa-solid fa-chalkboard`). */\n Icon: string;\n /** What the tab renders. */\n Kind: RealtimeSurfaceTabKind;\n /**\n * Accent color for the tab's dot + active underline. Channel tabs carry a distinct color\n * (plugin-supplied or a deterministic hash of the name); the Activity tab uses its own\n * fixed accent in CSS, so its `Color` is left undefined.\n */\n Color?: string;\n /** Kind-specific payload. */\n Data?: RealtimeSurfaceTabData;\n}\n\n/**\n * Registration for an interactive-channel tab. The overlay shell registers one per\n * USED channel plugin (supplying {@link Plugin}); supplying {@link Plugin} or\n * {@link Content} later under the same `Key` upgrades a placeholder tab to the real surface.\n */\nexport interface RealtimeChannelTabRegistration {\n /** Stable channel key (the plugin's `ChannelName`, e.g. `Whiteboard`). Re-registering the same key updates the tab. */\n Key: string;\n /** Tab strip label (e.g. `Whiteboard`). */\n Title: string;\n /** Font Awesome icon class (e.g. `fa-solid fa-chalkboard`). */\n Icon: string;\n /**\n * Optional explicit accent color for the tab. When omitted, a deterministic color is\n * derived from {@link Key} so every channel tab still reads as a distinct surface.\n */\n Color?: string | null;\n /** The channel plugin whose surface the pane creates + binds. Preferred over {@link Content}. */\n Plugin?: BaseRealtimeChannelClient;\n /** A template-based pane body (legacy/bespoke panes). Omit both to show the \"coming online…\" placeholder. */\n Content?: TemplateRef<unknown>;\n /** Focus the tab immediately after registration (default `false`). */\n Focus?: boolean;\n}\n\n/**\n * Framework-free state for the call overlay's tabbed surface panel: the ordered tab list\n * (CHANNEL tabs first — the marquee surfaces, left cluster — with the session-activity tab\n * pinned LAST and right-aligned by the strip), the active tab, and the transient \"flash\"\n * highlight for a just-revealed channel tab.\n *\n * The Activity tab is GATED: it isn't listed until {@link SetShowActivityTab}(true) — i.e.\n * once ≥1 agent run has occurred (or in review mode). Channel tabs appear only as channels\n * come into play (the whiteboard up-front; every other channel on first use), so an\n * idle voice-first session shows an empty/near-empty strip rather than a row of unused tabs.\n *\n * Owned by `RealtimeSurfaceTabsComponent`; kept free of Angular runtime imports so the\n * add / focus / dedupe / flash logic is unit-testable in isolation. All collections are\n * REPLACED (never mutated) on change, and every change emits {@link Changed$}.\n */\nexport class RealtimeSurfaceTabsModel {\n /** The fixed key of the session-activity tab (pinned LAST, right-aligned). */\n public static readonly ActivityTabKey = 'activity';\n\n /** The activity tab definition, appended last whenever {@link showActivity} is true. */\n private static readonly ActivityTab: RealtimeSurfaceTab = {\n Key: RealtimeSurfaceTabsModel.ActivityTabKey,\n Title: 'Activity',\n Icon: 'fa-solid fa-wave-square',\n Kind: 'activity'\n };\n\n /** Channel tabs (left cluster), in registration order. Replaced immutably on change. */\n private channelTabs: RealtimeSurfaceTab[] = [];\n\n /** Whether the gated Activity tab is currently shown (≥1 agent run, or review mode). */\n private showActivity = false;\n\n /** Key of the currently focused tab. */\n public ActiveKey: string = RealtimeSurfaceTabsModel.ActivityTabKey;\n\n /**\n * Key of the tab currently \"flashing\" (the brief highlight a just-revealed channel tab\n * gets when the agent first acts on it). Cleared by the owning component after a beat via\n * {@link ClearFlash}.\n */\n public FlashKey: string | null = null;\n\n /** Emits after every model change so the owning component can mark for check. */\n public readonly Changed$ = new Subject<void>();\n\n /**\n * The ordered tabs: channel tabs (left), then the Activity tab LAST when shown. The strip\n * right-aligns the Activity tab via a flex spacer, so this order also matches reading order.\n */\n public get Tabs(): RealtimeSurfaceTab[] {\n return this.showActivity\n ? [...this.channelTabs, RealtimeSurfaceTabsModel.ActivityTab]\n : [...this.channelTabs];\n }\n\n /** Whether the Activity tab is currently part of the strip. */\n public get IsActivityShown(): boolean {\n return this.showActivity;\n }\n\n /**\n * The currently focused tab. Resolves to the active key when it still exists, else falls\n * back to the Activity tab (when shown), else the first channel tab, else the Activity tab\n * definition (so a consumer always has SOMETHING to render even on an empty strip).\n */\n public get ActiveTab(): RealtimeSurfaceTab {\n const tabs = this.Tabs;\n return tabs.find(t => t.Key === this.ActiveKey)\n ?? tabs.find(t => t.Key === RealtimeSurfaceTabsModel.ActivityTabKey)\n ?? tabs[0]\n ?? RealtimeSurfaceTabsModel.ActivityTab;\n }\n\n /**\n * Shows or hides the gated Activity tab. Turning it ON when an empty strip was implicitly\n * focusing Activity keeps focus on Activity; turning it OFF while it was focused falls\n * focus back to the first channel tab (if any). No-op (no emission) when unchanged.\n *\n * @param show Whether ≥1 agent run has occurred (or review mode) — the gate.\n */\n public SetShowActivityTab(show: boolean): void {\n if (this.showActivity === show) {\n return;\n }\n this.showActivity = show;\n if (!show && this.ActiveKey === RealtimeSurfaceTabsModel.ActivityTabKey) {\n this.ActiveKey = this.channelTabs[0]?.Key ?? RealtimeSurfaceTabsModel.ActivityTabKey;\n }\n this.Changed$.next();\n }\n\n /**\n * Registers (or updates) an interactive-channel tab. Re-registering an existing key\n * replaces its title/icon/color/plugin/content in place (this is how a placeholder\n * upgrades to the real surface once the channel comes online). New channel tabs join the\n * left cluster in registration order. A registration without an explicit {@link\n * RealtimeChannelTabRegistration.Color} gets a deterministic color from its key.\n *\n * @param registration The channel tab registration.\n * @returns The (new or updated) tab.\n */\n public RegisterChannelTab(registration: RealtimeChannelTabRegistration): RealtimeSurfaceTab {\n const tab: RealtimeSurfaceTab = {\n Key: registration.Key,\n Title: registration.Title,\n Icon: registration.Icon,\n Kind: 'channel',\n Color: registration.Color ?? ChannelTabColor(registration.Key),\n Data: { Plugin: registration.Plugin, Content: registration.Content }\n };\n const idx = this.channelTabs.findIndex(t => t.Key === registration.Key);\n if (idx >= 0) {\n const next = [...this.channelTabs];\n next[idx] = tab;\n this.channelTabs = next;\n } else {\n this.channelTabs = [...this.channelTabs, tab];\n }\n if (registration.Focus) {\n this.ActiveKey = tab.Key;\n }\n this.Changed$.next();\n return tab;\n }\n\n /** Focuses the tab with `key` (no-op when it doesn't exist or is already active). */\n public Focus(key: string): void {\n if (!this.Tabs.some(t => t.Key === key) || this.ActiveKey === key) {\n return;\n }\n this.ActiveKey = key;\n this.Changed$.next();\n }\n\n /**\n * Marks the tab with `key` as the {@link FlashKey} (the brief \"just arrived\" highlight)\n * WITHOUT changing focus — used by the auto-reveal path when the agent first acts on a\n * channel, so the user's eye lands on the tab that just came alive. No-op for unknown\n * keys; the owning component clears it after a beat via {@link ClearFlash}.\n */\n public FlashTab(key: string): void {\n if (this.FlashKey === key || !this.Tabs.some(t => t.Key === key)) {\n return;\n }\n this.FlashKey = key;\n this.Changed$.next();\n }\n\n /**\n * Removes the channel tab with `key`. Rules:\n * - the Activity tab is IRREMOVABLE — removing it is a no-op;\n * - an unknown key is a no-op (returns `false`);\n * - when the removed tab was focused, focus falls back to the Activity tab (if shown),\n * else the first remaining channel tab;\n * - a pending flash on the removed tab is cleaned up so the highlight can't dangle.\n *\n * @param key The tab key to remove.\n * @returns `true` when a tab was removed.\n */\n public RemoveTab(key: string): boolean {\n if (key === RealtimeSurfaceTabsModel.ActivityTabKey || !this.channelTabs.some(t => t.Key === key)) {\n return false;\n }\n this.channelTabs = this.channelTabs.filter(t => t.Key !== key);\n if (this.ActiveKey === key) {\n this.ActiveKey = this.showActivity\n ? RealtimeSurfaceTabsModel.ActivityTabKey\n : (this.channelTabs[0]?.Key ?? RealtimeSurfaceTabsModel.ActivityTabKey);\n }\n if (this.FlashKey === key) {\n this.FlashKey = null;\n }\n this.Changed$.next();\n return true;\n }\n\n /** Clears the transient flash highlight (called by the component after a beat). */\n public ClearFlash(): void {\n if (this.FlashKey !== null) {\n this.FlashKey = null;\n this.Changed$.next();\n }\n }\n}\n\n/**\n * Pure decision helper for the REVIEW→LIVE continuation edge: should the overlay REMOVE the\n * review-registered (template-based, read-only) Whiteboard tab?\n *\n * Yes only when ALL hold:\n * - a live session is active (the channel set emission belongs to a real session start, not\n * the initial/teardown `[]` replay);\n * - review mode actually registered a whiteboard tab (otherwise there is nothing stale);\n * - the live session's resolved channel set has NO Whiteboard channel — when it HAS one, the\n * live plugin re-registers the same tab key and upgrades the pane in place instead.\n *\n * Kept framework-free (like the model) so the rule is unit-testable in isolation.\n */\nexport function ShouldRemoveReviewWhiteboardTab(\n liveSessionActive: boolean,\n reviewWhiteboardTabRegistered: boolean,\n liveChannels: ReadonlyArray<{ ChannelName: string }>\n): boolean {\n if (!liveSessionActive || !reviewWhiteboardTabRegistered) {\n return false;\n }\n return !liveChannels.some(c => c.ChannelName?.trim().toLowerCase() === 'whiteboard');\n}\n"]}
|
|
1
|
+
{"version":3,"file":"realtime-surface-tabs.model.js","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-surface-tabs.model.ts"],"names":[],"mappings":"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","sourcesContent":["import { Subject } from 'rxjs';\nimport type { TemplateRef } from '@angular/core';\nimport type { BaseRealtimeChannelClient } from '@memberjunction/realtime-runtime';\nimport { ChannelTabColor } from './realtime-surface-tab-style';\n\n/**\n * The kind of a surface-panel tab:\n * - `activity` — the session-activity tab (pinned LAST, right-aligned). Hosts the activity\n * rail AND, since the artifact redesign, the inline artifact previews + the split-pane\n * artifact viewer. Shown only once ≥1 agent run has occurred (see\n * {@link RealtimeSurfaceTabsModel.SetShowActivityTab}).\n * - `channel` — an interactive-channel surface (e.g. the Whiteboard). Registered per\n * used channel via {@link RealtimeSurfaceTabsModel.RegisterChannelTab}; renders the\n * plugin's dynamically-created surface component (or a registered template for\n * legacy/template-based panes), with the \"coming online…\" placeholder until either\n * is supplied.\n *\n * NOTE: artifacts NO LONGER get their own tab. A delegated run's artifacts now render\n * INSIDE the Activity tab (inline previews + an `as-split` viewer pane) — see\n * `RealtimeActivityRailComponent`.\n */\nexport type RealtimeSurfaceTabKind = 'activity' | 'channel';\n\n/**\n * Per-kind payload carried on a {@link RealtimeSurfaceTab}.\n */\nexport interface RealtimeSurfaceTabData {\n /**\n * For `channel` tabs: the channel PLUGIN whose surface component the pane creates\n * dynamically (and binds back to the plugin) — the registry-driven path every real\n * channel uses. Takes precedence over {@link Content}.\n */\n Plugin?: BaseRealtimeChannelClient;\n /**\n * For `channel` tabs: a TEMPLATE-based pane body. Backward-compatible alternative to\n * {@link Plugin} for hosts that render a bespoke surface without a channel plugin.\n * When BOTH are absent the pane renders the built-in \"coming online…\" placeholder.\n */\n Content?: TemplateRef<unknown>;\n}\n\n/**\n * One tab on the call overlay's tabbed surface panel (the right panel): a channel surface\n * (left cluster) or the session-activity tab (right-aligned).\n */\nexport interface RealtimeSurfaceTab {\n /** Stable unique key (`activity`, or the channel's registered key). */\n Key: string;\n /** Tab strip label (channel name, or \"Activity\"). */\n Title: string;\n /** Font Awesome icon class for the tab strip (e.g. `fa-solid fa-chalkboard`). */\n Icon: string;\n /** What the tab renders. */\n Kind: RealtimeSurfaceTabKind;\n /**\n * Accent color for the tab's dot + active underline. Channel tabs carry a distinct color\n * (plugin-supplied or a deterministic hash of the name); the Activity tab uses its own\n * fixed accent in CSS, so its `Color` is left undefined.\n */\n Color?: string;\n /** Kind-specific payload. */\n Data?: RealtimeSurfaceTabData;\n}\n\n/**\n * Registration for an interactive-channel tab. The overlay shell registers one per\n * USED channel plugin (supplying {@link Plugin}); supplying {@link Plugin} or\n * {@link Content} later under the same `Key` upgrades a placeholder tab to the real surface.\n */\nexport interface RealtimeChannelTabRegistration {\n /** Stable channel key (the plugin's `ChannelName`, e.g. `Whiteboard`). Re-registering the same key updates the tab. */\n Key: string;\n /** Tab strip label (e.g. `Whiteboard`). */\n Title: string;\n /** Font Awesome icon class (e.g. `fa-solid fa-chalkboard`). */\n Icon: string;\n /**\n * Optional explicit accent color for the tab. When omitted, a deterministic color is\n * derived from {@link Key} so every channel tab still reads as a distinct surface.\n */\n Color?: string | null;\n /** The channel plugin whose surface the pane creates + binds. Preferred over {@link Content}. */\n Plugin?: BaseRealtimeChannelClient;\n /** A template-based pane body (legacy/bespoke panes). Omit both to show the \"coming online…\" placeholder. */\n Content?: TemplateRef<unknown>;\n /** Focus the tab immediately after registration (default `false`). */\n Focus?: boolean;\n}\n\n/**\n * Framework-free state for the call overlay's tabbed surface panel: the ordered tab list\n * (CHANNEL tabs first — the marquee surfaces, left cluster — with the session-activity tab\n * pinned LAST and right-aligned by the strip), the active tab, and the transient \"flash\"\n * highlight for a just-revealed channel tab.\n *\n * The Activity tab is GATED: it isn't listed until {@link SetShowActivityTab}(true) — i.e.\n * once ≥1 agent run has occurred (or in review mode). Channel tabs appear only as channels\n * come into play (the whiteboard up-front; every other channel on first use), so an\n * idle voice-first session shows an empty/near-empty strip rather than a row of unused tabs.\n *\n * Owned by `RealtimeSurfaceTabsComponent`; kept free of Angular runtime imports so the\n * add / focus / dedupe / flash logic is unit-testable in isolation. All collections are\n * REPLACED (never mutated) on change, and every change emits {@link Changed$}.\n */\nexport class RealtimeSurfaceTabsModel {\n /** The fixed key of the session-activity tab (pinned LAST, right-aligned). */\n public static readonly ActivityTabKey = 'activity';\n\n /** The activity tab definition, appended last whenever {@link showActivity} is true. */\n private static readonly ActivityTab: RealtimeSurfaceTab = {\n Key: RealtimeSurfaceTabsModel.ActivityTabKey,\n Title: 'Activity',\n Icon: 'fa-solid fa-wave-square',\n Kind: 'activity'\n };\n\n /** Channel tabs (left cluster), in registration order. Replaced immutably on change. */\n private channelTabs: RealtimeSurfaceTab[] = [];\n\n /** Whether the gated Activity tab is currently shown (≥1 agent run, or review mode). */\n private showActivity = false;\n\n /** Key of the currently focused tab. */\n public ActiveKey: string = RealtimeSurfaceTabsModel.ActivityTabKey;\n\n /**\n * Key of the tab currently \"flashing\" (the brief highlight a just-revealed channel tab\n * gets when the agent first acts on it). Cleared by the owning component after a beat via\n * {@link ClearFlash}.\n */\n public FlashKey: string | null = null;\n\n /** Emits after every model change so the owning component can mark for check. */\n public readonly Changed$ = new Subject<void>();\n\n /**\n * The ordered tabs: channel tabs (left), then the Activity tab LAST when shown. The strip\n * right-aligns the Activity tab via a flex spacer, so this order also matches reading order.\n */\n public get Tabs(): RealtimeSurfaceTab[] {\n return this.showActivity\n ? [...this.channelTabs, RealtimeSurfaceTabsModel.ActivityTab]\n : [...this.channelTabs];\n }\n\n /** Whether the Activity tab is currently part of the strip. */\n public get IsActivityShown(): boolean {\n return this.showActivity;\n }\n\n /**\n * The currently focused tab. Resolves to the active key when it still exists, else falls\n * back to the Activity tab (when shown), else the first channel tab, else the Activity tab\n * definition (so a consumer always has SOMETHING to render even on an empty strip).\n */\n public get ActiveTab(): RealtimeSurfaceTab {\n const tabs = this.Tabs;\n return tabs.find(t => t.Key === this.ActiveKey)\n ?? tabs.find(t => t.Key === RealtimeSurfaceTabsModel.ActivityTabKey)\n ?? tabs[0]\n ?? RealtimeSurfaceTabsModel.ActivityTab;\n }\n\n /**\n * Shows or hides the gated Activity tab. Turning it ON when an empty strip was implicitly\n * focusing Activity keeps focus on Activity; turning it OFF while it was focused falls\n * focus back to the first channel tab (if any). No-op (no emission) when unchanged.\n *\n * @param show Whether ≥1 agent run has occurred (or review mode) — the gate.\n */\n public SetShowActivityTab(show: boolean): void {\n if (this.showActivity === show) {\n return;\n }\n this.showActivity = show;\n if (!show && this.ActiveKey === RealtimeSurfaceTabsModel.ActivityTabKey) {\n this.ActiveKey = this.channelTabs[0]?.Key ?? RealtimeSurfaceTabsModel.ActivityTabKey;\n }\n this.Changed$.next();\n }\n\n /**\n * Registers (or updates) an interactive-channel tab. Re-registering an existing key\n * replaces its title/icon/color/plugin/content in place (this is how a placeholder\n * upgrades to the real surface once the channel comes online). New channel tabs join the\n * left cluster in registration order. A registration without an explicit {@link\n * RealtimeChannelTabRegistration.Color} gets a deterministic color from its key.\n *\n * @param registration The channel tab registration.\n * @returns The (new or updated) tab.\n */\n public RegisterChannelTab(registration: RealtimeChannelTabRegistration): RealtimeSurfaceTab {\n const tab: RealtimeSurfaceTab = {\n Key: registration.Key,\n Title: registration.Title,\n Icon: registration.Icon,\n Kind: 'channel',\n Color: registration.Color ?? ChannelTabColor(registration.Key),\n Data: { Plugin: registration.Plugin, Content: registration.Content }\n };\n const idx = this.channelTabs.findIndex(t => t.Key === registration.Key);\n if (idx >= 0) {\n const next = [...this.channelTabs];\n next[idx] = tab;\n this.channelTabs = next;\n } else {\n this.channelTabs = [...this.channelTabs, tab];\n }\n if (registration.Focus) {\n this.ActiveKey = tab.Key;\n }\n this.Changed$.next();\n return tab;\n }\n\n /** Focuses the tab with `key` (no-op when it doesn't exist or is already active). */\n public Focus(key: string): void {\n if (!this.Tabs.some(t => t.Key === key) || this.ActiveKey === key) {\n return;\n }\n this.ActiveKey = key;\n this.Changed$.next();\n }\n\n /**\n * Marks the tab with `key` as the {@link FlashKey} (the brief \"just arrived\" highlight)\n * WITHOUT changing focus — used by the auto-reveal path when the agent first acts on a\n * channel, so the user's eye lands on the tab that just came alive. No-op for unknown\n * keys; the owning component clears it after a beat via {@link ClearFlash}.\n */\n public FlashTab(key: string): void {\n if (this.FlashKey === key || !this.Tabs.some(t => t.Key === key)) {\n return;\n }\n this.FlashKey = key;\n this.Changed$.next();\n }\n\n /**\n * Removes the channel tab with `key`. Rules:\n * - the Activity tab is IRREMOVABLE — removing it is a no-op;\n * - an unknown key is a no-op (returns `false`);\n * - when the removed tab was focused, focus falls back to the Activity tab (if shown),\n * else the first remaining channel tab;\n * - a pending flash on the removed tab is cleaned up so the highlight can't dangle.\n *\n * @param key The tab key to remove.\n * @returns `true` when a tab was removed.\n */\n public RemoveTab(key: string): boolean {\n if (key === RealtimeSurfaceTabsModel.ActivityTabKey || !this.channelTabs.some(t => t.Key === key)) {\n return false;\n }\n this.channelTabs = this.channelTabs.filter(t => t.Key !== key);\n if (this.ActiveKey === key) {\n this.ActiveKey = this.showActivity\n ? RealtimeSurfaceTabsModel.ActivityTabKey\n : (this.channelTabs[0]?.Key ?? RealtimeSurfaceTabsModel.ActivityTabKey);\n }\n if (this.FlashKey === key) {\n this.FlashKey = null;\n }\n this.Changed$.next();\n return true;\n }\n\n /** Clears the transient flash highlight (called by the component after a beat). */\n public ClearFlash(): void {\n if (this.FlashKey !== null) {\n this.FlashKey = null;\n this.Changed$.next();\n }\n }\n}\n\n/**\n * Pure decision helper for the REVIEW→LIVE continuation edge: should the overlay REMOVE the\n * review-registered (template-based, read-only) Whiteboard tab?\n *\n * Yes only when ALL hold:\n * - a live session is active (the channel set emission belongs to a real session start, not\n * the initial/teardown `[]` replay);\n * - review mode actually registered a whiteboard tab (otherwise there is nothing stale);\n * - the live session's resolved channel set has NO Whiteboard channel — when it HAS one, the\n * live plugin re-registers the same tab key and upgrades the pane in place instead.\n *\n * Kept framework-free (like the model) so the rule is unit-testable in isolation.\n */\nexport function ShouldRemoveReviewWhiteboardTab(\n liveSessionActive: boolean,\n reviewWhiteboardTabRegistered: boolean,\n liveChannels: ReadonlyArray<{ ChannelName: string }>\n): boolean {\n if (!liveSessionActive || !reviewWhiteboardTabRegistered) {\n return false;\n }\n return !liveChannels.some(c => c.ChannelName?.trim().toLowerCase() === 'whiteboard');\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Type } from '@angular/core';
|
|
2
2
|
import { RealtimeToolDefinition, RealtimeTrackDescriptor } from '@memberjunction/ai';
|
|
3
3
|
import { IChannelFrameProvider } from '@memberjunction/ai-realtime-client';
|
|
4
|
-
import { BaseRealtimeChannelClient, ChannelOnboardingDetails } from '
|
|
4
|
+
import { BaseRealtimeChannelClient, ChannelOnboardingDetails } from '@memberjunction/realtime-runtime';
|
|
5
5
|
import { RemoteBrowserSurfaceComponent } from './remote-browser-surface.component';
|
|
6
6
|
import { RemoteBrowserAudioChunkInput } from './remote-browser-audio-player';
|
|
7
7
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-browser-channel.d.ts","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/remote-browser/remote-browser-channel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAG1C,OAAO,EAA0C,sBAAsB,EAAiB,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC5I,OAAO,EAA6B,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AACtG,OAAO,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"remote-browser-channel.d.ts","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/remote-browser/remote-browser-channel.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,7 +8,7 @@ var RemoteBrowserChannel_1;
|
|
|
8
8
|
import { RegisterClass } from '@memberjunction/global';
|
|
9
9
|
import { CHANNEL_INBOUND_VIDEO_TRACK } from '@memberjunction/ai';
|
|
10
10
|
import { ChannelInboundVideoBridge } from '@memberjunction/ai-realtime-client';
|
|
11
|
-
import { BaseRealtimeChannelClient } from '
|
|
11
|
+
import { BaseRealtimeChannelClient } from '@memberjunction/realtime-runtime';
|
|
12
12
|
import { RemoteBrowserSurfaceComponent } from './remote-browser-surface.component';
|
|
13
13
|
import { MapToolToAction, REMOTE_BROWSER_TOOL_DEFINITIONS, REMOTE_BROWSER_TOOL_NAMES, REMOTE_BROWSER_TOOL_PREFIX, RemoteBrowserToolArgError, } from './remote-browser-tools';
|
|
14
14
|
import { MediaSourceAudioSink, RemoteBrowserAudioPlayer } from './remote-browser-audio-player';
|