@memberjunction/ng-conversations 6.2.0-edge.4 → 6.2.0-edge.6

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.
Files changed (144) hide show
  1. package/README.md +29 -0
  2. package/dist/lib/components/attachment/image-viewer.component.d.ts +3 -1
  3. package/dist/lib/components/attachment/image-viewer.component.d.ts.map +1 -1
  4. package/dist/lib/components/attachment/image-viewer.component.js +5 -1
  5. package/dist/lib/components/attachment/image-viewer.component.js.map +1 -1
  6. package/dist/lib/components/conversation/conversation-agent-picker.component.d.ts +1 -1
  7. package/dist/lib/components/conversation/conversation-agent-picker.component.js +3 -3
  8. package/dist/lib/components/conversation/conversation-agent-picker.component.js.map +1 -1
  9. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +88 -20
  10. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
  11. package/dist/lib/components/conversation/conversation-chat-area.component.js +785 -387
  12. package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
  13. package/dist/lib/components/message/message-input.component.d.ts +60 -20
  14. package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
  15. package/dist/lib/components/message/message-input.component.js +290 -389
  16. package/dist/lib/components/message/message-input.component.js.map +1 -1
  17. package/dist/lib/components/message/message-item.component.d.ts +153 -17
  18. package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
  19. package/dist/lib/components/message/message-item.component.js +1400 -299
  20. package/dist/lib/components/message/message-item.component.js.map +1 -1
  21. package/dist/lib/components/message/message-list.component.d.ts +25 -2
  22. package/dist/lib/components/message/message-list.component.d.ts.map +1 -1
  23. package/dist/lib/components/message/message-list.component.js +79 -40
  24. package/dist/lib/components/message/message-list.component.js.map +1 -1
  25. package/dist/lib/components/overlay/chat-overlay.component.d.ts +19 -0
  26. package/dist/lib/components/overlay/chat-overlay.component.d.ts.map +1 -1
  27. package/dist/lib/components/overlay/chat-overlay.component.js +125 -13
  28. package/dist/lib/components/overlay/chat-overlay.component.js.map +1 -1
  29. package/dist/lib/components/project/project-form-modal.component.js +2 -2
  30. package/dist/lib/components/project/project-form-modal.component.js.map +1 -1
  31. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts +6 -1
  32. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts.map +1 -1
  33. package/dist/lib/components/realtime/realtime-agent-banner.component.js +110 -82
  34. package/dist/lib/components/realtime/realtime-agent-banner.component.js.map +1 -1
  35. package/dist/lib/components/realtime/realtime-call-failure-notice.d.ts +13 -0
  36. package/dist/lib/components/realtime/realtime-call-failure-notice.d.ts.map +1 -0
  37. package/dist/lib/components/realtime/realtime-call-failure-notice.js +21 -0
  38. package/dist/lib/components/realtime/realtime-call-failure-notice.js.map +1 -0
  39. package/dist/lib/components/realtime/realtime-composer.component.js +114 -102
  40. package/dist/lib/components/realtime/realtime-composer.component.js.map +1 -1
  41. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts +21 -2
  42. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts.map +1 -1
  43. package/dist/lib/components/realtime/realtime-session-overlay.component.js +113 -76
  44. package/dist/lib/components/realtime/realtime-session-overlay.component.js.map +1 -1
  45. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts.map +1 -1
  46. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js +7 -1
  47. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js.map +1 -1
  48. package/dist/lib/components/sidebar/routines-section.component.js +1 -1
  49. package/dist/lib/components/sidebar/routines-section.component.js.map +1 -1
  50. package/dist/lib/components/task/tasks-full-view.component.d.ts +152 -31
  51. package/dist/lib/components/task/tasks-full-view.component.d.ts.map +1 -1
  52. package/dist/lib/components/task/tasks-full-view.component.js +2227 -214
  53. package/dist/lib/components/task/tasks-full-view.component.js.map +1 -1
  54. package/dist/lib/components/tasks/tasks-dropdown.component.js +4 -4
  55. package/dist/lib/components/tasks/tasks-dropdown.component.js.map +1 -1
  56. package/dist/lib/components/workspace/conversation-workspace.component.d.ts +11 -1
  57. package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
  58. package/dist/lib/components/workspace/conversation-workspace.component.js +25 -28
  59. package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
  60. package/dist/lib/services/agent-state.service.d.ts.map +1 -1
  61. package/dist/lib/services/agent-state.service.js +8 -8
  62. package/dist/lib/services/agent-state.service.js.map +1 -1
  63. package/dist/lib/services/browser-realtime-media-host.d.ts +7 -7
  64. package/dist/lib/services/browser-realtime-media-host.js +8 -78
  65. package/dist/lib/services/browser-realtime-media-host.js.map +1 -1
  66. package/dist/lib/services/conversation-agent.service.d.ts +53 -20
  67. package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
  68. package/dist/lib/services/conversation-agent.service.js +108 -54
  69. package/dist/lib/services/conversation-agent.service.js.map +1 -1
  70. package/dist/lib/services/conversation-detail-window.store.d.ts +5 -0
  71. package/dist/lib/services/conversation-detail-window.store.d.ts.map +1 -1
  72. package/dist/lib/services/conversation-detail-window.store.js +52 -5
  73. package/dist/lib/services/conversation-detail-window.store.js.map +1 -1
  74. package/dist/lib/services/conversation-naming.d.ts.map +1 -1
  75. package/dist/lib/services/conversation-naming.js +9 -2
  76. package/dist/lib/services/conversation-naming.js.map +1 -1
  77. package/dist/lib/services/conversation-tasks-filter.d.ts +15 -0
  78. package/dist/lib/services/conversation-tasks-filter.d.ts.map +1 -0
  79. package/dist/lib/services/conversation-tasks-filter.js +69 -0
  80. package/dist/lib/services/conversation-tasks-filter.js.map +1 -0
  81. package/dist/lib/services/realtime-audio-recorder.d.ts +94 -86
  82. package/dist/lib/services/realtime-audio-recorder.d.ts.map +1 -1
  83. package/dist/lib/services/realtime-audio-recorder.js +222 -195
  84. package/dist/lib/services/realtime-audio-recorder.js.map +1 -1
  85. package/dist/lib/services/realtime-session.service.d.ts +30 -2
  86. package/dist/lib/services/realtime-session.service.d.ts.map +1 -1
  87. package/dist/lib/services/realtime-session.service.js +35 -7
  88. package/dist/lib/services/realtime-session.service.js.map +1 -1
  89. package/dist/lib/services/recording/libopus-wasm-binary.d.ts +3 -0
  90. package/dist/lib/services/recording/libopus-wasm-binary.d.ts.map +1 -0
  91. package/dist/lib/services/recording/libopus-wasm-binary.js +489 -0
  92. package/dist/lib/services/recording/libopus-wasm-binary.js.map +1 -0
  93. package/dist/lib/services/recording/libopus-worker-source.d.ts +48 -0
  94. package/dist/lib/services/recording/libopus-worker-source.d.ts.map +1 -0
  95. package/dist/lib/services/recording/libopus-worker-source.js +170 -0
  96. package/dist/lib/services/recording/libopus-worker-source.js.map +1 -0
  97. package/dist/lib/services/recording/linear-resampler.d.ts +45 -0
  98. package/dist/lib/services/recording/linear-resampler.d.ts.map +1 -0
  99. package/dist/lib/services/recording/linear-resampler.js +85 -0
  100. package/dist/lib/services/recording/linear-resampler.js.map +1 -0
  101. package/dist/lib/services/recording/opus-packet-encoder.d.ts +50 -0
  102. package/dist/lib/services/recording/opus-packet-encoder.d.ts.map +1 -0
  103. package/dist/lib/services/recording/opus-packet-encoder.js +41 -0
  104. package/dist/lib/services/recording/opus-packet-encoder.js.map +1 -0
  105. package/dist/lib/services/recording/wasm-opus-encoder.d.ts +86 -0
  106. package/dist/lib/services/recording/wasm-opus-encoder.d.ts.map +1 -0
  107. package/dist/lib/services/recording/wasm-opus-encoder.js +232 -0
  108. package/dist/lib/services/recording/wasm-opus-encoder.js.map +1 -0
  109. package/dist/lib/services/recording/webcodecs-opus-encoder.d.ts +39 -0
  110. package/dist/lib/services/recording/webcodecs-opus-encoder.d.ts.map +1 -0
  111. package/dist/lib/services/recording/webcodecs-opus-encoder.js +101 -0
  112. package/dist/lib/services/recording/webcodecs-opus-encoder.js.map +1 -0
  113. package/dist/lib/services/search.service.d.ts.map +1 -1
  114. package/dist/lib/services/search.service.js +3 -16
  115. package/dist/lib/services/search.service.js.map +1 -1
  116. package/dist/lib/utils/agent-failure-display.d.ts +14 -0
  117. package/dist/lib/utils/agent-failure-display.d.ts.map +1 -0
  118. package/dist/lib/utils/agent-failure-display.js +26 -0
  119. package/dist/lib/utils/agent-failure-display.js.map +1 -0
  120. package/dist/lib/utils/distinct-artifacts.d.ts +9 -3
  121. package/dist/lib/utils/distinct-artifacts.d.ts.map +1 -1
  122. package/dist/lib/utils/distinct-artifacts.js +24 -5
  123. package/dist/lib/utils/distinct-artifacts.js.map +1 -1
  124. package/dist/lib/utils/message-list-order.d.ts +13 -0
  125. package/dist/lib/utils/message-list-order.d.ts.map +1 -0
  126. package/dist/lib/utils/message-list-order.js +31 -0
  127. package/dist/lib/utils/message-list-order.js.map +1 -0
  128. package/dist/lib/utils/pin-state.d.ts +11 -0
  129. package/dist/lib/utils/pin-state.d.ts.map +1 -0
  130. package/dist/lib/utils/pin-state.js +9 -0
  131. package/dist/lib/utils/pin-state.js.map +1 -0
  132. package/dist/public-api.d.ts +1 -0
  133. package/dist/public-api.d.ts.map +1 -1
  134. package/dist/public-api.js +1 -0
  135. package/dist/public-api.js.map +1 -1
  136. package/package.json +36 -36
  137. package/dist/lib/services/browser-recording-unload-guard.d.ts +0 -30
  138. package/dist/lib/services/browser-recording-unload-guard.d.ts.map +0 -1
  139. package/dist/lib/services/browser-recording-unload-guard.js +0 -43
  140. package/dist/lib/services/browser-recording-unload-guard.js.map +0 -1
  141. package/dist/lib/services/realtime-pcm-wav.d.ts +0 -79
  142. package/dist/lib/services/realtime-pcm-wav.d.ts.map +0 -1
  143. package/dist/lib/services/realtime-pcm-wav.js +0 -213
  144. package/dist/lib/services/realtime-pcm-wav.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"chat-overlay.component.js","sourceRoot":"","sources":["../../../../src/lib/components/overlay/chat-overlay.component.ts","../../../../src/lib/components/overlay/chat-overlay.component.html"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Floating Chat Overlay Component\n *\n * A collapsible floating panel (bottom-right corner) that wraps the\n * conversation-chat-area component. Provides a persistent, minimizable chat\n * experience across the application.\n *\n * This component is GENERIC -- it does NOT know about NavigationService,\n * Knowledge Hub, or any Explorer-specific concepts. It raises events that\n * the consuming application handles.\n *\n * Coordinates with the full Conversations workspace view through\n * ConversationBridgeService so that switching between overlay and workspace\n * preserves conversation continuity.\n */\n\nimport {\n Component,\n EventEmitter,\n Input,\n OnDestroy,\n OnInit,\n Output,\n ChangeDetectorRef,\n inject\n} from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { takeUntil } from 'rxjs/operators';\nimport { UserInfo, Metadata, CompositeKey } from '@memberjunction/core';\nimport { MJConversationEntity, MJTaskEntity, MJEnvironmentEntityExtended, UserInfoEngine } from '@memberjunction/core-entities';\nimport { AgentClientService } from '@memberjunction/ng-agent-client';\nimport { ClientToolResultEvent } from '@memberjunction/ai-agent-client';\nimport { ConversationBridgeService, ConversationSwitchEvent } from '../../services/conversation-bridge.service';\nimport { NavigationRequest } from '@memberjunction/ng-artifacts';\nimport { PendingAttachment } from '@memberjunction/ng-composer';\n\n/** Visual state of the overlay panel */\nexport type ChatOverlayState = 'collapsed' | 'expanded' | 'maximized';\n\n/** Event payload when the active conversation changes in the overlay */\nexport interface OverlayConversationSwitchedEvent {\n PreviousConversationID: string | null;\n NewConversationID: string | null;\n}\n\n/** Persisted overlay size and position preferences */\ninterface OverlayPrefs {\n width: number;\n height: number;\n /** Pixels the bubble has been dragged up from its default bottom position. Optional for back-compat with older saved prefs. */\n bubbleOffsetY?: number;\n /** When true, the bubble is hidden and only a thin sliver shows on the right edge. */\n bubbleHidden?: boolean;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-chat-agents-overlay',\n templateUrl: './chat-overlay.component.html',\n styleUrls: ['./chat-overlay.component.css']\n})\nexport class ChatAgentsOverlayComponent extends BaseAngularComponent implements OnInit, OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n private bridge = inject(ConversationBridgeService);\n private agentClient = inject(AgentClientService);\n private destroy$ = new Subject<void>();\n\n // --- Settings persistence ---\n private static readonly SIZE_SETTING_KEY = 'ChatOverlay.Size';\n private static readonly DEFAULT_WIDTH = 420;\n private static readonly DEFAULT_HEIGHT = 600;\n private static readonly MIN_WIDTH = 320;\n private static readonly MIN_HEIGHT = 350;\n private static readonly MAX_WIDTH = 900;\n private static readonly MAX_HEIGHT = 1000;\n\n // --- Bubble drag constants ---\n /** Default `bottom` for both bubble and panel (matches CSS 1.5rem). */\n private static readonly BASE_BOTTOM_PX = 24;\n /** Floating bubble diameter in pixels (matches CSS 3.5rem). */\n private static readonly BUBBLE_SIZE_PX = 56;\n /** Minimum gap to keep between the overlay and the viewport top edge. */\n private static readonly VIEWPORT_TOP_PADDING_PX = 16;\n /** Mousedown-to-mousemove distance that promotes a click into a drag. */\n private static readonly BUBBLE_DRAG_THRESHOLD_PX = 5;\n\n // --- Inputs ---\n\n /** Controls external visibility (e.g., parent hides overlay on chat route) */\n private _isVisible = true;\n\n @Input()\n set IsVisible(value: boolean) {\n const prev = this._isVisible;\n this._isVisible = value;\n if (!value && prev && this.State !== 'collapsed') {\n this.Collapse();\n }\n this.cdr.detectChanges();\n }\n get IsVisible(): boolean {\n return this._isVisible;\n }\n\n /** Current user info, passed through to conversation-chat-area. Auto-resolved from Metadata if not provided. */\n @Input() CurrentUser!: UserInfo;\n\n /** Environment ID, passed through to conversation-chat-area. Auto-resolved from default if not provided. */\n @Input() EnvironmentId!: string;\n\n /** Application context snapshot for AI agent awareness. Updated by the host app on navigation transitions. */\n @Input() AppContext: Record<string, unknown> | null = null;\n\n /** Greeting message shown in the empty state when no conversation is active */\n @Input() EmptyStateGreeting: string = 'How can I help you?';\n\n /**\n * Pixels reserved at the top of the viewport that the bubble and panel must not\n * cross. Set this from the host app to the height of any fixed top chrome (e.g.\n * Explorer's shell-header). Defaults to 0 — generic apps without top chrome\n * keep the full viewport available.\n */\n @Input() TopBoundaryPx: number = 0;\n\n // --- Outputs ---\n\n /** Emitted when the overlay visibility changes */\n @Output() VisibilityChanged = new EventEmitter<ChatOverlayState>();\n\n /** Emitted when a tool finishes executing in the agent client */\n @Output() ToolExecuted = new EventEmitter<ClientToolResultEvent>();\n\n /** Emitted when the active conversation changes in the overlay */\n @Output() ConversationSwitched = new EventEmitter<OverlayConversationSwitchedEvent>();\n\n /** Emitted when the user requests opening the full chat workspace */\n @Output() OpenFullChatWorkspace = new EventEmitter<string | null>();\n\n /** Emitted when navigation is requested (entity record, etc.) */\n @Output() NavigationRequested = new EventEmitter<NavigationRequest>();\n\n /** Emitted when an entity record open is requested */\n @Output() OpenEntityRecord = new EventEmitter<{entityName: string; compositeKey: CompositeKey}>();\n\n /** Emitted when a task is clicked */\n @Output() TaskClicked = new EventEmitter<MJTaskEntity>();\n\n // --- Component State ---\n\n public State: ChatOverlayState = 'collapsed';\n public UnreadCount = 0;\n\n /** Panel dimensions (persisted via UserInfoEngine) */\n public PanelWidth = ChatAgentsOverlayComponent.DEFAULT_WIDTH;\n public PanelHeight = ChatAgentsOverlayComponent.DEFAULT_HEIGHT;\n\n /**\n * Pixels the floating bubble has been dragged up from its default\n * bottom-right corner position. Always >= 0; clamping at render time\n * keeps the bubble on-screen even after a viewport resize.\n */\n public BubbleOffsetY = 0;\n\n /** True while the user is actively dragging the bubble; used to swap cursor + suppress click. */\n public IsBubbleDragging = false;\n\n /**\n * True from mousedown until mouseup on the bubble, regardless of whether the\n * gesture became a drag. Used to give immediate \"I'm being held\" feedback so\n * the user can see drag is possible even before crossing the move threshold.\n */\n public IsBubblePressed = false;\n\n /**\n * When true, the floating bubble is hidden and replaced by a thin sliver\n * flush with the right edge of the viewport. Persisted across sessions via\n * OverlayPrefs.bubbleHidden. Clicking the sliver restores the bubble.\n */\n public IsHidden = false;\n\n /** Active conversation ID managed locally */\n private _conversationId: string | null = null;\n public get ConversationId(): string | null {\n return this._conversationId;\n }\n\n /** Active conversation entity */\n public Conversation: MJConversationEntity | null = null;\n\n /** Whether a new unsaved conversation is in progress */\n public IsNewConversation = true;\n\n /** Pending message to send after conversation creation */\n public PendingMessage: string | null = null;\n /** The conversation {@link PendingMessage} is destined for — pins the auto-send to that\n * conversation's input so a fast conversation-swap can't redirect it elsewhere. */\n public PendingMessageConversationId: string | null = null;\n\n /** Pending attachments to send after conversation creation */\n public PendingAttachments: PendingAttachment[] | null = null;\n\n /** Resize drag state */\n private isResizing = false;\n private resizeEdge: 'left' | 'top' | 'top-left' | null = null;\n private resizeStartX = 0;\n private resizeStartY = 0;\n private resizeStartWidth = 0;\n private resizeStartHeight = 0;\n\n /** Bubble drag state */\n private bubbleDragStartMouseY = 0;\n private bubbleDragStartOffset = 0;\n /** True once the pointer has moved past BUBBLE_DRAG_THRESHOLD_PX; suppresses the implicit click. */\n private bubbleDragMoved = false;\n /** ID of the pointer currently driving the drag — guards against multi-touch confusion. */\n private activeBubblePointerId: number | null = null;\n /** Element that captured the pointer; needed to release capture on end/cancel. */\n private bubbleCaptureTarget: HTMLElement | null = null;\n\n // --- Lifecycle ---\n\n ngOnInit(): void {\n this.resolveDefaults();\n this.loadPreferences();\n this.subscribeToBridgeEvents();\n this.subscribeToToolEvents();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n this.removeResizeListeners();\n this.removeBubbleDragListeners();\n }\n\n // --- Public Methods ---\n\n /** Toggle between collapsed and expanded states */\n public Toggle(): void {\n if (this.State === 'collapsed') {\n this.Expand();\n } else {\n this.Collapse();\n }\n }\n\n /** Expand the overlay to show the chat panel */\n public Expand(): void {\n // Expanding implies the user wants the chat visible — clear any hidden\n // state so collapse returns to the bubble, not back to the sliver.\n if (this.IsHidden) {\n this.IsHidden = false;\n this.savePreferences();\n }\n this.State = 'expanded';\n this.UnreadCount = 0;\n this.bridge.NotifyOverlayActive(true);\n this.VisibilityChanged.emit(this.State);\n this.cdr.detectChanges();\n }\n\n /** Collapse the overlay to the floating button */\n public Collapse(): void {\n this.State = 'collapsed';\n this.bridge.NotifyOverlayActive(false);\n this.VisibilityChanged.emit(this.State);\n this.cdr.detectChanges();\n }\n\n /** Toggle between expanded and maximized states */\n public ToggleMaximize(): void {\n if (this.State === 'maximized') {\n this.State = 'expanded';\n } else {\n this.State = 'maximized';\n }\n this.bridge.NotifyOverlayActive(true);\n this.VisibilityChanged.emit(this.State);\n this.cdr.detectChanges();\n }\n\n /** Handle the user requesting to open full chat workspace */\n public OnOpenFullChatWorkspace(): void {\n this.OpenFullChatWorkspace.emit(this._conversationId);\n this.bridge.SwitchToWorkspace(this._conversationId);\n this.Collapse();\n }\n\n /** Handle conversation creation from the chat area */\n public OnConversationCreated(event: {\n conversation: MJConversationEntity;\n pendingMessage?: string;\n pendingAttachments?: PendingAttachment[];\n }): void {\n // Set ALL state atomically before Angular change detection runs\n this.PendingMessage = event.pendingMessage || null;\n this.PendingAttachments = event.pendingAttachments || null;\n this.PendingMessageConversationId = event.conversation.ID;\n const prevId = this._conversationId;\n this._conversationId = event.conversation.ID;\n this.Conversation = event.conversation;\n this.IsNewConversation = false;\n this.bridge.SetActiveFromOverlay(event.conversation.ID);\n this.emitConversationSwitched(prevId, event.conversation.ID);\n }\n\n /** Handle pending message consumed by chat area */\n public OnPendingMessageConsumed(): void {\n this.PendingMessage = null;\n this.PendingAttachments = null;\n this.PendingMessageConversationId = null;\n }\n\n /** Handle conversation rename from chat area */\n public OnConversationRenamed(_event: {conversationId: string; name: string; description: string}): void {\n // The overlay doesn't need to do anything specific here;\n // the conversation entity is updated in-place by the chat area.\n }\n\n /** Handle entity record open requests */\n public OnOpenEntityRecord(event: {entityName: string; compositeKey: CompositeKey}): void {\n this.OpenEntityRecord.emit(event);\n }\n\n /** Handle navigation requests from the chat area */\n public OnNavigationRequest(event: NavigationRequest): void {\n this.NavigationRequested.emit(event);\n }\n\n /** Handle task clicks from the chat area */\n public OnTaskClicked(task: MJTaskEntity): void {\n this.TaskClicked.emit(task);\n }\n\n /** Start a new conversation in the overlay */\n public StartNewConversation(): void {\n const prevId = this._conversationId;\n this._conversationId = null;\n this.Conversation = null;\n // Force Angular change detection by toggling off then on\n // so the setter fires even if already in new-conversation state\n this.IsNewConversation = false;\n this.cdr.detectChanges();\n this.IsNewConversation = true;\n this.bridge.SetActiveFromOverlay(null);\n this.emitConversationSwitched(prevId, null);\n this.cdr.detectChanges();\n }\n\n /**\n * Hide the floating bubble — leaves a thin sliver on the right edge as the\n * only affordance to bring it back. Invoked from the small \"×\" pill that\n * appears on hover. Stops propagation so the bubble's own click handler\n * doesn't fire and toggle the panel open.\n */\n public Hide(event: Event): void {\n event.stopPropagation();\n event.preventDefault();\n if (this.IsHidden) return;\n this.IsHidden = true;\n this.savePreferences();\n this.cdr.detectChanges();\n }\n\n /** Restore the floating bubble after it was hidden. Triggered by clicking the sliver. */\n public Show(): void {\n if (!this.IsHidden) return;\n this.IsHidden = false;\n this.savePreferences();\n this.cdr.detectChanges();\n }\n\n /** Increment unread badge (called externally when messages arrive while collapsed) */\n public IncrementUnread(): void {\n if (this.State === 'collapsed') {\n this.UnreadCount++;\n this.cdr.detectChanges();\n }\n }\n\n // --- Resize Methods ---\n\n /** Start resizing from an edge or corner */\n public OnResizeStart(event: MouseEvent, edge: 'left' | 'top' | 'top-left'): void {\n event.preventDefault();\n event.stopPropagation();\n this.isResizing = true;\n this.resizeEdge = edge;\n this.resizeStartX = event.clientX;\n this.resizeStartY = event.clientY;\n this.resizeStartWidth = this.PanelWidth;\n this.resizeStartHeight = this.PanelHeight;\n\n document.addEventListener('mousemove', this.onResizeMove);\n document.addEventListener('mouseup', this.onResizeEnd);\n }\n\n private onResizeMove = (event: MouseEvent): void => {\n if (!this.isResizing || !this.resizeEdge) return;\n\n const deltaX = this.resizeStartX - event.clientX; // Inverted: dragging left increases width\n const deltaY = this.resizeStartY - event.clientY; // Inverted: dragging up increases height\n\n if (this.resizeEdge === 'left' || this.resizeEdge === 'top-left') {\n this.PanelWidth = this.clampWidth(this.resizeStartWidth + deltaX);\n }\n if (this.resizeEdge === 'top' || this.resizeEdge === 'top-left') {\n this.PanelHeight = this.clampHeight(this.resizeStartHeight + deltaY);\n }\n this.cdr.detectChanges();\n };\n\n private onResizeEnd = (): void => {\n if (!this.isResizing) return;\n this.isResizing = false;\n this.resizeEdge = null;\n this.removeResizeListeners();\n this.savePreferences();\n };\n\n private removeResizeListeners(): void {\n document.removeEventListener('mousemove', this.onResizeMove);\n document.removeEventListener('mouseup', this.onResizeEnd);\n }\n\n private clampWidth(value: number): number {\n return Math.max(ChatAgentsOverlayComponent.MIN_WIDTH, Math.min(ChatAgentsOverlayComponent.MAX_WIDTH, value));\n }\n\n private clampHeight(value: number): number {\n return Math.max(ChatAgentsOverlayComponent.MIN_HEIGHT, Math.min(ChatAgentsOverlayComponent.MAX_HEIGHT, value));\n }\n\n // --- Bubble Drag Methods (Pointer Events — unified mouse / touch / pen) ---\n\n /**\n * Start tracking a potential bubble drag. We don't enter drag mode until\n * the pointer moves past BUBBLE_DRAG_THRESHOLD_PX — releasing before that\n * threshold is treated as a normal click/tap and opens the chat (via Toggle()).\n *\n * Pointer Events (not mousedown) so the same code path serves desktop mouse,\n * touch on phones/tablets, and pen input. setPointerCapture keeps the gesture\n * tied to this element even if the finger or cursor strays off the bubble.\n */\n public OnBubblePointerDown(event: PointerEvent): void {\n // Mouse: respect primary-button only. Touch/pen: button is always 0, so this passes naturally.\n if (event.pointerType === 'mouse' && event.button !== 0) return;\n // Don't start a second drag while one is in flight (e.g. second finger on touch).\n if (this.activeBubblePointerId !== null) return;\n event.preventDefault();\n\n const target = event.currentTarget as HTMLElement;\n target.setPointerCapture(event.pointerId);\n this.bubbleCaptureTarget = target;\n\n this.activeBubblePointerId = event.pointerId;\n this.bubbleDragStartMouseY = event.clientY;\n this.bubbleDragStartOffset = this.BubbleOffsetY;\n this.bubbleDragMoved = false;\n this.IsBubblePressed = true;\n this.cdr.detectChanges();\n\n document.addEventListener('pointermove', this.onBubbleDragMove);\n document.addEventListener('pointerup', this.onBubbleDragEnd);\n document.addEventListener('pointercancel', this.onBubbleDragEnd);\n }\n\n private onBubbleDragMove = (event: PointerEvent): void => {\n if (event.pointerId !== this.activeBubblePointerId) return;\n const deltaY = this.bubbleDragStartMouseY - event.clientY; // dragging up = positive\n if (!this.bubbleDragMoved) {\n if (Math.abs(deltaY) < ChatAgentsOverlayComponent.BUBBLE_DRAG_THRESHOLD_PX) return;\n this.bubbleDragMoved = true;\n this.IsBubbleDragging = true;\n }\n this.BubbleOffsetY = this.clampBubbleOffsetY(this.bubbleDragStartOffset + deltaY);\n this.cdr.detectChanges();\n };\n\n private onBubbleDragEnd = (event: PointerEvent): void => {\n if (event.pointerId !== this.activeBubblePointerId) return;\n this.removeBubbleDragListeners();\n\n if (this.bubbleCaptureTarget) {\n // Browser may have implicitly released capture on pointerup already (per the\n // Pointer Events spec). releasePointerCapture throws in that race; safe to ignore.\n try { this.bubbleCaptureTarget.releasePointerCapture(event.pointerId); } catch { /* noop */ }\n }\n this.bubbleCaptureTarget = null;\n this.activeBubblePointerId = null;\n\n const wasDragged = this.bubbleDragMoved;\n const wasCancelled = event.type === 'pointercancel';\n this.bubbleDragMoved = false;\n this.IsBubbleDragging = false;\n this.IsBubblePressed = false;\n if (wasDragged) {\n this.savePreferences();\n this.cdr.detectChanges();\n } else if (!wasCancelled) {\n this.Toggle();\n } else {\n this.cdr.detectChanges();\n }\n };\n\n private removeBubbleDragListeners(): void {\n document.removeEventListener('pointermove', this.onBubbleDragMove);\n document.removeEventListener('pointerup', this.onBubbleDragEnd);\n document.removeEventListener('pointercancel', this.onBubbleDragEnd);\n }\n\n /**\n * Reserved space at the top of the viewport — host-supplied chrome plus\n * the padding gap we always keep above the bubble/panel.\n */\n private get topReservedPx(): number {\n return Math.max(0, this.TopBoundaryPx) + ChatAgentsOverlayComponent.VIEWPORT_TOP_PADDING_PX;\n }\n\n /** Clamp the offset so the bubble stays fully visible below the top boundary. */\n private clampBubbleOffsetY(value: number): number {\n const maxOffset = window.innerHeight\n - ChatAgentsOverlayComponent.BUBBLE_SIZE_PX\n - ChatAgentsOverlayComponent.BASE_BOTTOM_PX\n - this.topReservedPx;\n return Math.max(0, Math.min(Math.max(0, maxOffset), value));\n }\n\n // --- Render Position Getters ---\n\n /** Effective `bottom` (px) for the floating bubble, clamped to the current viewport. */\n public get BubbleBottomPx(): number {\n const ideal = ChatAgentsOverlayComponent.BASE_BOTTOM_PX + this.BubbleOffsetY;\n const max = window.innerHeight\n - ChatAgentsOverlayComponent.BUBBLE_SIZE_PX\n - this.topReservedPx;\n return Math.max(\n ChatAgentsOverlayComponent.BASE_BOTTOM_PX,\n Math.min(ideal, Math.max(ChatAgentsOverlayComponent.BASE_BOTTOM_PX, max))\n );\n }\n\n /**\n * Effective `bottom` (px) for the expanded panel. Anchors to the bubble's\n * current bottom edge so the panel grows up from where the user parked the\n * bubble, but clamps downward whenever the panel would otherwise extend\n * past the viewport's top boundary — that's the \"reposition lower so the\n * chat interface stays visible\" behavior.\n */\n public get PanelBottomPx(): number {\n const ideal = ChatAgentsOverlayComponent.BASE_BOTTOM_PX + this.BubbleOffsetY;\n const maxBottomForVisibility = window.innerHeight\n - this.PanelHeight\n - this.topReservedPx;\n return Math.max(\n ChatAgentsOverlayComponent.BASE_BOTTOM_PX,\n Math.min(ideal, maxBottomForVisibility)\n );\n }\n\n // --- Private Methods ---\n\n /** Auto-resolve CurrentUser and EnvironmentId from Metadata when not provided as inputs */\n private resolveDefaults(): void {\n if (!this.CurrentUser) {\n const md = this.ProviderToUse;\n this.CurrentUser = md.CurrentUser;\n }\n if (!this.EnvironmentId) {\n this.EnvironmentId = MJEnvironmentEntityExtended.DefaultEnvironmentID;\n }\n }\n\n /** Load saved panel size and bubble position from UserInfoEngine */\n private loadPreferences(): void {\n try {\n const engine = UserInfoEngine.Instance;\n const raw = engine.GetSetting(ChatAgentsOverlayComponent.SIZE_SETTING_KEY);\n if (raw) {\n const prefs: OverlayPrefs = JSON.parse(raw);\n this.PanelWidth = this.clampWidth(prefs.width);\n this.PanelHeight = this.clampHeight(prefs.height);\n if (typeof prefs.bubbleOffsetY === 'number') {\n this.BubbleOffsetY = Math.max(0, prefs.bubbleOffsetY);\n }\n if (typeof prefs.bubbleHidden === 'boolean') {\n this.IsHidden = prefs.bubbleHidden;\n }\n }\n } catch {\n // Use defaults on error\n }\n }\n\n /** Persist panel size and bubble position to UserInfoEngine (debounced) */\n private savePreferences(): void {\n const prefs: OverlayPrefs = {\n width: this.PanelWidth,\n height: this.PanelHeight,\n bubbleOffsetY: this.BubbleOffsetY,\n bubbleHidden: this.IsHidden\n };\n UserInfoEngine.Instance.SetSettingDebounced(\n ChatAgentsOverlayComponent.SIZE_SETTING_KEY,\n JSON.stringify(prefs)\n );\n }\n\n /** Subscribe to bridge events for cross-view coordination */\n private subscribeToBridgeEvents(): void {\n this.bridge.SwitchEvent$\n .pipe(takeUntil(this.destroy$))\n .subscribe((event: ConversationSwitchEvent) => {\n if (event.Target === 'overlay') {\n this.handleSwitchToOverlay(event);\n }\n });\n\n // Allow arbitrary callers (Form Builder cockpit, etc.) to ask the\n // overlay to expand. Idempotent if we're already expanded —\n // Expand() is safe to call in any state.\n this.bridge.ExpandOverlayRequested$\n .pipe(takeUntil(this.destroy$))\n .subscribe(() => {\n if (this.State === 'collapsed') {\n this.Expand();\n }\n });\n\n this.bridge.ActiveConversationID$\n .pipe(takeUntil(this.destroy$))\n .subscribe((id: string | null) => {\n // Only update if the change came from outside (workspace)\n if (id !== this._conversationId && this.bridge.WorkspaceActive$.value) {\n const prevId = this._conversationId;\n this._conversationId = id;\n this.IsNewConversation = id === null;\n this.Conversation = null; // Will be loaded by chat area\n this.emitConversationSwitched(prevId, id);\n this.cdr.detectChanges();\n }\n });\n }\n\n /** Subscribe to agent client tool execution events */\n private subscribeToToolEvents(): void {\n this.agentClient.ToolExecuted$\n .pipe(takeUntil(this.destroy$))\n .subscribe((event: ClientToolResultEvent) => {\n this.ToolExecuted.emit(event);\n });\n }\n\n /** Handle request to switch conversation to the overlay */\n private handleSwitchToOverlay(event: ConversationSwitchEvent): void {\n const prevId = this._conversationId;\n this._conversationId = event.ConversationID;\n this.IsNewConversation = event.ConversationID === null;\n this.Conversation = null; // Will be reloaded by chat area\n this.Expand();\n this.emitConversationSwitched(prevId, event.ConversationID);\n }\n\n /** Emit a conversation switched event */\n private emitConversationSwitched(prevId: string | null, newId: string | null): void {\n this.ConversationSwitched.emit({\n PreviousConversationID: prevId,\n NewConversationID: newId\n });\n }\n}\n","@if (IsVisible) {\n <!-- Floating Button (collapsed state, not hidden) -->\n @if (State === 'collapsed' && !IsHidden) {\n <div class=\"chat-overlay-bubble\"\n [class.is-pressed]=\"IsBubblePressed\"\n [class.is-dragging]=\"IsBubbleDragging\"\n [style.bottom.px]=\"BubbleBottomPx\"\n (pointerdown)=\"OnBubblePointerDown($event)\">\n <i class=\"fa-solid fa-chevron-up chat-overlay-bubble-arrow chat-overlay-bubble-arrow-up\" aria-hidden=\"true\"></i>\n <i class=\"fa-solid fa-chevron-down chat-overlay-bubble-arrow chat-overlay-bubble-arrow-down\" aria-hidden=\"true\"></i>\n <i class=\"fa-solid fa-comments chat-overlay-bubble-icon\"></i>\n @if (UnreadCount > 0) {\n <span class=\"chat-overlay-badge\">{{ UnreadCount > 9 ? '9+' : UnreadCount }}</span>\n }\n <!-- Hide affordance: revealed on hover. pointerdown stops drag from starting; click hides the bubble. -->\n <button type=\"button\"\n class=\"chat-overlay-bubble-close\"\n title=\"Hide chat — a thin sliver will remain on the right edge\"\n aria-label=\"Hide chat overlay\"\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"Hide($event)\">\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n\n <!-- Collapsed sliver — flush with the right edge when the bubble is hidden.\n Click opens the chat directly; closing returns to the bubble (not the\n sliver). To re-enter hidden mode the user clicks the × pill again. -->\n @if (State === 'collapsed' && IsHidden) {\n <button type=\"button\"\n class=\"chat-overlay-sliver\"\n title=\"Open chat\"\n aria-label=\"Open chat\"\n [style.bottom.px]=\"BubbleBottomPx\"\n (click)=\"Expand()\">\n <i class=\"fa-solid fa-comments chat-overlay-sliver-icon\" aria-hidden=\"true\"></i>\n @if (UnreadCount > 0) {\n <span class=\"chat-overlay-badge chat-overlay-sliver-badge\">{{ UnreadCount > 9 ? '9+' : UnreadCount }}</span>\n }\n </button>\n }\n\n <!-- Expanded / Maximized Chat Panel -->\n @if (State === 'expanded' || State === 'maximized') {\n <div class=\"chat-overlay-panel\"\n [class.maximized]=\"State === 'maximized'\"\n [style.width.px]=\"State === 'maximized' ? null : PanelWidth\"\n [style.height.px]=\"State === 'maximized' ? null : PanelHeight\"\n [style.bottom.px]=\"State === 'maximized' ? null : PanelBottomPx\">\n\n <!-- Resize handles (only in expanded, not maximized) -->\n @if (State === 'expanded') {\n <div class=\"resize-handle resize-left\"\n (mousedown)=\"OnResizeStart($event, 'left')\"></div>\n <div class=\"resize-handle resize-top\"\n (mousedown)=\"OnResizeStart($event, 'top')\"></div>\n <div class=\"resize-handle resize-top-left\"\n (mousedown)=\"OnResizeStart($event, 'top-left')\"></div>\n }\n\n <!-- Panel Header -->\n <div class=\"chat-overlay-header\">\n <div class=\"chat-overlay-title\">\n <i class=\"fa-solid fa-robot\"></i>\n <span>AI Assistant</span>\n </div>\n <div class=\"chat-overlay-header-actions\">\n <button\n class=\"chat-overlay-header-btn\"\n title=\"New conversation\"\n (click)=\"StartNewConversation()\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n @if (ConversationId) {\n <button\n class=\"chat-overlay-header-btn\"\n title=\"Open in full chat workspace\"\n (click)=\"OnOpenFullChatWorkspace()\">\n <i class=\"fa-solid fa-up-right-from-square\"></i>\n </button>\n }\n <button\n class=\"chat-overlay-header-btn\"\n [title]=\"State === 'maximized' ? 'Restore size' : 'Maximize'\"\n (click)=\"ToggleMaximize()\">\n <i class=\"fa-solid\" [class.fa-expand]=\"State !== 'maximized'\" [class.fa-compress]=\"State === 'maximized'\"></i>\n </button>\n <button\n class=\"chat-overlay-header-btn\"\n title=\"Minimize\"\n (click)=\"Collapse()\">\n <i class=\"fa-solid fa-minus\"></i>\n </button>\n </div>\n </div>\n\n <!-- Chat Content — wraps conversation-chat-area -->\n <div class=\"chat-overlay-body\">\n <mj-conversation-chat-area\n [environmentId]=\"EnvironmentId\"\n [currentUser]=\"CurrentUser\"\n [conversationId]=\"ConversationId\"\n [conversation]=\"Conversation\"\n [isNewConversation]=\"IsNewConversation\"\n [pendingMessage]=\"PendingMessage\"\n [pendingAttachments]=\"PendingAttachments\"\n [pendingMessageConversationId]=\"PendingMessageConversationId\"\n [overlayMode]=\"true\"\n [showExportButton]=\"false\"\n [showShareButton]=\"false\"\n [showArtifactIndicator]=\"false\"\n [appContext]=\"AppContext\"\n [emptyStateGreeting]=\"EmptyStateGreeting\"\n (conversationCreated)=\"OnConversationCreated($event)\"\n (conversationRenamed)=\"OnConversationRenamed($event)\"\n (pendingMessageConsumed)=\"OnPendingMessageConsumed()\"\n (openEntityRecord)=\"OnOpenEntityRecord($event)\"\n (navigationRequest)=\"OnNavigationRequest($event)\"\n (taskClicked)=\"OnTaskClicked($event)\"\n ></mj-conversation-chat-area>\n </div>\n </div>\n }\n}\n"]}
1
+ {"version":3,"file":"chat-overlay.component.js","sourceRoot":"","sources":["../../../../src/lib/components/overlay/chat-overlay.component.ts","../../../../src/lib/components/overlay/chat-overlay.component.html"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Floating Chat Overlay Component\n *\n * A collapsible floating panel (bottom-right corner) that wraps the\n * conversation-chat-area component. Provides a persistent, minimizable chat\n * experience across the application.\n *\n * This component is GENERIC -- it does NOT know about NavigationService,\n * Knowledge Hub, or any Explorer-specific concepts. It raises events that\n * the consuming application handles.\n *\n * Coordinates with the full Conversations workspace view through\n * ConversationBridgeService so that switching between overlay and workspace\n * preserves conversation continuity.\n */\n\nimport {\n Component,\n EventEmitter,\n Input,\n OnDestroy,\n OnInit,\n Output,\n ChangeDetectorRef,\n inject\n} from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { takeUntil } from 'rxjs/operators';\nimport { UserInfo, Metadata, CompositeKey } from '@memberjunction/core';\nimport { MJConversationEntity, MJTaskEntity, MJEnvironmentEntityExtended, UserInfoEngine } from '@memberjunction/core-entities';\nimport { AgentClientService } from '@memberjunction/ng-agent-client';\nimport { ClientToolResultEvent } from '@memberjunction/ai-agent-client';\nimport { ConversationBridgeService, ConversationSwitchEvent } from '../../services/conversation-bridge.service';\nimport { NavigationRequest } from '@memberjunction/ng-artifacts';\nimport { PendingAttachment } from '@memberjunction/ng-composer';\n\n/** Visual state of the overlay panel */\nexport type ChatOverlayState = 'collapsed' | 'expanded' | 'maximized';\n\n/** Event payload when the active conversation changes in the overlay */\nexport interface OverlayConversationSwitchedEvent {\n PreviousConversationID: string | null;\n NewConversationID: string | null;\n}\n\n/** Summary of the active record context extracted from `AppContext.AdditionalContext.Form` */\nexport interface OverlayActiveRecordContextSummary {\n Entity: string;\n RecordPrimaryKey: string | null;\n RecordDisplayName: string | null;\n EditMode: boolean;\n Dirty: boolean;\n DirtyFieldNames: readonly string[];\n HasExternalUpdateConflict: boolean;\n PreviewingHistoricalChangeID: string | null;\n TotalLinksCount: number;\n OutgoingLinksCount: number;\n IncomingLinksCount: number;\n}\n\n/** Persisted overlay size and position preferences */\ninterface OverlayPrefs {\n width: number;\n height: number;\n /** Pixels the bubble has been dragged up from its default bottom position. Optional for back-compat with older saved prefs. */\n bubbleOffsetY?: number;\n /** When true, the bubble is hidden and only a thin sliver shows on the right edge. */\n bubbleHidden?: boolean;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-chat-agents-overlay',\n templateUrl: './chat-overlay.component.html',\n styleUrls: ['./chat-overlay.component.css']\n})\nexport class ChatAgentsOverlayComponent extends BaseAngularComponent implements OnInit, OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n private bridge = inject(ConversationBridgeService);\n private agentClient = inject(AgentClientService);\n private destroy$ = new Subject<void>();\n\n // --- Settings persistence ---\n private static readonly SIZE_SETTING_KEY = 'ChatOverlay.Size';\n private static readonly DEFAULT_WIDTH = 420;\n private static readonly DEFAULT_HEIGHT = 600;\n private static readonly MIN_WIDTH = 320;\n private static readonly MIN_HEIGHT = 350;\n private static readonly MAX_WIDTH = 900;\n private static readonly MAX_HEIGHT = 1000;\n\n // --- Bubble drag constants ---\n /** Default `bottom` for both bubble and panel (matches CSS 1.5rem). */\n private static readonly BASE_BOTTOM_PX = 24;\n /** Floating bubble diameter in pixels (matches CSS 3.5rem). */\n private static readonly BUBBLE_SIZE_PX = 56;\n /** Minimum gap to keep between the overlay and the viewport top edge. */\n private static readonly VIEWPORT_TOP_PADDING_PX = 16;\n /** Mousedown-to-mousemove distance that promotes a click into a drag. */\n private static readonly BUBBLE_DRAG_THRESHOLD_PX = 5;\n\n // --- Inputs ---\n\n /** Controls external visibility (e.g., parent hides overlay on chat route) */\n private _isVisible = true;\n\n @Input()\n set IsVisible(value: boolean) {\n const prev = this._isVisible;\n this._isVisible = value;\n if (!value && prev && this.State !== 'collapsed') {\n this.Collapse();\n }\n this.cdr.detectChanges();\n }\n get IsVisible(): boolean {\n return this._isVisible;\n }\n\n /** Current user info, passed through to conversation-chat-area. Auto-resolved from Metadata if not provided. */\n @Input() CurrentUser!: UserInfo;\n\n /** Environment ID, passed through to conversation-chat-area. Auto-resolved from default if not provided. */\n @Input() EnvironmentId!: string;\n\n /** Application context snapshot for AI agent awareness. Updated by the host app on navigation transitions. */\n @Input() AppContext: Record<string, unknown> | null = null;\n\n /** Greeting message shown in the empty state when no conversation is active */\n @Input() EmptyStateGreeting: string = 'How can I help you?';\n\n /**\n * Pixels reserved at the top of the viewport that the bubble and panel must not\n * cross. Set this from the host app to the height of any fixed top chrome (e.g.\n * Explorer's shell-header). Defaults to 0 — generic apps without top chrome\n * keep the full viewport available.\n */\n @Input() TopBoundaryPx: number = 0;\n\n // --- Outputs ---\n\n /** Emitted when the overlay visibility changes */\n @Output() VisibilityChanged = new EventEmitter<ChatOverlayState>();\n\n /** Emitted when a tool finishes executing in the agent client */\n @Output() ToolExecuted = new EventEmitter<ClientToolResultEvent>();\n\n /** Emitted when the active conversation changes in the overlay */\n @Output() ConversationSwitched = new EventEmitter<OverlayConversationSwitchedEvent>();\n\n /** Emitted when the user requests opening the full chat workspace */\n @Output() OpenFullChatWorkspace = new EventEmitter<string | null>();\n\n /** Emitted when navigation is requested (entity record, etc.) */\n @Output() NavigationRequested = new EventEmitter<NavigationRequest>();\n\n /** Emitted when an entity record open is requested */\n @Output() OpenEntityRecord = new EventEmitter<{entityName: string; compositeKey: CompositeKey}>();\n\n /** Emitted when a task is clicked */\n @Output() TaskClicked = new EventEmitter<MJTaskEntity>();\n\n // --- Component State ---\n\n public State: ChatOverlayState = 'collapsed';\n public UnreadCount = 0;\n\n /** Panel dimensions (persisted via UserInfoEngine) */\n public PanelWidth = ChatAgentsOverlayComponent.DEFAULT_WIDTH;\n public PanelHeight = ChatAgentsOverlayComponent.DEFAULT_HEIGHT;\n\n /**\n * Pixels the floating bubble has been dragged up from its default\n * bottom-right corner position. Always >= 0; clamping at render time\n * keeps the bubble on-screen even after a viewport resize.\n */\n public BubbleOffsetY = 0;\n\n /** True while the user is actively dragging the bubble; used to swap cursor + suppress click. */\n public IsBubbleDragging = false;\n\n /**\n * True from mousedown until mouseup on the bubble, regardless of whether the\n * gesture became a drag. Used to give immediate \"I'm being held\" feedback so\n * the user can see drag is possible even before crossing the move threshold.\n */\n public IsBubblePressed = false;\n\n /**\n * When true, the floating bubble is hidden and replaced by a thin sliver\n * flush with the right edge of the viewport. Persisted across sessions via\n * OverlayPrefs.bubbleHidden. Clicking the sliver restores the bubble.\n */\n public IsHidden = false;\n\n /** Active conversation ID managed locally */\n private _conversationId: string | null = null;\n public get ConversationId(): string | null {\n return this._conversationId;\n }\n\n /** Active conversation entity */\n public Conversation: MJConversationEntity | null = null;\n\n /** Whether a new unsaved conversation is in progress */\n public IsNewConversation = true;\n\n /** Pending message to send after conversation creation */\n public PendingMessage: string | null = null;\n /** The conversation {@link PendingMessage} is destined for — pins the auto-send to that\n * conversation's input so a fast conversation-swap can't redirect it elsewhere. */\n public PendingMessageConversationId: string | null = null;\n\n /** Pending attachments to send after conversation creation */\n public PendingAttachments: PendingAttachment[] | null = null;\n\n /** Resize drag state */\n private isResizing = false;\n private resizeEdge: 'left' | 'top' | 'top-left' | null = null;\n private resizeStartX = 0;\n private resizeStartY = 0;\n private resizeStartWidth = 0;\n private resizeStartHeight = 0;\n\n /** Bubble drag state */\n private bubbleDragStartMouseY = 0;\n private bubbleDragStartOffset = 0;\n /** True once the pointer has moved past BUBBLE_DRAG_THRESHOLD_PX; suppresses the implicit click. */\n private bubbleDragMoved = false;\n /** ID of the pointer currently driving the drag — guards against multi-touch confusion. */\n private activeBubblePointerId: number | null = null;\n /** Element that captured the pointer; needed to release capture on end/cancel. */\n private bubbleCaptureTarget: HTMLElement | null = null;\n\n // --- Lifecycle ---\n\n ngOnInit(): void {\n this.resolveDefaults();\n this.loadPreferences();\n this.subscribeToBridgeEvents();\n this.subscribeToToolEvents();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n this.removeResizeListeners();\n this.removeBubbleDragListeners();\n }\n\n // --- Public Methods ---\n\n /** Toggle between collapsed and expanded states */\n public Toggle(): void {\n if (this.State === 'collapsed') {\n this.Expand();\n } else {\n this.Collapse();\n }\n }\n\n /** Expand the overlay to show the chat panel */\n public Expand(): void {\n // Expanding implies the user wants the chat visible — clear any hidden\n // state so collapse returns to the bubble, not back to the sliver.\n if (this.IsHidden) {\n this.IsHidden = false;\n this.savePreferences();\n }\n this.State = 'expanded';\n this.UnreadCount = 0;\n this.bridge.NotifyOverlayActive(true);\n this.VisibilityChanged.emit(this.State);\n this.cdr.detectChanges();\n }\n\n /** Collapse the overlay to the floating button */\n public Collapse(): void {\n this.State = 'collapsed';\n this.bridge.NotifyOverlayActive(false);\n this.VisibilityChanged.emit(this.State);\n this.cdr.detectChanges();\n }\n\n /** Toggle between expanded and maximized states */\n public ToggleMaximize(): void {\n if (this.State === 'maximized') {\n this.State = 'expanded';\n } else {\n this.State = 'maximized';\n }\n this.bridge.NotifyOverlayActive(true);\n this.VisibilityChanged.emit(this.State);\n this.cdr.detectChanges();\n }\n\n /** Handle the user requesting to open full chat workspace */\n public OnOpenFullChatWorkspace(): void {\n this.OpenFullChatWorkspace.emit(this._conversationId);\n this.bridge.SwitchToWorkspace(this._conversationId);\n this.Collapse();\n }\n\n /** Handle conversation creation from the chat area */\n public OnConversationCreated(event: {\n conversation: MJConversationEntity;\n pendingMessage?: string;\n pendingAttachments?: PendingAttachment[];\n }): void {\n // Set ALL state atomically before Angular change detection runs\n this.PendingMessage = event.pendingMessage || null;\n this.PendingAttachments = event.pendingAttachments || null;\n this.PendingMessageConversationId = event.conversation.ID;\n const prevId = this._conversationId;\n this._conversationId = event.conversation.ID;\n this.Conversation = event.conversation;\n this.IsNewConversation = false;\n this.bridge.SetActiveFromOverlay(event.conversation.ID);\n this.emitConversationSwitched(prevId, event.conversation.ID);\n }\n\n /** Handle pending message consumed by chat area */\n public OnPendingMessageConsumed(): void {\n this.PendingMessage = null;\n this.PendingAttachments = null;\n this.PendingMessageConversationId = null;\n }\n\n /** Handle conversation rename from chat area */\n public OnConversationRenamed(_event: {conversationId: string; name: string; description: string}): void {\n // The overlay doesn't need to do anything specific here;\n // the conversation entity is updated in-place by the chat area.\n }\n\n /** Handle entity record open requests */\n public OnOpenEntityRecord(event: {entityName: string; compositeKey: CompositeKey}): void {\n this.OpenEntityRecord.emit(event);\n }\n\n /** Handle navigation requests from the chat area */\n public OnNavigationRequest(event: NavigationRequest): void {\n this.NavigationRequested.emit(event);\n }\n\n /** Handle task clicks from the chat area */\n public OnTaskClicked(task: MJTaskEntity): void {\n this.TaskClicked.emit(task);\n }\n\n /** Start a new conversation in the overlay */\n public StartNewConversation(): void {\n const prevId = this._conversationId;\n this._conversationId = null;\n this.Conversation = null;\n // Force Angular change detection by toggling off then on\n // so the setter fires even if already in new-conversation state\n this.IsNewConversation = false;\n this.cdr.detectChanges();\n this.IsNewConversation = true;\n this.bridge.SetActiveFromOverlay(null);\n this.emitConversationSwitched(prevId, null);\n this.cdr.detectChanges();\n }\n\n /**\n * Hide the floating bubble — leaves a thin sliver on the right edge as the\n * only affordance to bring it back. Invoked from the small \"×\" pill that\n * appears on hover. Stops propagation so the bubble's own click handler\n * doesn't fire and toggle the panel open.\n */\n public Hide(event: Event): void {\n event.stopPropagation();\n event.preventDefault();\n if (this.IsHidden) return;\n this.IsHidden = true;\n this.savePreferences();\n this.cdr.detectChanges();\n }\n\n /** Restore the floating bubble after it was hidden. Triggered by clicking the sliver. */\n public Show(): void {\n if (!this.IsHidden) return;\n this.IsHidden = false;\n this.savePreferences();\n this.cdr.detectChanges();\n }\n\n /** Increment unread badge (called externally when messages arrive while collapsed) */\n public IncrementUnread(): void {\n if (this.State === 'collapsed') {\n this.UnreadCount++;\n this.cdr.detectChanges();\n }\n }\n\n // --- Resize Methods ---\n\n /** Start resizing from an edge or corner */\n public OnResizeStart(event: MouseEvent, edge: 'left' | 'top' | 'top-left'): void {\n event.preventDefault();\n event.stopPropagation();\n this.isResizing = true;\n this.resizeEdge = edge;\n this.resizeStartX = event.clientX;\n this.resizeStartY = event.clientY;\n this.resizeStartWidth = this.PanelWidth;\n this.resizeStartHeight = this.PanelHeight;\n\n document.addEventListener('mousemove', this.onResizeMove);\n document.addEventListener('mouseup', this.onResizeEnd);\n }\n\n private onResizeMove = (event: MouseEvent): void => {\n if (!this.isResizing || !this.resizeEdge) return;\n\n const deltaX = this.resizeStartX - event.clientX; // Inverted: dragging left increases width\n const deltaY = this.resizeStartY - event.clientY; // Inverted: dragging up increases height\n\n if (this.resizeEdge === 'left' || this.resizeEdge === 'top-left') {\n this.PanelWidth = this.clampWidth(this.resizeStartWidth + deltaX);\n }\n if (this.resizeEdge === 'top' || this.resizeEdge === 'top-left') {\n this.PanelHeight = this.clampHeight(this.resizeStartHeight + deltaY);\n }\n this.cdr.detectChanges();\n };\n\n private onResizeEnd = (): void => {\n if (!this.isResizing) return;\n this.isResizing = false;\n this.resizeEdge = null;\n this.removeResizeListeners();\n this.savePreferences();\n };\n\n private removeResizeListeners(): void {\n document.removeEventListener('mousemove', this.onResizeMove);\n document.removeEventListener('mouseup', this.onResizeEnd);\n }\n\n private clampWidth(value: number): number {\n return Math.max(ChatAgentsOverlayComponent.MIN_WIDTH, Math.min(ChatAgentsOverlayComponent.MAX_WIDTH, value));\n }\n\n private clampHeight(value: number): number {\n return Math.max(ChatAgentsOverlayComponent.MIN_HEIGHT, Math.min(ChatAgentsOverlayComponent.MAX_HEIGHT, value));\n }\n\n // --- Bubble Drag Methods (Pointer Events — unified mouse / touch / pen) ---\n\n /**\n * Start tracking a potential bubble drag. We don't enter drag mode until\n * the pointer moves past BUBBLE_DRAG_THRESHOLD_PX — releasing before that\n * threshold is treated as a normal click/tap and opens the chat (via Toggle()).\n *\n * Pointer Events (not mousedown) so the same code path serves desktop mouse,\n * touch on phones/tablets, and pen input. setPointerCapture keeps the gesture\n * tied to this element even if the finger or cursor strays off the bubble.\n */\n public OnBubblePointerDown(event: PointerEvent): void {\n // Mouse: respect primary-button only. Touch/pen: button is always 0, so this passes naturally.\n if (event.pointerType === 'mouse' && event.button !== 0) return;\n // Don't start a second drag while one is in flight (e.g. second finger on touch).\n if (this.activeBubblePointerId !== null) return;\n event.preventDefault();\n\n const target = event.currentTarget as HTMLElement;\n target.setPointerCapture(event.pointerId);\n this.bubbleCaptureTarget = target;\n\n this.activeBubblePointerId = event.pointerId;\n this.bubbleDragStartMouseY = event.clientY;\n this.bubbleDragStartOffset = this.BubbleOffsetY;\n this.bubbleDragMoved = false;\n this.IsBubblePressed = true;\n this.cdr.detectChanges();\n\n document.addEventListener('pointermove', this.onBubbleDragMove);\n document.addEventListener('pointerup', this.onBubbleDragEnd);\n document.addEventListener('pointercancel', this.onBubbleDragEnd);\n }\n\n private onBubbleDragMove = (event: PointerEvent): void => {\n if (event.pointerId !== this.activeBubblePointerId) return;\n const deltaY = this.bubbleDragStartMouseY - event.clientY; // dragging up = positive\n if (!this.bubbleDragMoved) {\n if (Math.abs(deltaY) < ChatAgentsOverlayComponent.BUBBLE_DRAG_THRESHOLD_PX) return;\n this.bubbleDragMoved = true;\n this.IsBubbleDragging = true;\n }\n this.BubbleOffsetY = this.clampBubbleOffsetY(this.bubbleDragStartOffset + deltaY);\n this.cdr.detectChanges();\n };\n\n private onBubbleDragEnd = (event: PointerEvent): void => {\n if (event.pointerId !== this.activeBubblePointerId) return;\n this.removeBubbleDragListeners();\n\n if (this.bubbleCaptureTarget) {\n // Browser may have implicitly released capture on pointerup already (per the\n // Pointer Events spec). releasePointerCapture throws in that race; safe to ignore.\n try { this.bubbleCaptureTarget.releasePointerCapture(event.pointerId); } catch { /* noop */ }\n }\n this.bubbleCaptureTarget = null;\n this.activeBubblePointerId = null;\n\n const wasDragged = this.bubbleDragMoved;\n const wasCancelled = event.type === 'pointercancel';\n this.bubbleDragMoved = false;\n this.IsBubbleDragging = false;\n this.IsBubblePressed = false;\n if (wasDragged) {\n this.savePreferences();\n this.cdr.detectChanges();\n } else if (!wasCancelled) {\n this.Toggle();\n } else {\n this.cdr.detectChanges();\n }\n };\n\n private removeBubbleDragListeners(): void {\n document.removeEventListener('pointermove', this.onBubbleDragMove);\n document.removeEventListener('pointerup', this.onBubbleDragEnd);\n document.removeEventListener('pointercancel', this.onBubbleDragEnd);\n }\n\n /**\n * Reserved space at the top of the viewport — host-supplied chrome plus\n * the padding gap we always keep above the bubble/panel.\n */\n private get topReservedPx(): number {\n return Math.max(0, this.TopBoundaryPx) + ChatAgentsOverlayComponent.VIEWPORT_TOP_PADDING_PX;\n }\n\n /** Clamp the offset so the bubble stays fully visible below the top boundary. */\n private clampBubbleOffsetY(value: number): number {\n const maxOffset = window.innerHeight\n - ChatAgentsOverlayComponent.BUBBLE_SIZE_PX\n - ChatAgentsOverlayComponent.BASE_BOTTOM_PX\n - this.topReservedPx;\n return Math.max(0, Math.min(Math.max(0, maxOffset), value));\n }\n\n // --- Render Position Getters ---\n\n /** Effective `bottom` (px) for the floating bubble, clamped to the current viewport. */\n public get BubbleBottomPx(): number {\n const ideal = ChatAgentsOverlayComponent.BASE_BOTTOM_PX + this.BubbleOffsetY;\n const max = window.innerHeight\n - ChatAgentsOverlayComponent.BUBBLE_SIZE_PX\n - this.topReservedPx;\n return Math.max(\n ChatAgentsOverlayComponent.BASE_BOTTOM_PX,\n Math.min(ideal, Math.max(ChatAgentsOverlayComponent.BASE_BOTTOM_PX, max))\n );\n }\n\n /**\n * Effective `bottom` (px) for the expanded panel. Anchors to the bubble's\n * current bottom edge so the panel grows up from where the user parked the\n * bubble, but clamps downward whenever the panel would otherwise extend\n * past the viewport's top boundary — that's the \"reposition lower so the\n * chat interface stays visible\" behavior.\n */\n public get PanelBottomPx(): number {\n const ideal = ChatAgentsOverlayComponent.BASE_BOTTOM_PX + this.BubbleOffsetY;\n const maxBottomForVisibility = window.innerHeight\n - this.PanelHeight\n - this.topReservedPx;\n return Math.max(\n ChatAgentsOverlayComponent.BASE_BOTTOM_PX,\n Math.min(ideal, maxBottomForVisibility)\n );\n }\n\n /**\n * Extracts a structured summary of the currently open record form from\n * `AppContext.AdditionalContext.Form` when the user is viewing a record.\n */\n public get ActiveRecordContext(): OverlayActiveRecordContextSummary | null {\n const additional = this.AppContext?.['AdditionalContext'] as Record<string, unknown> | undefined;\n const form = additional?.['Form'] as Record<string, unknown> | undefined;\n if (!form || typeof form['Entity'] !== 'string' || !form['Entity']) {\n return null;\n }\n const recordState = form['RecordState'] as Record<string, unknown> | undefined;\n const links = form['Links'] as Record<string, unknown> | undefined;\n const dirtyFieldNames = Array.isArray(recordState?.['DirtyFieldNames'])\n ? (recordState['DirtyFieldNames'] as unknown[]).filter((f): f is string => typeof f === 'string')\n : [];\n return {\n Entity: form['Entity'] as string,\n RecordPrimaryKey: typeof form['RecordPrimaryKey'] === 'string' ? (form['RecordPrimaryKey'] as string) : null,\n RecordDisplayName: typeof recordState?.['RecordDisplayName'] === 'string' ? (recordState['RecordDisplayName'] as string) : null,\n EditMode: recordState?.['EditMode'] === true,\n Dirty: recordState?.['Dirty'] === true,\n DirtyFieldNames: dirtyFieldNames,\n HasExternalUpdateConflict: recordState?.['HasExternalUpdateConflict'] === true,\n PreviewingHistoricalChangeID: typeof recordState?.['PreviewingHistoricalChangeID'] === 'string'\n ? (recordState['PreviewingHistoricalChangeID'] as string)\n : null,\n TotalLinksCount: typeof links?.['TotalCount'] === 'number' ? (links['TotalCount'] as number) : 0,\n OutgoingLinksCount: typeof links?.['OutgoingCount'] === 'number' ? (links['OutgoingCount'] as number) : 0,\n IncomingLinksCount: typeof links?.['IncomingCount'] === 'number' ? (links['IncomingCount'] as number) : 0,\n };\n }\n\n // --- Private Methods ---\n\n /** Auto-resolve CurrentUser and EnvironmentId from Metadata when not provided as inputs */\n private resolveDefaults(): void {\n if (!this.CurrentUser) {\n const md = this.ProviderToUse;\n this.CurrentUser = md.CurrentUser;\n }\n if (!this.EnvironmentId) {\n this.EnvironmentId = MJEnvironmentEntityExtended.DefaultEnvironmentID;\n }\n }\n\n /** Load saved panel size and bubble position from UserInfoEngine */\n private loadPreferences(): void {\n try {\n const engine = UserInfoEngine.Instance;\n const raw = engine.GetSetting(ChatAgentsOverlayComponent.SIZE_SETTING_KEY);\n if (raw) {\n const prefs: OverlayPrefs = JSON.parse(raw);\n this.PanelWidth = this.clampWidth(prefs.width);\n this.PanelHeight = this.clampHeight(prefs.height);\n if (typeof prefs.bubbleOffsetY === 'number') {\n this.BubbleOffsetY = Math.max(0, prefs.bubbleOffsetY);\n }\n if (typeof prefs.bubbleHidden === 'boolean') {\n this.IsHidden = prefs.bubbleHidden;\n }\n }\n } catch {\n // Use defaults on error\n }\n }\n\n /** Persist panel size and bubble position to UserInfoEngine (debounced) */\n private savePreferences(): void {\n const prefs: OverlayPrefs = {\n width: this.PanelWidth,\n height: this.PanelHeight,\n bubbleOffsetY: this.BubbleOffsetY,\n bubbleHidden: this.IsHidden\n };\n UserInfoEngine.Instance.SetSettingDebounced(\n ChatAgentsOverlayComponent.SIZE_SETTING_KEY,\n JSON.stringify(prefs)\n );\n }\n\n /** Subscribe to bridge events for cross-view coordination */\n private subscribeToBridgeEvents(): void {\n this.bridge.SwitchEvent$\n .pipe(takeUntil(this.destroy$))\n .subscribe((event: ConversationSwitchEvent) => {\n if (event.Target === 'overlay') {\n this.handleSwitchToOverlay(event);\n }\n });\n\n // Allow arbitrary callers (Form Builder cockpit, etc.) to ask the\n // overlay to expand. Idempotent if we're already expanded —\n // Expand() is safe to call in any state.\n this.bridge.ExpandOverlayRequested$\n .pipe(takeUntil(this.destroy$))\n .subscribe(() => {\n if (this.State === 'collapsed') {\n this.Expand();\n }\n });\n\n this.bridge.ActiveConversationID$\n .pipe(takeUntil(this.destroy$))\n .subscribe((id: string | null) => {\n // Only update if the change came from outside (workspace)\n if (id !== this._conversationId && this.bridge.WorkspaceActive$.value) {\n const prevId = this._conversationId;\n this._conversationId = id;\n this.IsNewConversation = id === null;\n this.Conversation = null; // Will be loaded by chat area\n this.emitConversationSwitched(prevId, id);\n this.cdr.detectChanges();\n }\n });\n }\n\n /** Subscribe to agent client tool execution events */\n private subscribeToToolEvents(): void {\n this.agentClient.ToolExecuted$\n .pipe(takeUntil(this.destroy$))\n .subscribe((event: ClientToolResultEvent) => {\n this.ToolExecuted.emit(event);\n });\n }\n\n /** Handle request to switch conversation to the overlay */\n private handleSwitchToOverlay(event: ConversationSwitchEvent): void {\n const prevId = this._conversationId;\n this._conversationId = event.ConversationID;\n this.IsNewConversation = event.ConversationID === null;\n this.Conversation = null; // Will be reloaded by chat area\n this.Expand();\n this.emitConversationSwitched(prevId, event.ConversationID);\n }\n\n /** Emit a conversation switched event */\n private emitConversationSwitched(prevId: string | null, newId: string | null): void {\n this.ConversationSwitched.emit({\n PreviousConversationID: prevId,\n NewConversationID: newId\n });\n }\n}\n","@if (IsVisible) {\n <!-- Floating Button (collapsed state, not hidden) -->\n @if (State === 'collapsed' && !IsHidden) {\n <div class=\"chat-overlay-bubble\"\n [class.is-pressed]=\"IsBubblePressed\"\n [class.is-dragging]=\"IsBubbleDragging\"\n [style.bottom.px]=\"BubbleBottomPx\"\n (pointerdown)=\"OnBubblePointerDown($event)\">\n <i class=\"fa-solid fa-chevron-up chat-overlay-bubble-arrow chat-overlay-bubble-arrow-up\" aria-hidden=\"true\"></i>\n <i class=\"fa-solid fa-chevron-down chat-overlay-bubble-arrow chat-overlay-bubble-arrow-down\" aria-hidden=\"true\"></i>\n <i class=\"fa-solid fa-comments chat-overlay-bubble-icon\"></i>\n @if (UnreadCount > 0) {\n <span class=\"chat-overlay-badge\">{{ UnreadCount > 9 ? '9+' : UnreadCount }}</span>\n }\n <!-- Hide affordance: revealed on hover. pointerdown stops drag from starting; click hides the bubble. -->\n <button type=\"button\"\n class=\"chat-overlay-bubble-close\"\n title=\"Hide chat — a thin sliver will remain on the right edge\"\n aria-label=\"Hide chat overlay\"\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"Hide($event)\">\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n\n <!-- Collapsed sliver — flush with the right edge when the bubble is hidden.\n Click opens the chat directly; closing returns to the bubble (not the\n sliver). To re-enter hidden mode the user clicks the × pill again. -->\n @if (State === 'collapsed' && IsHidden) {\n <button type=\"button\"\n class=\"chat-overlay-sliver\"\n title=\"Open chat\"\n aria-label=\"Open chat\"\n [style.bottom.px]=\"BubbleBottomPx\"\n (click)=\"Expand()\">\n <i class=\"fa-solid fa-comments chat-overlay-sliver-icon\" aria-hidden=\"true\"></i>\n @if (UnreadCount > 0) {\n <span class=\"chat-overlay-badge chat-overlay-sliver-badge\">{{ UnreadCount > 9 ? '9+' : UnreadCount }}</span>\n }\n </button>\n }\n\n <!-- Expanded / Maximized Chat Panel -->\n @if (State === 'expanded' || State === 'maximized') {\n <div class=\"chat-overlay-panel\"\n [class.maximized]=\"State === 'maximized'\"\n [style.width.px]=\"State === 'maximized' ? null : PanelWidth\"\n [style.height.px]=\"State === 'maximized' ? null : PanelHeight\"\n [style.bottom.px]=\"State === 'maximized' ? null : PanelBottomPx\">\n\n <!-- Resize handles (only in expanded, not maximized) -->\n @if (State === 'expanded') {\n <div class=\"resize-handle resize-left\"\n (mousedown)=\"OnResizeStart($event, 'left')\"></div>\n <div class=\"resize-handle resize-top\"\n (mousedown)=\"OnResizeStart($event, 'top')\"></div>\n <div class=\"resize-handle resize-top-left\"\n (mousedown)=\"OnResizeStart($event, 'top-left')\"></div>\n }\n\n <!-- Panel Header -->\n <div class=\"chat-overlay-header\">\n <div class=\"chat-overlay-title\">\n <i class=\"fa-solid fa-robot\"></i>\n <span>AI Assistant</span>\n </div>\n <div class=\"chat-overlay-header-actions\">\n <button\n class=\"chat-overlay-header-btn\"\n title=\"New conversation\"\n (click)=\"StartNewConversation()\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n @if (ConversationId) {\n <button\n class=\"chat-overlay-header-btn\"\n title=\"Open in full chat workspace\"\n (click)=\"OnOpenFullChatWorkspace()\">\n <i class=\"fa-solid fa-up-right-from-square\"></i>\n </button>\n }\n <button\n class=\"chat-overlay-header-btn\"\n [title]=\"State === 'maximized' ? 'Restore size' : 'Maximize'\"\n (click)=\"ToggleMaximize()\">\n <i class=\"fa-solid\" [class.fa-expand]=\"State !== 'maximized'\" [class.fa-compress]=\"State === 'maximized'\"></i>\n </button>\n <button\n class=\"chat-overlay-header-btn\"\n title=\"Minimize\"\n (click)=\"Collapse()\">\n <i class=\"fa-solid fa-minus\"></i>\n </button>\n </div>\n </div>\n\n <!-- Active Record Context Bar (when viewing an entity record form) -->\n @if (ActiveRecordContext; as ctx) {\n <div class=\"chat-overlay-record-context-bar\" role=\"status\" aria-live=\"polite\">\n <div class=\"chat-overlay-context-main\">\n <i class=\"fa-solid fa-wand-magic-sparkles chat-overlay-context-icon\" aria-hidden=\"true\"></i>\n <span class=\"chat-overlay-context-entity\">{{ ctx.Entity }}</span>\n @if (ctx.RecordDisplayName) {\n <span class=\"chat-overlay-context-sep\" aria-hidden=\"true\">·</span>\n <span class=\"chat-overlay-context-record-name\" [title]=\"ctx.RecordDisplayName\">{{ ctx.RecordDisplayName }}</span>\n }\n </div>\n <div class=\"chat-overlay-context-chips\">\n @if (ctx.Dirty) {\n <span class=\"chat-overlay-context-chip chat-overlay-context-chip-dirty\"\n [title]=\"'Unsaved edits: ' + ctx.DirtyFieldNames.join(', ')\">\n <i class=\"fa-solid fa-pen\" aria-hidden=\"true\"></i>\n {{ ctx.DirtyFieldNames.length }} unsaved\n </span>\n }\n @if (ctx.HasExternalUpdateConflict) {\n <span class=\"chat-overlay-context-chip chat-overlay-context-chip-conflict\"\n title=\"Record has an external update conflict\">\n <i class=\"fa-solid fa-triangle-exclamation\" aria-hidden=\"true\"></i>\n Conflict\n </span>\n }\n @if (ctx.PreviewingHistoricalChangeID) {\n <span class=\"chat-overlay-context-chip chat-overlay-context-chip-timetravel\"\n title=\"Previewing a historical version in form\">\n <i class=\"fa-solid fa-clock-rotate-left\" aria-hidden=\"true\"></i>\n Time-Travel\n </span>\n }\n @if (ctx.TotalLinksCount > 0) {\n <span class=\"chat-overlay-context-chip chat-overlay-context-chip-links\"\n [title]=\"ctx.OutgoingLinksCount + ' on this record · ' + ctx.IncomingLinksCount + ' linked to this'\">\n <i class=\"fa-solid fa-diagram-project\" aria-hidden=\"true\"></i>\n {{ ctx.TotalLinksCount }} {{ ctx.TotalLinksCount === 1 ? 'link' : 'links' }}\n </span>\n }\n </div>\n </div>\n }\n\n <!-- Chat Content — wraps conversation-chat-area -->\n <div class=\"chat-overlay-body\">\n <mj-conversation-chat-area\n [environmentId]=\"EnvironmentId\"\n [currentUser]=\"CurrentUser\"\n [conversationId]=\"ConversationId\"\n [conversation]=\"Conversation\"\n [isNewConversation]=\"IsNewConversation\"\n [pendingMessage]=\"PendingMessage\"\n [pendingAttachments]=\"PendingAttachments\"\n [pendingMessageConversationId]=\"PendingMessageConversationId\"\n [overlayMode]=\"true\"\n [showExportButton]=\"false\"\n [showShareButton]=\"false\"\n [showArtifactIndicator]=\"false\"\n [appContext]=\"AppContext\"\n [emptyStateGreeting]=\"EmptyStateGreeting\"\n (conversationCreated)=\"OnConversationCreated($event)\"\n (conversationRenamed)=\"OnConversationRenamed($event)\"\n (pendingMessageConsumed)=\"OnPendingMessageConsumed()\"\n (openEntityRecord)=\"OnOpenEntityRecord($event)\"\n (navigationRequest)=\"OnNavigationRequest($event)\"\n (taskClicked)=\"OnTaskClicked($event)\"\n ></mj-conversation-chat-area>\n </div>\n </div>\n }\n}\n"]}
@@ -49,7 +49,7 @@ function ProjectFormModalComponent_Conditional_18_Template(rf, ctx) { if (rf & 1
49
49
  i0.ɵɵproperty("value", false);
50
50
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.FormData.isPersonal);
51
51
  i0.ɵɵadvance(4);
52
- i0.ɵɵtextInterpolate1(" ", ctx_r1.FormData.isPersonal ? "Only you can see this folder." : "Everyone can see this folder and its name. They will not see the conversations you keep in it.", " ");
52
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.FormData.isPersonal ? "Only you can see this folder." : "Everyone can see this folder and its name. They will not see the conversations you keep in it. Once shared, a folder can't be made private again.", " ");
53
53
  } }
54
54
  function ProjectFormModalComponent_For_25_Template(rf, ctx) { if (rf & 1) {
55
55
  const _r3 = i0.ɵɵgetCurrentView();
@@ -544,7 +544,7 @@ export class ProjectFormModalComponent extends BaseAngularComponent {
544
544
  <p class="visibility-hint" id="projectVisibilityHint">
545
545
  {{ FormData.isPersonal
546
546
  ? 'Only you can see this folder.'
547
- : 'Everyone can see this folder and its name. They will not see the conversations you keep in it.' }}
547
+ : "Everyone can see this folder and its name. They will not see the conversations you keep in it. Once shared, a folder can't be made private again." }}
548
548
  </p>
549
549
  </fieldset>
550
550
  }
@@ -1 +1 @@
1
- {"version":3,"file":"project-form-modal.component.js","sourceRoot":"","sources":["../../../../src/lib/components/project/project-form-modal.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, ViewChild, ChangeDetectorRef } from '@angular/core';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { MJDialogRef } from '@memberjunction/ng-ui-components';\nimport { MJProjectEntity } from '@memberjunction/core-entities';\nimport { UserInfo, Metadata } from '@memberjunction/core';\n\nexport interface ProjectFormData {\n name: string;\n description: string;\n color: string;\n icon: string;\n /** true = only the owner sees it; false = everyone in the environment does. */\n isPersonal: boolean;\n}\n\nconst DEFAULT_PROJECT_COLORS = [\n '#0076B6', // MJ Blue\n '#F44336', // Red\n '#E91E63', // Pink\n '#9C27B0', // Purple\n '#673AB7', // Deep Purple\n '#3F51B5', // Indigo\n '#2196F3', // Blue\n '#03A9F4', // Light Blue\n '#00BCD4', // Cyan\n '#009688', // Teal\n '#4CAF50', // Green\n '#8BC34A', // Light Green\n '#CDDC39', // Lime\n '#FFEB3B', // Yellow\n '#FFC107', // Amber\n '#FF9800', // Orange\n '#FF5722', // Deep Orange\n '#795548', // Brown\n '#607D8B', // Blue Grey\n '#9E9E9E' // Grey\n];\n\nconst DEFAULT_PROJECT_ICONS = [\n 'fa-folder',\n 'fa-folder-open',\n 'fa-briefcase',\n 'fa-project-diagram',\n 'fa-chart-line',\n 'fa-tasks',\n 'fa-clipboard-list',\n 'fa-bullseye',\n 'fa-rocket',\n 'fa-lightbulb',\n 'fa-brain',\n 'fa-cogs',\n 'fa-code',\n 'fa-database',\n 'fa-server',\n 'fa-cloud',\n 'fa-mobile-alt',\n 'fa-desktop',\n 'fa-globe',\n 'fa-users'\n];\n\n@Component({\n standalone: false,\n selector: 'mj-project-form-modal',\n template: `\n <mj-dialog\n [Title]=\"isEditMode ? 'Edit Folder' : 'New Folder'\"\n [Width]=\"560\"\n [MinWidth]=\"400\"\n [Visible]=\"true\"\n (Close)=\"onCancel()\">\n\n <div class=\"project-form\">\n <!-- Live preview chip -->\n <div class=\"folder-preview\">\n <span class=\"folder-preview-chip\" [style.backgroundColor]=\"chipBackground\" [style.color]=\"formData.color\">\n <i class=\"fa-solid {{ formData.icon }}\"></i>\n </span>\n <span class=\"folder-preview-name\">{{ formData.name.trim() || 'Untitled folder' }}</span>\n </div>\n\n <!-- Name Input -->\n <div class=\"form-field\">\n <label for=\"projectName\" class=\"required\">\n Folder Name\n </label>\n <input\n id=\"projectName\"\n type=\"text\"\n [(ngModel)]=\"formData.name\"\n placeholder=\"e.g. Client work, Research, Ideas\"\n class=\"mj-input full-width\"\n (keydown.enter)=\"onSave()\"\n autofocus />\n @if (showNameError) {\n <div class=\"error-message\">Folder name is required</div>\n }\n </div>\n\n <!-- Description Textarea -->\n <div class=\"form-field\">\n <label for=\"projectDescription\">\n Description\n </label>\n <textarea\n id=\"projectDescription\"\n [(ngModel)]=\"formData.description\"\n placeholder=\"What goes in this folder? (optional)\"\n class=\"mj-textarea full-width\"\n rows=\"2\"></textarea>\n </div>\n\n <!-- Visibility. TWO NAMED OPTIONS, not a checkbox: with a checkbox the unchecked\n meaning lives only in the helper text, so the shared state is never actually\n named. A fieldset/legend also gives the group a real accessible name, which a\n bare <label>Visibility</label> did not, and the hint is a sibling of the\n options rather than inside one — inside, a screen reader read the whole hint\n as part of the option's name.\n\n A SHARED folder shows a statement instead of the control. Visibility is a\n create-time choice in one direction only: personal -> shared stays available,\n because it only ever adds. See VisibilityIsLocked for why the reverse is not\n offered. -->\n <div class=\"form-field\">\n @if (VisibilityIsLocked) {\n <fieldset class=\"visibility-set\" aria-describedby=\"projectVisibilityHint\">\n <legend>Visibility</legend>\n <p class=\"visibility-locked\">\n <i class=\"fa-solid fa-users\" aria-hidden=\"true\"></i>\n Shared with everyone\n </p>\n <p class=\"visibility-hint\" id=\"projectVisibilityHint\">\n A shared folder stays shared. To keep something to yourself, create a new\n private folder and move it there.\n </p>\n </fieldset>\n } @else {\n <fieldset class=\"visibility-set\" aria-describedby=\"projectVisibilityHint\">\n <legend>Visibility</legend>\n <label class=\"visibility-choice\">\n <input type=\"radio\" name=\"projectVisibility\" [value]=\"true\"\n [(ngModel)]=\"FormData.isPersonal\" />\n <span>Only me</span>\n </label>\n <label class=\"visibility-choice\">\n <input type=\"radio\" name=\"projectVisibility\" [value]=\"false\"\n [(ngModel)]=\"FormData.isPersonal\" />\n <span>Everyone</span>\n </label>\n <p class=\"visibility-hint\" id=\"projectVisibilityHint\">\n {{ FormData.isPersonal\n ? 'Only you can see this folder.'\n : 'Everyone can see this folder and its name. They will not see the conversations you keep in it.' }}\n </p>\n </fieldset>\n }\n </div>\n\n <!-- Color Picker -->\n <div class=\"form-field\">\n <label>Color</label>\n <div class=\"color-picker-section\">\n <div class=\"color-palette\">\n @for (color of availableColors; track color) {\n <button\n type=\"button\"\n class=\"color-swatch\"\n [class.selected]=\"formData.color === color\"\n [style.backgroundColor]=\"color\"\n (click)=\"selectColor(color)\"\n [title]=\"color\">\n </button>\n }\n </div>\n <div class=\"custom-color-input\">\n <label for=\"customColor\">Custom:</label>\n <input\n id=\"customColor\"\n type=\"color\"\n [(ngModel)]=\"formData.color\"\n class=\"custom-color-picker\" />\n <span class=\"color-value\">{{ formData.color }}</span>\n </div>\n </div>\n </div>\n\n <!-- Icon Selector -->\n <div class=\"form-field\">\n <label>Icon</label>\n <div class=\"icon-grid\">\n @for (icon of availableIcons; track icon) {\n <button\n type=\"button\"\n class=\"icon-option\"\n [class.selected]=\"formData.icon === icon\"\n [style.color]=\"formData.icon === icon ? formData.color : null\"\n (click)=\"selectIcon(icon)\"\n [title]=\"icon\">\n <i class=\"fa-solid {{ icon }}\"></i>\n </button>\n }\n </div>\n </div>\n </div>\n\n <mj-dialog-actions>\n <button mjButton variant=\"primary\" (click)=\"onSave()\">\n {{ isEditMode ? 'Save Changes' : 'Create Folder' }}\n </button>\n <button mjButton (click)=\"onCancel()\">Cancel</button>\n </mj-dialog-actions>\n </mj-dialog>\n `,\n styles: [`\n .project-form {\n padding: 20px 24px 8px;\n display: flex;\n flex-direction: column;\n gap: 22px;\n }\n\n /* Live preview chip */\n .folder-preview {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n border-radius: 12px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-subtle);\n }\n .folder-preview-chip {\n width: 40px;\n height: 40px;\n border-radius: 10px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 18px;\n flex-shrink: 0;\n transition: background-color 150ms ease, color 150ms ease;\n }\n .folder-preview-name {\n font-size: 15px;\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .form-field {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n .form-field label {\n font-weight: 600;\n font-size: 13px;\n letter-spacing: 0.01em;\n color: var(--mj-text-secondary);\n }\n\n .form-field label.required::after {\n content: '*';\n color: var(--mj-status-error);\n margin-left: 4px;\n }\n\n .full-width { width: 100%; }\n\n .error-message {\n color: var(--mj-status-error);\n font-size: 12px;\n }\n\n /* Color Picker */\n .visibility-set {\n border: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 0.35rem;\n }\n\n /* A <legend> is not matched by the .form-field label rule, so it inherited 16px/400\n and read larger and lighter than every other field label. Restated here rather than\n widening that selector, which would also catch the option labels below.\n (No backticks in this block: it is a template literal.) */\n .visibility-set legend {\n padding: 0;\n margin-bottom: 0.15rem;\n font-weight: 600;\n font-size: 13px;\n letter-spacing: 0.01em;\n color: var(--mj-text-secondary);\n }\n\n /* Scoped as .form-field .visibility-choice (0,2,1) so it deliberately outranks the\n .form-field label rule (0,1,1) this sits inside — at equal specificity that rule\n won on source order and rendered the option text bold.\n (No backticks in here: this block is a template literal.) */\n .form-field .visibility-choice {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n cursor: pointer;\n font-weight: 400;\n font-size: 13px;\n margin: 0;\n /* The rows were the height of the radio alone (~16px). The checkbox this replaced\n sat in a 31px row, so the tap target got smaller when the control got clearer. */\n padding: 0.25rem 0;\n }\n\n .visibility-choice input {\n flex: 0 0 auto;\n margin: 0;\n }\n\n /* The shared-folder statement that stands in for the radios. Matches the option rows\n it replaces — same size, same weight, same 0.25rem row padding — so the dialog does\n not visibly reflow between a folder that offers the choice and one that does not.\n (No backticks in here: this block is a template literal.) */\n .form-field .visibility-locked {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n margin: 0;\n padding: 0.25rem 0;\n font-weight: 400;\n font-size: 13px;\n color: var(--mj-text-primary);\n }\n\n .visibility-locked i {\n font-size: 12px;\n color: var(--mj-text-muted);\n }\n\n .visibility-hint {\n margin: 0.15rem 0 0;\n /* Unsized it inherited 16px and read LARGER than the options it describes. */\n font-size: 12px;\n line-height: 1.4;\n color: var(--mj-text-muted);\n }\n\n .color-picker-section {\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 14px;\n background: var(--mj-bg-surface);\n }\n\n .color-palette {\n display: grid;\n grid-template-columns: repeat(10, 1fr);\n gap: 8px;\n margin-bottom: 12px;\n }\n\n .color-swatch {\n width: 100%;\n aspect-ratio: 1;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n padding: 0;\n transition: transform 120ms ease, box-shadow 120ms ease;\n box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--mj-text-primary) 8%, transparent);\n }\n\n .color-swatch:hover {\n transform: scale(1.12);\n }\n\n .color-swatch.selected {\n box-shadow: 0 0 0 2px var(--mj-bg-surface), 0 0 0 4px var(--mj-brand-primary);\n }\n\n .custom-color-input {\n display: flex;\n align-items: center;\n gap: 10px;\n padding-top: 14px;\n border-top: 1px solid var(--mj-border-subtle);\n }\n\n .custom-color-input label {\n margin: 0;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n }\n\n .custom-color-picker {\n width: 44px;\n height: 30px;\n padding: 2px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n background: var(--mj-bg-surface);\n }\n\n .color-value {\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 13px;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n }\n\n /* Icon Selector */\n .icon-grid {\n display: grid;\n grid-template-columns: repeat(10, 1fr);\n gap: 8px;\n max-height: 184px;\n overflow-y: auto;\n padding: 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n background: var(--mj-bg-surface);\n }\n\n .icon-option {\n aspect-ratio: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 1px solid var(--mj-border-subtle);\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n cursor: pointer;\n color: var(--mj-text-secondary);\n transition: transform 120ms ease, border-color 120ms ease, background 120ms ease;\n }\n\n .icon-option:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-border-strong);\n transform: translateY(-1px);\n }\n\n .icon-option.selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 1px var(--mj-brand-primary);\n }\n\n .icon-option i { font-size: 17px; }\n\n /* Scrollbar */\n .icon-grid::-webkit-scrollbar { width: 8px; }\n .icon-grid::-webkit-scrollbar-track {\n background: transparent;\n }\n .icon-grid::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 4px;\n }\n .icon-grid::-webkit-scrollbar-thumb:hover {\n background: var(--mj-text-disabled);\n }\n `]\n})\nexport class ProjectFormModalComponent extends BaseAngularComponent implements OnInit {\n @Input() DialogRef!: MJDialogRef;\n\n /** @deprecated Use {@link DialogRef}. */\n @Input() set dialogRef(value: MJDialogRef) {\n this.DialogRef = value;\n }\n /** @deprecated Use {@link DialogRef}. */\n get dialogRef(): MJDialogRef {\n return this.DialogRef;\n }\n @Input() Project: MJProjectEntity | null = null;\n\n /** @deprecated Use {@link Project}. */\n @Input() set project(value: MJProjectEntity | null) {\n this.Project = value;\n }\n /** @deprecated Use {@link Project}. */\n get project(): MJProjectEntity | null {\n return this.Project;\n }\n @Input() EnvironmentId!: string;\n\n /** @deprecated Use {@link EnvironmentId}. */\n @Input() set environmentId(value: string) {\n this.EnvironmentId = value;\n }\n /** @deprecated Use {@link EnvironmentId}. */\n get environmentId(): string {\n return this.EnvironmentId;\n }\n @Input() CurrentUser!: UserInfo;\n\n /** @deprecated Use {@link CurrentUser}. */\n @Input() set currentUser(value: UserInfo) {\n this.CurrentUser = value;\n }\n /** @deprecated Use {@link CurrentUser}. */\n get currentUser(): UserInfo {\n return this.CurrentUser;\n }\n /** When creating a new folder, the parent folder ID for nesting (null = top level). */\n @Input() ParentId: string | null = null;\n\n /** @deprecated Use {@link ParentId}. */\n @Input() set parentId(value: string | null) {\n this.ParentId = value;\n }\n /** @deprecated Use {@link ParentId}. */\n get parentId(): string | null {\n return this.ParentId;\n }\n\n @Output() ProjectSaved = new EventEmitter<MJProjectEntity>();\n\n /**\n * @deprecated Use {@link ProjectSaved}.\n *\n * The same emitter under the old binding name, so a template still binding\n * (projectSaved) keeps working. Must stay AFTER ProjectSaved: class fields\n * initialise in order, and the other way round this captures undefined.\n */\n @Output() projectSaved = this.ProjectSaved;\n\n public FormData: ProjectFormData = {\n name: '',\n description: '',\n color: '#0076B6',\n icon: 'fa-folder',\n // A NEW folder is personal by default. The conversation sidebar is a personal\n // surface — the conversations in it are already bound to their owner — so a\n // folder everyone can see is the surprising option, not the private one. Folder\n // NAMES are user-authored free text, and before OwnerUserID existed every one of\n // them was readable by every user of the environment, which is what prompted\n // this. Existing folders are untouched: they carry NULL, which still means shared.\n isPersonal: true\n };\n\n /** @deprecated Use {@link FormData}. */\n public get formData(): ProjectFormData {\n return this.FormData;\n }\n /** @deprecated Use {@link FormData}. */\n public set formData(value: ProjectFormData) {\n this.FormData = value;\n }\n\n public ShowNameError = false;\n\n /** @deprecated Use {@link ShowNameError}. */\n public get showNameError() {\n return this.ShowNameError;\n }\n /** @deprecated Use {@link ShowNameError}. */\n public set showNameError(value) {\n this.ShowNameError = value;\n }\n public IsEditMode = false;\n\n /** @deprecated Use {@link IsEditMode}. */\n public get isEditMode() {\n return this.IsEditMode;\n }\n /** @deprecated Use {@link IsEditMode}. */\n public set isEditMode(value) {\n this.IsEditMode = value;\n }\n public AvailableColors = DEFAULT_PROJECT_COLORS;\n\n /** @deprecated Use {@link AvailableColors}. */\n public get availableColors() {\n return this.AvailableColors;\n }\n /** @deprecated Use {@link AvailableColors}. */\n public set availableColors(value) {\n this.AvailableColors = value;\n }\n public AvailableIcons = DEFAULT_PROJECT_ICONS;\n\n /** @deprecated Use {@link AvailableIcons}. */\n public get availableIcons() {\n return this.AvailableIcons;\n }\n /** @deprecated Use {@link AvailableIcons}. */\n public set availableIcons(value) {\n this.AvailableIcons = value;\n }\n\n /**\n * True when this dialog is editing a folder that is currently SHARED — in which case\n * visibility is shown as a statement rather than a control.\n *\n * Sharing is one-way by design, and the reason is in the data model rather than the UI.\n * NULL-means-shared conflates \"shared\" with \"unowned\": the moment a folder is shared its\n * `OwnerUserID` goes to NULL and there is no column anywhere recording who created it\n * (`Project` has `__mj_CreatedAt`, but no created-by). So `OwnerUserID = currentUser.ID`\n * on a shared folder is indistinguishable from any other user claiming it — the system\n * cannot tell reclaiming from appropriating, which makes \"take it back\" an affordance\n * that was never really there.\n *\n * What that would cost on day one is the deciding argument. Every folder that exists\n * today carries NULL, so without this the whole team's folder structure — subfolders\n * included — is one radio button away from belonging to whichever person opens its\n * settings first. A confirm does not fix that; it only narrates it.\n *\n * Personal -> shared stays available, because it only ever adds. Someone who wants a\n * private copy makes a private folder. If personal folders later grow features that need\n * a stable creator (sharing with named users, transfer, recovering a departed employee's\n * folders), the fix is a separate IsShared flag so ownership stops being erased by\n * sharing — a bigger change, and deliberately not this one.\n */\n public get VisibilityIsLocked(): boolean {\n return this.IsEditMode && !this.Project?.OwnerUserID;\n }\n\n /** Translucent tint of the selected color, used behind the preview/icon glyph. */\n public get ChipBackground(): string {\n const hex = this.FormData.color || '#0076B6';\n // 8-digit hex (#RRGGBBAA) — ~14% alpha tint of the chosen color\n return /^#[0-9a-fA-F]{6}$/.test(hex) ? `${hex}24` : hex;\n }\n\n /** @deprecated Use {@link ChipBackground}. */\n public get chipBackground(): string {\n return this.ChipBackground;\n }\n\n constructor(private cdr: ChangeDetectorRef) {\n super();}\n\n ngOnInit(): void {\n this.IsEditMode = this.Project != null;\n\n if (this.Project) {\n this.loadProjectData();\n }\n }\n\n private loadProjectData(): void {\n if (!this.Project) return;\n\n this.FormData = {\n name: this.Project.Name || '',\n description: this.Project.Description || '',\n color: this.Project.Color || '#0076B6',\n icon: this.Project.Icon || 'fa-folder',\n // Reflect what the folder IS, not the create-time default — otherwise opening\n // a shared folder's settings and pressing Save would silently make it private.\n isPersonal: !!this.Project.OwnerUserID\n };\n }\n\n SelectColor(color: string): void {\n this.FormData.color = color;\n this.cdr.detectChanges();\n }\n\n /** @deprecated Use {@link SelectColor}. */\n selectColor(color: string): void {\n return this.SelectColor(color);\n }\n\n SelectIcon(icon: string): void {\n this.FormData.icon = icon;\n this.cdr.detectChanges();\n }\n\n /** @deprecated Use {@link SelectIcon}. */\n selectIcon(icon: string): void {\n return this.SelectIcon(icon);\n }\n\n async OnSave(): Promise<void> {\n // Validate\n if (!this.FormData.name.trim()) {\n this.ShowNameError = true;\n this.cdr.detectChanges();\n return;\n }\n\n this.ShowNameError = false;\n\n try {\n const md = this.ProviderToUse;\n\n // A shared folder cannot be taken private — the control is not rendered for one\n // (see VisibilityIsLocked). This is the same rule expressed where the write happens,\n // so a future template change, a stale `formData` from a reopened dialog, or anything\n // else that sets the flag cannot quietly appropriate a folder the whole team uses.\n // It resolves to the folder's CURRENT state, so it is a no-op in every other case.\n const isPersonal = this.VisibilityIsLocked ? false : this.FormData.isPersonal;\n\n const project = this.Project || await md.GetEntityObject<MJProjectEntity>('MJ: Projects', this.CurrentUser);\n\n project.Name = this.FormData.name.trim();\n project.Description = this.FormData.description.trim() || null;\n project.Color = this.FormData.color;\n project.Icon = this.FormData.icon;\n\n // Settable on edit, in one direction: a personal folder can be shared with the team.\n // Null means shared, which is what every folder created before this column existed\n // carries — and, because sharing erases the owner, is also why the reverse is not on\n // offer. See VisibilityIsLocked.\n project.OwnerUserID = isPersonal ? this.CurrentUser.ID : null;\n\n if (!this.IsEditMode) {\n project.EnvironmentID = this.EnvironmentId;\n project.IsArchived = false;\n if (this.ParentId) {\n project.ParentID = this.ParentId;\n }\n }\n\n const saved = await project.Save();\n if (saved) {\n this.ProjectSaved.emit(project);\n this.DialogRef.Close();\n } else {\n // Save() records WHY it refused on LatestResult and returns false — a\n // server refusal, a constraint violation, a failed validation. Reporting\n // a generic message here would throw the only copy of that reason away.\n throw new Error(project.LatestResult?.CompleteMessage || 'The save was refused with no reason given.');\n }\n } catch (error) {\n console.error('Error saving project:', error);\n const reason = error instanceof Error ? error.message : String(error);\n alert(`Failed to save folder.\\n\\n${reason}`);\n }\n }\n\n /** @deprecated Use {@link OnSave}. */\n async onSave(): Promise<void> {\n return this.OnSave();\n }\n\n onCancel(): void {\n this.DialogRef.Close();\n }\n}\n"]}
1
+ {"version":3,"file":"project-form-modal.component.js","sourceRoot":"","sources":["../../../../src/lib/components/project/project-form-modal.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, ViewChild, ChangeDetectorRef } from '@angular/core';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { MJDialogRef } from '@memberjunction/ng-ui-components';\nimport { MJProjectEntity } from '@memberjunction/core-entities';\nimport { UserInfo, Metadata } from '@memberjunction/core';\n\nexport interface ProjectFormData {\n name: string;\n description: string;\n color: string;\n icon: string;\n /** true = only the owner sees it; false = everyone in the environment does. */\n isPersonal: boolean;\n}\n\nconst DEFAULT_PROJECT_COLORS = [\n '#0076B6', // MJ Blue\n '#F44336', // Red\n '#E91E63', // Pink\n '#9C27B0', // Purple\n '#673AB7', // Deep Purple\n '#3F51B5', // Indigo\n '#2196F3', // Blue\n '#03A9F4', // Light Blue\n '#00BCD4', // Cyan\n '#009688', // Teal\n '#4CAF50', // Green\n '#8BC34A', // Light Green\n '#CDDC39', // Lime\n '#FFEB3B', // Yellow\n '#FFC107', // Amber\n '#FF9800', // Orange\n '#FF5722', // Deep Orange\n '#795548', // Brown\n '#607D8B', // Blue Grey\n '#9E9E9E' // Grey\n];\n\nconst DEFAULT_PROJECT_ICONS = [\n 'fa-folder',\n 'fa-folder-open',\n 'fa-briefcase',\n 'fa-project-diagram',\n 'fa-chart-line',\n 'fa-tasks',\n 'fa-clipboard-list',\n 'fa-bullseye',\n 'fa-rocket',\n 'fa-lightbulb',\n 'fa-brain',\n 'fa-cogs',\n 'fa-code',\n 'fa-database',\n 'fa-server',\n 'fa-cloud',\n 'fa-mobile-alt',\n 'fa-desktop',\n 'fa-globe',\n 'fa-users'\n];\n\n@Component({\n standalone: false,\n selector: 'mj-project-form-modal',\n template: `\n <mj-dialog\n [Title]=\"isEditMode ? 'Edit Folder' : 'New Folder'\"\n [Width]=\"560\"\n [MinWidth]=\"400\"\n [Visible]=\"true\"\n (Close)=\"onCancel()\">\n\n <div class=\"project-form\">\n <!-- Live preview chip -->\n <div class=\"folder-preview\">\n <span class=\"folder-preview-chip\" [style.backgroundColor]=\"chipBackground\" [style.color]=\"formData.color\">\n <i class=\"fa-solid {{ formData.icon }}\"></i>\n </span>\n <span class=\"folder-preview-name\">{{ formData.name.trim() || 'Untitled folder' }}</span>\n </div>\n\n <!-- Name Input -->\n <div class=\"form-field\">\n <label for=\"projectName\" class=\"required\">\n Folder Name\n </label>\n <input\n id=\"projectName\"\n type=\"text\"\n [(ngModel)]=\"formData.name\"\n placeholder=\"e.g. Client work, Research, Ideas\"\n class=\"mj-input full-width\"\n (keydown.enter)=\"onSave()\"\n autofocus />\n @if (showNameError) {\n <div class=\"error-message\">Folder name is required</div>\n }\n </div>\n\n <!-- Description Textarea -->\n <div class=\"form-field\">\n <label for=\"projectDescription\">\n Description\n </label>\n <textarea\n id=\"projectDescription\"\n [(ngModel)]=\"formData.description\"\n placeholder=\"What goes in this folder? (optional)\"\n class=\"mj-textarea full-width\"\n rows=\"2\"></textarea>\n </div>\n\n <!-- Visibility. TWO NAMED OPTIONS, not a checkbox: with a checkbox the unchecked\n meaning lives only in the helper text, so the shared state is never actually\n named. A fieldset/legend also gives the group a real accessible name, which a\n bare <label>Visibility</label> did not, and the hint is a sibling of the\n options rather than inside one — inside, a screen reader read the whole hint\n as part of the option's name.\n\n A SHARED folder shows a statement instead of the control. Visibility is a\n create-time choice in one direction only: personal -> shared stays available,\n because it only ever adds. See VisibilityIsLocked for why the reverse is not\n offered. -->\n <div class=\"form-field\">\n @if (VisibilityIsLocked) {\n <fieldset class=\"visibility-set\" aria-describedby=\"projectVisibilityHint\">\n <legend>Visibility</legend>\n <p class=\"visibility-locked\">\n <i class=\"fa-solid fa-users\" aria-hidden=\"true\"></i>\n Shared with everyone\n </p>\n <p class=\"visibility-hint\" id=\"projectVisibilityHint\">\n A shared folder stays shared. To keep something to yourself, create a new\n private folder and move it there.\n </p>\n </fieldset>\n } @else {\n <fieldset class=\"visibility-set\" aria-describedby=\"projectVisibilityHint\">\n <legend>Visibility</legend>\n <label class=\"visibility-choice\">\n <input type=\"radio\" name=\"projectVisibility\" [value]=\"true\"\n [(ngModel)]=\"FormData.isPersonal\" />\n <span>Only me</span>\n </label>\n <label class=\"visibility-choice\">\n <input type=\"radio\" name=\"projectVisibility\" [value]=\"false\"\n [(ngModel)]=\"FormData.isPersonal\" />\n <span>Everyone</span>\n </label>\n <p class=\"visibility-hint\" id=\"projectVisibilityHint\">\n {{ FormData.isPersonal\n ? 'Only you can see this folder.'\n : \"Everyone can see this folder and its name. They will not see the conversations you keep in it. Once shared, a folder can't be made private again.\" }}\n </p>\n </fieldset>\n }\n </div>\n\n <!-- Color Picker -->\n <div class=\"form-field\">\n <label>Color</label>\n <div class=\"color-picker-section\">\n <div class=\"color-palette\">\n @for (color of availableColors; track color) {\n <button\n type=\"button\"\n class=\"color-swatch\"\n [class.selected]=\"formData.color === color\"\n [style.backgroundColor]=\"color\"\n (click)=\"selectColor(color)\"\n [title]=\"color\">\n </button>\n }\n </div>\n <div class=\"custom-color-input\">\n <label for=\"customColor\">Custom:</label>\n <input\n id=\"customColor\"\n type=\"color\"\n [(ngModel)]=\"formData.color\"\n class=\"custom-color-picker\" />\n <span class=\"color-value\">{{ formData.color }}</span>\n </div>\n </div>\n </div>\n\n <!-- Icon Selector -->\n <div class=\"form-field\">\n <label>Icon</label>\n <div class=\"icon-grid\">\n @for (icon of availableIcons; track icon) {\n <button\n type=\"button\"\n class=\"icon-option\"\n [class.selected]=\"formData.icon === icon\"\n [style.color]=\"formData.icon === icon ? formData.color : null\"\n (click)=\"selectIcon(icon)\"\n [title]=\"icon\">\n <i class=\"fa-solid {{ icon }}\"></i>\n </button>\n }\n </div>\n </div>\n </div>\n\n <mj-dialog-actions>\n <button mjButton variant=\"primary\" (click)=\"onSave()\">\n {{ isEditMode ? 'Save Changes' : 'Create Folder' }}\n </button>\n <button mjButton (click)=\"onCancel()\">Cancel</button>\n </mj-dialog-actions>\n </mj-dialog>\n `,\n styles: [`\n .project-form {\n padding: 20px 24px 8px;\n display: flex;\n flex-direction: column;\n gap: 22px;\n }\n\n /* Live preview chip */\n .folder-preview {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n border-radius: 12px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-subtle);\n }\n .folder-preview-chip {\n width: 40px;\n height: 40px;\n border-radius: 10px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 18px;\n flex-shrink: 0;\n transition: background-color 150ms ease, color 150ms ease;\n }\n .folder-preview-name {\n font-size: 15px;\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .form-field {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n .form-field label {\n font-weight: 600;\n font-size: 13px;\n letter-spacing: 0.01em;\n color: var(--mj-text-secondary);\n }\n\n .form-field label.required::after {\n content: '*';\n color: var(--mj-status-error);\n margin-left: 4px;\n }\n\n .full-width { width: 100%; }\n\n .error-message {\n color: var(--mj-status-error);\n font-size: 12px;\n }\n\n /* Color Picker */\n .visibility-set {\n border: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 0.35rem;\n }\n\n /* A <legend> is not matched by the .form-field label rule, so it inherited 16px/400\n and read larger and lighter than every other field label. Restated here rather than\n widening that selector, which would also catch the option labels below.\n (No backticks in this block: it is a template literal.) */\n .visibility-set legend {\n padding: 0;\n margin-bottom: 0.15rem;\n font-weight: 600;\n font-size: 13px;\n letter-spacing: 0.01em;\n color: var(--mj-text-secondary);\n }\n\n /* Scoped as .form-field .visibility-choice (0,2,1) so it deliberately outranks the\n .form-field label rule (0,1,1) this sits inside — at equal specificity that rule\n won on source order and rendered the option text bold.\n (No backticks in here: this block is a template literal.) */\n .form-field .visibility-choice {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n cursor: pointer;\n font-weight: 400;\n font-size: 13px;\n margin: 0;\n /* The rows were the height of the radio alone (~16px). The checkbox this replaced\n sat in a 31px row, so the tap target got smaller when the control got clearer. */\n padding: 0.25rem 0;\n }\n\n .visibility-choice input {\n flex: 0 0 auto;\n margin: 0;\n }\n\n /* The shared-folder statement that stands in for the radios. Matches the option rows\n it replaces — same size, same weight, same 0.25rem row padding — so the dialog does\n not visibly reflow between a folder that offers the choice and one that does not.\n (No backticks in here: this block is a template literal.) */\n .form-field .visibility-locked {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n margin: 0;\n padding: 0.25rem 0;\n font-weight: 400;\n font-size: 13px;\n color: var(--mj-text-primary);\n }\n\n .visibility-locked i {\n font-size: 12px;\n color: var(--mj-text-muted);\n }\n\n .visibility-hint {\n margin: 0.15rem 0 0;\n /* Unsized it inherited 16px and read LARGER than the options it describes. */\n font-size: 12px;\n line-height: 1.4;\n color: var(--mj-text-muted);\n }\n\n .color-picker-section {\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 14px;\n background: var(--mj-bg-surface);\n }\n\n .color-palette {\n display: grid;\n grid-template-columns: repeat(10, 1fr);\n gap: 8px;\n margin-bottom: 12px;\n }\n\n .color-swatch {\n width: 100%;\n aspect-ratio: 1;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n padding: 0;\n transition: transform 120ms ease, box-shadow 120ms ease;\n box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--mj-text-primary) 8%, transparent);\n }\n\n .color-swatch:hover {\n transform: scale(1.12);\n }\n\n .color-swatch.selected {\n box-shadow: 0 0 0 2px var(--mj-bg-surface), 0 0 0 4px var(--mj-brand-primary);\n }\n\n .custom-color-input {\n display: flex;\n align-items: center;\n gap: 10px;\n padding-top: 14px;\n border-top: 1px solid var(--mj-border-subtle);\n }\n\n .custom-color-input label {\n margin: 0;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n }\n\n .custom-color-picker {\n width: 44px;\n height: 30px;\n padding: 2px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n background: var(--mj-bg-surface);\n }\n\n .color-value {\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 13px;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n }\n\n /* Icon Selector */\n .icon-grid {\n display: grid;\n grid-template-columns: repeat(10, 1fr);\n gap: 8px;\n max-height: 184px;\n overflow-y: auto;\n padding: 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n background: var(--mj-bg-surface);\n }\n\n .icon-option {\n aspect-ratio: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 1px solid var(--mj-border-subtle);\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n cursor: pointer;\n color: var(--mj-text-secondary);\n transition: transform 120ms ease, border-color 120ms ease, background 120ms ease;\n }\n\n .icon-option:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-border-strong);\n transform: translateY(-1px);\n }\n\n .icon-option.selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 1px var(--mj-brand-primary);\n }\n\n .icon-option i { font-size: 17px; }\n\n /* Scrollbar */\n .icon-grid::-webkit-scrollbar { width: 8px; }\n .icon-grid::-webkit-scrollbar-track {\n background: transparent;\n }\n .icon-grid::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 4px;\n }\n .icon-grid::-webkit-scrollbar-thumb:hover {\n background: var(--mj-text-disabled);\n }\n `]\n})\nexport class ProjectFormModalComponent extends BaseAngularComponent implements OnInit {\n @Input() DialogRef!: MJDialogRef;\n\n /** @deprecated Use {@link DialogRef}. */\n @Input() set dialogRef(value: MJDialogRef) {\n this.DialogRef = value;\n }\n /** @deprecated Use {@link DialogRef}. */\n get dialogRef(): MJDialogRef {\n return this.DialogRef;\n }\n @Input() Project: MJProjectEntity | null = null;\n\n /** @deprecated Use {@link Project}. */\n @Input() set project(value: MJProjectEntity | null) {\n this.Project = value;\n }\n /** @deprecated Use {@link Project}. */\n get project(): MJProjectEntity | null {\n return this.Project;\n }\n @Input() EnvironmentId!: string;\n\n /** @deprecated Use {@link EnvironmentId}. */\n @Input() set environmentId(value: string) {\n this.EnvironmentId = value;\n }\n /** @deprecated Use {@link EnvironmentId}. */\n get environmentId(): string {\n return this.EnvironmentId;\n }\n @Input() CurrentUser!: UserInfo;\n\n /** @deprecated Use {@link CurrentUser}. */\n @Input() set currentUser(value: UserInfo) {\n this.CurrentUser = value;\n }\n /** @deprecated Use {@link CurrentUser}. */\n get currentUser(): UserInfo {\n return this.CurrentUser;\n }\n /** When creating a new folder, the parent folder ID for nesting (null = top level). */\n @Input() ParentId: string | null = null;\n\n /** @deprecated Use {@link ParentId}. */\n @Input() set parentId(value: string | null) {\n this.ParentId = value;\n }\n /** @deprecated Use {@link ParentId}. */\n get parentId(): string | null {\n return this.ParentId;\n }\n\n @Output() ProjectSaved = new EventEmitter<MJProjectEntity>();\n\n /**\n * @deprecated Use {@link ProjectSaved}.\n *\n * The same emitter under the old binding name, so a template still binding\n * (projectSaved) keeps working. Must stay AFTER ProjectSaved: class fields\n * initialise in order, and the other way round this captures undefined.\n */\n @Output() projectSaved = this.ProjectSaved;\n\n public FormData: ProjectFormData = {\n name: '',\n description: '',\n color: '#0076B6',\n icon: 'fa-folder',\n // A NEW folder is personal by default. The conversation sidebar is a personal\n // surface — the conversations in it are already bound to their owner — so a\n // folder everyone can see is the surprising option, not the private one. Folder\n // NAMES are user-authored free text, and before OwnerUserID existed every one of\n // them was readable by every user of the environment, which is what prompted\n // this. Existing folders are untouched: they carry NULL, which still means shared.\n isPersonal: true\n };\n\n /** @deprecated Use {@link FormData}. */\n public get formData(): ProjectFormData {\n return this.FormData;\n }\n /** @deprecated Use {@link FormData}. */\n public set formData(value: ProjectFormData) {\n this.FormData = value;\n }\n\n public ShowNameError = false;\n\n /** @deprecated Use {@link ShowNameError}. */\n public get showNameError() {\n return this.ShowNameError;\n }\n /** @deprecated Use {@link ShowNameError}. */\n public set showNameError(value) {\n this.ShowNameError = value;\n }\n public IsEditMode = false;\n\n /** @deprecated Use {@link IsEditMode}. */\n public get isEditMode() {\n return this.IsEditMode;\n }\n /** @deprecated Use {@link IsEditMode}. */\n public set isEditMode(value) {\n this.IsEditMode = value;\n }\n public AvailableColors = DEFAULT_PROJECT_COLORS;\n\n /** @deprecated Use {@link AvailableColors}. */\n public get availableColors() {\n return this.AvailableColors;\n }\n /** @deprecated Use {@link AvailableColors}. */\n public set availableColors(value) {\n this.AvailableColors = value;\n }\n public AvailableIcons = DEFAULT_PROJECT_ICONS;\n\n /** @deprecated Use {@link AvailableIcons}. */\n public get availableIcons() {\n return this.AvailableIcons;\n }\n /** @deprecated Use {@link AvailableIcons}. */\n public set availableIcons(value) {\n this.AvailableIcons = value;\n }\n\n /**\n * True when this dialog is editing a folder that is currently SHARED — in which case\n * visibility is shown as a statement rather than a control.\n *\n * Sharing is one-way by design, and the reason is in the data model rather than the UI.\n * NULL-means-shared conflates \"shared\" with \"unowned\": the moment a folder is shared its\n * `OwnerUserID` goes to NULL and there is no column anywhere recording who created it\n * (`Project` has `__mj_CreatedAt`, but no created-by). So `OwnerUserID = currentUser.ID`\n * on a shared folder is indistinguishable from any other user claiming it — the system\n * cannot tell reclaiming from appropriating, which makes \"take it back\" an affordance\n * that was never really there.\n *\n * What that would cost on day one is the deciding argument. Every folder that exists\n * today carries NULL, so without this the whole team's folder structure — subfolders\n * included — is one radio button away from belonging to whichever person opens its\n * settings first. A confirm does not fix that; it only narrates it.\n *\n * Personal -> shared stays available, because it only ever adds. Someone who wants a\n * private copy makes a private folder. If personal folders later grow features that need\n * a stable creator (sharing with named users, transfer, recovering a departed employee's\n * folders), the fix is a separate IsShared flag so ownership stops being erased by\n * sharing — a bigger change, and deliberately not this one.\n */\n public get VisibilityIsLocked(): boolean {\n return this.IsEditMode && !this.Project?.OwnerUserID;\n }\n\n /** Translucent tint of the selected color, used behind the preview/icon glyph. */\n public get ChipBackground(): string {\n const hex = this.FormData.color || '#0076B6';\n // 8-digit hex (#RRGGBBAA) — ~14% alpha tint of the chosen color\n return /^#[0-9a-fA-F]{6}$/.test(hex) ? `${hex}24` : hex;\n }\n\n /** @deprecated Use {@link ChipBackground}. */\n public get chipBackground(): string {\n return this.ChipBackground;\n }\n\n constructor(private cdr: ChangeDetectorRef) {\n super();}\n\n ngOnInit(): void {\n this.IsEditMode = this.Project != null;\n\n if (this.Project) {\n this.loadProjectData();\n }\n }\n\n private loadProjectData(): void {\n if (!this.Project) return;\n\n this.FormData = {\n name: this.Project.Name || '',\n description: this.Project.Description || '',\n color: this.Project.Color || '#0076B6',\n icon: this.Project.Icon || 'fa-folder',\n // Reflect what the folder IS, not the create-time default — otherwise opening\n // a shared folder's settings and pressing Save would silently make it private.\n isPersonal: !!this.Project.OwnerUserID\n };\n }\n\n SelectColor(color: string): void {\n this.FormData.color = color;\n this.cdr.detectChanges();\n }\n\n /** @deprecated Use {@link SelectColor}. */\n selectColor(color: string): void {\n return this.SelectColor(color);\n }\n\n SelectIcon(icon: string): void {\n this.FormData.icon = icon;\n this.cdr.detectChanges();\n }\n\n /** @deprecated Use {@link SelectIcon}. */\n selectIcon(icon: string): void {\n return this.SelectIcon(icon);\n }\n\n async OnSave(): Promise<void> {\n // Validate\n if (!this.FormData.name.trim()) {\n this.ShowNameError = true;\n this.cdr.detectChanges();\n return;\n }\n\n this.ShowNameError = false;\n\n try {\n const md = this.ProviderToUse;\n\n // A shared folder cannot be taken private — the control is not rendered for one\n // (see VisibilityIsLocked). This is the same rule expressed where the write happens,\n // so a future template change, a stale `formData` from a reopened dialog, or anything\n // else that sets the flag cannot quietly appropriate a folder the whole team uses.\n // It resolves to the folder's CURRENT state, so it is a no-op in every other case.\n const isPersonal = this.VisibilityIsLocked ? false : this.FormData.isPersonal;\n\n const project = this.Project || await md.GetEntityObject<MJProjectEntity>('MJ: Projects', this.CurrentUser);\n\n project.Name = this.FormData.name.trim();\n project.Description = this.FormData.description.trim() || null;\n project.Color = this.FormData.color;\n project.Icon = this.FormData.icon;\n\n // Settable on edit, in one direction: a personal folder can be shared with the team.\n // Null means shared, which is what every folder created before this column existed\n // carries — and, because sharing erases the owner, is also why the reverse is not on\n // offer. See VisibilityIsLocked.\n project.OwnerUserID = isPersonal ? this.CurrentUser.ID : null;\n\n if (!this.IsEditMode) {\n project.EnvironmentID = this.EnvironmentId;\n project.IsArchived = false;\n if (this.ParentId) {\n project.ParentID = this.ParentId;\n }\n }\n\n const saved = await project.Save();\n if (saved) {\n this.ProjectSaved.emit(project);\n this.DialogRef.Close();\n } else {\n // Save() records WHY it refused on LatestResult and returns false — a\n // server refusal, a constraint violation, a failed validation. Reporting\n // a generic message here would throw the only copy of that reason away.\n throw new Error(project.LatestResult?.CompleteMessage || 'The save was refused with no reason given.');\n }\n } catch (error) {\n console.error('Error saving project:', error);\n const reason = error instanceof Error ? error.message : String(error);\n alert(`Failed to save folder.\\n\\n${reason}`);\n }\n }\n\n /** @deprecated Use {@link OnSave}. */\n async onSave(): Promise<void> {\n return this.OnSave();\n }\n\n onCancel(): void {\n this.DialogRef.Close();\n }\n}\n"]}
@@ -33,6 +33,11 @@ export declare class RealtimeAgentBannerComponent {
33
33
  * Default `false` (the full console banner is unchanged).
34
34
  */
35
35
  Compact: boolean;
36
+ /**
37
+ * Whether to suppress the turn-state pill and redundant "speaking as" label in the banner
38
+ * because the center hero orb is already displaying the agent's name and live turn state.
39
+ */
40
+ HideState: boolean;
36
41
  /** Display name of the agent the voice session fronts (e.g. "Sage"). */
37
42
  AgentName: string;
38
43
  /**
@@ -120,6 +125,6 @@ export declare class RealtimeAgentBannerComponent {
120
125
  /** True while the state pill should show a spinner instead of the waveform. */
121
126
  IsBusy(state: RealtimeConnectionState): boolean;
122
127
  static ɵfac: i0.ɵɵFactoryDeclaration<RealtimeAgentBannerComponent, never>;
123
- static ɵcmp: i0.ɵɵComponentDeclaration<RealtimeAgentBannerComponent, "mj-realtime-agent-banner", never, { "State": { "alias": "State"; "required": true; }; "Compact": { "alias": "Compact"; "required": false; }; "AgentName": { "alias": "AgentName"; "required": false; }; "ErrorLabel": { "alias": "ErrorLabel"; "required": false; }; "ModelName": { "alias": "ModelName"; "required": false; }; "DevMode": { "alias": "DevMode"; "required": false; }; "SessionID": { "alias": "SessionID"; "required": false; }; "ReviewMode": { "alias": "ReviewMode"; "required": false; }; "ReviewStartedAt": { "alias": "ReviewStartedAt"; "required": false; }; "ReviewClosedAt": { "alias": "ReviewClosedAt"; "required": false; }; "ReviewCloseReason": { "alias": "ReviewCloseReason"; "required": false; }; "ShowGear": { "alias": "ShowGear"; "required": false; }; "ShowDensityPicker": { "alias": "ShowDensityPicker"; "required": false; }; "ShowMinimize": { "alias": "ShowMinimize"; "required": false; }; "ShowStartLive": { "alias": "ShowStartLive"; "required": false; }; "Density": { "alias": "Density"; "required": false; }; }, { "OpenSessionRequested": "OpenSessionRequested"; "DevModeToggled": "DevModeToggled"; "DensityChanged": "DensityChanged"; "MinimizeRequested": "MinimizeRequested"; "StartLiveRequested": "StartLiveRequested"; "CloseRequested": "CloseRequested"; }, never, never, true, never>;
128
+ static ɵcmp: i0.ɵɵComponentDeclaration<RealtimeAgentBannerComponent, "mj-realtime-agent-banner", never, { "State": { "alias": "State"; "required": true; }; "Compact": { "alias": "Compact"; "required": false; }; "HideState": { "alias": "HideState"; "required": false; }; "AgentName": { "alias": "AgentName"; "required": false; }; "ErrorLabel": { "alias": "ErrorLabel"; "required": false; }; "ModelName": { "alias": "ModelName"; "required": false; }; "DevMode": { "alias": "DevMode"; "required": false; }; "SessionID": { "alias": "SessionID"; "required": false; }; "ReviewMode": { "alias": "ReviewMode"; "required": false; }; "ReviewStartedAt": { "alias": "ReviewStartedAt"; "required": false; }; "ReviewClosedAt": { "alias": "ReviewClosedAt"; "required": false; }; "ReviewCloseReason": { "alias": "ReviewCloseReason"; "required": false; }; "ShowGear": { "alias": "ShowGear"; "required": false; }; "ShowDensityPicker": { "alias": "ShowDensityPicker"; "required": false; }; "ShowMinimize": { "alias": "ShowMinimize"; "required": false; }; "ShowStartLive": { "alias": "ShowStartLive"; "required": false; }; "Density": { "alias": "Density"; "required": false; }; }, { "OpenSessionRequested": "OpenSessionRequested"; "DevModeToggled": "DevModeToggled"; "DensityChanged": "DensityChanged"; "MinimizeRequested": "MinimizeRequested"; "StartLiveRequested": "StartLiveRequested"; "CloseRequested": "CloseRequested"; }, never, never, true, never>;
124
129
  }
125
130
  //# sourceMappingURL=realtime-agent-banner.component.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"realtime-agent-banner.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-agent-banner.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAA+B,MAAM,eAAe,CAAC;AAErF,OAAO,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;;AAE1D;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAOa,4BAA4B;IACvC,gFAAgF;IACrD,KAAK,EAAG,uBAAuB,CAAC;IAE3D;;;;;;;OAOG;IACM,OAAO,UAAS;IAEzB,wEAAwE;IAC/D,SAAS,SAAe;IAEjC;;;OAGG;IACM,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE1C;;;OAGG;IACM,SAAS,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEzC,yFAAyF;IAChF,OAAO,UAAS;IAEzB,wFAAwF;IAC/E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEzC;;;;OAIG;IACM,UAAU,UAAS;IAE5B,wEAAwE;IAC/D,eAAe,EAAE,IAAI,GAAG,IAAI,CAAQ;IAE7C,kFAAkF;IACzE,cAAc,EAAE,IAAI,GAAG,IAAI,CAAQ;IAE5C,+GAA+G;IACtG,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAMjD,0FAA0F;IACjF,QAAQ,UAAS;IAE1B;;;;;OAKG;IACM,iBAAiB,UAAQ;IAElC,iEAAiE;IACxD,YAAY,UAAS;IAE9B,oEAAoE;IAC3D,aAAa,UAAQ;IAE9B,0FAA0F;IACjF,OAAO,EAAE,iBAAiB,CAAU;IAE7C,wFAAwF;IAC9E,oBAAoB,uBAA8B;IAE5D,2EAA2E;IACjE,cAAc,wBAA+B;IAEvD,4EAA4E;IAClE,cAAc,kCAAyC;IAEjE,2EAA2E;IACjE,iBAAiB,qBAA4B;IAEvD,qFAAqF;IAC3E,kBAAkB,qBAA4B;IAExD,sFAAsF;IAC5E,cAAc,qBAA4B;IAEpD,sEAAsE;IAC/D,QAAQ,UAAS;IAExB,qEAAqE;IACrE,SAAgB,SAAS,EAAE,aAAa,CAAC;QAAE,GAAG,EAAE,iBAAiB,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAKjF;IAEF,wFAAwF;IACxF,IAAW,eAAe,IAAI,OAAO,CAEpC;IAED,wEAAwE;IACjE,WAAW,IAAI,IAAI;IAM1B,6FAA6F;IACtF,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAK1C,iDAAiD;IAE1C,eAAe,IAAI,IAAI;IAM9B,mFAAmF;IAC5E,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI;IAItD,4CAA4C;IACrC,SAAS,IAAI,IAAI;IAKxB,iGAAiG;IACjG,IAAW,gBAAgB,IAAI,MAAM,CASpC;IAED,oEAAoE;IACpE,IAAW,sBAAsB,IAAI,MAAM,CAQ1C;IAED,iFAAiF;IACjF,OAAO,CAAC,WAAW;IAQnB,kGAAkG;IAC3F,QAAQ,CAAC,KAAK,EAAE,uBAAuB,GAAG,UAAU,GAAG,WAAW,GAAG,UAAU;IAQtF,qEAAqE;IAC9D,UAAU,CAAC,KAAK,EAAE,uBAAuB,GAAG,MAAM;IAYzD,+EAA+E;IACxE,MAAM,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO;yCApM3C,4BAA4B;2CAA5B,4BAA4B;CAuMxC"}
1
+ {"version":3,"file":"realtime-agent-banner.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/realtime/realtime-agent-banner.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAA+B,MAAM,eAAe,CAAC;AAErF,OAAO,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;;AAE1D;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAOa,4BAA4B;IACvC,gFAAgF;IACrD,KAAK,EAAG,uBAAuB,CAAC;IAE3D;;;;;;;OAOG;IACM,OAAO,UAAS;IAEzB;;;OAGG;IACM,SAAS,UAAS;IAE3B,wEAAwE;IAC/D,SAAS,SAAe;IAEjC;;;OAGG;IACM,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE1C;;;OAGG;IACM,SAAS,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEzC,yFAAyF;IAChF,OAAO,UAAS;IAEzB,wFAAwF;IAC/E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEzC;;;;OAIG;IACM,UAAU,UAAS;IAE5B,wEAAwE;IAC/D,eAAe,EAAE,IAAI,GAAG,IAAI,CAAQ;IAE7C,kFAAkF;IACzE,cAAc,EAAE,IAAI,GAAG,IAAI,CAAQ;IAE5C,+GAA+G;IACtG,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAMjD,0FAA0F;IACjF,QAAQ,UAAS;IAE1B;;;;;OAKG;IACM,iBAAiB,UAAQ;IAElC,iEAAiE;IACxD,YAAY,UAAS;IAE9B,oEAAoE;IAC3D,aAAa,UAAQ;IAE9B,0FAA0F;IACjF,OAAO,EAAE,iBAAiB,CAAU;IAE7C,wFAAwF;IAC9E,oBAAoB,uBAA8B;IAE5D,2EAA2E;IACjE,cAAc,wBAA+B;IAEvD,4EAA4E;IAClE,cAAc,kCAAyC;IAEjE,2EAA2E;IACjE,iBAAiB,qBAA4B;IAEvD,qFAAqF;IAC3E,kBAAkB,qBAA4B;IAExD,sFAAsF;IAC5E,cAAc,qBAA4B;IAEpD,sEAAsE;IAC/D,QAAQ,UAAS;IAExB,qEAAqE;IACrE,SAAgB,SAAS,EAAE,aAAa,CAAC;QAAE,GAAG,EAAE,iBAAiB,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAKjF;IAEF,wFAAwF;IACxF,IAAW,eAAe,IAAI,OAAO,CAEpC;IAED,wEAAwE;IACjE,WAAW,IAAI,IAAI;IAM1B,6FAA6F;IACtF,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAK1C,iDAAiD;IAE1C,eAAe,IAAI,IAAI;IAM9B,mFAAmF;IAC5E,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI;IAItD,4CAA4C;IACrC,SAAS,IAAI,IAAI;IAKxB,iGAAiG;IACjG,IAAW,gBAAgB,IAAI,MAAM,CASpC;IAED,oEAAoE;IACpE,IAAW,sBAAsB,IAAI,MAAM,CAQ1C;IAED,iFAAiF;IACjF,OAAO,CAAC,WAAW;IAQnB,kGAAkG;IAC3F,QAAQ,CAAC,KAAK,EAAE,uBAAuB,GAAG,UAAU,GAAG,WAAW,GAAG,UAAU;IAQtF,qEAAqE;IAC9D,UAAU,CAAC,KAAK,EAAE,uBAAuB,GAAG,MAAM;IAYzD,+EAA+E;IACxE,MAAM,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO;yCA1M3C,4BAA4B;2CAA5B,4BAA4B;CA6MxC"}