Protected_Advanced customization (persisted): per-token overrides + raw scoped CSS.
ReadonlybarReadonlybarHeight %s + labels for the demo bar chart.
ReadonlybarReadonlychromeRecipes (Q2#3): curated intents expanded to token sets. On/off is tracked by
PROVENANCE — activeRecipeKeys records exactly which override keys each active
recipe produced, so hand-set overrides never masquerade as an active recipe and
toggling off removes only keys the recipe still owns.
ReadonlycssCodeMirror extensions for the custom-CSS editor: MJ selector + token completions.
Inline custom-CSS validation results (Q3#6).
Protecteddestroy$Subclasses can emit anytime an error occurs.
ReadonlyfontPreview-only branding/density knobs (not part of the seed contract yet).
Subclasses can emit this event anytime they want to communicate with the container to let it know that something has happened of significance.
ReadonlymockInteractive-mock state (Q1#6) — clickable tabs/nav/switches/accordion so the derived state token families (hover/active/focus) demonstrate themselves live.
ReadonlymockReadonlymodeProtectednavigationSubclasses can emit this event anytime they want to open a record within a particular entity. The container should handle this event and open the record.
Panel sizing (Q3#1/#2).
Tab ID for query param notification scoping. Set by resource wrappers that render child dashboards, so the child knows which tab it belongs to. If not set, falls back to Data.Configuration.tabId.
Preset gallery shown as step one of "New theme" (Q1#2).
ReadonlypresetsIf specified, this provider will be used for communication and for all metadata purposes. By default, if not provided, the Metadata and RunView classes are used for this and the default GraphQLDataProvider is used which is connected to the same back-end MJAPI instance as the Metadata and RunView classes. If you want to have this component connect to a different MJAPI back-end, create an instance of a ProviderBase sub-class like GraphQLDataProvider/etc, and configure it as appropriate to connect to the MJAPI back-end you want to use, and then pass it in here.
ReadonlysurfaceToolbar segmented controls (mj-view-toggle options).
Visual token browser state (Q2#1).
Subclasses should emit this event anytime their internal state changes in a way that they'd like to persist.
"Preview on my workspace" (Q3#8).
StaticɵdirStaticɵfacClosed-state summary — "3 token overrides · 14 lines CSS" (Q3#7).
Set or change the dashboard configuration. Changing this property will NOT cause the dashboard to reload. Call Refresh() to do that.
Dark-mode primary the theme derives (ramp step), shown as a note on the Brand card.
The actual overlay CSS this theme produces (tokens + advanced layer) — read-only view.
The protected built-in theme is read-only — editing/saving over it is blocked.
Per-mode text-on-primary detail shown alongside the worst-of-both headline.
The text-on-primary contrast headline, reporting the WORST of light and dark (Q1#3).
Token names in the derived contract (completion, insert picker, validation).
Returns either the default Metadata provider or the one specified in the Provider property, if it was specified
Returns either the default RunQuery provider or the one specified in the Provider property, if it was specified
Returns either the default RunReport provider or the one specified in the Provider property, if it was specified
Returns either the default RunView provider or the one specified in the Provider property, if it was specified
Secondary (deep brand) derived for light mode.
All 10 derived categorical colors (--mj-viz-1..10) — the full chart-palette contract.
Apply this theme to the current user's workspace now and remember it as their choice (persists across sessions). Distinct from "Set as org default", which is the organization-wide fallback for everyone.
Begin inline text editing for a non-color token value.
Preset gallery: pick a personality card as step one of a new theme.
Close the gallery keeping the MJ-default draft (the "start blank" path).
ProtectedGetRead current query params from tab configuration. Use in initDashboard() / ngOnInit() to get initial URL state.
Sub-classes can override this to provide a custom icon class
Get this component's tab ID. Checks ParentTabId input first (set by resource wrappers for child dashboards), then falls back to Data.Configuration.tabId.
Outline the preview elements that use token (exact by construction — the canvas
markup is ours; see TOKEN_PREVIEW_TARGETS). Unmapped tokens simply don't highlight.
ProtectedinitSubclasses can override this method to perform any initialization they need. This method only runs once when the dashboard is created.
Insert a chrome selector at the caret; on an empty line, scaffold a full rule.
Whether a picker row is the currently-loaded theme (case-insensitive GUID compare).
A category is open when toggled open, or always while a search narrows the rows.
ProtectedloadSubclasses should override this method to load their data. This method is called when the dashboard is created and when Refresh() is called.
Start a fresh, unsaved draft. From the UI this opens on the preset gallery (choosing a personality first, Q1#2); agent-driven calls skip straight to the MJ default seeds.
A callback method that is invoked immediately after Angular has completed initialization of a component's view. It is invoked only once when the view is instantiated.
A callback method that performs custom clean-up, invoked immediately before a directive, pipe, or service instance is destroyed.
A callback method that is invoked immediately after the default change detector has checked the directive's data-bound properties for the first time, and before any of the view or content children have been checked. It is invoked only once when the directive is instantiated.
ProtectedNotifyAsk the host shell to close/dismiss this resource (typically: close the tab). Called by subclasses that hosted a form that emitted a 'dismiss' navigation event — most often, a brand-new record where the user clicked Discard. The record was never saved, the form is empty, and leaving it open serves no purpose. The tab-container listens for this and closes the workspace tab.
ProtectedNotifyCall this to notify the tab system that the resource's display name has changed. The tab container will update the tab title and browser title accordingly.
ProtectedNotifyProtectedNotifyOverrides/custom CSS don't change derivation — re-apply the preview layer, refresh the browser rows + recipe states, and keep any live workspace preview in sync.
Insert-token picker (same enumeration the overrides use).
mj-view-toggle (KeyChange) adapter for the light/dark segment.
ProtectedOnCalled by the framework when query params change from an external source (browser back/forward, deep link navigation). Override in subclasses to react to query param changes.
The new query params from the URL
'popstate' for back/forward, 'deeplink' for external URL entry
mj-view-toggle (KeyChange) adapter for the preview-surface chips.
This method will result in the dashboard being reloaded.
ProtectedRefreshMarks this component's view (and its ancestors) as needing change detection and schedules a tick — the reliable way for a resource component to re-render after updating state from async work (RunView/RunQuery continuations, timers, websocket pushes, RxJS subscriptions).
WHY THIS EXISTS: the Explorer shell hosts resource components dynamically — createComponent()
ApplicationRef.attachView() — because tab content mounts into Golden Layout / cached DOM
containers, not into an Angular template. Since Angular 18's change-detection scheduler
rework (Explorer is on Angular 21), ApplicationRef.tick() only refreshes attached views
that are FLAGGED dirty; a root-level attached view whose component mutates plain fields from
an async continuation is never flagged, so the view silently never re-renders — even though
the component uses default (non-OnPush) change detection (issue #3106).The framework calls this automatically from NotifyLoadStarted() / NotifyLoadComplete(), so the standard load lifecycle re-renders without any subclass action. Call it yourself after any LATER async state change that must reach the DOM outside those signals.
ProtectedResourceFork the current seeds into a new, editable theme (used to customize the built-in).
This method can be used by a container to let the dashboard know that it is being opened/closed. Base class just sets a flag.
Inline-rename the current theme in the header. For a saved theme the new name is persisted immediately on commit; for an unsaved draft it persists on Save.
Expand/collapse the Advanced card, auto-widening the panel while it's open (Q3#2).
Prefer the native Fullscreen API — it promotes the canvas to the browser's top
layer, so it fills the real screen regardless of any transformed/contained
ancestor, and browser Esc reliably exits. Falls back to CSS-fixed overlay if the
API is unavailable or rejects.
Toggle a recipe: expand its token set into overrides (recording ownership), or remove exactly the keys it still owns. Keys the user hand-edited after enabling were released from ownership at edit time and are never touched here.
Toggle the theme switcher; refresh the list on open so deletes/renames made in the Manage Themes tab are reflected without a hard refresh.
Temporarily apply the in-memory draft (seeds + overrides + custom CSS) to the real app chrome so custom-CSS selectors are authored against reality. The preview stays on while you navigate other tabs (that's the point — the Studio tab is cached, not destroyed) and reverts on toggle-off or when the Studio tab is closed. It is never persisted ({ persist: false }), so a reload always restores the user's real theme.
ProtectedUpdatePush query param changes to the URL. Creates a browser history entry. Safe to call during OnQueryParamsChanged — auto-suppressed to prevent loops.
Make the base class a directive so we can use Angular functionality and sub-classes can be
Component