@memberjunction/ng-explorer-core 6.2.0-edge.2 → 6.2.0-edge.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -0
- package/dist/app-routing.module.d.ts.map +1 -1
- package/dist/app-routing.module.js +5 -0
- package/dist/app-routing.module.js.map +1 -1
- package/dist/generated/lazy-feature-config.d.ts +1 -1
- package/dist/generated/lazy-feature-config.d.ts.map +1 -1
- package/dist/generated/lazy-feature-config.js +12 -2
- package/dist/generated/lazy-feature-config.js.map +1 -1
- package/dist/lib/guards/moved-nav-item-redirect.d.ts +15 -0
- package/dist/lib/guards/moved-nav-item-redirect.d.ts.map +1 -0
- package/dist/lib/guards/moved-nav-item-redirect.js +37 -0
- package/dist/lib/guards/moved-nav-item-redirect.js.map +1 -0
- package/dist/lib/omnibar/omnibar-dashboard-matches.d.ts +34 -0
- package/dist/lib/omnibar/omnibar-dashboard-matches.d.ts.map +1 -0
- package/dist/lib/omnibar/omnibar-dashboard-matches.js +70 -0
- package/dist/lib/omnibar/omnibar-dashboard-matches.js.map +1 -0
- package/dist/lib/omnibar/omnibar-palette.component.d.ts +27 -2
- package/dist/lib/omnibar/omnibar-palette.component.d.ts.map +1 -1
- package/dist/lib/omnibar/omnibar-palette.component.js +126 -65
- package/dist/lib/omnibar/omnibar-palette.component.js.map +1 -1
- package/dist/lib/omnibar/omnibar-provider.d.ts +4 -0
- package/dist/lib/omnibar/omnibar-provider.d.ts.map +1 -1
- package/dist/lib/omnibar/omnibar-provider.js.map +1 -1
- package/dist/lib/omnibar/providers/omnibar-record.provider.d.ts +2 -2
- package/dist/lib/omnibar/providers/omnibar-record.provider.d.ts.map +1 -1
- package/dist/lib/omnibar/providers/omnibar-record.provider.js +3 -7
- package/dist/lib/omnibar/providers/omnibar-record.provider.js.map +1 -1
- package/dist/lib/omnibar/providers/omnibar-search.provider.d.ts +15 -2
- package/dist/lib/omnibar/providers/omnibar-search.provider.d.ts.map +1 -1
- package/dist/lib/omnibar/providers/omnibar-search.provider.js +59 -7
- package/dist/lib/omnibar/providers/omnibar-search.provider.js.map +1 -1
- package/dist/lib/profile/forking-setting.d.ts +8 -0
- package/dist/lib/profile/forking-setting.d.ts.map +1 -0
- package/dist/lib/profile/forking-setting.js +18 -0
- package/dist/lib/profile/forking-setting.js.map +1 -0
- package/dist/lib/profile/profile-dialog.component.d.ts +8 -0
- package/dist/lib/profile/profile-dialog.component.d.ts.map +1 -1
- package/dist/lib/profile/profile-dialog.component.js +182 -92
- package/dist/lib/profile/profile-dialog.component.js.map +1 -1
- package/dist/lib/resource-wrappers/artifact-resource.component.d.ts +23 -4
- package/dist/lib/resource-wrappers/artifact-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/artifact-resource.component.js +36 -8
- package/dist/lib/resource-wrappers/artifact-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts +7 -18
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.js +20 -41
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/chat-search-routing.d.ts +10 -3
- package/dist/lib/resource-wrappers/chat-search-routing.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/chat-search-routing.js +11 -4
- package/dist/lib/resource-wrappers/chat-search-routing.js.map +1 -1
- package/dist/lib/resource-wrappers/dashboard-add-to-menu.component.d.ts +29 -0
- package/dist/lib/resource-wrappers/dashboard-add-to-menu.component.d.ts.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-add-to-menu.component.js +141 -0
- package/dist/lib/resource-wrappers/dashboard-add-to-menu.component.js.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-part-config.d.ts +28 -0
- package/dist/lib/resource-wrappers/dashboard-part-config.d.ts.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-part-config.js +150 -0
- package/dist/lib/resource-wrappers/dashboard-part-config.js.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts +361 -56
- package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/dashboard-resource.component.js +1312 -361
- package/dist/lib/resource-wrappers/dashboard-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/dashboard-source-search.d.ts +86 -0
- package/dist/lib/resource-wrappers/dashboard-source-search.d.ts.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-source-search.js +136 -0
- package/dist/lib/resource-wrappers/dashboard-source-search.js.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-studio-pane.d.ts +30 -0
- package/dist/lib/resource-wrappers/dashboard-studio-pane.d.ts.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-studio-pane.js +55 -0
- package/dist/lib/resource-wrappers/dashboard-studio-pane.js.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-studio-tools.d.ts +135 -0
- package/dist/lib/resource-wrappers/dashboard-studio-tools.d.ts.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-studio-tools.js +856 -0
- package/dist/lib/resource-wrappers/dashboard-studio-tools.js.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-tab-agent.d.ts +87 -0
- package/dist/lib/resource-wrappers/dashboard-tab-agent.d.ts.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-tab-agent.js +125 -0
- package/dist/lib/resource-wrappers/dashboard-tab-agent.js.map +1 -0
- package/dist/lib/resource-wrappers/human-handoff-console-resource.component.d.ts +32 -0
- package/dist/lib/resource-wrappers/human-handoff-console-resource.component.d.ts.map +1 -0
- package/dist/lib/resource-wrappers/human-handoff-console-resource.component.js +114 -0
- package/dist/lib/resource-wrappers/human-handoff-console-resource.component.js.map +1 -0
- package/dist/lib/resource-wrappers/livekit-room-resource.component.d.ts +40 -6
- package/dist/lib/resource-wrappers/livekit-room-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/livekit-room-resource.component.js +287 -147
- package/dist/lib/resource-wrappers/livekit-room-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/meetings-resource.component.d.ts +42 -0
- package/dist/lib/resource-wrappers/meetings-resource.component.d.ts.map +1 -0
- package/dist/lib/resource-wrappers/meetings-resource.component.js +225 -0
- package/dist/lib/resource-wrappers/meetings-resource.component.js.map +1 -0
- package/dist/lib/resource-wrappers/record-resource.component.d.ts +27 -2
- package/dist/lib/resource-wrappers/record-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/record-resource.component.js +58 -6
- package/dist/lib/resource-wrappers/record-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/search-results-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/search-results-resource.component.js +5 -4
- package/dist/lib/resource-wrappers/search-results-resource.component.js.map +1 -1
- package/dist/lib/shell/components/tabs/component-cache-manager.d.ts.map +1 -1
- package/dist/lib/shell/components/tabs/component-cache-manager.js.map +1 -1
- package/dist/lib/shell/components/tabs/tab-container.component.d.ts +38 -0
- package/dist/lib/shell/components/tabs/tab-container.component.d.ts.map +1 -1
- package/dist/lib/shell/components/tabs/tab-container.component.js +77 -4
- package/dist/lib/shell/components/tabs/tab-container.component.js.map +1 -1
- package/dist/lib/shell/dashboard-tab-for-url.d.ts +35 -0
- package/dist/lib/shell/dashboard-tab-for-url.d.ts.map +1 -0
- package/dist/lib/shell/dashboard-tab-for-url.js +39 -0
- package/dist/lib/shell/dashboard-tab-for-url.js.map +1 -0
- package/dist/lib/shell/shell.component.d.ts +31 -2
- package/dist/lib/shell/shell.component.d.ts.map +1 -1
- package/dist/lib/shell/shell.component.js +119 -42
- package/dist/lib/shell/shell.component.js.map +1 -1
- package/dist/lib/shell/shell.module.d.ts +2 -1
- package/dist/lib/shell/shell.module.d.ts.map +1 -1
- package/dist/lib/shell/shell.module.js +6 -2
- package/dist/lib/shell/shell.module.js.map +1 -1
- package/dist/lib/single-dashboard/single-dashboard.component.js +1 -1
- package/dist/lib/single-dashboard/single-dashboard.component.js.map +1 -1
- package/dist/lib/single-record/single-record.component.d.ts +29 -3
- package/dist/lib/single-record/single-record.component.d.ts.map +1 -1
- package/dist/lib/single-record/single-record.component.js +44 -4
- package/dist/lib/single-record/single-record.component.js.map +1 -1
- package/dist/lib/template-user/template-user-banner.component.d.ts +20 -0
- package/dist/lib/template-user/template-user-banner.component.d.ts.map +1 -0
- package/dist/lib/template-user/template-user-banner.component.js +67 -0
- package/dist/lib/template-user/template-user-banner.component.js.map +1 -0
- package/dist/lib/user-notifications/user-notifications.component.d.ts +13 -0
- package/dist/lib/user-notifications/user-notifications.component.d.ts.map +1 -1
- package/dist/lib/user-notifications/user-notifications.component.js +67 -0
- package/dist/lib/user-notifications/user-notifications.component.js.map +1 -1
- package/dist/module.d.ts +61 -56
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +32 -4
- package/dist/module.js.map +1 -1
- package/dist/public-api.d.ts +2 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +2 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +58 -52
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"omnibar-palette.component.js","sourceRoot":"","sources":["../../../src/lib/omnibar/omnibar-palette.component.ts","../../../src/lib/omnibar/omnibar-palette.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter,\n OnDestroy, Output, ViewChild, inject,\n} from '@angular/core';\nimport { CompositeKey, UserInfo } from '@memberjunction/core';\nimport { Metadata } from '@memberjunction/core';\nimport { MentionSuggestion } from '@memberjunction/ng-composer';\nimport { NavigationService } from '@memberjunction/ng-shared';\nimport { ApplicationManager } from '@memberjunction/ng-base-application';\nimport { SearchService, SearchScopeInfo } from '@memberjunction/ng-search';\nimport { FileOpenService } from '@memberjunction/ng-file-storage';\nimport { Subscription, firstValueFrom, skip } from 'rxjs';\nimport { CommandPaletteService } from '../command-palette/command-palette.service';\nimport {\n DiscoverOmnibarProviders, GetOmnibarNavPayload, OmnibarProvider,\n} from './omnibar-provider';\nimport { LoadOmnibarProviders } from './index';\n\n/** One rendered result row: the suggestion + presentation extras. */\ninterface OmnibarRow {\n Suggestion: MentionSuggestion;\n /** Set only on the FIRST row of each group — drives the section header. */\n GroupLabel: string | null;\n /** 0-100 relevance bar (search mode only). */\n ScorePercent: number | null;\n}\n\n/** Debounce for the default (network-backed) search mode; trigger modes serve warm caches. */\nconst SEARCH_DEBOUNCE_MS = 300;\n\n/**\n * Debounce for trigger modes (e.g. '#' jump-to-record). Entity-name matching is in-memory,\n * but the record-suggestion path issues a RunView per keystroke — firing on every character\n * floods MJAPI during a typing burst. A short debounce collapses rapid typing into a single\n * backend query while keeping the picker responsive.\n */\nconst TRIGGER_DEBOUNCE_MS = 150;\n\n/** Max suggestions requested per keystroke. */\nconst MAX_RESULTS = 9;\n\n/**\n * The unified Explorer command palette (Ctrl/Cmd+K): one surface for global\n * cross-source search (plain text), jump-to-record ('#'), commands & apps ('/'),\n * and agents ('@') — every mode a pluggable {@link OmnibarProvider}, discovered via\n * the MJ ClassFactory so OpenApps can add modes without touching this component.\n *\n * Design source of truth: plans/composer-adoption/mockups/omnibar-command-palette.html.\n */\n@Component({\n standalone: false,\n selector: 'mj-omnibar-palette',\n templateUrl: './omnibar-palette.component.html',\n styleUrls: ['./omnibar-palette.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class OmnibarPaletteComponent implements OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n private host = inject<ElementRef<HTMLElement>>(ElementRef);\n private navigation = inject(NavigationService);\n private appManager = inject(ApplicationManager);\n private search = inject(SearchService);\n private paletteService = inject(CommandPaletteService);\n private fileOpen = inject(FileOpenService);\n\n @ViewChild('paletteInput') private inputRef?: ElementRef<HTMLInputElement>;\n\n /** Palette visibility (open via {@link Open}; Escape/backdrop close). */\n public IsOpen = false;\n /** Raw input text including any leading trigger char. */\n public Query = '';\n public Rows: OmnibarRow[] = [];\n public RecentRows: OmnibarRow[] = [];\n public SelectedIndex = 0;\n public IsLoading = false;\n public Scopes: SearchScopeInfo[] = [];\n public SelectedScopeIDs: string[] = [];\n\n @Output() Opened = new EventEmitter<void>();\n @Output() Closed = new EventEmitter<void>();\n /** Footer gear clicked — the host opens its settings surface (Explorer: My\n Profile, where the Command Palette opt-in section lives). The palette\n closes first so the settings dialog isn't buried under it. */\n @Output() SettingsRequested = new EventEmitter<void>();\n\n private providers: OmnibarProvider[] = [];\n private defaultProvider: OmnibarProvider | null = null;\n private byTrigger = new Map<string, OmnibarProvider>();\n private queryGeneration = 0;\n private debounceHandle: ReturnType<typeof setTimeout> | null = null;\n /** Element focused before the palette opened — restored on close (a11y). */\n private previousFocus: HTMLElement | null = null;\n private recentsSub: Subscription | null = null;\n\n // ---------------------------------------------------------------\n // Derived view state\n // ---------------------------------------------------------------\n\n /** The active trigger char ('' = default/global-search mode). */\n public get ActiveTriggerChar(): string {\n const first = this.Query.charAt(0);\n return this.byTrigger.has(first) ? first : '';\n }\n\n /** Query text with the trigger char stripped. */\n public get EffectiveQuery(): string {\n return this.ActiveTriggerChar ? this.Query.substring(1) : this.Query;\n }\n\n public get ActiveModeLabel(): string {\n return this.activeProvider?.ModeLabel ?? 'Search';\n }\n\n public get ActivePlaceholder(): string {\n return this.activeProvider?.Placeholder ?? 'Search everything — or type #, /, @ …';\n }\n\n /** Scope pills only apply to the cross-source search mode. */\n public get ShowScopes(): boolean {\n return this.ActiveTriggerChar === '' && this.EffectiveQuery.trim().length > 0;\n }\n\n /** Footer gear: close, then let the host present its settings surface. */\n public RequestSettings(): void {\n this.Close();\n this.SettingsRequested.emit();\n }\n\n /** Hint chips for the empty state — one per non-default provider. */\n public get TriggerHints(): Array<{ Char: string; Label: string }> {\n return this.providers\n .filter((p) => p.TriggerChar !== '')\n .map((p) => ({ Char: p.TriggerChar, Label: p.ModeLabel }));\n }\n\n /** RecentRows render after the hint bar; selection indexes continue into them. */\n public get RecentBaseIndex(): number {\n return 0;\n }\n\n private get activeProvider(): OmnibarProvider | null {\n const char = this.ActiveTriggerChar;\n return char ? (this.byTrigger.get(char) ?? null) : this.defaultProvider;\n }\n\n private get selectableRows(): OmnibarRow[] {\n return this.Rows.length > 0 ? this.Rows : this.RecentRows;\n }\n\n /**\n * ARIA combobox wiring: the input keeps DOM focus while this points at the\n * virtually-highlighted option row, so screen readers announce selection moves.\n */\n public get ActiveDescendantId(): string | null {\n return this.selectableRows.length > 0 ? `ob-opt-${this.SelectedIndex}` : null;\n }\n\n /** Whether any option rows exist — drives the combobox's aria-expanded. */\n public get HasOptions(): boolean {\n return this.selectableRows.length > 0;\n }\n\n // ---------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------\n\n /** Opens the palette, optionally pre-seeded (e.g. '/' from the legacy Ctrl+/ path). */\n public Open(initialQuery = ''): void {\n this.ensureProviders();\n this.previousFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null;\n this.IsOpen = true;\n this.Query = initialQuery;\n this.Rows = [];\n this.SelectedIndex = 0;\n void this.loadScopes();\n void this.loadRecents();\n if (initialQuery.length > 0) {\n this.runQuery();\n }\n this.Opened.emit();\n this.cdr.markForCheck();\n // Input mounts via @if — focus next tick.\n setTimeout(() => this.inputRef?.nativeElement.focus(), 30);\n }\n\n public Close(): void {\n if (!this.IsOpen) {\n return;\n }\n this.IsOpen = false;\n this.Query = '';\n this.Rows = [];\n this.Closed.emit();\n this.cdr.markForCheck();\n // Return focus to where the user was (skip if that element left the DOM).\n if (this.previousFocus?.isConnected) {\n this.previousFocus.focus();\n }\n this.previousFocus = null;\n }\n\n public Toggle(initialQuery = ''): void {\n if (this.IsOpen) {\n this.Close();\n } else {\n this.Open(initialQuery);\n }\n }\n\n ngOnDestroy(): void {\n if (this.debounceHandle != null) {\n clearTimeout(this.debounceHandle);\n }\n this.recentsSub?.unsubscribe();\n }\n\n // ---------------------------------------------------------------\n // Input handling\n // ---------------------------------------------------------------\n\n public OnQueryChange(value: string): void {\n this.Query = value;\n this.SelectedIndex = 0;\n this.runQuery();\n }\n\n public OnInputKeydown(event: KeyboardEvent): void {\n const rows = this.selectableRows;\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n this.moveSelection(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n this.moveSelection(-1);\n break;\n case 'Enter': {\n event.preventDefault();\n const row = rows[this.SelectedIndex];\n if (row) {\n this.Execute(row.Suggestion);\n } else if (this.ActiveTriggerChar === '' && this.EffectiveQuery.trim().length > 1) {\n // No rows yet (still loading / no matches): honest escape hatch to full search.\n this.openFullSearch(this.EffectiveQuery.trim());\n }\n break;\n }\n }\n }\n\n /**\n * Dialog-level keys (bubbled from anywhere inside the palette):\n * - Escape closes from any focused element, not just the input.\n * - Tab follows the natural visual order — input → scope pills → mode chips →\n * the selected result row (roving tabindex) — and TRAPS at the ends so focus\n * cycles inside the dialog instead of escaping to the page underneath.\n * (Design review: Tab must reach the three mode chips, not skip them.)\n */\n public OnPaletteKeydown(event: KeyboardEvent): void {\n if (event.key === 'Escape') {\n event.preventDefault();\n this.Close();\n return;\n }\n if (event.key !== 'Tab') {\n return;\n }\n // On a result row, Tab / Shift+Tab step through the RESULTS themselves\n // (mirrors ArrowDown/Up) until walking off either end of the list — then\n // the trap logic below takes over. Same model as mj-search-overlay.\n const activeEl = document.activeElement as HTMLElement | null;\n if (activeEl?.classList.contains('ob-row')) {\n const last = this.selectableRows.length - 1;\n if (!event.shiftKey && this.SelectedIndex < last) {\n event.preventDefault();\n this.moveSelection(1, true);\n return;\n }\n if (event.shiftKey && this.SelectedIndex > 0) {\n event.preventDefault();\n this.moveSelection(-1, true);\n return;\n }\n // At either end: fall through so Tab leaves the list naturally.\n }\n const root = this.host.nativeElement.querySelector('.omnibar-palette') as HTMLElement | null;\n if (!root) {\n return;\n }\n const focusables = Array.from(root.querySelectorAll<HTMLElement>('input, button, .ob-row[tabindex=\"0\"]'))\n .filter((el) => el.offsetParent !== null);\n if (focusables.length === 0) {\n return;\n }\n const active = document.activeElement as HTMLElement | null;\n if (!event.shiftKey && active === focusables[focusables.length - 1]) {\n event.preventDefault();\n focusables[0].focus();\n } else if (event.shiftKey && active === focusables[0]) {\n event.preventDefault();\n focusables[focusables.length - 1].focus();\n }\n }\n\n /** Keys on a focused result row (rows are real focus stops via roving tabindex). */\n public OnRowKeydown(event: KeyboardEvent, suggestion: MentionSuggestion): void {\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n this.moveSelection(1, true);\n break;\n case 'ArrowUp':\n event.preventDefault();\n this.moveSelection(-1, true);\n break;\n case 'Enter':\n event.preventDefault();\n this.Execute(suggestion);\n break;\n }\n }\n\n /**\n * Keyboard-driven selection move: wraps at both ends (standard picker behavior)\n * and keeps the highlighted row visible. Mouse hover sets SelectedIndex directly\n * in the template and deliberately does NOT scroll — auto-scrolling under the\n * pointer would fight the user's hand. When the move originates from a focused\n * row (roving tabindex), DOM focus follows the selection.\n */\n private moveSelection(delta: 1 | -1, focusRow = false): void {\n const count = this.selectableRows.length;\n if (count === 0) {\n return;\n }\n this.SelectedIndex = (this.SelectedIndex + delta + count) % count;\n this.cdr.markForCheck();\n const row = this.host.nativeElement.querySelector<HTMLElement>(`#ob-opt-${this.SelectedIndex}`);\n row?.scrollIntoView({ block: 'nearest' });\n if (focusRow) {\n row?.focus();\n }\n }\n\n /** Hint-chip click: seed the trigger char and refocus. */\n public SeedTrigger(char: string): void {\n this.Query = char;\n this.SelectedIndex = 0;\n this.runQuery();\n this.inputRef?.nativeElement.focus();\n }\n\n // ---------------------------------------------------------------\n // Scopes\n // ---------------------------------------------------------------\n\n public IsScopeSelected(id: string): boolean {\n return this.SelectedScopeIDs.includes(id);\n }\n\n public ToggleScope(id: string): void {\n this.SelectedScopeIDs = this.IsScopeSelected(id)\n ? this.SelectedScopeIDs.filter((s) => s !== id)\n : [...this.SelectedScopeIDs, id];\n this.cdr.markForCheck();\n }\n\n public ClearScopes(): void {\n this.SelectedScopeIDs = [];\n this.cdr.markForCheck();\n }\n\n // ---------------------------------------------------------------\n // Execution\n // ---------------------------------------------------------------\n\n /** Executes a suggestion: navigate per its payload, or re-seed for entity drill-in. */\n public Execute(suggestion: MentionSuggestion): void {\n const nav = GetOmnibarNavPayload(suggestion);\n if (!nav) {\n return; // foreign suggestion with no navigation — nothing to execute\n }\n // Default-mode queries count as \"searches\" even when the user executes a\n // suggestion that navigates directly (no full ExecuteSearch downstream to\n // record them). Trigger-mode fragments ('#accounts ac…') are NOT searches —\n // recording those would pollute recents. 'search' payloads skip too: the\n // results page records them with the real result count.\n const typed = this.EffectiveQuery.trim();\n if (this.ActiveTriggerChar === '' && typed.length > 0 && nav.kind !== 'search') {\n this.search.RecordRecentSearch(typed);\n }\n switch (nav.kind) {\n case 'record': {\n // `recordId` is a compact CompositeKey segment (bare value for a single-column key,\n // \"F1|v1||F2|v2\" for a composite one) on an ARBITRARY entity, so the key column can\n // have any name. `FromID` hardcoded `ID` and broke record-open for every entity whose\n // key is called something else; resolve against the entity's metadata instead.\n const entityInfo = this.search.Provider.EntityByName(nav.entityName);\n this.navigation.OpenEntityRecord(nav.entityName, CompositeKey.FromURLSegment(entityInfo, nav.recordId));\n break;\n }\n case 'entity-list':\n this.navigation.OpenDynamicView(nav.entityName);\n break;\n case 'search':\n this.openFullSearch(nav.query);\n return; // openFullSearch closes\n case 'app':\n void this.paletteService.TrackAppAccess(nav.appId);\n void this.navigation.SwitchToApp(nav.appId);\n break;\n case 'nav':\n void this.navigation.SwitchToApp(nav.appId, nav.navItemName);\n break;\n case 'agent':\n void this.openAgentChat(nav.agentName);\n break;\n case 'file':\n if (!this.fileOpen.OpenPreviewFromSearchResult(nav.rawMetadata)) {\n void this.fileOpen.OpenFileFromSearchResult(nav.rawMetadata);\n }\n break;\n }\n this.Close();\n }\n\n private openFullSearch(query: string): void {\n const opts = this.SelectedScopeIDs.length > 0 ? { scopeIDs: [...this.SelectedScopeIDs] } : undefined;\n this.navigation.OpenSearch(query, opts);\n this.Close();\n }\n\n /** '@' selection: switch to the Chat app pre-addressed to the agent. */\n private async openAgentChat(agentName: string): Promise<void> {\n const apps = await firstValueFrom(this.appManager.Applications).catch(() => []);\n const chat = apps.find((a) => a.Name.trim().toLowerCase() === 'chat');\n if (chat) {\n // agentReq is a one-shot request nonce: the chat wrapper applies each\n // agent|nonce instruction exactly once, so URL↔tab-config sync echoes\n // of an already-consumed param can never re-stage the pre-address (and\n // wipe an in-progress composer draft), while a genuine re-tag of the\n // SAME agent still applies because it carries a fresh nonce.\n await this.navigation.SwitchToApp(chat.ID, undefined, {\n agent: agentName,\n agentReq: Date.now().toString(36),\n });\n }\n }\n\n // ---------------------------------------------------------------\n // Query execution\n // ---------------------------------------------------------------\n\n private ensureProviders(): void {\n if (this.providers.length > 0) {\n return;\n }\n // Kick off the persisted-recents load (idempotent; resolves via LoggedIn\n // replay). The legacy search composite used to be the only caller — with\n // the omnibar enabled it never renders, so prior-session recents were\n // invisible until the palette started requesting them itself.\n void this.search.LoadRecentSearches();\n // Refresh the empty-state Recent rows whenever recents change while the\n // palette is idle-open (skip(1): BehaviorSubject replays its current\n // value on subscribe, which loadRecents already read directly).\n this.recentsSub = this.search.RecentSearches$.pipe(skip(1)).subscribe(() => {\n if (this.IsOpen && this.Query.length === 0) {\n void this.loadRecents();\n }\n });\n LoadOmnibarProviders();\n this.providers = DiscoverOmnibarProviders();\n const context = {\n Search: this.search,\n Apps: this.appManager,\n PaletteService: this.paletteService,\n Navigation: this.navigation,\n };\n for (const provider of this.providers) {\n provider.Attach(context);\n if (provider.TriggerChar === '') {\n this.defaultProvider = this.defaultProvider ?? provider;\n } else if (!this.byTrigger.has(provider.TriggerChar)) {\n this.byTrigger.set(provider.TriggerChar, provider);\n }\n }\n }\n\n private runQuery(): void {\n if (this.debounceHandle != null) {\n clearTimeout(this.debounceHandle);\n this.debounceHandle = null;\n }\n const generation = ++this.queryGeneration;\n const provider = this.activeProvider;\n const query = this.EffectiveQuery;\n const isTriggerMode = this.ActiveTriggerChar !== '';\n\n if (!provider || (query.trim().length === 0 && !isTriggerMode)) {\n this.Rows = [];\n this.IsLoading = false;\n this.cdr.markForCheck();\n return;\n }\n\n const fire = () => void this.fetchSuggestions(provider, query, generation);\n if (isTriggerMode) {\n // Short debounce: entity matching is in-memory, but record suggestions issue a\n // RunView per keystroke — debouncing collapses a typing burst into one backend query.\n this.debounceHandle = setTimeout(fire, TRIGGER_DEBOUNCE_MS);\n } else {\n this.IsLoading = this.Rows.length === 0;\n this.cdr.markForCheck();\n this.debounceHandle = setTimeout(fire, SEARCH_DEBOUNCE_MS);\n }\n }\n\n private async fetchSuggestions(provider: OmnibarProvider, query: string, generation: number): Promise<void> {\n const request = {\n Query: query,\n MaxResults: MAX_RESULTS,\n ContextUser: this.currentUser,\n Provider: null,\n };\n const suggestions = query.trim().length === 0\n ? await provider.EmptyStateSuggestions(request)\n : await provider.GetSuggestions(request);\n if (generation !== this.queryGeneration) {\n return; // stale response — a newer keystroke superseded it\n }\n this.Rows = this.toRows(suggestions);\n this.SelectedIndex = 0;\n this.IsLoading = false;\n this.cdr.markForCheck();\n }\n\n private toRows(suggestions: MentionSuggestion[]): OmnibarRow[] {\n let lastGroup: string | null = null;\n return suggestions.map((s) => {\n const group = typeof s.data?.['group'] === 'string' ? (s.data['group'] as string) : '';\n const isNewGroup = group.length > 0 && group !== lastGroup;\n if (group.length > 0) {\n lastGroup = group;\n }\n const score = typeof s.data?.['score'] === 'number' ? (s.data['score'] as number) : null;\n return {\n Suggestion: s,\n GroupLabel: isNewGroup ? group : null,\n ScorePercent: score != null ? Math.round(Math.max(0, Math.min(1, score)) * 100) : null,\n };\n });\n }\n\n private async loadScopes(): Promise<void> {\n try {\n this.Scopes = await this.search.LoadScopes();\n this.cdr.markForCheck();\n } catch {\n this.Scopes = [];\n }\n }\n\n /** Empty-state recents: recent searches + recent apps (best-effort). */\n private async loadRecents(): Promise<void> {\n const rows: OmnibarRow[] = [];\n try {\n const recentSearches = this.search.RecentSearches$.value.slice(0, 3);\n for (const recent of recentSearches) {\n rows.push({\n Suggestion: {\n type: 'search',\n id: `recent-search:${recent.Query}`,\n name: recent.Query,\n displayName: recent.Query,\n description: 'Recent search',\n icon: 'fa-solid fa-clock-rotate-left',\n data: { nav: { kind: 'search', query: recent.Query } },\n },\n GroupLabel: null,\n ScorePercent: null,\n });\n }\n } catch {\n // recents are decorative — never block the palette\n }\n try {\n const commandProvider = this.byTrigger.get('/');\n if (commandProvider) {\n const apps = await commandProvider.EmptyStateSuggestions({\n Query: '', MaxResults: 3, ContextUser: this.currentUser, Provider: null,\n });\n rows.push(...apps.map((s) => ({ Suggestion: s, GroupLabel: null, ScorePercent: null })));\n }\n } catch {\n // ditto\n }\n this.RecentRows = rows;\n this.cdr.markForCheck();\n }\n\n private get currentUser(): UserInfo | null {\n return Metadata.Provider?.CurrentUser ?? null; // global-provider-ok: Explorer shell palette is app chrome bound to the session's default provider\n }\n}\n\n/** Tree-shaking guard for the palette component. */\nexport function LoadOmnibarPaletteComponent(): void {\n // intentional no-op\n}\n","@if (IsOpen) {\n <div class=\"omnibar-overlay\" (click)=\"Close()\"></div>\n <div class=\"omnibar-palette\" role=\"dialog\" aria-modal=\"true\" aria-label=\"Command palette\"\n (keydown)=\"OnPaletteKeydown($event)\">\n\n <div class=\"ob-input-row\">\n <div class=\"ob-field\">\n <span class=\"ob-lead\" [class.ob-lead--trigger]=\"ActiveTriggerChar.length > 0\">\n @if (ActiveTriggerChar.length > 0) {\n <b>{{ ActiveTriggerChar }}</b>\n } @else {\n <i class=\"fa-solid fa-magnifying-glass\"></i>\n }\n </span>\n <input #paletteInput class=\"ob-input\" type=\"text\" autocomplete=\"off\" spellcheck=\"false\"\n role=\"combobox\" aria-controls=\"ob-listbox\" aria-autocomplete=\"list\"\n [attr.aria-expanded]=\"HasOptions\"\n [attr.aria-activedescendant]=\"ActiveDescendantId\"\n [placeholder]=\"ActivePlaceholder\"\n [ngModel]=\"Query\" (ngModelChange)=\"OnQueryChange($event)\"\n (keydown)=\"OnInputKeydown($event)\" />\n <span class=\"ob-mode-badge\">{{ ActiveModeLabel }}</span>\n <kbd class=\"ob-kbd\">esc</kbd>\n </div>\n <button type=\"button\" class=\"ob-close\" aria-label=\"Close\" title=\"Close\" (click)=\"Close()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n\n @if (ShowScopes && Scopes.length > 0) {\n <div class=\"ob-scopes\">\n <button type=\"button\" class=\"ob-scope\" [class.ob-scope--on]=\"SelectedScopeIDs.length === 0\"\n (click)=\"ClearScopes()\">All sources</button>\n @for (scope of Scopes; track scope.ID) {\n <button type=\"button\" class=\"ob-scope\" [class.ob-scope--on]=\"IsScopeSelected(scope.ID)\"\n (click)=\"ToggleScope(scope.ID)\">{{ scope.Name }}</button>\n }\n </div>\n }\n\n <div class=\"ob-body\">\n @if (IsLoading) {\n <div class=\"ob-loading\"><i class=\"fa-solid fa-circle-notch fa-spin\"></i> Searching…</div>\n } @else if (Rows.length === 0 && Query.length === 0) {\n <div class=\"ob-hintbar\">\n @for (hint of TriggerHints; track hint.Char) {\n <button type=\"button\" class=\"ob-hint-chip\" (click)=\"SeedTrigger(hint.Char)\">\n <b>{{ hint.Char }}</b><span>{{ hint.Label }}</span>\n </button>\n }\n </div>\n @if (RecentRows.length > 0) {\n <div class=\"ob-group-label\" role=\"presentation\">Recent</div>\n <div id=\"ob-listbox\" role=\"listbox\" aria-label=\"Suggestions\">\n @for (row of RecentRows; track row.Suggestion.id; let i = $index) {\n <div class=\"ob-row\" role=\"option\" [attr.id]=\"'ob-opt-' + (RecentBaseIndex + i)\"\n [attr.tabindex]=\"RecentBaseIndex + i === SelectedIndex ? 0 : -1\"\n [attr.aria-selected]=\"RecentBaseIndex + i === SelectedIndex\"\n [class.ob-row--sel]=\"RecentBaseIndex + i === SelectedIndex\"\n (focus)=\"SelectedIndex = RecentBaseIndex + i\"\n (keydown)=\"OnRowKeydown($event, row.Suggestion)\"\n (mouseenter)=\"SelectedIndex = RecentBaseIndex + i\" (click)=\"Execute(row.Suggestion)\">\n <span class=\"ob-ric\"><i [class]=\"row.Suggestion.icon || 'fa-solid fa-clock-rotate-left'\"></i></span>\n <span class=\"ob-rmain\">\n <span class=\"ob-rname\">{{ row.Suggestion.displayName }}</span>\n <span class=\"ob-rsub\">{{ row.Suggestion.description }}</span>\n </span>\n <span class=\"ob-raux\"><span class=\"ob-rtype\">{{ row.Suggestion.type }}</span></span>\n </div>\n }\n </div>\n }\n } @else if (Rows.length === 0) {\n <div class=\"ob-empty\">No matches — press <kbd class=\"ob-kbd\">↵</kbd> to search everything for “{{ EffectiveQuery }}”.</div>\n } @else {\n <div id=\"ob-listbox\" role=\"listbox\" aria-label=\"Suggestions\">\n @for (row of Rows; track row.Suggestion.id; let i = $index) {\n @if (row.GroupLabel) {\n <div class=\"ob-group-label\" role=\"presentation\">{{ row.GroupLabel }}</div>\n }\n <div class=\"ob-row\" role=\"option\" [attr.id]=\"'ob-opt-' + i\"\n [attr.tabindex]=\"i === SelectedIndex ? 0 : -1\"\n [attr.aria-selected]=\"i === SelectedIndex\"\n [class.ob-row--sel]=\"i === SelectedIndex\"\n (focus)=\"SelectedIndex = i\"\n (keydown)=\"OnRowKeydown($event, row.Suggestion)\"\n (mouseenter)=\"SelectedIndex = i\" (click)=\"Execute(row.Suggestion)\">\n <span class=\"ob-ric\"><i [class]=\"row.Suggestion.icon || 'fa-solid fa-circle'\"></i></span>\n <span class=\"ob-rmain\">\n <span class=\"ob-rname\">{{ row.Suggestion.displayName }}</span>\n @if (row.Suggestion.description) {\n <span class=\"ob-rsub\">{{ row.Suggestion.description }}</span>\n }\n </span>\n <span class=\"ob-raux\">\n @if (row.ScorePercent != null) {\n <span class=\"ob-score\"><i [style.width.%]=\"row.ScorePercent\"></i></span>\n }\n <span class=\"ob-rtype\">{{ row.Suggestion.type }}</span>\n <span class=\"ob-go\">open <kbd class=\"ob-kbd\">↵</kbd></span>\n </span>\n </div>\n }\n </div>\n }\n </div>\n\n <div class=\"ob-foot\">\n <span class=\"ob-k\"><kbd class=\"ob-kbd\">↑</kbd><kbd class=\"ob-kbd\">↓</kbd> navigate</span>\n <span class=\"ob-k\"><kbd class=\"ob-kbd\">↵</kbd> open</span>\n <button type=\"button\" class=\"ob-settings\" aria-label=\"Command Palette settings\"\n title=\"Command Palette settings\" (click)=\"RequestSettings()\">\n <i class=\"fa-solid fa-gear\" aria-hidden=\"true\"></i>\n <span>Settings</span>\n </button>\n </div>\n </div>\n}\n"]}
|
|
1
|
+
{"version":3,"file":"omnibar-palette.component.js","sourceRoot":"","sources":["../../../src/lib/omnibar/omnibar-palette.component.ts","../../../src/lib/omnibar/omnibar-palette.component.html"],"names":[],"mappings":"AAAA,OAAO,EACH,uBAAuB,EAAE,iBAAiB,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EACpE,MAAM,EAAE,SAAS,EAAE,MAAM,GACvC,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAY,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,aAAa,EAAmB,MAAM,2BAA2B,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAgB,cAAc,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AACnF,OAAO,EACH,wBAAwB,EAAE,oBAAoB,GACjD,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;;;;;;;;ICPnC,yBAAG;IAAA,YAAuB;IAAA,iBAAI;;;IAA3B,cAAuB;IAAvB,8CAAuB;;;IAE1B,uBAA4C;;;;IAuB9C,kCACkC;IAAhC,4OAAS,+BAAqB,KAAC;IAAC,YAAgB;IAAA,iBAAS;;;;IADpB,mEAAgD;IACrD,cAAgB;IAAhB,mCAAgB;;;;IAJpD,AADF,+BAAuB,iBAEK;IAAxB,2MAAS,oBAAa,KAAC;IAAC,2BAAW;IAAA,iBAAS;IAC9C,2HAGC;IACH,iBAAM;;;IANmC,cAAoD;IAApD,oEAAoD;IAE3F,eAGC;IAHD,4BAGC;;;IAMD,+BAAwB;IAAA,wBAAgD;IAAC,gCAAU;IAAA,iBAAM;;;;IAIrF,kCAA4E;IAAjC,2OAAS,gCAAsB,KAAC;IACzE,yBAAG;IAAA,YAAe;IAAA,iBAAI;IAAA,4BAAM;IAAA,YAAgB;IAC9C,AAD8C,iBAAO,EAC5C;;;IADJ,eAAe;IAAf,kCAAe;IAAU,eAAgB;IAAhB,mCAAgB;;;;IAQ9C,+BAMuF;IAAlC,AAAnD,AADA,AADA,2TAA6C,mPAClC,+CAAoC,KAAC,wTACE,yOAAU,kCAAuB,KAAC;IACpF,gCAAqB;IAAA,oBAAwE;IAAA,iBAAO;IAElG,AADF,gCAAuB,eACE;IAAA,YAAgC;IAAA,iBAAO;IAC9D,gCAAsB;IAAA,YAAgC;IACxD,AADwD,iBAAO,EACxD;IACe,AAAtB,gCAAsB,eAAuB;IAAA,aAAyB;IACxE,AAD+E,AAAP,iBAAO,EAAO,EAChF;;;;;IAVJ,8FAA2D;;IAInC,eAAgE;IAAhE,yEAAgE;IAE/D,eAAgC;IAAhC,oDAAgC;IACjC,eAAgC;IAAhC,oDAAgC;IAEX,eAAyB;IAAzB,6CAAyB;;;IAf1E,+BAAgD;IAAA,sBAAM;IAAA,iBAAM;IAC5D,+BAA6D;IAC7D,wIAeC;IACD,iBAAM;;;IAhBN,eAeC;IAfD,gCAeC;;;IAzBH,+BAAwB;IACtB,2HAIC;IACH,iBAAM;IACN,4GAA6B;;;IAN3B,cAIC;IAJD,kCAIC;IAEH,eAoBC;IApBD,uDAoBC;;;IAMC,+BAAsB;IAAA,wCAAmB;IAAA,8BAAoB;IAAA,sBAAC;IAAA,iBAAM;IAAC,YAAgD;IAAA,iBAAM;;;IAAtD,eAAgD;IAAhD,2FAAgD;;;IAErH,+BAAsB;IAAA,YAAsC;IAAA,iBAAM;;;IAA5C,cAAsC;IAAtC,gFAAsC;;;IAD5D,AAFF,uHAA6B,iGAEpB;;;IAFT,sDAIC;;;IAKG,+BAAgD;IAAA,YAAoB;IAAA,iBAAM;;;IAA1B,cAAoB;IAApB,wCAAoB;;;IAahE,gCAAsB;IAAA,YAAgC;IAAA,iBAAO;;;IAAvC,cAAgC;IAAhC,oDAAgC;;;IAKtD,gCAAuB;IAAA,oBAA0C;IAAA,iBAAO;;;IAA9C,cAAkC;IAAlC,kDAAkC;;;;IAnBlE,6HAA+B;IAG/B,+BAMqE;IAAlC,AAAjC,AADA,AADA,yRAA2B,sOAChB,+CAAoC,KAAC,sRAChB,4NAAU,kCAAuB,KAAC;IAClE,gCAAqB;IAAA,oBAA6D;IAAA,iBAAO;IAEvF,AADF,gCAAuB,eACE;IAAA,YAAgC;IAAA,iBAAO;IAC9D,8HAAkC;IAGpC,iBAAO;IACP,gCAAsB;IACpB,8HAAgC;IAGhC,iCAAuB;IAAA,aAAyB;IAAA,iBAAO;IACvD,iCAAoB;IAAA,sBAAK;IAAA,+BAAoB;IAAA,uBAAC;IAElD,AADE,AADsD,AAAN,iBAAM,EAAO,EACtD,EACH;;;;;IAxBN,sDAEC;IAIC,cAAyC;IAAzC,uEAAyC;;IAIjB,eAAqD;IAArD,8DAAqD;IAEpD,eAAgC;IAAhC,oDAAgC;IACvD,cAEC;IAFD,yDAEC;IAGD,eAEC;IAFD,uDAEC;IACsB,eAAyB;IAAzB,6CAAyB;;;IAvBtD,+BAA6D;IAC7D,2HA0BC;IACD,iBAAM;;;IA3BN,cA0BC;IA1BD,0BA0BC;;;;IA5GP,8BAA+C;IAAlB,wLAAS,cAAO,KAAC;IAAC,iBAAM;IACrD,8BACuC;IAArC,kMAAW,+BAAwB,KAAC;IAIhC,AADF,AADF,8BAA0B,aACF,cAC0D;IAG1E,AAFF,kGAAoC,+EAE3B;IAGX,iBAAO;IACP,mCAMuC;IAArC,AADkB,gNAAiB,4BAAqB,KAAC,uLAC9C,6BAAsB,KAAC;IANpC,iBAMuC;IACvC,+BAA4B;IAAA,aAAqB;IAAA,iBAAO;IACxD,+BAAoB;IAAA,oBAAG;IACzB,AADyB,iBAAM,EACzB;IACN,mCAA0F;IAAlB,4LAAS,cAAO,KAAC;IACvF,yBAAiC;IAErC,AADE,iBAAS,EACL;IAEN,0GAAuC;IAWvC,gCAAqB;IAyCjB,AATA,AA7BA,AAFF,0GAAiB,yEAEqC,yEA6BtB,oFASvB;IA+BX,iBAAM;IAGe,AAAnB,AADF,gCAAqB,gBACA,cAAoB;IAAA,uBAAC;IAAA,iBAAM;IAAA,+BAAoB;IAAA,uBAAC;IAAA,iBAAM;IAAC,0BAAQ;IAAA,iBAAO;IACtE,AAAnB,iCAAmB,cAAoB;IAAA,uBAAC;IAAA,iBAAM;IAAC,sBAAI;IAAA,iBAAO;IAC1D,mCAC+D;IAA5B,4LAAS,wBAAiB,KAAC;IAC5D,yBAAmD;IACnD,6BAAM;IAAA,yBAAQ;IAGpB,AADE,AADE,AADgB,iBAAO,EACd,EACL,EACF;;;IApHsB,eAAuD;IAAvD,uEAAuD;IAC3E,cAIC;IAJD,6DAIC;IAMD,eAAiC;IACjC,AADA,sDAAiC,yBAChB;;IAES,eAAqB;IAArB,4CAAqB;IAQrD,eASC;IATD,yEASC;IAGC,eAsEC;IAtED,yIAsEC;;ADhFP,8FAA8F;AAC9F,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAE/B;;;;;GAKG;AACH,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEhC,+CAA+C;AAC/C,MAAM,WAAW,GAAG,CAAC,CAAC;AAEtB;;;;;;;GAOG;AAQH,MAAM,OAAO,uBAAuB;IACxB,GAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAChC,IAAI,GAAG,MAAM,CAA0B,UAAU,CAAC,CAAC;IACnD,UAAU,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;IACvC,UAAU,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACxC,MAAM,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC;IAC/B,cAAc,GAAG,MAAM,CAAC,qBAAqB,CAAC,CAAC;IAC/C,QAAQ,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC;IAER,QAAQ,CAAgC;IAE3E,yEAAyE;IAClE,MAAM,GAAG,KAAK,CAAC;IACtB,yDAAyD;IAClD,KAAK,GAAG,EAAE,CAAC;IACX,IAAI,GAAiB,EAAE,CAAC;IACxB,UAAU,GAAiB,EAAE,CAAC;IAC9B,aAAa,GAAG,CAAC,CAAC;IAClB,SAAS,GAAG,KAAK,CAAC;IAClB,MAAM,GAAsB,EAAE,CAAC;IAC/B,gBAAgB,GAAa,EAAE,CAAC;IAE7B,MAAM,GAAG,IAAI,YAAY,EAAQ,CAAC;IAClC,MAAM,GAAG,IAAI,YAAY,EAAQ,CAAC;IAC5C;;qEAEiE;IACvD,iBAAiB,GAAG,IAAI,YAAY,EAAQ,CAAC;IAE/C,SAAS,GAAsB,EAAE,CAAC;IAClC,eAAe,GAA2B,IAAI,CAAC;IAC/C,SAAS,GAAG,IAAI,GAAG,EAA2B,CAAC;IAC/C,eAAe,GAAG,CAAC,CAAC;IAC5B,2EAA2E;IACnE,mBAAmB,GAAG,EAAE,CAAC;IACzB,cAAc,GAAyC,IAAI,CAAC;IACpE,4EAA4E;IACpE,aAAa,GAAuB,IAAI,CAAC;IACzC,UAAU,GAAwB,IAAI,CAAC;IAE/C,kEAAkE;IAClE,qBAAqB;IACrB,kEAAkE;IAElE,iEAAiE;IACjE,IAAW,iBAAiB;QACxB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAClD,CAAC;IAED,iDAAiD;IACjD,IAAW,cAAc;QACrB,OAAO,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;IACzE,CAAC;IAED,IAAW,eAAe;QACtB,OAAO,IAAI,CAAC,cAAc,EAAE,SAAS,IAAI,QAAQ,CAAC;IACtD,CAAC;IAED,IAAW,iBAAiB;QACxB,OAAO,IAAI,CAAC,cAAc,EAAE,WAAW,IAAI,uCAAuC,CAAC;IACvF,CAAC;IAED,8DAA8D;IAC9D,IAAW,UAAU;QACjB,OAAO,IAAI,CAAC,iBAAiB,KAAK,EAAE,IAAI,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IAClF,CAAC;IAED,0EAA0E;IACnE,eAAe;QAClB,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC;IAClC,CAAC;IAED,qEAAqE;IACrE,IAAW,YAAY;QACnB,OAAO,IAAI,CAAC,SAAS;aAChB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,EAAE,CAAC;aACnC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;IACnE,CAAC;IAED,kFAAkF;IAClF,IAAW,eAAe;QACtB,OAAO,CAAC,CAAC;IACb,CAAC;IAED,IAAY,cAAc;QACtB,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC;QACpC,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC;IAC5E,CAAC;IAED;;;OAGG;IACH,IAAY,cAAc;QACtB,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC,IAAI,CAAC;QACrB,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1D,CAAC;IAED;;;;;;;OAOG;IACH,IAAW,qBAAqB;QAC5B,IAAI,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YACzC,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,OAAO,IAAI,CAAC,iBAAiB,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;IAC5D,CAAC;IAED;;;OAGG;IACH,IAAW,kBAAkB;QACzB,OAAO,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAClF,CAAC;IAED,2EAA2E;IAC3E,IAAW,UAAU;QACjB,OAAO,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1C,CAAC;IAED,kEAAkE;IAClE,aAAa;IACb,kEAAkE;IAElE,uFAAuF;IAChF,IAAI,CAAC,YAAY,GAAG,EAAE;QACzB,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC,aAAa,YAAY,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC;QACnG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,KAAK,GAAG,YAAY,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC;QACf,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;QACvB,gFAAgF;QAChF,mCAAmC;QACnC,IAAI,CAAC,mBAAmB,GAAG,EAAE,CAAC;QAC9B,KAAK,IAAI,CAAC,UAAU,EAAE,CAAC;QACvB,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;QACxB,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACpB,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACnB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QACxB,0CAA0C;QAC1C,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;IAC/D,CAAC;IAEM,KAAK;QACR,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACf,OAAO;QACX,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC;QACf,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACnB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QACxB,0EAA0E;QAC1E,IAAI,IAAI,CAAC,aAAa,EAAE,WAAW,EAAE,CAAC;YAClC,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QAC/B,CAAC;QACD,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;IAC9B,CAAC;IAEM,MAAM,CAAC,YAAY,GAAG,EAAE;QAC3B,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,IAAI,CAAC,KAAK,EAAE,CAAC;QACjB,CAAC;aAAM,CAAC;YACJ,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC5B,CAAC;IACL,CAAC;IAED,WAAW;QACP,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI,EAAE,CAAC;YAC9B,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACtC,CAAC;QACD,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE,CAAC;IACnC,CAAC;IAED,kEAAkE;IAClE,iBAAiB;IACjB,kEAAkE;IAE3D,aAAa,CAAC,KAAa;QAC9B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,QAAQ,EAAE,CAAC;IACpB,CAAC;IAEM,cAAc,CAAC,KAAoB;QACtC,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,CAAC;QACjC,QAAQ,KAAK,CAAC,GAAG,EAAE,CAAC;YAChB,KAAK,WAAW;gBACZ,KAAK,CAAC,cAAc,EAAE,CAAC;gBACvB,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;gBACtB,MAAM;YACV,KAAK,SAAS;gBACV,KAAK,CAAC,cAAc,EAAE,CAAC;gBACvB,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;gBACvB,MAAM;YACV,KAAK,OAAO,CAAC,CAAC,CAAC;gBACX,KAAK,CAAC,cAAc,EAAE,CAAC;gBACvB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;gBACrC,IAAI,GAAG,EAAE,CAAC;oBACN,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;gBACjC,CAAC;qBAAM,IAAI,IAAI,CAAC,qBAAqB,EAAE,CAAC;oBACpC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC;gBACpD,CAAC;gBACD,MAAM;YACV,CAAC;QACL,CAAC;IACL,CAAC;IAED;;;;;;;OAOG;IACI,gBAAgB,CAAC,KAAoB;QACxC,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;YACzB,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,IAAI,CAAC,KAAK,EAAE,CAAC;YACb,OAAO;QACX,CAAC;QACD,IAAI,KAAK,CAAC,GAAG,KAAK,KAAK,EAAE,CAAC;YACtB,OAAO;QACX,CAAC;QACD,uEAAuE;QACvE,yEAAyE;QACzE,oEAAoE;QACpE,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAmC,CAAC;QAC9D,IAAI,QAAQ,EAAE,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC;YAC5C,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC,aAAa,GAAG,IAAI,EAAE,CAAC;gBAC/C,KAAK,CAAC,cAAc,EAAE,CAAC;gBACvB,IAAI,CAAC,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;gBAC5B,OAAO;YACX,CAAC;YACD,IAAI,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;gBAC3C,KAAK,CAAC,cAAc,EAAE,CAAC;gBACvB,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;gBAC7B,OAAO;YACX,CAAC;YACD,gEAAgE;QACpE,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,kBAAkB,CAAuB,CAAC;QAC7F,IAAI,CAAC,IAAI,EAAE,CAAC;YACR,OAAO;QACX,CAAC;QACD,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAc,sCAAsC,CAAC,CAAC;aACpG,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC;QAC9C,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO;QACX,CAAC;QACD,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAmC,CAAC;QAC5D,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,MAAM,KAAK,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;YAClE,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;QAC1B,CAAC;aAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;YACpD,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;QAC9C,CAAC;IACL,CAAC;IAED,oFAAoF;IAC7E,YAAY,CAAC,KAAoB,EAAE,UAA6B;QACnE,QAAQ,KAAK,CAAC,GAAG,EAAE,CAAC;YAChB,KAAK,WAAW;gBACZ,KAAK,CAAC,cAAc,EAAE,CAAC;gBACvB,IAAI,CAAC,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;gBAC5B,MAAM;YACV,KAAK,SAAS;gBACV,KAAK,CAAC,cAAc,EAAE,CAAC;gBACvB,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;gBAC7B,MAAM;YACV,KAAK,OAAO;gBACR,KAAK,CAAC,cAAc,EAAE,CAAC;gBACvB,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;gBACzB,MAAM;QACd,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACK,aAAa,CAAC,KAAa,EAAE,QAAQ,GAAG,KAAK;QACjD,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC;QACzC,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;YACd,OAAO;QACX,CAAC;QACD,IAAI,CAAC,aAAa,GAAG,CAAC,IAAI,CAAC,aAAa,GAAG,KAAK,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC;QAClE,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,aAAa,CAAc,WAAW,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;QAChG,GAAG,EAAE,cAAc,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QAC1C,IAAI,QAAQ,EAAE,CAAC;YACX,GAAG,EAAE,KAAK,EAAE,CAAC;QACjB,CAAC;IACL,CAAC;IAED,0DAA0D;IACnD,WAAW,CAAC,IAAY;QAC3B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChB,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,KAAK,EAAE,CAAC;IACzC,CAAC;IAED,kEAAkE;IAClE,SAAS;IACT,kEAAkE;IAE3D,eAAe,CAAC,EAAU;QAC7B,OAAO,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC;IAEM,WAAW,CAAC,EAAU;QACzB,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC;YAC5C,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;YAC/C,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;QACrC,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC5B,CAAC;IAEM,WAAW;QACd,IAAI,CAAC,gBAAgB,GAAG,EAAE,CAAC;QAC3B,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC5B,CAAC;IAED,kEAAkE;IAClE,YAAY;IACZ,kEAAkE;IAElE;;;;;;OAMG;IACI,OAAO,CAAC,UAA6B;QACxC,MAAM,GAAG,GAAG,oBAAoB,CAAC,UAAU,CAAC,CAAC;QAC7C,IAAI,CAAC,GAAG,EAAE,CAAC;YACP,OAAO,CAAC,6DAA6D;QACzE,CAAC;QACD,yEAAyE;QACzE,0EAA0E;QAC1E,4EAA4E;QAC5E,yEAAyE;QACzE,wDAAwD;QACxD,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QACzC,IAAI,IAAI,CAAC,iBAAiB,KAAK,EAAE,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7E,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;QAC1C,CAAC;QACD,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;YACf,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACZ,oFAAoF;gBACpF,oFAAoF;gBACpF,sFAAsF;gBACtF,+EAA+E;gBAC/E,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;gBACrE,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,GAAG,CAAC,UAAU,EAAE,YAAY,CAAC,cAAc,CAAC,UAAU,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACxG,MAAM;YACV,CAAC;YACD,KAAK,aAAa;gBACd,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;gBAChD,MAAM;YACV,KAAK,QAAQ;gBACT,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBAC/B,OAAO,CAAC,wBAAwB;YACpC,KAAK,KAAK;gBACN,KAAK,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBACnD,KAAK,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBAC5C,MAAM;YACV,KAAK,KAAK;gBACN,KAAK,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;gBAC7D,MAAM;YACV,KAAK,OAAO;gBACR,KAAK,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBACvC,MAAM;YACV,KAAK,MAAM;gBACP,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,2BAA2B,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;oBAC9D,KAAK,IAAI,CAAC,QAAQ,CAAC,wBAAwB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;gBACjE,CAAC;gBACD,MAAM;YACV,KAAK,WAAW;gBACZ,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;gBAClE,MAAM;QACd,CAAC;QACD,IAAI,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC;IAEO,cAAc,CAAC,KAAa;QAChC,MAAM,IAAI,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QACrG,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC;IAED,wEAAwE;IAChE,KAAK,CAAC,aAAa,CAAC,SAAiB;QACzC,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAChF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,CAAC;QACtE,IAAI,IAAI,EAAE,CAAC;YACP,sEAAsE;YACtE,sEAAsE;YACtE,uEAAuE;YACvE,qEAAqE;YACrE,6DAA6D;YAC7D,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE;gBAClD,KAAK,EAAE,SAAS;gBAChB,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;aACpC,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED,kEAAkE;IAClE,kBAAkB;IAClB,kEAAkE;IAE1D,eAAe;QACnB,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,OAAO;QACX,CAAC;QACD,yEAAyE;QACzE,yEAAyE;QACzE,sEAAsE;QACtE,8DAA8D;QAC9D,KAAK,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC;QACtC,wEAAwE;QACxE,qEAAqE;QACrE,gEAAgE;QAChE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,EAAE;YACvE,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzC,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;YAC5B,CAAC;QACL,CAAC,CAAC,CAAC;QACH,oBAAoB,EAAE,CAAC;QACvB,IAAI,CAAC,SAAS,GAAG,wBAAwB,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG;YACZ,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,IAAI,EAAE,IAAI,CAAC,UAAU;YACrB,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,UAAU,EAAE,IAAI,CAAC,UAAU;SAC9B,CAAC;QACF,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACpC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACzB,IAAI,QAAQ,CAAC,WAAW,KAAK,EAAE,EAAE,CAAC;gBAC9B,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,IAAI,QAAQ,CAAC;YAC5D,CAAC;iBAAM,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;gBACnD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;YACvD,CAAC;QACL,CAAC;IACL,CAAC;IAEO,QAAQ;QACZ,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI,EAAE,CAAC;YAC9B,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAClC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC/B,CAAC;QACD,MAAM,UAAU,GAAG,EAAE,IAAI,CAAC,eAAe,CAAC;QAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC;QACrC,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC;QAClC,MAAM,aAAa,GAAG,IAAI,CAAC,iBAAiB,KAAK,EAAE,CAAC;QAEpD,IAAI,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;YAC7D,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC;YACf,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;YACvB,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,iBAAiB,CAAC;YAClD,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;YACxB,OAAO;QACX,CAAC;QAED,kFAAkF;QAClF,6EAA6E;QAC7E,IAAI,IAAI,CAAC,iBAAiB,KAAK,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACtD,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC;QACnB,CAAC;QAED,mFAAmF;QACnF,sDAAsD;QACtD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC;QACxC,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAExB,6EAA6E;QAC7E,kFAAkF;QAClF,0BAA0B;QAC1B,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;QAC3E,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC;IACrG,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,QAAyB,EAAE,KAAa,EAAE,UAAkB;QACvF,MAAM,OAAO,GAAG;YACZ,KAAK,EAAE,KAAK;YACZ,UAAU,EAAE,WAAW;YACvB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,QAAQ,EAAE,IAAI;SACjB,CAAC;QACF,6EAA6E;QAC7E,2DAA2D;QAC3D,IAAI,WAAW,GAAwB,EAAE,CAAC;QAC1C,IAAI,CAAC;YACD,WAAW,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;gBACnC,CAAC,CAAC,MAAM,QAAQ,CAAC,qBAAqB,CAAC,OAAO,CAAC;gBAC/C,CAAC,CAAC,MAAM,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QACjD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,QAAQ,CAAC,CAAC,CAAC,CAAC;QAChB,CAAC;QACD,IAAI,UAAU,KAAK,IAAI,CAAC,eAAe,EAAE,CAAC;YACtC,OAAO,CAAC,mDAAmD;QAC/D,CAAC;QACD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACrC,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,iBAAiB,CAAC;QAClD,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC5B,CAAC;IAEO,MAAM,CAAC,WAAgC;QAC3C,8DAA8D;QAC9D,IAAI,aAAa,GAAG,EAAE,CAAC;QACvB,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACzB,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAY,CAAC,CAAC,CAAC,EAAE,CAAC;YACvF,MAAM,UAAU,GAAG,KAAK,KAAK,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;YAC1D,aAAa,GAAG,KAAK,CAAC;YACtB,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAY,CAAC,CAAC,CAAC,IAAI,CAAC;YACzF,OAAO;gBACH,UAAU,EAAE,CAAC;gBACb,UAAU,EAAE,UAAU;gBACtB,YAAY,EAAE,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI;aACzF,CAAC;QACN,CAAC,CAAC,CAAC;IACP,CAAC;IAEO,KAAK,CAAC,UAAU;QACpB,IAAI,CAAC;YACD,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;YAC7C,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACL,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACrB,CAAC;IACL,CAAC;IAED,wEAAwE;IAChE,KAAK,CAAC,WAAW;QACrB,MAAM,IAAI,GAAiB,EAAE,CAAC;QAC9B,IAAI,CAAC;YACD,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACrE,KAAK,MAAM,MAAM,IAAI,cAAc,EAAE,CAAC;gBAClC,IAAI,CAAC,IAAI,CAAC;oBACN,UAAU,EAAE;wBACR,IAAI,EAAE,QAAQ;wBACd,EAAE,EAAE,iBAAiB,MAAM,CAAC,KAAK,EAAE;wBACnC,IAAI,EAAE,MAAM,CAAC,KAAK;wBAClB,WAAW,EAAE,MAAM,CAAC,KAAK;wBACzB,WAAW,EAAE,eAAe;wBAC5B,IAAI,EAAE,+BAA+B;wBACrC,IAAI,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,EAAE;qBACzD;oBACD,UAAU,EAAE,IAAI;oBAChB,YAAY,EAAE,IAAI;iBACrB,CAAC,CAAC;YACP,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACL,mDAAmD;QACvD,CAAC;QACD,IAAI,CAAC;YACD,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAChD,IAAI,eAAe,EAAE,CAAC;gBAClB,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC,qBAAqB,CAAC;oBACrD,KAAK,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI;iBAC1E,CAAC,CAAC;gBACH,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAC7F,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACL,QAAQ;QACZ,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC5B,CAAC;IAED,IAAY,WAAW;QACnB,OAAO,QAAQ,CAAC,QAAQ,EAAE,WAAW,IAAI,IAAI,CAAC,CAAC,mGAAmG;IACtJ,CAAC;iHAnlBQ,uBAAuB;6DAAvB,uBAAuB;;;;;;YC5DpC,iFAAc;;YAAd,qCA4HC;;;iFDhEY,uBAAuB;cAPnC,SAAS;6BACM,KAAK,YACP,oBAAoB,mBAGb,uBAAuB,CAAC,MAAM;;kBAW9C,SAAS;mBAAC,cAAc;;kBAaxB,MAAM;;kBACN,MAAM;;kBAIN,MAAM;;kFA3BE,uBAAuB;AAslBpC,oDAAoD;AACpD,MAAM,UAAU,2BAA2B;IACvC,oBAAoB;AACxB,CAAC","sourcesContent":["import {\n ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter,\n OnDestroy, Output, ViewChild, inject,\n} from '@angular/core';\nimport { CompositeKey, LogError, UserInfo } from '@memberjunction/core';\nimport { Metadata } from '@memberjunction/core';\nimport { MentionSuggestion } from '@memberjunction/ng-composer';\nimport { NavigationService } from '@memberjunction/ng-shared';\nimport { ApplicationManager } from '@memberjunction/ng-base-application';\nimport { SearchService, SearchScopeInfo } from '@memberjunction/ng-search';\nimport { FileOpenService } from '@memberjunction/ng-file-storage';\nimport { Subscription, firstValueFrom, skip } from 'rxjs';\nimport { CommandPaletteService } from '../command-palette/command-palette.service';\nimport {\n DiscoverOmnibarProviders, GetOmnibarNavPayload, OmnibarProvider,\n} from './omnibar-provider';\nimport { LoadOmnibarProviders } from './index';\n\n/** One rendered result row: the suggestion + presentation extras. */\ninterface OmnibarRow {\n Suggestion: MentionSuggestion;\n /**\n * Section header before this row, set where the group changes: the group name, '' for the\n * empty spacer before an ungrouped row that follows a group (the \"see all\" row), or null\n * for no header. A group that comes back after another group gets its header again.\n */\n GroupLabel: string | null;\n /** 0-100 relevance bar (search mode only). */\n ScorePercent: number | null;\n}\n\n/** Debounce for the default (network-backed) search mode; trigger modes serve warm caches. */\nconst SEARCH_DEBOUNCE_MS = 300;\n\n/**\n * Debounce for trigger modes (e.g. '#' jump-to-record). Entity-name matching is in-memory,\n * but the record-suggestion path issues a RunView per keystroke — firing on every character\n * floods MJAPI during a typing burst. A short debounce collapses rapid typing into a single\n * backend query while keeping the picker responsive.\n */\nconst TRIGGER_DEBOUNCE_MS = 150;\n\n/** Max suggestions requested per keystroke. */\nconst MAX_RESULTS = 9;\n\n/**\n * The unified Explorer command palette (Ctrl/Cmd+K): one surface for global\n * cross-source search (plain text), jump-to-record ('#'), commands & apps ('/'),\n * and agents ('@') — every mode a pluggable {@link OmnibarProvider}, discovered via\n * the MJ ClassFactory so OpenApps can add modes without touching this component.\n *\n * Design source of truth: plans/composer-adoption/mockups/omnibar-command-palette.html.\n */\n@Component({\n standalone: false,\n selector: 'mj-omnibar-palette',\n templateUrl: './omnibar-palette.component.html',\n styleUrls: ['./omnibar-palette.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class OmnibarPaletteComponent implements OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n private host = inject<ElementRef<HTMLElement>>(ElementRef);\n private navigation = inject(NavigationService);\n private appManager = inject(ApplicationManager);\n private search = inject(SearchService);\n private paletteService = inject(CommandPaletteService);\n private fileOpen = inject(FileOpenService);\n\n @ViewChild('paletteInput') private inputRef?: ElementRef<HTMLInputElement>;\n\n /** Palette visibility (open via {@link Open}; Escape/backdrop close). */\n public IsOpen = false;\n /** Raw input text including any leading trigger char. */\n public Query = '';\n public Rows: OmnibarRow[] = [];\n public RecentRows: OmnibarRow[] = [];\n public SelectedIndex = 0;\n public IsLoading = false;\n public Scopes: SearchScopeInfo[] = [];\n public SelectedScopeIDs: string[] = [];\n\n @Output() Opened = new EventEmitter<void>();\n @Output() Closed = new EventEmitter<void>();\n /** Footer gear clicked — the host opens its settings surface (Explorer: My\n Profile, where the Command Palette opt-in section lives). The palette\n closes first so the settings dialog isn't buried under it. */\n @Output() SettingsRequested = new EventEmitter<void>();\n\n private providers: OmnibarProvider[] = [];\n private defaultProvider: OmnibarProvider | null = null;\n private byTrigger = new Map<string, OmnibarProvider>();\n private queryGeneration = 0;\n /** Trigger char of the provider that produced the current {@link Rows}. */\n private renderedTriggerChar = '';\n private debounceHandle: ReturnType<typeof setTimeout> | null = null;\n /** Element focused before the palette opened — restored on close (a11y). */\n private previousFocus: HTMLElement | null = null;\n private recentsSub: Subscription | null = null;\n\n // ---------------------------------------------------------------\n // Derived view state\n // ---------------------------------------------------------------\n\n /** The active trigger char ('' = default/global-search mode). */\n public get ActiveTriggerChar(): string {\n const first = this.Query.charAt(0);\n return this.byTrigger.has(first) ? first : '';\n }\n\n /** Query text with the trigger char stripped. */\n public get EffectiveQuery(): string {\n return this.ActiveTriggerChar ? this.Query.substring(1) : this.Query;\n }\n\n public get ActiveModeLabel(): string {\n return this.activeProvider?.ModeLabel ?? 'Search';\n }\n\n public get ActivePlaceholder(): string {\n return this.activeProvider?.Placeholder ?? 'Search everything — or type #, /, @ …';\n }\n\n /** Scope pills only apply to the cross-source search mode. */\n public get ShowScopes(): boolean {\n return this.ActiveTriggerChar === '' && this.EffectiveQuery.trim().length > 0;\n }\n\n /** Footer gear: close, then let the host present its settings surface. */\n public RequestSettings(): void {\n this.Close();\n this.SettingsRequested.emit();\n }\n\n /** Hint chips for the empty state — one per non-default provider. */\n public get TriggerHints(): Array<{ Char: string; Label: string }> {\n return this.providers\n .filter((p) => p.TriggerChar !== '')\n .map((p) => ({ Char: p.TriggerChar, Label: p.ModeLabel }));\n }\n\n /** RecentRows render after the hint bar; selection indexes continue into them. */\n public get RecentBaseIndex(): number {\n return 0;\n }\n\n private get activeProvider(): OmnibarProvider | null {\n const char = this.ActiveTriggerChar;\n return char ? (this.byTrigger.get(char) ?? null) : this.defaultProvider;\n }\n\n /**\n * Rows that keyboard selection may target: only rendered rows. {@link RecentRows}\n * render only in the empty-query state, so they are selectable only then.\n */\n private get selectableRows(): OmnibarRow[] {\n if (this.Rows.length > 0) {\n return this.Rows;\n }\n return this.Query.length === 0 ? this.RecentRows : [];\n }\n\n /**\n * Whether <kbd>Enter</kbd> on a palette with no rows may open the full Search Results\n * workspace for the typed text. Drives both the key handler and the empty-state wording.\n *\n * Default mode always allows it, because full search is that mode's own action. A trigger\n * mode allows it only after its fetch settles, because there full search is a different\n * action from what the rows offer (switch app, open record).\n */\n public get CanEscapeToFullSearch(): boolean {\n if (this.EffectiveQuery.trim().length <= 1) {\n return false;\n }\n return this.ActiveTriggerChar === '' || !this.IsLoading;\n }\n\n /**\n * ARIA combobox wiring: the input keeps DOM focus while this points at the\n * virtually-highlighted option row, so screen readers announce selection moves.\n */\n public get ActiveDescendantId(): string | null {\n return this.selectableRows.length > 0 ? `ob-opt-${this.SelectedIndex}` : null;\n }\n\n /** Whether any option rows exist — drives the combobox's aria-expanded. */\n public get HasOptions(): boolean {\n return this.selectableRows.length > 0;\n }\n\n // ---------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------\n\n /** Opens the palette, optionally pre-seeded (e.g. '/' from the legacy Ctrl+/ path). */\n public Open(initialQuery = ''): void {\n this.ensureProviders();\n this.previousFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null;\n this.IsOpen = true;\n this.Query = initialQuery;\n this.Rows = [];\n this.SelectedIndex = 0;\n // The empty row set we just installed belongs to no mode, so the first fetch is\n // correctly seen as a mode change.\n this.renderedTriggerChar = '';\n void this.loadScopes();\n void this.loadRecents();\n if (initialQuery.length > 0) {\n this.runQuery();\n }\n this.Opened.emit();\n this.cdr.markForCheck();\n // Input mounts via @if — focus next tick.\n setTimeout(() => this.inputRef?.nativeElement.focus(), 30);\n }\n\n public Close(): void {\n if (!this.IsOpen) {\n return;\n }\n this.IsOpen = false;\n this.Query = '';\n this.Rows = [];\n this.Closed.emit();\n this.cdr.markForCheck();\n // Return focus to where the user was (skip if that element left the DOM).\n if (this.previousFocus?.isConnected) {\n this.previousFocus.focus();\n }\n this.previousFocus = null;\n }\n\n public Toggle(initialQuery = ''): void {\n if (this.IsOpen) {\n this.Close();\n } else {\n this.Open(initialQuery);\n }\n }\n\n ngOnDestroy(): void {\n if (this.debounceHandle != null) {\n clearTimeout(this.debounceHandle);\n }\n this.recentsSub?.unsubscribe();\n }\n\n // ---------------------------------------------------------------\n // Input handling\n // ---------------------------------------------------------------\n\n public OnQueryChange(value: string): void {\n this.Query = value;\n this.SelectedIndex = 0;\n this.runQuery();\n }\n\n public OnInputKeydown(event: KeyboardEvent): void {\n const rows = this.selectableRows;\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n this.moveSelection(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n this.moveSelection(-1);\n break;\n case 'Enter': {\n event.preventDefault();\n const row = rows[this.SelectedIndex];\n if (row) {\n this.Execute(row.Suggestion);\n } else if (this.CanEscapeToFullSearch) {\n this.openFullSearch(this.EffectiveQuery.trim());\n }\n break;\n }\n }\n }\n\n /**\n * Dialog-level keys (bubbled from anywhere inside the palette):\n * - Escape closes from any focused element, not just the input.\n * - Tab follows the natural visual order — input → scope pills → mode chips →\n * the selected result row (roving tabindex) — and TRAPS at the ends so focus\n * cycles inside the dialog instead of escaping to the page underneath.\n * (Design review: Tab must reach the three mode chips, not skip them.)\n */\n public OnPaletteKeydown(event: KeyboardEvent): void {\n if (event.key === 'Escape') {\n event.preventDefault();\n this.Close();\n return;\n }\n if (event.key !== 'Tab') {\n return;\n }\n // On a result row, Tab / Shift+Tab step through the RESULTS themselves\n // (mirrors ArrowDown/Up) until walking off either end of the list — then\n // the trap logic below takes over. Same model as mj-search-overlay.\n const activeEl = document.activeElement as HTMLElement | null;\n if (activeEl?.classList.contains('ob-row')) {\n const last = this.selectableRows.length - 1;\n if (!event.shiftKey && this.SelectedIndex < last) {\n event.preventDefault();\n this.moveSelection(1, true);\n return;\n }\n if (event.shiftKey && this.SelectedIndex > 0) {\n event.preventDefault();\n this.moveSelection(-1, true);\n return;\n }\n // At either end: fall through so Tab leaves the list naturally.\n }\n const root = this.host.nativeElement.querySelector('.omnibar-palette') as HTMLElement | null;\n if (!root) {\n return;\n }\n const focusables = Array.from(root.querySelectorAll<HTMLElement>('input, button, .ob-row[tabindex=\"0\"]'))\n .filter((el) => el.offsetParent !== null);\n if (focusables.length === 0) {\n return;\n }\n const active = document.activeElement as HTMLElement | null;\n if (!event.shiftKey && active === focusables[focusables.length - 1]) {\n event.preventDefault();\n focusables[0].focus();\n } else if (event.shiftKey && active === focusables[0]) {\n event.preventDefault();\n focusables[focusables.length - 1].focus();\n }\n }\n\n /** Keys on a focused result row (rows are real focus stops via roving tabindex). */\n public OnRowKeydown(event: KeyboardEvent, suggestion: MentionSuggestion): void {\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n this.moveSelection(1, true);\n break;\n case 'ArrowUp':\n event.preventDefault();\n this.moveSelection(-1, true);\n break;\n case 'Enter':\n event.preventDefault();\n this.Execute(suggestion);\n break;\n }\n }\n\n /**\n * Keyboard-driven selection move: wraps at both ends (standard picker behavior)\n * and keeps the highlighted row visible. Mouse hover sets SelectedIndex directly\n * in the template and deliberately does NOT scroll — auto-scrolling under the\n * pointer would fight the user's hand. When the move originates from a focused\n * row (roving tabindex), DOM focus follows the selection.\n */\n private moveSelection(delta: 1 | -1, focusRow = false): void {\n const count = this.selectableRows.length;\n if (count === 0) {\n return;\n }\n this.SelectedIndex = (this.SelectedIndex + delta + count) % count;\n this.cdr.markForCheck();\n const row = this.host.nativeElement.querySelector<HTMLElement>(`#ob-opt-${this.SelectedIndex}`);\n row?.scrollIntoView({ block: 'nearest' });\n if (focusRow) {\n row?.focus();\n }\n }\n\n /** Hint-chip click: seed the trigger char and refocus. */\n public SeedTrigger(char: string): void {\n this.Query = char;\n this.SelectedIndex = 0;\n this.runQuery();\n this.inputRef?.nativeElement.focus();\n }\n\n // ---------------------------------------------------------------\n // Scopes\n // ---------------------------------------------------------------\n\n public IsScopeSelected(id: string): boolean {\n return this.SelectedScopeIDs.includes(id);\n }\n\n public ToggleScope(id: string): void {\n this.SelectedScopeIDs = this.IsScopeSelected(id)\n ? this.SelectedScopeIDs.filter((s) => s !== id)\n : [...this.SelectedScopeIDs, id];\n this.cdr.markForCheck();\n }\n\n public ClearScopes(): void {\n this.SelectedScopeIDs = [];\n this.cdr.markForCheck();\n }\n\n // ---------------------------------------------------------------\n // Execution\n // ---------------------------------------------------------------\n\n /**\n * Executes a suggestion: navigate per its payload, or re-seed for entity drill-in.\n *\n * Not blocked while a fetch is pending: every activation path targets a rendered row,\n * because {@link selectableRows} offers only rendered rows and a mode change clears\n * {@link Rows}.\n */\n public Execute(suggestion: MentionSuggestion): void {\n const nav = GetOmnibarNavPayload(suggestion);\n if (!nav) {\n return; // foreign suggestion with no navigation — nothing to execute\n }\n // Default-mode queries count as \"searches\" even when the user executes a\n // suggestion that navigates directly (no full ExecuteSearch downstream to\n // record them). Trigger-mode fragments ('#accounts ac…') are NOT searches —\n // recording those would pollute recents. 'search' payloads skip too: the\n // results page records them with the real result count.\n const typed = this.EffectiveQuery.trim();\n if (this.ActiveTriggerChar === '' && typed.length > 0 && nav.kind !== 'search') {\n this.search.RecordRecentSearch(typed);\n }\n switch (nav.kind) {\n case 'record': {\n // `recordId` is a compact CompositeKey segment (bare value for a single-column key,\n // \"F1|v1||F2|v2\" for a composite one) on an ARBITRARY entity, so the key column can\n // have any name. `FromID` hardcoded `ID` and broke record-open for every entity whose\n // key is called something else; resolve against the entity's metadata instead.\n const entityInfo = this.search.Provider.EntityByName(nav.entityName);\n this.navigation.OpenEntityRecord(nav.entityName, CompositeKey.FromURLSegment(entityInfo, nav.recordId));\n break;\n }\n case 'entity-list':\n this.navigation.OpenDynamicView(nav.entityName);\n break;\n case 'search':\n this.openFullSearch(nav.query);\n return; // openFullSearch closes\n case 'app':\n void this.paletteService.TrackAppAccess(nav.appId);\n void this.navigation.SwitchToApp(nav.appId);\n break;\n case 'nav':\n void this.navigation.SwitchToApp(nav.appId, nav.navItemName);\n break;\n case 'agent':\n void this.openAgentChat(nav.agentName);\n break;\n case 'file':\n if (!this.fileOpen.OpenPreviewFromSearchResult(nav.rawMetadata)) {\n void this.fileOpen.OpenFileFromSearchResult(nav.rawMetadata);\n }\n break;\n case 'dashboard':\n this.navigation.OpenDashboard(nav.dashboardId, nav.dashboardName);\n break;\n }\n this.Close();\n }\n\n private openFullSearch(query: string): void {\n const opts = this.SelectedScopeIDs.length > 0 ? { scopeIDs: [...this.SelectedScopeIDs] } : undefined;\n this.navigation.OpenSearch(query, opts);\n this.Close();\n }\n\n /** '@' selection: switch to the Chat app pre-addressed to the agent. */\n private async openAgentChat(agentName: string): Promise<void> {\n const apps = await firstValueFrom(this.appManager.Applications).catch(() => []);\n const chat = apps.find((a) => a.Name.trim().toLowerCase() === 'chat');\n if (chat) {\n // agentReq is a one-shot request nonce: the chat wrapper applies each\n // agent|nonce instruction exactly once, so URL↔tab-config sync echoes\n // of an already-consumed param can never re-stage the pre-address (and\n // wipe an in-progress composer draft), while a genuine re-tag of the\n // SAME agent still applies because it carries a fresh nonce.\n await this.navigation.SwitchToApp(chat.ID, undefined, {\n agent: agentName,\n agentReq: Date.now().toString(36),\n });\n }\n }\n\n // ---------------------------------------------------------------\n // Query execution\n // ---------------------------------------------------------------\n\n private ensureProviders(): void {\n if (this.providers.length > 0) {\n return;\n }\n // Kick off the persisted-recents load (idempotent; resolves via LoggedIn\n // replay). The legacy search composite used to be the only caller — with\n // the omnibar enabled it never renders, so prior-session recents were\n // invisible until the palette started requesting them itself.\n void this.search.LoadRecentSearches();\n // Refresh the empty-state Recent rows whenever recents change while the\n // palette is idle-open (skip(1): BehaviorSubject replays its current\n // value on subscribe, which loadRecents already read directly).\n this.recentsSub = this.search.RecentSearches$.pipe(skip(1)).subscribe(() => {\n if (this.IsOpen && this.Query.length === 0) {\n void this.loadRecents();\n }\n });\n LoadOmnibarProviders();\n this.providers = DiscoverOmnibarProviders();\n const context = {\n Search: this.search,\n Apps: this.appManager,\n PaletteService: this.paletteService,\n Navigation: this.navigation,\n };\n for (const provider of this.providers) {\n provider.Attach(context);\n if (provider.TriggerChar === '') {\n this.defaultProvider = this.defaultProvider ?? provider;\n } else if (!this.byTrigger.has(provider.TriggerChar)) {\n this.byTrigger.set(provider.TriggerChar, provider);\n }\n }\n }\n\n private runQuery(): void {\n if (this.debounceHandle != null) {\n clearTimeout(this.debounceHandle);\n this.debounceHandle = null;\n }\n const generation = ++this.queryGeneration;\n const provider = this.activeProvider;\n const query = this.EffectiveQuery;\n const isTriggerMode = this.ActiveTriggerChar !== '';\n\n if (!provider || (query.trim().length === 0 && !isTriggerMode)) {\n this.Rows = [];\n this.IsLoading = false;\n this.renderedTriggerChar = this.ActiveTriggerChar;\n this.cdr.markForCheck();\n return;\n }\n\n // A mode change clears the rows, because a different provider answers a different\n // question. Rows for the same mode stay on screen while the next fetch runs.\n if (this.ActiveTriggerChar !== this.renderedTriggerChar) {\n this.Rows = [];\n }\n\n // In every mode, show the spinner while no rows are on screen, so the \"No matches\"\n // empty state appears only after a fetch has settled.\n this.IsLoading = this.Rows.length === 0;\n this.cdr.markForCheck();\n\n // Shorter debounce in trigger mode: entity matching is in-memory, but record\n // suggestions issue a RunView per keystroke — debouncing collapses a typing burst\n // into one backend query.\n const fire = () => void this.fetchSuggestions(provider, query, generation);\n this.debounceHandle = setTimeout(fire, isTriggerMode ? TRIGGER_DEBOUNCE_MS : SEARCH_DEBOUNCE_MS);\n }\n\n private async fetchSuggestions(provider: OmnibarProvider, query: string, generation: number): Promise<void> {\n const request = {\n Query: query,\n MaxResults: MAX_RESULTS,\n ContextUser: this.currentUser,\n Provider: null,\n };\n // A failed fetch still settles this generation, so the spinner clears and no\n // rejection escapes the `void fetchSuggestions(...)` call.\n let suggestions: MentionSuggestion[] = [];\n try {\n suggestions = query.trim().length === 0\n ? await provider.EmptyStateSuggestions(request)\n : await provider.GetSuggestions(request);\n } catch (e) {\n LogError(e);\n }\n if (generation !== this.queryGeneration) {\n return; // stale response — a newer keystroke superseded it\n }\n this.Rows = this.toRows(suggestions);\n this.SelectedIndex = 0;\n this.IsLoading = false;\n this.renderedTriggerChar = this.ActiveTriggerChar;\n this.cdr.markForCheck();\n }\n\n private toRows(suggestions: MentionSuggestion[]): OmnibarRow[] {\n // '' = ungrouped, so ungrouped rows at the top get no header.\n let previousGroup = '';\n return suggestions.map((s) => {\n const group = typeof s.data?.['group'] === 'string' ? (s.data['group'] as string) : '';\n const groupLabel = group !== previousGroup ? group : null;\n previousGroup = group;\n const score = typeof s.data?.['score'] === 'number' ? (s.data['score'] as number) : null;\n return {\n Suggestion: s,\n GroupLabel: groupLabel,\n ScorePercent: score != null ? Math.round(Math.max(0, Math.min(1, score)) * 100) : null,\n };\n });\n }\n\n private async loadScopes(): Promise<void> {\n try {\n this.Scopes = await this.search.LoadScopes();\n this.cdr.markForCheck();\n } catch {\n this.Scopes = [];\n }\n }\n\n /** Empty-state recents: recent searches + recent apps (best-effort). */\n private async loadRecents(): Promise<void> {\n const rows: OmnibarRow[] = [];\n try {\n const recentSearches = this.search.RecentSearches$.value.slice(0, 3);\n for (const recent of recentSearches) {\n rows.push({\n Suggestion: {\n type: 'search',\n id: `recent-search:${recent.Query}`,\n name: recent.Query,\n displayName: recent.Query,\n description: 'Recent search',\n icon: 'fa-solid fa-clock-rotate-left',\n data: { nav: { kind: 'search', query: recent.Query } },\n },\n GroupLabel: null,\n ScorePercent: null,\n });\n }\n } catch {\n // recents are decorative — never block the palette\n }\n try {\n const commandProvider = this.byTrigger.get('/');\n if (commandProvider) {\n const apps = await commandProvider.EmptyStateSuggestions({\n Query: '', MaxResults: 3, ContextUser: this.currentUser, Provider: null,\n });\n rows.push(...apps.map((s) => ({ Suggestion: s, GroupLabel: null, ScorePercent: null })));\n }\n } catch {\n // ditto\n }\n this.RecentRows = rows;\n this.cdr.markForCheck();\n }\n\n private get currentUser(): UserInfo | null {\n return Metadata.Provider?.CurrentUser ?? null; // global-provider-ok: Explorer shell palette is app chrome bound to the session's default provider\n }\n}\n\n/** Tree-shaking guard for the palette component. */\nexport function LoadOmnibarPaletteComponent(): void {\n // intentional no-op\n}\n","@if (IsOpen) {\n <div class=\"omnibar-overlay\" (click)=\"Close()\"></div>\n <div class=\"omnibar-palette\" role=\"dialog\" aria-modal=\"true\" aria-label=\"Command palette\"\n (keydown)=\"OnPaletteKeydown($event)\">\n\n <div class=\"ob-input-row\">\n <div class=\"ob-field\">\n <span class=\"ob-lead\" [class.ob-lead--trigger]=\"ActiveTriggerChar.length > 0\">\n @if (ActiveTriggerChar.length > 0) {\n <b>{{ ActiveTriggerChar }}</b>\n } @else {\n <i class=\"fa-solid fa-magnifying-glass\"></i>\n }\n </span>\n <input #paletteInput class=\"ob-input\" type=\"text\" autocomplete=\"off\" spellcheck=\"false\"\n role=\"combobox\" aria-controls=\"ob-listbox\" aria-autocomplete=\"list\"\n [attr.aria-expanded]=\"HasOptions\"\n [attr.aria-activedescendant]=\"ActiveDescendantId\"\n [placeholder]=\"ActivePlaceholder\"\n [ngModel]=\"Query\" (ngModelChange)=\"OnQueryChange($event)\"\n (keydown)=\"OnInputKeydown($event)\" />\n <span class=\"ob-mode-badge\">{{ ActiveModeLabel }}</span>\n <kbd class=\"ob-kbd\">esc</kbd>\n </div>\n <button type=\"button\" class=\"ob-close\" aria-label=\"Close\" title=\"Close\" (click)=\"Close()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n\n @if (ShowScopes && Scopes.length > 0) {\n <div class=\"ob-scopes\">\n <button type=\"button\" class=\"ob-scope\" [class.ob-scope--on]=\"SelectedScopeIDs.length === 0\"\n (click)=\"ClearScopes()\">All sources</button>\n @for (scope of Scopes; track scope.ID) {\n <button type=\"button\" class=\"ob-scope\" [class.ob-scope--on]=\"IsScopeSelected(scope.ID)\"\n (click)=\"ToggleScope(scope.ID)\">{{ scope.Name }}</button>\n }\n </div>\n }\n\n <div class=\"ob-body\">\n @if (IsLoading) {\n <div class=\"ob-loading\"><i class=\"fa-solid fa-circle-notch fa-spin\"></i> Searching…</div>\n } @else if (Rows.length === 0 && Query.length === 0) {\n <div class=\"ob-hintbar\">\n @for (hint of TriggerHints; track hint.Char) {\n <button type=\"button\" class=\"ob-hint-chip\" (click)=\"SeedTrigger(hint.Char)\">\n <b>{{ hint.Char }}</b><span>{{ hint.Label }}</span>\n </button>\n }\n </div>\n @if (RecentRows.length > 0) {\n <div class=\"ob-group-label\" role=\"presentation\">Recent</div>\n <div id=\"ob-listbox\" role=\"listbox\" aria-label=\"Suggestions\">\n @for (row of RecentRows; track row.Suggestion.id; let i = $index) {\n <div class=\"ob-row\" role=\"option\" [attr.id]=\"'ob-opt-' + (RecentBaseIndex + i)\"\n [attr.tabindex]=\"RecentBaseIndex + i === SelectedIndex ? 0 : -1\"\n [attr.aria-selected]=\"RecentBaseIndex + i === SelectedIndex\"\n [class.ob-row--sel]=\"RecentBaseIndex + i === SelectedIndex\"\n (focus)=\"SelectedIndex = RecentBaseIndex + i\"\n (keydown)=\"OnRowKeydown($event, row.Suggestion)\"\n (mouseenter)=\"SelectedIndex = RecentBaseIndex + i\" (click)=\"Execute(row.Suggestion)\">\n <span class=\"ob-ric\"><i [class]=\"row.Suggestion.icon || 'fa-solid fa-clock-rotate-left'\"></i></span>\n <span class=\"ob-rmain\">\n <span class=\"ob-rname\">{{ row.Suggestion.displayName }}</span>\n <span class=\"ob-rsub\">{{ row.Suggestion.description }}</span>\n </span>\n <span class=\"ob-raux\"><span class=\"ob-rtype\">{{ row.Suggestion.type }}</span></span>\n </div>\n }\n </div>\n }\n } @else if (Rows.length === 0) {\n <!-- Only promise the Enter escape hatch when Enter will actually take it —\n CanEscapeToFullSearch gates both, so the two can't drift apart. It's false for\n a 1-char query, and in a trigger mode until the fetch settles. -->\n @if (CanEscapeToFullSearch) {\n <div class=\"ob-empty\">No matches — press <kbd class=\"ob-kbd\">↵</kbd> to search everything for “{{ EffectiveQuery }}”.</div>\n } @else {\n <div class=\"ob-empty\">No matches for “{{ EffectiveQuery }}”.</div>\n }\n } @else {\n <div id=\"ob-listbox\" role=\"listbox\" aria-label=\"Suggestions\">\n @for (row of Rows; track row.Suggestion.id; let i = $index) {\n @if (row.GroupLabel !== null) {\n <div class=\"ob-group-label\" role=\"presentation\">{{ row.GroupLabel }}</div>\n }\n <div class=\"ob-row\" role=\"option\" [attr.id]=\"'ob-opt-' + i\"\n [attr.tabindex]=\"i === SelectedIndex ? 0 : -1\"\n [attr.aria-selected]=\"i === SelectedIndex\"\n [class.ob-row--sel]=\"i === SelectedIndex\"\n (focus)=\"SelectedIndex = i\"\n (keydown)=\"OnRowKeydown($event, row.Suggestion)\"\n (mouseenter)=\"SelectedIndex = i\" (click)=\"Execute(row.Suggestion)\">\n <span class=\"ob-ric\"><i [class]=\"row.Suggestion.icon || 'fa-solid fa-circle'\"></i></span>\n <span class=\"ob-rmain\">\n <span class=\"ob-rname\">{{ row.Suggestion.displayName }}</span>\n @if (row.Suggestion.description) {\n <span class=\"ob-rsub\">{{ row.Suggestion.description }}</span>\n }\n </span>\n <span class=\"ob-raux\">\n @if (row.ScorePercent != null) {\n <span class=\"ob-score\"><i [style.width.%]=\"row.ScorePercent\"></i></span>\n }\n <span class=\"ob-rtype\">{{ row.Suggestion.type }}</span>\n <span class=\"ob-go\">open <kbd class=\"ob-kbd\">↵</kbd></span>\n </span>\n </div>\n }\n </div>\n }\n </div>\n\n <div class=\"ob-foot\">\n <span class=\"ob-k\"><kbd class=\"ob-kbd\">↑</kbd><kbd class=\"ob-kbd\">↓</kbd> navigate</span>\n <span class=\"ob-k\"><kbd class=\"ob-kbd\">↵</kbd> open</span>\n <button type=\"button\" class=\"ob-settings\" aria-label=\"Command Palette settings\"\n title=\"Command Palette settings\" (click)=\"RequestSettings()\">\n <i class=\"fa-solid fa-gear\" aria-hidden=\"true\"></i>\n <span>Settings</span>\n </button>\n </div>\n </div>\n}\n"]}
|
|
@@ -35,6 +35,10 @@ export type OmnibarNavPayload = {
|
|
|
35
35
|
kind: 'file';
|
|
36
36
|
fileName: string;
|
|
37
37
|
rawMetadata?: string;
|
|
38
|
+
} | {
|
|
39
|
+
kind: 'dashboard';
|
|
40
|
+
dashboardId: string;
|
|
41
|
+
dashboardName: string;
|
|
38
42
|
};
|
|
39
43
|
/** Key under which the nav payload rides in `MentionSuggestion.data`. */
|
|
40
44
|
export declare const OMNIBAR_NAV_KEY = "nav";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"omnibar-provider.d.ts","sourceRoot":"","sources":["../../../src/lib/omnibar/omnibar-provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AACpH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AAExF;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GACvB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACxD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"omnibar-provider.d.ts","sourceRoot":"","sources":["../../../src/lib/omnibar/omnibar-provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AACpH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AAExF;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GACvB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACxD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACxD;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC;AAExE,yEAAyE;AACzE,eAAO,MAAM,eAAe,QAAQ,CAAC;AAErC,+EAA+E;AAC/E,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,iBAAiB,GAAG,iBAAiB,GAAG,IAAI,CAG5F;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC3B,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAC1B,cAAc,CAAC,EAAE,qBAAqB,CAAC;IACvC,UAAU,CAAC,EAAE,iBAAiB,CAAC;CAClC;AAED;;;;;;;;;;;;;;GAcG;AACH,8BAAsB,eAAgB,SAAQ,uBAAuB;IACjE,8EAA8E;IAC9E,kBAAyB,SAAS,EAAE,MAAM,CAAC;IAE3C,8EAA8E;IAC9E,SAAgB,WAAW,EAAE,MAAM,CAAqB;IAExD,SAAS,CAAC,OAAO,EAAE,cAAc,CAAM;IAEvC;;;;OAIG;IACI,MAAM,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAI5C;;;OAGG;IACU,qBAAqB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;CAIvG;AAKD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,eAAe,EAAE,CAkCnF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"omnibar-provider.js","sourceRoot":"","sources":["../../../src/lib/omnibar/omnibar-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAgD,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"omnibar-provider.js","sourceRoot":"","sources":["../../../src/lib/omnibar/omnibar-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import { MJGlobal } from '@memberjunction/global';\nimport { ComposerTriggerProvider, MentionSuggestion, ComposerSuggestionRequest } from '@memberjunction/ng-composer';\nimport type { NavigationService } from '@memberjunction/ng-shared';\nimport type { ApplicationManager } from '@memberjunction/ng-base-application';\nimport type { SearchService } from '@memberjunction/ng-search';\nimport type { CommandPaletteService } from '../command-palette/command-palette.service';\n\n/**\n * What selecting an omnibar suggestion DOES. Every {@link OmnibarProvider}\n * suggestion carries one of these in `MentionSuggestion.data['nav']`; the palette\n * executes it through the existing navigation seams (NavigationService et al.) —\n * providers never navigate themselves.\n */\nexport type OmnibarNavPayload =\n | { kind: 'record'; entityName: string; recordId: string }\n | { kind: 'search'; query: string; scopeIDs?: string[] }\n | { kind: 'app'; appId: string; appName: string }\n | { kind: 'nav'; appId: string; navItemName: string }\n | { kind: 'entity-list'; entityName: string }\n | { kind: 'agent'; agentName: string }\n | { kind: 'file'; fileName: string; rawMetadata?: string }\n | { kind: 'dashboard'; dashboardId: string; dashboardName: string };\n\n/** Key under which the nav payload rides in `MentionSuggestion.data`. */\nexport const OMNIBAR_NAV_KEY = 'nav';\n\n/** Convenience: read a suggestion's nav payload (null when absent/foreign). */\nexport function GetOmnibarNavPayload(suggestion: MentionSuggestion): OmnibarNavPayload | null {\n const nav = suggestion.data?.[OMNIBAR_NAV_KEY];\n return nav ? (nav as OmnibarNavPayload) : null;\n}\n\n/**\n * Angular-owned services the palette hands to providers before use. Providers are\n * ClassFactory-instantiated (no Angular DI), so anything injectable arrives here.\n * All members optional — a provider must degrade gracefully (return []) when a\n * dependency it needs wasn't supplied.\n */\nexport interface OmnibarContext {\n Search?: SearchService;\n Apps?: ApplicationManager;\n PaletteService?: CommandPaletteService;\n Navigation?: NavigationService;\n}\n\n/**\n * Pluggable mode for the Explorer command palette (the Ctrl+K omnibar).\n *\n * Registers under its OWN ClassFactory base — `@RegisterClass(OmnibarProvider, '<key>')`\n * — deliberately separate from the composer's `ComposerTriggerProvider` discovery, so\n * palette semantics (e.g. '#' = jump to a specific record) never leak into text\n * editors' mention discovery (where '#' means something else). The shape is shared\n * with the composer contract for consistency; the palette is the only consumer of\n * this base.\n *\n * `TriggerChar` conventions: '' (empty string) = the DEFAULT mode consulted when the\n * input has no trigger prefix (global search); any single char ('#', '/', '@', …)\n * claims that prefix. OpenApps extend the palette by registering additional\n * subclasses — no core changes required.\n */\nexport abstract class OmnibarProvider extends ComposerTriggerProvider {\n /** Human label for the palette's mode badge while this provider is active. */\n public abstract readonly ModeLabel: string;\n\n /** Placeholder shown in the input while this provider's trigger is active. */\n public readonly Placeholder: string = 'Type to search…';\n\n protected context: OmnibarContext = {};\n\n /**\n * Called by the palette after discovery, before any GetSuggestions call, with the\n * Angular services providers may need (ClassFactory construction has no DI).\n * Override to validate required members; keep it idempotent.\n */\n public Attach(context: OmnibarContext): void {\n this.context = context;\n }\n\n /**\n * Suggestions for the EMPTY query in this mode (recents, hints). Default: none.\n * The palette shows these when the trigger is active but nothing is typed yet.\n */\n public async EmptyStateSuggestions(request: ComposerSuggestionRequest): Promise<MentionSuggestion[]> {\n void request;\n return [];\n }\n}\n\n/** One shared instance per registered subclass (providers are stateless facades). */\nconst instanceCache = new Map<unknown, OmnibarProvider>();\n\n/**\n * Resolves every `@RegisterClass(OmnibarProvider, ...)` registration into a provider\n * list — highest-priority registration wins per key, results sorted by provider\n * `Priority` desc then `Key` asc. Returns [] gracefully when nothing is registered.\n */\nexport function DiscoverOmnibarProviders(excludedKeys?: string[]): OmnibarProvider[] {\n const factory = MJGlobal.Instance.ClassFactory;\n const registrations = factory.GetAllRegistrations(OmnibarProvider);\n if (!registrations || registrations.length === 0) {\n return [];\n }\n\n const excluded = new Set((excludedKeys ?? []).map((k) => k.trim().toLowerCase()));\n const seenKeys = new Set<string>();\n const providers: OmnibarProvider[] = [];\n\n for (const registration of registrations) {\n const normalizedKey = registration.Key?.trim().toLowerCase();\n if (!normalizedKey || seenKeys.has(normalizedKey) || excluded.has(normalizedKey)) {\n continue;\n }\n seenKeys.add(normalizedKey);\n\n // Winning registration per key — mirrors GetRegistration's priority semantics\n // (same pattern as DiscoverComposerTriggerProviders).\n const winner = factory.GetRegistration(OmnibarProvider, registration.Key);\n if (!winner?.SubClass) {\n continue;\n }\n let instance = instanceCache.get(winner.SubClass);\n if (!instance) {\n const ProviderConstructor = winner.SubClass as new () => OmnibarProvider;\n instance = new ProviderConstructor();\n instanceCache.set(winner.SubClass, instance);\n }\n providers.push(instance);\n }\n\n return providers.sort((a, b) => (b.Priority - a.Priority) || a.Key.localeCompare(b.Key));\n}\n"]}
|
|
@@ -14,8 +14,8 @@ export declare class OmnibarRecordProvider extends OmnibarProvider {
|
|
|
14
14
|
readonly ModeLabel = "Jump to Record";
|
|
15
15
|
readonly Placeholder = "Type an entity, then a record \u2014 e.g. #accounts acme";
|
|
16
16
|
/**
|
|
17
|
-
* Bare '#' empty state: the user's recently OPENED records (from
|
|
18
|
-
*
|
|
17
|
+
* Bare '#' empty state: the user's recently OPENED records (queried from
|
|
18
|
+
* 'MJ: User Record Logs' via UserInfoEngine.LoadRecentRecordLogs), newest first. Previously
|
|
19
19
|
* this returned nothing — deliberate (avoid a full-entity dump) but it read
|
|
20
20
|
* as "no results / broken" in the design review. Fail-soft throughout:
|
|
21
21
|
* any error just yields an empty list, never blocks the palette.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"omnibar-record.provider.d.ts","sourceRoot":"","sources":["../../../../src/lib/omnibar/providers/omnibar-record.provider.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAChG,OAAO,EAAE,eAAe,EAAsC,MAAM,qBAAqB,CAAC;AAK1F;;;;;;GAMG;AACH,qBACa,qBAAsB,SAAQ,eAAe;IACtD,SAAgB,WAAW,OAAO;IAClC,SAAgB,GAAG,qBAAqB;IACxC,SAAyB,QAAQ,MAAM;IACvC,SAAgB,SAAS,oBAAoB;IAG7C,SAAyB,WAAW,8DAAyD;IAE7F;;;;;;OAMG;IACmB,qBAAqB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"omnibar-record.provider.d.ts","sourceRoot":"","sources":["../../../../src/lib/omnibar/providers/omnibar-record.provider.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAChG,OAAO,EAAE,eAAe,EAAsC,MAAM,qBAAqB,CAAC;AAK1F;;;;;;GAMG;AACH,qBACa,qBAAsB,SAAQ,eAAe;IACtD,SAAgB,WAAW,OAAO;IAClC,SAAgB,GAAG,qBAAqB;IACxC,SAAyB,QAAQ,MAAM;IACvC,SAAgB,SAAS,oBAAoB;IAG7C,SAAyB,WAAW,8DAAyD;IAE7F;;;;;;OAMG;IACmB,qBAAqB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IA+B7G,oGAAoG;YACtF,kBAAkB;IAyBnB,cAAc,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAiB7F,2GAA2G;IAC3G,OAAO,CAAC,aAAa;IAerB,OAAO,CAAC,gBAAgB;IAexB,+EAA+E;YACjE,iBAAiB;CAsClC;AAED,iEAAiE;AACjE,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD"}
|
|
@@ -26,8 +26,8 @@ let OmnibarRecordProvider = class OmnibarRecordProvider extends OmnibarProvider
|
|
|
26
26
|
// pattern wasn't discoverable from a generic hint (design-review finding).
|
|
27
27
|
Placeholder = 'Type an entity, then a record — e.g. #accounts acme';
|
|
28
28
|
/**
|
|
29
|
-
* Bare '#' empty state: the user's recently OPENED records (from
|
|
30
|
-
*
|
|
29
|
+
* Bare '#' empty state: the user's recently OPENED records (queried from
|
|
30
|
+
* 'MJ: User Record Logs' via UserInfoEngine.LoadRecentRecordLogs), newest first. Previously
|
|
31
31
|
* this returned nothing — deliberate (avoid a full-entity dump) but it read
|
|
32
32
|
* as "no results / broken" in the design review. Fail-soft throughout:
|
|
33
33
|
* any error just yields an empty list, never blocks the palette.
|
|
@@ -36,11 +36,7 @@ let OmnibarRecordProvider = class OmnibarRecordProvider extends OmnibarProvider
|
|
|
36
36
|
try {
|
|
37
37
|
const md = request.Provider ?? Metadata.Provider;
|
|
38
38
|
const user = request.ContextUser ?? md.CurrentUser;
|
|
39
|
-
const
|
|
40
|
-
await engine.Config(false, user ?? undefined); // no-op when already loaded
|
|
41
|
-
const logs = [...engine.UserRecordLogs]
|
|
42
|
-
.sort((a, b) => new Date(b.LatestAt).getTime() - new Date(a.LatestAt).getTime())
|
|
43
|
-
.slice(0, request.MaxResults);
|
|
39
|
+
const logs = await UserInfoEngine.Instance.LoadRecentRecordLogs(request.MaxResults, user ?? undefined, md);
|
|
44
40
|
if (logs.length === 0) {
|
|
45
41
|
return [];
|
|
46
42
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"omnibar-record.provider.js","sourceRoot":"","sources":["../../../../src/lib/omnibar/providers/omnibar-record.provider.ts"],"names":[],"mappings":"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","sourcesContent":["import { RegisterClass } from '@memberjunction/global';\nimport { CompositeKey, Metadata, RunView, EntityInfo, IMetadataProvider, IRunViewProvider, UserInfo } from '@memberjunction/core';\nimport { UserInfoEngine } from '@memberjunction/core-entities';\nimport type { MentionSuggestion, ComposerSuggestionRequest } from '@memberjunction/ng-composer';\nimport { OmnibarProvider, OMNIBAR_NAV_KEY, OmnibarNavPayload } from '../omnibar-provider';\n\n/** How many record rows the best-matching entity contributes. */\nconst MAX_RECORD_ROWS = 5;\n\n/**\n * '#' — jump straight to a record. Two-phase within one query:\n * 1. Entity-name matches from metadata (grouped \"Entities\").\n * 2. Top records of the BEST-matching entity, searched by its name field\n * (grouped \"Matching records\") — fail-soft per entity (RLS/permission errors\n * simply yield no record rows).\n */\n@RegisterClass(OmnibarProvider, 'omnibar-records')\nexport class OmnibarRecordProvider extends OmnibarProvider {\n public readonly TriggerChar = '#';\n public readonly Key = 'omnibar-records';\n public override readonly Priority = 50;\n public readonly ModeLabel = 'Jump to Record';\n // Placeholder doubles as syntax education — the two-phase '#<entity> <record>'\n // pattern wasn't discoverable from a generic hint (design-review finding).\n public override readonly Placeholder = 'Type an entity, then a record — e.g. #accounts acme';\n\n /**\n * Bare '#' empty state: the user's recently OPENED records (from the\n * UserInfoEngine's cached 'MJ: User Record Logs'), newest first. Previously\n * this returned nothing — deliberate (avoid a full-entity dump) but it read\n * as \"no results / broken\" in the design review. Fail-soft throughout:\n * any error just yields an empty list, never blocks the palette.\n */\n public override async EmptyStateSuggestions(request: ComposerSuggestionRequest): Promise<MentionSuggestion[]> {\n try {\n const md: IMetadataProvider = request.Provider ?? Metadata.Provider;\n const user = request.ContextUser ?? md.CurrentUser;\n const engine = UserInfoEngine.Instance;\n await engine.Config(false, user ?? undefined); // no-op when already loaded\n const logs = [...engine.UserRecordLogs]\n .sort((a, b) => new Date(b.LatestAt).getTime() - new Date(a.LatestAt).getTime())\n .slice(0, request.MaxResults);\n if (logs.length === 0) {\n return [];\n }\n const names = await this.resolveRecordNames(\n md,\n logs.map((l) => ({ entityName: l.Entity, recordId: l.RecordID })),\n user ?? undefined,\n );\n return logs.map((log) => {\n const nav: OmnibarNavPayload = { kind: 'record', entityName: log.Entity, recordId: log.RecordID };\n const display = names.get(`${log.Entity}||${log.RecordID}`) ?? log.RecordID;\n return {\n type: 'record',\n id: `recent-record:${log.Entity}:${log.RecordID}`,\n name: display,\n displayName: display,\n description: log.Entity,\n icon: 'fa-solid fa-clock-rotate-left',\n data: { [OMNIBAR_NAV_KEY]: nav, group: 'Recently opened' },\n } satisfies MentionSuggestion;\n });\n } catch {\n return [];\n }\n }\n\n /** Batch display-name lookup; entries that fail resolve to absent (caller falls back to the ID). */\n private async resolveRecordNames(\n md: IMetadataProvider,\n targets: Array<{ entityName: string; recordId: string }>,\n user?: UserInfo,\n ): Promise<Map<string, string>> {\n const resolved = new Map<string, string>();\n try {\n // Recents span arbitrary entities whose key column can have any name; `FromID` assumed\n // `ID` and left those records showing a raw id instead of a name.\n const inputs = targets.map((t) => ({\n EntityName: t.entityName,\n CompositeKey: CompositeKey.FromURLSegment(md.EntityByName(t.entityName), t.recordId),\n }));\n const results = await md.GetEntityRecordNames(inputs, user);\n for (const r of results ?? []) {\n if (r.Success && r.RecordName) {\n resolved.set(`${r.EntityName}||${r.CompositeKey.GetValueByIndex(0)}`, r.RecordName);\n }\n }\n } catch {\n // name lookup is cosmetic — IDs are an acceptable fallback\n }\n return resolved;\n }\n\n public async GetSuggestions(request: ComposerSuggestionRequest): Promise<MentionSuggestion[]> {\n const query = request.Query.trim().toLowerCase();\n const md: IMetadataProvider = request.Provider ?? Metadata.Provider;\n const matches = this.matchEntities(md.Entities, query);\n const suggestions: MentionSuggestion[] = matches.slice(0, 4).map((e) => this.entitySuggestion(e));\n if (matches.length > 0 && query.length > 0) {\n // Record term = the query MINUS the matched entity name when the query leads\n // with it ('#mj: ai agents amanda' → term 'amanda'); an exact entity-name\n // query lists the entity's top records (empty term = browse).\n const best = matches[0];\n const bestName = best.Name.toLowerCase();\n const term = query.startsWith(bestName) ? query.substring(bestName.length).trim() : query;\n suggestions.push(...await this.recordSuggestions(best, term, request));\n }\n return suggestions.slice(0, request.MaxResults);\n }\n\n /** Name-ranked entity matches: startsWith beats contains; empty query = none (avoid a 300-entity dump). */\n private matchEntities(entities: EntityInfo[], query: string): EntityInfo[] {\n if (query.length === 0) {\n return [];\n }\n const scored = entities\n .map((e) => {\n const name = e.Name.toLowerCase();\n const score = name === query ? 3 : name.startsWith(query) ? 2 : name.includes(query) ? 1 : 0;\n return { e, score };\n })\n .filter((x) => x.score > 0)\n .sort((a, b) => (b.score - a.score) || a.e.Name.localeCompare(b.e.Name));\n return scored.map((x) => x.e);\n }\n\n private entitySuggestion(entity: EntityInfo): MentionSuggestion {\n // Enter/click on an entity row NAVIGATES: opens the entity's dynamic list view.\n // Drilling into records happens by TYPING ('#<entity name> <record term>').\n const nav: OmnibarNavPayload = { kind: 'entity-list', entityName: entity.Name };\n return {\n type: 'entity',\n id: entity.ID,\n name: entity.Name,\n displayName: entity.Name,\n description: entity.Description ? entity.Description.substring(0, 120) : 'Entity — open list view',\n icon: entity.Icon || 'fa-solid fa-table',\n data: { [OMNIBAR_NAV_KEY]: nav, group: 'Entities', entityName: entity.Name },\n };\n }\n\n /** Top records of one entity whose name field matches the query. Fail-soft. */\n private async recordSuggestions(entity: EntityInfo, term: string, request: ComposerSuggestionRequest): Promise<MentionSuggestion[]> {\n const nameField = entity.NameField;\n if (!nameField) {\n return [];\n }\n try {\n const escaped = term.replace(/'/g, \"''\");\n const rv = request.Provider ? RunView.FromMetadataProvider(request.Provider) : new RunView();\n const result = await rv.RunView<Record<string, unknown>>({\n EntityName: entity.Name,\n ExtraFilter: escaped.length > 0 ? `${nameField.Name} LIKE '%${escaped}%'` : '',\n Fields: [...entity.PrimaryKeys.map((pk) => pk.Name), nameField.Name],\n OrderBy: nameField.Name,\n MaxRows: MAX_RECORD_ROWS,\n ResultType: 'simple',\n }, request.ContextUser ?? undefined);\n if (!result.Success) {\n return [];\n }\n return result.Results.map((row) => {\n // Compact key segment (raw value, or \"F1|v1||F2|v2\" for a composite key) — the palette resolves it with FromURLSegment\n const recordId = CompositeKey.FromEntityRecord(entity, row).ToCompactURLSegment();\n const name = String(row[nameField.Name] ?? recordId);\n const nav: OmnibarNavPayload = { kind: 'record', entityName: entity.Name, recordId };\n return {\n type: 'record',\n id: `${entity.Name}:${recordId}`,\n name,\n displayName: name,\n description: entity.Name,\n icon: 'fa-solid fa-id-card',\n data: { [OMNIBAR_NAV_KEY]: nav, group: 'Matching records' },\n } satisfies MentionSuggestion;\n });\n } catch {\n return [];\n }\n }\n}\n\n/** Tree-shaking guard — referenced by LoadOmnibarProviders(). */\nexport function LoadOmnibarRecordProvider(): void {\n // intentional no-op\n}\n"]}
|
|
1
|
+
{"version":3,"file":"omnibar-record.provider.js","sourceRoot":"","sources":["../../../../src/lib/omnibar/providers/omnibar-record.provider.ts"],"names":[],"mappings":"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","sourcesContent":["import { RegisterClass } from '@memberjunction/global';\nimport { CompositeKey, Metadata, RunView, EntityInfo, IMetadataProvider, IRunViewProvider, UserInfo } from '@memberjunction/core';\nimport { UserInfoEngine } from '@memberjunction/core-entities';\nimport type { MentionSuggestion, ComposerSuggestionRequest } from '@memberjunction/ng-composer';\nimport { OmnibarProvider, OMNIBAR_NAV_KEY, OmnibarNavPayload } from '../omnibar-provider';\n\n/** How many record rows the best-matching entity contributes. */\nconst MAX_RECORD_ROWS = 5;\n\n/**\n * '#' — jump straight to a record. Two-phase within one query:\n * 1. Entity-name matches from metadata (grouped \"Entities\").\n * 2. Top records of the BEST-matching entity, searched by its name field\n * (grouped \"Matching records\") — fail-soft per entity (RLS/permission errors\n * simply yield no record rows).\n */\n@RegisterClass(OmnibarProvider, 'omnibar-records')\nexport class OmnibarRecordProvider extends OmnibarProvider {\n public readonly TriggerChar = '#';\n public readonly Key = 'omnibar-records';\n public override readonly Priority = 50;\n public readonly ModeLabel = 'Jump to Record';\n // Placeholder doubles as syntax education — the two-phase '#<entity> <record>'\n // pattern wasn't discoverable from a generic hint (design-review finding).\n public override readonly Placeholder = 'Type an entity, then a record — e.g. #accounts acme';\n\n /**\n * Bare '#' empty state: the user's recently OPENED records (queried from\n * 'MJ: User Record Logs' via UserInfoEngine.LoadRecentRecordLogs), newest first. Previously\n * this returned nothing — deliberate (avoid a full-entity dump) but it read\n * as \"no results / broken\" in the design review. Fail-soft throughout:\n * any error just yields an empty list, never blocks the palette.\n */\n public override async EmptyStateSuggestions(request: ComposerSuggestionRequest): Promise<MentionSuggestion[]> {\n try {\n const md: IMetadataProvider = request.Provider ?? Metadata.Provider;\n const user = request.ContextUser ?? md.CurrentUser;\n const logs = await UserInfoEngine.Instance.LoadRecentRecordLogs(request.MaxResults, user ?? undefined, md);\n if (logs.length === 0) {\n return [];\n }\n const names = await this.resolveRecordNames(\n md,\n logs.map((l) => ({ entityName: l.Entity, recordId: l.RecordID })),\n user ?? undefined,\n );\n return logs.map((log) => {\n const nav: OmnibarNavPayload = { kind: 'record', entityName: log.Entity, recordId: log.RecordID };\n const display = names.get(`${log.Entity}||${log.RecordID}`) ?? log.RecordID;\n return {\n type: 'record',\n id: `recent-record:${log.Entity}:${log.RecordID}`,\n name: display,\n displayName: display,\n description: log.Entity,\n icon: 'fa-solid fa-clock-rotate-left',\n data: { [OMNIBAR_NAV_KEY]: nav, group: 'Recently opened' },\n } satisfies MentionSuggestion;\n });\n } catch {\n return [];\n }\n }\n\n /** Batch display-name lookup; entries that fail resolve to absent (caller falls back to the ID). */\n private async resolveRecordNames(\n md: IMetadataProvider,\n targets: Array<{ entityName: string; recordId: string }>,\n user?: UserInfo,\n ): Promise<Map<string, string>> {\n const resolved = new Map<string, string>();\n try {\n // Recents span arbitrary entities whose key column can have any name; `FromID` assumed\n // `ID` and left those records showing a raw id instead of a name.\n const inputs = targets.map((t) => ({\n EntityName: t.entityName,\n CompositeKey: CompositeKey.FromURLSegment(md.EntityByName(t.entityName), t.recordId),\n }));\n const results = await md.GetEntityRecordNames(inputs, user);\n for (const r of results ?? []) {\n if (r.Success && r.RecordName) {\n resolved.set(`${r.EntityName}||${r.CompositeKey.GetValueByIndex(0)}`, r.RecordName);\n }\n }\n } catch {\n // name lookup is cosmetic — IDs are an acceptable fallback\n }\n return resolved;\n }\n\n public async GetSuggestions(request: ComposerSuggestionRequest): Promise<MentionSuggestion[]> {\n const query = request.Query.trim().toLowerCase();\n const md: IMetadataProvider = request.Provider ?? Metadata.Provider;\n const matches = this.matchEntities(md.Entities, query);\n const suggestions: MentionSuggestion[] = matches.slice(0, 4).map((e) => this.entitySuggestion(e));\n if (matches.length > 0 && query.length > 0) {\n // Record term = the query MINUS the matched entity name when the query leads\n // with it ('#mj: ai agents amanda' → term 'amanda'); an exact entity-name\n // query lists the entity's top records (empty term = browse).\n const best = matches[0];\n const bestName = best.Name.toLowerCase();\n const term = query.startsWith(bestName) ? query.substring(bestName.length).trim() : query;\n suggestions.push(...await this.recordSuggestions(best, term, request));\n }\n return suggestions.slice(0, request.MaxResults);\n }\n\n /** Name-ranked entity matches: startsWith beats contains; empty query = none (avoid a 300-entity dump). */\n private matchEntities(entities: EntityInfo[], query: string): EntityInfo[] {\n if (query.length === 0) {\n return [];\n }\n const scored = entities\n .map((e) => {\n const name = e.Name.toLowerCase();\n const score = name === query ? 3 : name.startsWith(query) ? 2 : name.includes(query) ? 1 : 0;\n return { e, score };\n })\n .filter((x) => x.score > 0)\n .sort((a, b) => (b.score - a.score) || a.e.Name.localeCompare(b.e.Name));\n return scored.map((x) => x.e);\n }\n\n private entitySuggestion(entity: EntityInfo): MentionSuggestion {\n // Enter/click on an entity row NAVIGATES: opens the entity's dynamic list view.\n // Drilling into records happens by TYPING ('#<entity name> <record term>').\n const nav: OmnibarNavPayload = { kind: 'entity-list', entityName: entity.Name };\n return {\n type: 'entity',\n id: entity.ID,\n name: entity.Name,\n displayName: entity.Name,\n description: entity.Description ? entity.Description.substring(0, 120) : 'Entity — open list view',\n icon: entity.Icon || 'fa-solid fa-table',\n data: { [OMNIBAR_NAV_KEY]: nav, group: 'Entities', entityName: entity.Name },\n };\n }\n\n /** Top records of one entity whose name field matches the query. Fail-soft. */\n private async recordSuggestions(entity: EntityInfo, term: string, request: ComposerSuggestionRequest): Promise<MentionSuggestion[]> {\n const nameField = entity.NameField;\n if (!nameField) {\n return [];\n }\n try {\n const escaped = term.replace(/'/g, \"''\");\n const rv = request.Provider ? RunView.FromMetadataProvider(request.Provider) : new RunView();\n const result = await rv.RunView<Record<string, unknown>>({\n EntityName: entity.Name,\n ExtraFilter: escaped.length > 0 ? `${nameField.Name} LIKE '%${escaped}%'` : '',\n Fields: [...entity.PrimaryKeys.map((pk) => pk.Name), nameField.Name],\n OrderBy: nameField.Name,\n MaxRows: MAX_RECORD_ROWS,\n ResultType: 'simple',\n }, request.ContextUser ?? undefined);\n if (!result.Success) {\n return [];\n }\n return result.Results.map((row) => {\n // Compact key segment (raw value, or \"F1|v1||F2|v2\" for a composite key) — the palette resolves it with FromURLSegment\n const recordId = CompositeKey.FromEntityRecord(entity, row).ToCompactURLSegment();\n const name = String(row[nameField.Name] ?? recordId);\n const nav: OmnibarNavPayload = { kind: 'record', entityName: entity.Name, recordId };\n return {\n type: 'record',\n id: `${entity.Name}:${recordId}`,\n name,\n displayName: name,\n description: entity.Name,\n icon: 'fa-solid fa-id-card',\n data: { [OMNIBAR_NAV_KEY]: nav, group: 'Matching records' },\n } satisfies MentionSuggestion;\n });\n } catch {\n return [];\n }\n }\n}\n\n/** Tree-shaking guard — referenced by LoadOmnibarProviders(). */\nexport function LoadOmnibarRecordProvider(): void {\n // intentional no-op\n}\n"]}
|
|
@@ -3,8 +3,11 @@ import { OmnibarProvider } from '../omnibar-provider';
|
|
|
3
3
|
/**
|
|
4
4
|
* The omnibar's DEFAULT mode (empty TriggerChar): plain text = the same
|
|
5
5
|
* cross-source search that backs the Search Results page (vectors + full-text +
|
|
6
|
-
* entities + storage), served through `SearchService.PreviewSearch`.
|
|
7
|
-
*
|
|
6
|
+
* entities + storage), served through `SearchService.PreviewSearch`. Matching
|
|
7
|
+
* dashboards from the cached `DashboardEngine` form a "Dashboards" group: name matches
|
|
8
|
+
* come before the search results, and dashboards that match only by description or
|
|
9
|
+
* category come after them. Always appends a trailing "See all results" suggestion
|
|
10
|
+
* that opens the full Search workspace.
|
|
8
11
|
*/
|
|
9
12
|
export declare class OmnibarSearchProvider extends OmnibarProvider {
|
|
10
13
|
readonly TriggerChar = "";
|
|
@@ -13,6 +16,16 @@ export declare class OmnibarSearchProvider extends OmnibarProvider {
|
|
|
13
16
|
readonly ModeLabel = "Global Search";
|
|
14
17
|
readonly Placeholder = "Search everything \u2014 or type #, /, @ \u2026";
|
|
15
18
|
GetSuggestions(request: ComposerSuggestionRequest): Promise<MentionSuggestion[]>;
|
|
19
|
+
/**
|
|
20
|
+
* Dashboards the user can open in a dashboard tab whose name, description or category
|
|
21
|
+
* matches the query, split into name matches and description-or-category-only matches.
|
|
22
|
+
* Reads only the cached engine: returns empty lists when it is not loaded or no user
|
|
23
|
+
* is known, and never loads it.
|
|
24
|
+
*/
|
|
25
|
+
private dashboardSuggestions;
|
|
26
|
+
/** The DashboardEngine for the request's provider, else the global instance. */
|
|
27
|
+
private dashboardEngine;
|
|
28
|
+
private toDashboardSuggestion;
|
|
16
29
|
private toSuggestion;
|
|
17
30
|
private seeAllSuggestion;
|
|
18
31
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"omnibar-search.provider.d.ts","sourceRoot":"","sources":["../../../../src/lib/omnibar/providers/omnibar-search.provider.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"omnibar-search.provider.d.ts","sourceRoot":"","sources":["../../../../src/lib/omnibar/providers/omnibar-search.provider.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAEhG,OAAO,EAAE,eAAe,EAAsC,MAAM,qBAAqB,CAAC;AAwB1F;;;;;;;;GAQG;AACH,qBACa,qBAAsB,SAAQ,eAAe;IACtD,SAAgB,WAAW,MAAM;IACjC,SAAgB,GAAG,oBAAoB;IACvC,SAAyB,QAAQ,OAAO;IACxC,SAAgB,SAAS,mBAAmB;IAC5C,SAAyB,WAAW,qDAA2C;IAElE,cAAc,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAmB7F;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;IAmB5B,gFAAgF;IAChF,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,qBAAqB;IAa7B,OAAO,CAAC,YAAY;IAoBpB,OAAO,CAAC,gBAAgB;CAY3B;AAED,iEAAiE;AACjE,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD"}
|
|
@@ -5,7 +5,11 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
7
|
import { RegisterClass } from '@memberjunction/global';
|
|
8
|
+
import { DashboardEngine } from '@memberjunction/core-entities';
|
|
8
9
|
import { OmnibarProvider, OMNIBAR_NAV_KEY } from '../omnibar-provider';
|
|
10
|
+
import { CanOpenInDashboardTab, SplitDashboardMatches } from '../omnibar-dashboard-matches';
|
|
11
|
+
/** Most dashboard rows in the results: name matches and description or category matches together. */
|
|
12
|
+
const MAX_DASHBOARD_ROWS = 3;
|
|
9
13
|
/** Icon per cross-source result type (matches the Search Results page vocabulary). */
|
|
10
14
|
function iconForResult(item) {
|
|
11
15
|
switch (item.ResultType) {
|
|
@@ -25,8 +29,11 @@ function groupForResult(item) {
|
|
|
25
29
|
/**
|
|
26
30
|
* The omnibar's DEFAULT mode (empty TriggerChar): plain text = the same
|
|
27
31
|
* cross-source search that backs the Search Results page (vectors + full-text +
|
|
28
|
-
* entities + storage), served through `SearchService.PreviewSearch`.
|
|
29
|
-
*
|
|
32
|
+
* entities + storage), served through `SearchService.PreviewSearch`. Matching
|
|
33
|
+
* dashboards from the cached `DashboardEngine` form a "Dashboards" group: name matches
|
|
34
|
+
* come before the search results, and dashboards that match only by description or
|
|
35
|
+
* category come after them. Always appends a trailing "See all results" suggestion
|
|
36
|
+
* that opens the full Search workspace.
|
|
30
37
|
*/
|
|
31
38
|
let OmnibarSearchProvider = class OmnibarSearchProvider extends OmnibarProvider {
|
|
32
39
|
TriggerChar = '';
|
|
@@ -40,17 +47,62 @@ let OmnibarSearchProvider = class OmnibarSearchProvider extends OmnibarProvider
|
|
|
40
47
|
if (!search || query.length === 0) {
|
|
41
48
|
return [];
|
|
42
49
|
}
|
|
50
|
+
const dashboards = this.dashboardSuggestions(query, request);
|
|
51
|
+
const dashboardCount = dashboards.NameMatches.length + dashboards.DescriptionOrCategoryMatches.length;
|
|
43
52
|
try {
|
|
44
|
-
|
|
53
|
+
// Search fills the rows left after the dashboards and the trailing "see all".
|
|
54
|
+
const response = await search.PreviewSearch(query, Math.max(1, request.MaxResults - 1 - dashboardCount));
|
|
45
55
|
const suggestions = (response.Success ? response.Results : []).map((item) => this.toSuggestion(item));
|
|
46
|
-
suggestions.
|
|
47
|
-
return suggestions;
|
|
56
|
+
return [...dashboards.NameMatches, ...suggestions, ...dashboards.DescriptionOrCategoryMatches, this.seeAllSuggestion(query)];
|
|
48
57
|
}
|
|
49
58
|
catch {
|
|
50
|
-
// Fail soft — the palette still offers the full-search escape hatch.
|
|
51
|
-
return [this.seeAllSuggestion(query)];
|
|
59
|
+
// Fail soft — the palette still offers the dashboards and the full-search escape hatch.
|
|
60
|
+
return [...dashboards.NameMatches, ...dashboards.DescriptionOrCategoryMatches, this.seeAllSuggestion(query)];
|
|
52
61
|
}
|
|
53
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Dashboards the user can open in a dashboard tab whose name, description or category
|
|
65
|
+
* matches the query, split into name matches and description-or-category-only matches.
|
|
66
|
+
* Reads only the cached engine: returns empty lists when it is not loaded or no user
|
|
67
|
+
* is known, and never loads it.
|
|
68
|
+
*/
|
|
69
|
+
dashboardSuggestions(query, request) {
|
|
70
|
+
const none = { NameMatches: [], DescriptionOrCategoryMatches: [] };
|
|
71
|
+
try {
|
|
72
|
+
const engine = this.dashboardEngine(request.Provider);
|
|
73
|
+
const userId = request.ContextUser?.ID ?? (request.Provider ?? this.context.Search?.Provider)?.CurrentUser?.ID;
|
|
74
|
+
if (!userId || !engine.Loaded) {
|
|
75
|
+
return none;
|
|
76
|
+
}
|
|
77
|
+
const openable = engine.GetAccessibleDashboards(userId).filter(CanOpenInDashboardTab);
|
|
78
|
+
const matches = SplitDashboardMatches(openable, query, MAX_DASHBOARD_ROWS);
|
|
79
|
+
return {
|
|
80
|
+
NameMatches: matches.NameMatches.map((d) => this.toDashboardSuggestion(d)),
|
|
81
|
+
DescriptionOrCategoryMatches: matches.DescriptionOrCategoryMatches.map((d) => this.toDashboardSuggestion(d)),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return none;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/** The DashboardEngine for the request's provider, else the global instance. */
|
|
89
|
+
dashboardEngine(provider) {
|
|
90
|
+
return provider
|
|
91
|
+
? DashboardEngine.GetProviderInstance(provider, DashboardEngine)
|
|
92
|
+
: DashboardEngine.Instance;
|
|
93
|
+
}
|
|
94
|
+
toDashboardSuggestion(dashboard) {
|
|
95
|
+
const nav = { kind: 'dashboard', dashboardId: dashboard.ID, dashboardName: dashboard.Name };
|
|
96
|
+
return {
|
|
97
|
+
type: 'dashboard',
|
|
98
|
+
id: `dashboard:${dashboard.ID}`,
|
|
99
|
+
name: dashboard.Name,
|
|
100
|
+
displayName: dashboard.Name,
|
|
101
|
+
description: [dashboard.Category, dashboard.User].filter(Boolean).join(' · '),
|
|
102
|
+
icon: 'fa-solid fa-gauge-high',
|
|
103
|
+
data: { [OMNIBAR_NAV_KEY]: nav, group: 'Dashboards' },
|
|
104
|
+
};
|
|
105
|
+
}
|
|
54
106
|
toSuggestion(item) {
|
|
55
107
|
const isFile = item.ResultType === 'storage-file';
|
|
56
108
|
const nav = isFile
|