@arcgis/coding-components
Version:
ArcGIS Coding Components
218 lines (217 loc) • 16.5 kB
JavaScript
/* COPYRIGHT Esri - https://js.arcgis.com/5.1/LICENSE.txt */
import { c as v } from "../../chunks/runtime.js";
import { css as u, html as r } from "lit";
import { repeat as g } from "lit/directives/repeat.js";
import { LitElement as f, safeClassMap as w, nothing as b } from "@arcgis/lumina";
import { u as x } from "../../chunks/useT9n.js";
import { load as S } from "@arcgis/lumina/controllers";
import { i as $ } from "../../chunks/monaco-importer.js";
import { t as l } from "../../chunks/functional.js";
import { d as k, g as y, c as h } from "../../chunks/debugger-value-styles.js";
import { i as m, a as P, p as T, b as E, c as L, d as C, S as M, D as B, e as V } from "../../chunks/debugger-value-components.js";
import { observeAncestorsMutation as z, unsafeGetCalciteModeName as I } from "@arcgis/toolkit/dom";
import { generateGuid as A } from "@arcgis/toolkit/string";
import { d as p } from "../../chunks/ArcadeDebuggerPreviewTabsState.js";
import { Uri as D } from "monaco-editor";
const F = u`:host{--calcite-block-padding: var(--calcite-spacing-sm);--breakpoints-popover-max-height: min(14rem, 20vh);display:block;background-color:var(--calcite-color-foreground-1);color:var(--calcite-color-text-2);overflow:hidden;height:100%;.console-shell,.tabs-container,calcite-tabs{height:100%}.tabs-container{flex:1 1 auto;min-height:0;overflow:hidden}.console-shell,calcite-tabs{display:flex;flex-direction:column;min-height:0}.console-shell{container-type:size;container-name:debugger-console}calcite-tab-nav{--calcite-size-2xl: var(--calcite-space-md);justify-content:flex-start;padding-inline:var(--calcite-spacing-sm)}calcite-tab-title{font-size:var(--calcite-font-size-sm)}calcite-tab{--calcite-tab-content-block-padding: 0;--calcite-tab-content-space-y: 0;display:flex;flex-direction:column;min-height:0}calcite-tab:not([selected]){display:none}.disabled-state-text{font-size:var(--calcite-font-size-sm);color:var(--calcite-color-text-3);font-style:italic;text-align:center;display:block;padding:var(--calcite-spacing-md)}.breakpoint-header{display:flex;align-items:flex-start;gap:var(--calcite-spacing-sm);padding:var(--calcite-spacing-sm);border-bottom:1px solid var(--calcite-color-border-3);background-color:var(--calcite-color-foreground-1)}.load-action{--calcite-action-background-color: var(--calcite-color-foreground-2);--calcite-internal-action-height: 1.25rem;--calcite-internal-action-padding-block: 0;--calcite-internal-action-padding-inline: var(--calcite-spacing-xs);margin-block:var(--calcite-spacing-xxs)}.breakpoint-code-viewer{margin-block:0;width:100%}.tab-panel{display:flex;flex:1 1 auto;min-height:0;overflow:hidden}.tab-panel>*{flex:1 1 auto;min-height:0}.tab-panel>calcite-tree{margin-inline-end:var(--calcite-space-sm)}.preview-panel{display:flex;flex:1 1 auto;min-height:0}.preview-empty-state{display:flex;align-items:center;justify-content:center;width:100%;height:100%;padding:var(--calcite-spacing-md)}.preview-table-shell{display:flex;flex-direction:column;flex:1 1 auto;width:100%;min-height:0;overflow:hidden}.preview-table-summary{padding:var(--calcite-spacing-sm);border-bottom:1px solid var(--calcite-color-border-3);color:var(--calcite-color-text-2);font-family:var(--calcite-code-family);background-color:var(--calcite-color-foreground-1)}.table-scroll{overflow:auto;flex:1 1 auto;min-height:0;max-width:100%;background-color:var(--calcite-color-foreground-1);margin:var(--calcite-spacing-sm)}table{min-width:max-content;border-spacing:0;border-collapse:collapse;text-align:start;white-space:nowrap;thead{background-color:var(--calcite-color-foreground-2)}tr{border-top:1px solid var(--calcite-color-border-3);border-bottom:1px solid var(--calcite-color-border-3)}th,td{border-inline-start:1px solid var(--calcite-color-border-3);border-inline-end:1px solid var(--calcite-color-border-3);text-align:start;padding:var(--calcite-spacing-xxs);.string-value{white-space:pre}}th{font-weight:var(--calcite-font-weight-medium)}}.breakpoints-popover{--calcite-popover-max-size-x: min(22rem, 68vw)}.breakpoints-popover-content{max-block-size:var(--breakpoints-popover-max-height);overflow:hidden}.breakpoints-list{display:flex;flex-direction:column;gap:var(--calcite-spacing-xs);padding:var(--calcite-spacing-xs);min-width:min(18rem,58vw);max-block-size:var(--breakpoints-popover-max-height);overflow:auto}.breakpoints-popover .breakpoint-code-viewer{--calcite-font-size--2: var(--calcite-font-size--3);--calcite-spacing-md: var(--calcite-spacing-sm);--calcite-spacing-sm: var(--calcite-spacing-xs);--calcite-spacing-xs: var(--calcite-spacing-xxs)}.breakpoint-list-item{border:1px solid var(--calcite-color-border-3);border-radius:var(--calcite-corner-radius-sharp);background-color:var(--calcite-color-foreground-1);padding:var(--calcite-spacing-xxs)}.breakpoint-list-item--current{border-color:var(--calcite-color-brand)}.breakpoint-list-item-meta{color:var(--calcite-color-text-2);font-size:var(--calcite-font-size-xs);margin-bottom:var(--calcite-spacing-xxs)}}`;
class N extends f {
constructor() {
super(...arguments), this.messages = x(), this._monacoEditor = S($), this._breakpointPopoverId = `arcade-debugger-console-breakpoints-${A()}`, this.modelId = "";
}
static {
this.properties = { debuggerStore: 0, modelId: 1 };
}
static {
this.styles = [F, k, y()];
}
get breakpoints() {
return this.debuggerStore?.debuggerBreakpoints ?? [];
}
get previewTabsState() {
return this.debuggerStore.previewTabsState;
}
get lazyTreeState() {
return this.debuggerStore?.lazyTreeState;
}
get executionProgramState() {
return this.debuggerStore?.executionState?.result;
}
load() {
this.manager.onLifecycle(() => {
const e = z(this.el, ["class"], this.updateTheme.bind(this));
return this.updateTheme(), () => e();
});
}
getContentAtLine(e) {
if (!this.modelId)
return "";
const t = this._monacoEditor.getModel(D.parse(this.modelId));
return t ? t.getLineContent(e) : "";
}
updateTheme() {
I(this.el) === "dark" ? this.elementInternals.states.add(h) : this.elementInternals.states.delete(h);
}
getBreakpointCode(e) {
return e == null ? this.messages.nocontent ?? "No content" : this.getContentAtLine(e) || (this.messages.nocontent ?? "No content");
}
getPreviewLoadErrorMessage() {
return this.messages.previewloaderror ?? "Unable to load preview.";
}
getBreakpointPositionText(e) {
return (this.messages.breakpointposition ?? "{position} of {count}" ?? "{position} of {count}").replace("{position}", String(e)).replace("{count}", String(this.breakpoints.length));
}
findCollectionItemByPreviewSegment(e, t) {
if (t.startsWith("name:")) {
const a = t.slice(5);
return e.find((i) => i.name === a)?.featureSet;
}
if (t.startsWith("id:")) {
const a = t.slice(3);
return e.find((i) => String(i.id) === a)?.featureSet;
}
}
getExpandedDebuggerMap(e) {
if (e == null || !m(e))
return null;
const t = e.expand();
return Array.isArray(t) ? null : t;
}
getPreviewRows(e) {
return e.map((t) => {
const a = this.getExpandedDebuggerMap(t);
return a || /* @__PURE__ */ new Map();
});
}
getExpandedDebuggerChild(e, t) {
if (!e || !m(e))
return;
const a = e.expand();
if (Array.isArray(a)) {
const i = Number(t);
return !Number.isInteger(i) || String(i) !== t ? void 0 : a[i];
}
return a.get(t);
}
async resolvePreviewValueFromSegments(e, t) {
if (!t.length)
return e;
if (!e)
return;
const [a, ...i] = t;
let o;
if (P(e)) {
const s = await e.load();
o = this.findCollectionItemByPreviewSegment(s, a);
} else
o = this.getExpandedDebuggerChild(e, a);
return await this.resolvePreviewValueFromSegments(o, i);
}
getScope(e, t) {
switch (t) {
case "profile":
return e.profile;
case "globals":
return e.globals;
case "locals":
return e.locals;
}
}
async resolvePreviewValue(e) {
const t = this.executionProgramState;
if (!t)
return;
const a = T(e);
if (!a)
return;
const { scopeName: i, rootName: o, pathSegments: s } = a, n = this.getScope(t, i);
if (n)
return await this.resolvePreviewValueFromSegments(n.get(o), s);
}
async loadPreview({ label: e, sourcePath: t, value: a }) {
const i = this.previewTabsState, { snapshot: o } = i.startLoad(e, t);
let s = a;
if (s == null)
try {
s = await this.resolvePreviewValue(t);
} catch {
i.setError(o, this.getPreviewLoadErrorMessage());
return;
}
if (s == null || !E(s) || typeof s.querySample != "function" || typeof s.schema != "function") {
i.setUnavailable(o, this.messages.previewunavailable ?? "This preview is no longer available in the current paused state.");
return;
}
try {
const { fields: n, features: d } = await s.querySample(), c = this.getPreviewRows(d);
i.setLoaded(o, n, c);
} catch {
i.setError(o, this.getPreviewLoadErrorMessage());
}
}
activateTab(e) {
if (e === p) {
this.previewTabsState.selectScope();
return;
}
this.previewTabsState.selectTab(e);
const t = this.previewTabsState.getTab(e);
t?.invalidated && this.loadPreview({ label: t.label, sourcePath: t.sourcePath });
}
closePreviewTab(e) {
e.closed = !1, this.previewTabsState.closeTab(e.tab);
}
scrollToSelectedBreakpoint(e) {
const t = e.currentTarget;
requestAnimationFrame(() => {
t?.querySelector(".breakpoint-list-item--current")?.scrollIntoView({ block: "center" });
});
}
sortScopeEntries(e) {
return e.sort(([t], [a]) => t.localeCompare(a));
}
renderPreviewLabel(e) {
return r`<bdi>${e}</bdi>`;
}
renderPreviewCell(e) {
return e ? L(e) || C(e) ? M({ value: e }) : r`<span class="xs"></span>` : r`<span class="xs"></span>`;
}
renderScopeEntryForScope(e, t, a) {
const [i, o] = a, s = `${t}.${i}`, n = this.lazyTreeState;
return n ? B({ name: i, value: o, messages: this.messages, path: `${e}.${i}`, lazyTreeState: n, previewLabel: s, previewSourcePath: V(e, i), previewLoading: this.previewTabsState.isTabLoading(s), onLoadPreview: (d) => {
this.loadPreview(d);
} }) : null;
}
renderBreakpointPopover(e) {
return this.breakpoints.length ? r`<calcite-popover .referenceElement=${this._breakpointPopoverId} placement=bottom-end scale=s auto-close focus-trap-disabled =${(t) => this.scrollToSelectedBreakpoint(t)} .label=${this.messages.breakpoints ?? "Breakpoints"} class="breakpoints-popover" .heading=${this.messages.breakpoints ?? "Breakpoints"} heading-level=2><div class="breakpoints-popover-content"><div class="breakpoints-list">${this.breakpoints.map((t, a) => r`<div class=${w(t.line === e ? "breakpoint-list-item breakpoint-list-item--current" : "breakpoint-list-item")}><div class="breakpoint-list-item-meta"><bdi>${this.getBreakpointPositionText(a + 1)}</bdi></div><arcgis-code-viewer language=arcade class="breakpoint-code-viewer" .lineNumbers=${(i) => String(i + t.line - 1)}>${this.getBreakpointCode(t.line)}</arcgis-code-viewer></div>`)}</div></div></calcite-popover>` : null;
}
renderScopePanel() {
const e = this.executionProgramState, t = this.sortScopeEntries(Array.from(e?.profile ?? [])), a = this.sortScopeEntries(Array.from(e?.globals ?? [])), i = e?.locals ? this.sortScopeEntries(Array.from(e?.locals ?? [])) : void 0, o = !!e?.locals, s = i && i.length > 0, n = t.length > 0, d = a.length > 0;
return e ? r`<calcite-tree .scale=${l.scale} =${l.oncalciteTreeSelect} .lines=${l.lines} .selectionMode=${l.selectionMode}><calcite-tree-item expanded .disabled=${!s}>${this.messages.local ?? "Local"}<calcite-tree slot=children .lines=${l.lines} .selectionMode=${l.selectionMode} .scale=${l.scale} =${l.oncalciteTreeSelect}>${o ? s ? i.map((c) => this.renderScopeEntryForScope("locals", this.messages.local ?? "Local", c)) : r`<span><i>${this.messages.empty ?? "Empty"}</i></span>` : r`<span><i>${this.messages.nolocalscope ?? "No local scope"}</i></span>`}</calcite-tree></calcite-tree-item><calcite-tree-item expanded .disabled=${!d}>${this.messages.global ?? "Global"}<calcite-tree slot=children .lines=${l.lines} .selectionMode=${l.selectionMode} .scale=${l.scale} =${l.oncalciteTreeSelect}>${d ? a.map((c) => this.renderScopeEntryForScope("globals", this.messages.global ?? "Global", c)) : r`<span><i>${this.messages.empty ?? "Empty"}</i></span>`}</calcite-tree></calcite-tree-item><calcite-tree-item expanded .disabled=${!n}>${this.messages.profile ?? "Profile"}<calcite-tree slot=children .lines=${l.lines} .selectionMode=${l.selectionMode} .scale=${l.scale} =${l.oncalciteTreeSelect}>${n ? t.map((c) => this.renderScopeEntryForScope("profile", this.messages.profile ?? "Profile", c)) : r`<span><i>${this.messages.empty ?? "Empty"}</i></span>`}</calcite-tree></calcite-tree-item></calcite-tree>` : this.debuggerStore?.isExecuting ? r`<div class="preview-empty-state"><calcite-loader scale=s type=indeterminate .label=${this.messages.loading ?? "Loading"} .text=${this.messages.loading ?? "Loading"}></calcite-loader></div>` : r`<span class="disabled-state-text">${this.messages.notpaused ?? "Not paused"}</span>`;
}
renderPreviewPanel(e) {
switch (e.status) {
case "loading":
return r`<div class="preview-empty-state"><calcite-loader scale=s type=indeterminate .label=${this.messages.loadingpreview ?? "Loading preview"} .text=${this.messages.loadingpreview ?? "Loading preview"}></calcite-loader></div>`;
case "unavailable":
case "error":
return r`<span class="disabled-state-text">${e.message}</span>`;
case "loaded":
const { fields: t, label: a, rows: i } = e;
return !i.length || !t.length ? r`<span class="disabled-state-text">${this.messages.nopreviewrows ?? "No preview rows available."}</span>` : r`<div class="preview-table-shell"><div class="preview-table-summary">${this.renderPreviewLabel(a)}</div><div class="table-scroll"><table><thead><tr>${t.map((o) => r`<th><bdi>${o}</bdi></th>`)}</tr></thead><tbody>${i.map((o) => r`<tr>${t.map((s) => r`<td>${this.renderPreviewCell(o.get(s))}</td>`)}</tr>`)}</tbody></table></div></div>`;
default:
return r`<span class="disabled-state-text">${this.messages.nopreviewloaded ?? "Select a FeatureSet variable and load a preview."}</span>`;
}
}
renderTabs() {
const e = this.previewTabsState.activeTabId;
return r`<calcite-tabs><calcite-tab-nav slot=title-group><calcite-tab-title .tab=${p} .selected=${e === p} =${(t) => this.activateTab(t.target.tab)}>${this.messages.scope ?? "Scope"}</calcite-tab-title>${g(this.previewTabsState.tabs, (t) => `title-${t.id}`, (t) => r`<calcite-tab-title .tab=${t.id} title=${t.label ?? b} closable .selected=${e === t.id} =${(a) => this.activateTab(a.target.tab)} =${(a) => this.closePreviewTab(a.target)}><bdi>${t.title}</bdi></calcite-tab-title>`)}</calcite-tab-nav><calcite-tab .tab=${p} .selected=${e === p}><div class="tab-panel">${this.renderScopePanel()}</div></calcite-tab>${g(this.previewTabsState.tabs, (t) => `panel-${t.id}`, (t) => r`<calcite-tab .tab=${t.id} .selected=${e === t.id}><div class="tab-panel preview-panel">${this.renderPreviewPanel(t)}</div></calcite-tab>`)}</calcite-tabs>`;
}
render() {
const { line: e } = this.debuggerStore?.executionState ?? {}, t = e ? this.breakpoints.find((i) => i.line === e) : this.breakpoints[0], a = e ? this.breakpoints.findIndex((i) => i.line === e) : 0;
return r`<div class="console-shell">${this.breakpoints.length && r`<div class="breakpoint-header"><arcgis-code-viewer language=arcade class="breakpoint-code-viewer" .lineNumbers=${(i) => String(i + (t?.line ?? e ?? 1) - 1)}>${this.getBreakpointCode(t?.line ?? this.breakpoints[0]?.line ?? e ?? 1)}</arcgis-code-viewer>${this.breakpoints.length ? r`<calcite-action id=${this._breakpointPopoverId ?? b} scale=s .text=${this.getBreakpointPositionText(a >= 0 ? a + 1 : 1)} text-enabled icon=chevron-down></calcite-action>` : null}${this.renderBreakpointPopover(t?.line ?? e)}</div>` || ""}<div class="tabs-container">${this.renderTabs()}</div></div>`;
}
}
v("arcgis-arcade-debugger-console", N);
export {
N as ArcgisArcadeDebuggerConsole
};