UNPKG

@arcgis/coding-components

Version:
218 lines (217 loc) • 16.5 kB
/* 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 @calcitePopoverOpen=${(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} @calciteTreeSelect=${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} @calciteTreeSelect=${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} @calciteTreeSelect=${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} @calciteTreeSelect=${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} @calciteTabsActivate=${(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} @calciteTabsActivate=${(a) => this.activateTab(a.target.tab)} @calciteTabsClose=${(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 };