UNPKG

@arcgis/coding-components

Version:
967 lines (966 loc) • 46 kB
/* COPYRIGHT Esri - https://js.arcgis.com/5.1/LICENSE.txt */ import { g as Z, c as ee } from "../../chunks/runtime.js"; import { css as te, html as d, nothing as z } from "lit"; import { i as se } from "../../chunks/monaco-importer.js"; import { LitElement as ie, createEvent as N, safeClassMap as v } from "@arcgis/lumina"; import { generateGuid as ae } from "@arcgis/toolkit/string"; import { i as y, D as ne, e as K } from "../../chunks/arcade-executor.js"; import { s as oe, a as re } from "../../chunks/arcade-service-accessors.js"; import { b as $ } from "../../chunks/arcade-defaults.js"; import { setArcadeAskAiBinding as B, arcadeAskAiCommandId as ce, arcadeQuickFixKind as le } from "../../chunks/arcade-mode.js"; import { u as de } from "../../chunks/useT9n.js"; import { createRef as H, ref as j } from "lit/directives/ref.js"; import { load as ue } from "@arcgis/lumina/controllers"; import he from "@arcgis/core/config.js"; import Q from "@arcgis/core/identity/IdentityManager.js"; import { log as ge, rethrowError as u } from "@arcgis/toolkit/log"; import { watch as L } from "@arcgis/core/core/reactiveUtils.js"; import f from "@arcgis/core/core/Accessor.js"; import { property as c, subclass as x } from "@arcgis/core/core/accessorSupport/decorators.js"; import { A as W } from "../../chunks/ArcadeDebuggerPreviewTabsState.js"; import { r as pe } from "../../chunks/utilities.js"; import { Range as V, KeyCode as be, Uri as _e } from "monaco-editor"; const me = te`:host{height:100%}calcite-tooltip:not([calcite-hydrated])>*{display:none}.main-action-bar{calcite-action-group{padding-inline-end:var(--calcite-spacing-sm)}calcite-action-group calcite-action{padding-inline-end:var(--calcite-spacing-sm)}calcite-action-group calcite-action:not(:first-child){padding-inline-start:var(--calcite-spacing-sm)}calcite-action-group:last-child{border-inline-end-width:0px}calcite-action-group:not(:first-child){padding-inline-start:var(--calcite-spacing-sm)}}.bottom-action-bar.is-collapsed{border-bottom:0}.bottom-action-bar{display:flex;.bottom-action-bar__actions{flex:1 1 auto;min-inline-size:0}}`, G = "https://services6.arcgis.com/HXHga6CfMLMBOlBX/ArcGIS/rest/services/survey123_6e349a50b4504ca6b6107216d568db5f_form/FeatureServer/0", h = (t, e) => { ge(t, "Arcade Assistant", e); }, X = [ "orgAiAssistantsEnabled", "betaAppsAllowed", "serviceUrlAvailable", "userHasUseAiAssistantsPrivilege" ], fe = X, q = (t, e) => e.every((s) => t[s] === !0), xe = (t) => { const { aiAssistantsEnabled: e } = t; return e === void 0 ? (h("warn", "`areAiAssistantsEnabled` is not defined in the organizations settings."), !1) : e; }, Se = async (t) => (await Q.getCredential(t, { oAuthPopupConfirmation: !1 })).token, Ae = async (t) => { try { return !!await Q.checkSignInStatus(t); } catch { return h("warn", "User is not signed in."), !1; } }; async function Pe({ portalUrl: t }) { t && h( "warn", "The arcadeAssistant property is deprecated. Set esriConfig.portalUrl instead of arcadeAssistant.portalUrl." ); const e = t || he.portalUrl; if (!e) return h("warn", "Arcade Assistant initialization failed. Reason: missing portal url."), { shouldRender: !1 }; const s = e.replace(/\/sharing\/rest(\/.*)?$/iu, "").replace(/\/$/u, ""); if (!await Ae(s)) return { shouldRender: !1 }; const a = await Se(e), r = `${s}/sharing/rest/portals/self?f=json&token=${a}`, n = `${s}/sharing/rest/portals/self/settings?f=json&token=${a}`, o = `${s}/sharing/rest/portals/self/signinSettings?f=json&token=${a}`, b = await Promise.allSettled([ fetch(r, { credentials: "include" }).then((P) => P.json()), fetch(n, { credentials: "include" }).then((P) => P.json()), fetch(o, { credentials: "include" }).then((P) => P.json()) ]), [S, R, I] = b, A = S.status === "fulfilled" ? S.value : (h("warn", `Failed to fetch selfUrl. Reason: ${S.reason}.`), {}), T = R.status === "fulfilled" ? R.value : (h("warn", `Failed to fetch settingsUrl. Reason: ${R.reason}.`), {}), J = I.status === "fulfilled" ? I.value : (h("warn", `Failed to fetch signinSettingsUrl. Reason: ${I.reason}.`), {}); if (A.isPortal) return { shouldRender: !1 }; const M = A.helpBase || ""; if (!T) return h("warn", "Settings response is not available."), { shouldRender: !1 }; const k = { orgAiAssistantsEnabled: xe(T), betaAppsAllowed: J.blockBetaApps !== !0, serviceUrlAvailable: !!A?.helperServices?.aiAssistantServices?.url, userHasUseAiAssistantsPrivilege: A?.user?.privileges?.includes("portal:user:useAIAssistants") === !0 }; k.betaAppsAllowed || h( "warn", "Arcade Assistant is blocked by the organization settings. To enable it, do not block beta apps in the organization settings." ), k.userHasUseAiAssistantsPrivilege || h("warn", "User does not have the required privileges to use AI Assistants."); const F = q(k, fe), U = q(k, X), O = A?.helperServices?.aiAssistantServices?.url; return O ? { shouldRender: !0, portalUrl: e, availableFeatures: { codeActions: F, prompting: U }, serviceUrl: O, helpBase: M, feedbackServiceUrl: G } : { shouldRender: !0, portalUrl: e, availableFeatures: { codeActions: F, prompting: U }, helpBase: M, feedbackServiceUrl: G }; } var ve = Object.defineProperty, $e = Object.getOwnPropertyDescriptor, m = (t, e, s, i) => { for (var a = i > 1 ? void 0 : i ? $e(e, s) : e, r = t.length - 1, n; r >= 0; r--) (n = t[r]) && (a = (i ? n(e, s, a) : n(a)) || a); return i && a && ve(e, s, a), a; }; const Y = 100; let g = class extends f { constructor(t) { super(t), this.collectionItems = [], this.errorMessage = "", this.expanded = !1, this.requestId = 0, this.status = "idle", this.visibleChildCount = Y; } }; m([ c() ], g.prototype, "collectionItems", 2); m([ c() ], g.prototype, "errorMessage", 2); m([ c() ], g.prototype, "expanded", 2); m([ c() ], g.prototype, "requestId", 2); m([ c() ], g.prototype, "schemaValue", 2); m([ c() ], g.prototype, "status", 2); m([ c() ], g.prototype, "visibleChildCount", 2); g = m([ x("ArcadeDebuggerLazyTreeNodeState") ], g); let C = class extends f { constructor(t) { super(t), this.generation = 0, this.nodes = /* @__PURE__ */ new Map(); } reset() { this.generation += 1, this.destroyNodes(); } ensureNode(t, e = !1, s) { const i = this.nodes.get(t); if (i) return i; const a = new g(); return a.expanded = e, this.nodes.set(t, a), e && s && this.loadNode(t, s), a; } setExpanded(t, e, s) { const i = this.ensureNode(t, e, s); if (i.expanded === e) { e && s && this.loadNode(t, s); return; } i.expanded = e, e && s && this.loadNode(t, s); } showMore(t, e) { const s = this.ensureNode(t); s.visibleChildCount >= e || (s.visibleChildCount = Math.min(e, s.visibleChildCount + Y)); } loadNode(t, e) { switch (e.kind) { case "collection": this.runLoad(t, e.load, (s, i) => { s.collectionItems = i; }); return; case "schema": this.runLoad(t, e.load, (s, i) => { s.schemaValue = i; }); return; } } runLoad(t, e, s) { const i = this.nodes.get(t); if (!i || i.status === "loading" || i.status === "loaded") return; const a = this.generation, r = i.requestId + 1; i.requestId = r, i.status = "loading", i.errorMessage = "", i.schemaValue = void 0, i.collectionItems = [], e().then((n) => { const o = this.nodes.get(t); !o || this.generation !== a || o.requestId !== r || (s(o, n), o.status = "loaded"); }).catch(() => { const n = this.nodes.get(t); !n || this.generation !== a || n.requestId !== r || (n.status = "error"); }); } destroyNodes() { for (const t of this.nodes.values()) t.destroy(); this.nodes.clear(); } }; C = m([ x("ArcadeDebuggerLazyTreeState") ], C); var ye = Object.defineProperty, Ee = Object.getOwnPropertyDescriptor, l = (t, e, s, i) => { for (var a = i > 1 ? void 0 : i ? Ee(e, s) : e, r = t.length - 1, n; r >= 0; r--) (n = t[r]) && (a = (i ? n(e, s, a) : n(a)) || a); return i && a && ye(e, s, a), a; }; let _ = class extends f { constructor(t) { super(t), this.phase = "idle", this.sessionId = 0, this.consoleLogs = [], this.hasExecuted = !1; } get isExecuting() { return this.phase === "running" || this.phase === "debug-running" || this.phase === "debug-paused"; } get isDebugging() { return this.phase === "debug-running" || this.phase === "debug-paused"; } get isPaused() { return this.phase === "debug-paused"; } get runResult() { return this.result?.resultType === "run" ? this.result.result : void 0; } get debugResult() { return this.result?.resultType === "debug" ? this.result.result : void 0; } addConsoleLog(t) { this.consoleLogs = [...this.consoleLogs, t]; } }; l([ c() ], _.prototype, "phase", 2); l([ c() ], _.prototype, "mode", 2); l([ c() ], _.prototype, "sessionId", 2); l([ c() ], _.prototype, "result", 2); l([ c() ], _.prototype, "consoleLogs", 2); l([ c() ], _.prototype, "hasExecuted", 2); _ = l([ x("ArcadeDebuggerExecutionModel") ], _); let E = class extends f { constructor(t) { super(t), this.editorBreakpoints = [], this.executionBreakpoints = []; } setBreakpoints(t, e) { t === "editor" ? this.editorBreakpoints = Array.from(new Set(e)).sort((s, i) => s - i) : this.executionBreakpoints = Array.from(new Set(e)).sort((s, i) => s - i); } toggleBreakpoint(t, e) { const s = new Set(t === "editor" ? this.editorBreakpoints : this.executionBreakpoints); s.has(e) ? s.delete(e) : s.add(e), this.setBreakpoints(t, s); } clearBreakpoints(t) { t === "editor" ? this.editorBreakpoints = [] : this.executionBreakpoints = []; } syncExecutionBreakpointsFromEditor() { this.executionBreakpoints = this.editorBreakpoints; } }; l([ c() ], E.prototype, "editorBreakpoints", 2); l([ c() ], E.prototype, "executionBreakpoints", 2); E = l([ x("ArcadeDebuggerSessionModel") ], E); let D = class extends f { constructor(t) { super(t), this.openedPanel = "output", this.showPanel = !1; } }; l([ c() ], D.prototype, "openedPanel", 2); l([ c() ], D.prototype, "showPanel", 2); D = l([ x("ArcadeDebuggerUiModel") ], D); let w = class extends f { constructor(t) { super(t); } get line() { return this.pausedState?.line; } clearPausedState() { this.lastPausedState = this.pausedState, this.pausedState = void 0; } reset() { this.pausedState = void 0, this.lastPausedState = void 0; } setPausedState(t) { this.pausedState = t, this.lastPausedState = t; } }; l([ c() ], w.prototype, "pausedState", 2); l([ c() ], w.prototype, "lastPausedState", 2); w = l([ x("ArcadeDebuggerPausedFrameModel") ], w); let p = class extends f { constructor(t) { super(t), this.execution = new _(), this.lazyTreeState = new C(), this.pausedFrame = new w(), this.previewTabsState = new W(), this.session = new E(), this.ui = new D(); } get editorBreakpoints() { return this.session.editorBreakpoints; } /** The "displayed" breakpoints within the console. depends on if the debugger is paused or not */ get debuggerBreakpoints() { return this.isPaused ? this.session.executionBreakpoints.map((t) => ({ line: t })) : this.session.editorBreakpoints.map((t) => ({ line: t })); } get executionBreakpoints() { return this.session.executionBreakpoints; } get consoleLogs() { return this.execution.consoleLogs; } get debug() { if (!(!this.pausedFrame.pausedState && !this.pausedFrame.lastPausedState)) return { pausedState: this.pausedFrame.pausedState, lastPausedState: this.pausedFrame.lastPausedState }; } get debugResult() { return this.execution.debugResult; } get debuggerLine() { return this.pausedFrame.pausedState?.line; } get executionState() { return this.pausedFrame.pausedState; } get hasExecuted() { return this.execution.hasExecuted; } get isDebugging() { return this.execution.isDebugging; } get isExecuting() { return this.execution.isExecuting; } get isPaused() { return this.execution.isPaused; } get mode() { return this.execution.mode; } get openedPanel() { return this.ui.openedPanel; } get outputRenderer() { if (this.execution.result) return this.execution.result.resultType === "debug" ? "debugger" : "legacy"; } get phase() { return this.execution.phase; } get result() { return this.execution.result; } get runResult() { return this.execution.runResult; } get sessionId() { return this.execution.sessionId; } get showPanel() { return this.ui.showPanel; } addConsoleLog(t) { this.execution.addConsoleLog(t); } clearBreakpoints(t) { this.session.clearBreakpoints(t); } clearForMissingTestData() { this.stopDebug({ hidePanel: !0 }), this.execution.hasExecuted = !1, this.execution.result = void 0; } closePanel() { this.ui.showPanel = !1; } completeDebug(t) { this.execution.mode = "debug", this.execution.result = { resultType: "debug", result: t }, this.execution.phase = "completed", this.ui.openedPanel = "output", this.pausedFrame.reset(), this.resetTransientDebuggerState(); } completeRun(t, e = {}) { this.execution.mode = "run", !e.useDebugRenderer && y(t) ? this.execution.result = { resultType: "run", result: t } : e.useDebugRenderer && !y(t) && (this.execution.result = { resultType: "debug", result: t }), this.execution.phase = "completed", this.pausedFrame.reset(), this.ui.openedPanel = "output", this.resetTransientDebuggerState(); } continueDebug() { const t = this.pausedFrame.pausedState?.continue; t && (this.execution.phase = "debug-running", this.pausedFrame.clearPausedState(), t.resolve()); } disableDebugger() { this.stopDebug({ hidePanel: !0 }), this.clearBreakpoints("execution"), this.clearBreakpoints("editor"); } fail(t) { this.completeRun(t); } pauseDebug(t) { const e = this.pausedFrame.pausedState ?? this.pausedFrame.lastPausedState; this.syncPausedState(e, t), this.pausedFrame.setPausedState(t), this.execution.phase = "debug-paused"; } reset() { this.execution.phase = "idle", this.execution.mode = void 0, this.execution.result = void 0, this.execution.consoleLogs = [], this.execution.hasExecuted = !1, this.execution.sessionId = 0, this.ui.openedPanel = "output", this.ui.showPanel = !1, this.pausedFrame.reset(), this.clearBreakpoints("execution"), this.clearBreakpoints("editor"), this.replaceTransientDebuggerState(); } resetDebug() { this.stopDebug({ hidePanel: !1 }), this.execution.result = void 0, this.execution.consoleLogs = [], this.ui.openedPanel = "debug-console"; } disconnect() { this.stopDebug({ hidePanel: !0 }); } setBreakpoints(t) { this.session.setBreakpoints("editor", t); } setPanel(t) { this.execution.hasExecuted && (this.ui.openedPanel = t, this.ui.showPanel = !0); } startDebug() { return this.execution.mode = "debug", this.execution.phase = "debug-running", this.execution.hasExecuted = !0, this.execution.result = void 0, this.session.syncExecutionBreakpointsFromEditor(), this.execution.consoleLogs = [], this.ui.openedPanel = "debug-console", this.ui.showPanel = !0, this.execution.sessionId += 1, this.pausedFrame.reset(), this.replaceTransientDebuggerState(), this.execution.sessionId; } startRun() { return this.execution.mode = "run", this.execution.phase = "running", this.execution.hasExecuted = !0, this.execution.result = void 0, this.execution.consoleLogs = [], this.ui.openedPanel = "output", this.ui.showPanel = !0, this.execution.sessionId += 1, this.pausedFrame.reset(), this.replaceTransientDebuggerState(), this.execution.sessionId; } stopDebug({ hidePanel: t = !0, invalidateSession: e = !0 } = {}) { const s = this.pausedFrame.pausedState?.continue; e && (this.execution.sessionId += 1), this.execution.phase = this.execution.hasExecuted ? "completed" : "idle", this.pausedFrame.reset(), this.resetTransientDebuggerState(), t && (this.ui.showPanel = !1), this.ui.openedPanel === "debug-console" && (this.ui.openedPanel = "output"), s?.resolve(); } /** * Resets transient debugger state (paused line, lazy tree state, preview tabs state). * If the paused state has changed, also invalidates all preview tabs to ensure they are reloaded when next opened. */ syncPausedState(t, e) { this.lazyTreeState.reset(), t && e && t !== e && this.previewTabsState.invalidateAll(), this.pausedLine = e?.line; } toggleBreakpoint(t) { this.session.toggleBreakpoint("editor", t); } togglePanel(t) { if (this.execution.hasExecuted) { if (t == null) { this.ui.showPanel = !this.ui.showPanel; return; } if (this.ui.openedPanel === t && this.ui.showPanel) { this.ui.showPanel = !1; return; } this.setPanel(t); } } resetTransientDebuggerState() { this.pausedLine = void 0, this.lazyTreeState.reset(), this.previewTabsState.clear(); } replaceTransientDebuggerState() { this.pausedLine = void 0, this.lazyTreeState = new C(), this.previewTabsState = new W(); } }; l([ c() ], p.prototype, "execution", 2); l([ c() ], p.prototype, "lazyTreeState", 2); l([ c() ], p.prototype, "pausedLine", 2); l([ c() ], p.prototype, "pausedFrame", 2); l([ c() ], p.prototype, "previewTabsState", 2); l([ c() ], p.prototype, "session", 2); l([ c() ], p.prototype, "ui", 2); p = l([ x("ArcadeDebuggerStore") ], p); const De = { glyphMargin: !0, lineNumbersMinChars: 1 }; class we extends ie { constructor() { super(...arguments), this._codeEditorElt = H(), this._arcadeAssistantElt = H(), this._componentReadyDefer = Promise.withResolvers(), this._disposables = [], this._editorProfilePromise = Promise.resolve(void 0), this._debuggerState = new p(), this.messages = de(), this._modelId = ae(), this._openArcadeHelp = () => { window.open(ne, "Arcade Help"); }, this._decorations = void 0, this._monacoEditor = ue(se), this._editorOptions = {}, this._toggleSidePanel = (e) => { e.currentTarget instanceof HTMLElement && this._setOpenedSidePanel(e.currentTarget.dataset.panelName ?? "none"); }, this._closeSidePanel = () => { this._setOpenedSidePanel("none"); }, this._updateBreakpointsDecorations = () => { const e = this.editorInstance; if (!e) return; const s = this._debuggerState.editorBreakpoints.map((i) => ({ range: new V(i, 1, i, 1), options: { isWholeLine: !0, glyphMarginClassName: "arcgis-code-editor__breakpoint-glyph", // keeps decoration at the same line when typing at the edges of the line or the range gets collapsed. essentially keeps breakpoint decoration as a single-line stickiness: this._monacoEditor.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges } })); this._decorations?.clear(), this._decorations = e.createDecorationsCollection(s); }, this._clearDebuggerDecorations = () => { this._decorations?.clear(), this._decorations = void 0, this._debuggerPausedLineDecoration?.clear(), this._debuggerPausedLineDecoration = void 0; }, this._debuggerPausedLineDecoration = void 0, this._preparingArcade = !1, this._arcadeAssistantRemoteState = { shouldRender: !1 }, this._diagnostics = [], this.enableDebugger = !1, this.hideDocumentationActions = !1, this.hideSideBar = !1, this.openedSidePanel = "none", this.script = "", this.sideActionBarExpanded = !1, this.disableAssistant = !1, this.arcgisDiagnosticsChange = N({ bubbles: !1 }), this.arcgisScriptChange = N({ bubbles: !1 }); } static { this.properties = { _apiLibrary: 16, _editorProfile: 16, _preparingArcade: 16, _arcadeAssistantRemoteState: 16, _diagnostics: 16, editorInstance: 32, editorOptions: 0, enableDebugger: 5, hideDocumentationActions: 5, hideSideBar: 5, messageOverrides: 0, openedSidePanel: 3, profile: 0, script: 1, sideActionBarExpanded: 7, snippets: 0, suggestions: 0, testData: 0, customPanels: 0, disableAssistant: 5, arcadeAssistant: 0, externalExecutor: 0 }; } static { this.styles = [me]; } get _canExecute() { return !!(this.testData || this.externalExecutor); } get _usesBottomExecutionDrawer() { return this._canExecute && (this.enableDebugger || !!this.externalExecutor); } get editorInstance() { return this._codeEditorElt.value?.editorInstance; } get editorOptions() { return { ...De, ...this._editorOptions }; } set editorOptions(e) { this._editorOptions = e ?? {}; } async getTestResult() { if (!this.testData) return { type: "error", value: "Missing test data", error: null }; const e = await this._editorProfilePromise; if (!e) return { type: "error", value: "Missing editor profile", error: null }; await this._componentReadyDefer.promise; const s = this._codeEditorElt.value?.value, i = await K(e.definition, s, this.testData, { mode: "run" }); return y(i) ? i : { type: "error", value: "Unexpected debug result", error: null }; } async setFocus() { await this._componentReadyDefer.promise, await this._codeEditorElt.value?.setFocus(); } async openArcadeAssistant(e) { if (!this._arcadeAssistantRemoteState.shouldRender) return !1; if (this.openedSidePanel = "arcade-assistant", await this.updateComplete, !this._canPromptWithArcadeAssistant()) return !0; const s = this._arcadeAssistantElt.value; return e?.prompt && await s?.openPrompt(e.prompt), !0; } async load() { const e = Z("./assets"); oe(e), await this._updateDataModelDeps(), this.manager.onLifecycle(() => (this.hasUpdated && this._connectMonacoCustomizations().catch(u(this)), () => { for (this._askAiBindingKey && (B(this._askAiBindingKey, void 0), this._askAiBindingKey = void 0); this._disposables.length; ) this._disposables.pop()?.dispose(); this._abortExternalExecution(), this._connectMonacoCustomizationsPromise = void 0, this._executeScriptAction = void 0, this._clearDebuggerDecorations(), this._debuggerState.disconnect(); })); } willUpdate(e) { (e.has("messages") || e.has("profile")) && this._updateDataModelDeps(), (e.has("testData") || e.has("externalExecutor")) && this._executionContextChanged(), e.has("enableDebugger") && !this.enableDebugger && this._debuggerState.disableDebugger(), e.has("snippets") && $.updateApiContextForModel(this._modelId, { snippets: this.snippets }), (e.has("arcadeAssistant") || e.has("disableAssistant")) && this._updateArcadeAssistantRemoteState(); } async loaded() { await this._connectMonacoCustomizations(), this._componentReadyDefer.resolve(); } _setOpenedSidePanel(e) { this.openedSidePanel = e === this.openedSidePanel ? "none" : e; } async _connectMonacoCustomizations() { if (this._connectMonacoCustomizationsPromise) return await this._connectMonacoCustomizationsPromise; this._connectMonacoCustomizationsPromise = (async () => { if (!this.isConnected) return; const e = await re(); this._disposables.push(e.onDiagnosticsChange((o) => { this._preparingArcade || (this._diagnostics = o.diagnostics, this.arcgisDiagnosticsChange.emit(o.diagnostics)); })), this._canExecute && !this._executeScriptAction && this._addExecuteScriptAction(), this._syncAskAiAction(); const s = L(() => this._debuggerState.editorBreakpoints, () => this._updateBreakpointsDecorations(), { sync: !0 }), i = L(() => this._debuggerState.debuggerLine, () => this._updateDebuggerPausedLineDecoration(), { sync: !0 }), a = L(() => this._debuggerState.consoleLogs.length, () => this.requestUpdate(), { sync: !0 }); this._disposables.push({ dispose: () => s.remove() }, { dispose: () => i.remove() }, { dispose: () => a.remove() }); const r = this.editorInstance?.onMouseDown((o) => this._onEditorMouseDown(o)); r && this._disposables.push(r); const n = this.editorInstance?.onDidChangeModelContent((o) => this._onEditorModelContentChange(o)); n && this._disposables.push(n), this._updateBreakpointsDecorations(), this._updateDebuggerPausedLineDecoration(); })(); try { await this._connectMonacoCustomizationsPromise; } finally { this._connectMonacoCustomizationsPromise = void 0; } } _onEditorMouseDown(e) { if (!this.enableDebugger || ![this._monacoEditor.MouseTargetType.GUTTER_GLYPH_MARGIN].includes(e.target.type) || e.target.element?.classList.contains("codicon-gutter-lightbulb")) return; const s = e.target.position?.lineNumber; s && this._debuggerState.toggleBreakpoint(s); } _onEditorModelContentChange(e) { if (!this.enableDebugger || !this._debuggerState.editorBreakpoints.length || e.isFlush) return; const s = pe(this._debuggerState.editorBreakpoints, e.changes); s.length === this._debuggerState.editorBreakpoints.length && s.every((i, a) => i === this._debuggerState.editorBreakpoints[a]) || this._debuggerState.setBreakpoints(s); } _updateDebuggerPausedLineDecoration() { const e = this.editorInstance; if (!e) return; this._debuggerPausedLineDecoration?.clear(); const s = this._debuggerState.debuggerLine; s != null ? this._debuggerPausedLineDecoration = e.createDecorationsCollection([ { range: new V(s, 1, s, 1), options: { isWholeLine: !0, className: "arcgis-code-editor__debugger-paused-line", glyphMarginClassName: "arcgis-code-editor__debugger-paused-glyph", marginClassName: "arcgis-code-editor__debugger-paused-line arcgis-code-editor__debugger-paused-margin", // keeps decoration at the same line when typing at the edges of the line or the range gets collapsed. // essentially keeps paused decoration as a single-line no matter what stickiness: this._monacoEditor.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges } } ]) : this._debuggerPausedLineDecoration = void 0; } _continueDebugSession() { this._debuggerState.continueDebug(); } _abortExternalExecution() { this._externalExecutionAbortController?.abort(), this._externalExecutionAbortController = void 0; } _stopDebugSession() { this._abortExternalExecution(), this._debuggerState.stopDebug({ hidePanel: !1 }); } _resetDebugSession() { this._abortExternalExecution(), this._debuggerState.resetDebug(), this._executeScript("debug").catch(u(this)); } async _handleDebugPause(e, s, i) { if (!this._debuggerState.isDebugging || e !== this._debuggerState.sessionId) return; const a = Promise.withResolvers(); return this._debuggerState.pauseDebug({ line: s.line, result: i, continue: a }), await a.promise; } async _updateDataModelDeps() { await this._updateEditorProfile(), await this._updateApiLibrary(); } async _executeWithExternalExecutor(e, s, i) { if (!this.externalExecutor) return { type: "error", value: "Missing external executor", error: null }; const a = new AbortController(); this._abortExternalExecution(), this._externalExecutionAbortController = a; const r = i.console ?? (() => { }); try { if (e === "debug") { const { breakpoints: n, onDebugPause: o } = i; if (!n || !o) throw new Error("Missing debug execution options"); return await this.externalExecutor.execute({ mode: "debug", script: s, console: r, signal: a.signal, breakpoints: n, onDebugPause: o }); } return await this.externalExecutor.execute({ mode: "run", script: s, console: r, signal: a.signal }); } catch (n) { return { type: "error", value: "Execution failed", error: n instanceof Error ? n : new Error(String(n)) }; } finally { this._externalExecutionAbortController === a && (this._externalExecutionAbortController = void 0); } } _executionContextChanged() { !this._canExecute && this._executeScriptAction && (this._disposeSafely(this._executeScriptAction), this._executeScriptAction = void 0), this._canExecute && !this._executeScriptAction && this._addExecuteScriptAction(), !this.testData && this.enableDebugger && this._debuggerState.clearForMissingTestData(), this._debuggerState.openedPanel === "debug-console" && !this.enableDebugger && this._debuggerState.closePanel(), this._debuggerState.showPanel && this._executeScript("run").catch(u(this)); } async _updateEditorProfile() { this._preparingArcade = !0; try { await $.setProfileForModel(this._modelId, this.profile, { locale: this.messages._t9nLocale, snippets: this.snippets }), this._editorProfile = $.getEditorProfileForModel(this._modelId); } catch { this._editorProfile = void 0; } finally { this._editorProfilePromise = Promise.resolve(this._editorProfile), this._preparingArcade = !1; } } async _updateApiLibrary() { this._apiLibrary = await $.getApiLibraryForModel(this._modelId); } _setExecutionPanel(e) { this._debuggerState.setPanel(e); } async _executeScript(e) { const s = this.testData, i = this.externalExecutor; if (!this._codeEditorElt.value || !s && !i) return; const a = e === "debug" ? this._debuggerState.startDebug() : this._debuggerState.startRun(); setTimeout(() => { (async () => { const r = this._codeEditorElt.value?.value ?? this.script, n = { mode: e, console: (b) => this._debuggerState.addConsoleLog(b), breakpoints: e === "debug" ? this._debuggerState.debuggerBreakpoints : void 0 }; e === "debug" && (n.onDebugPause = this._handleDebugPause.bind(this, a)); let o; if (i) o = await this._executeWithExternalExecutor(e, r, n); else if (s) { const b = await this._editorProfilePromise; if (!b) { this._debuggerState.fail({ type: "error", value: "Missing editor profile", error: null }); return; } o = await K(b.definition, r, s, n); } else return; if (a === this._debuggerState.sessionId) { if (e === "debug") { if (y(o)) { this._debuggerState.fail(o); return; } this._debuggerState.completeDebug(o); return; } y(o) ? this._debuggerState.completeRun(o) : i ? this._debuggerState.completeRun(o, { useDebugRenderer: !0 }) : this._debuggerState.fail({ type: "error", value: "Unexpected debug result", error: null }); } })(); }, 0); } _toggleShowExecutionPanel() { this._debuggerState.togglePanel(); } _toggleSideActionBarExpanded() { this.sideActionBarExpanded = !this.sideActionBarExpanded; } _onCodeEditorValueChange(e) { e.stopPropagation(), this.script = e.detail, this.arcgisScriptChange.emit(e.detail); } _insertAsSnippet(e) { this._codeEditorElt.value?.insertSnippet(e.detail).catch(u(this)); } _insertAsText(e) { this._insertText(e.detail); } _insertText(e) { this._codeEditorElt.value?.insertText(e).catch(u(this)); } _onResultPanelChange(e) { const s = e.currentTarget; this._debuggerState.setPanel(s.openedResultPanel); } _onExecutionPanelClose() { this._debuggerState.closePanel(); } _addExecuteScriptAction() { const e = this.editorInstance?.addAction({ // An unique identifier for the action. id: "run-script", label: "Run Arcade Expression", keybindings: [be.F5], contextMenuGroupId: "code", contextMenuOrder: 1, run: () => { this._canExecute && this._executeScript("run").catch(u(this)); } }); e && (this._executeScriptAction = e, this._disposables.push(e)); } _getAskAiBindingKey() { return _e.parse(this._modelId).toString(); } _canRenderAskAiCodeActions() { const e = this._arcadeAssistantRemoteState; return e.shouldRender ? e.availableFeatures.codeActions : !1; } _canPromptWithArcadeAssistant() { const e = this._arcadeAssistantRemoteState; return e.shouldRender ? e.availableFeatures.prompting : !1; } _getAskAiCodeActions(e) { if (!this._canRenderAskAiCodeActions()) return []; if (!e.markers.length) return []; const s = this.messages.askarcadeassistant ?? "Ask Arcade Assistant", i = this._getAskAiBindingKey(); return [ { title: s, kind: le, diagnostics: e.markers, isPreferred: !1, // isAI adds the sparkle and adds it to the hover menu, but it changes the // behavior in the code editing experience, it shows up as a sparkle next to the error. // The sparkle doesn't explain what it does, and imo will cause confusion, thus we are opting to not use it for now. isAI: !1, command: { id: ce, title: s, arguments: [i, this.messages.askarcadeassistantprompt ?? "Fix the errors in my script"] } } ]; } _syncAskAiAction() { if (!this.editorInstance) return; const s = this._getAskAiBindingKey(); if (!this._arcadeAssistantRemoteState.shouldRender) { this._askAiBindingKey && (B(this._askAiBindingKey, void 0), this._askAiBindingKey = void 0); return; } this._askAiBindingKey && this._askAiBindingKey !== s && B(this._askAiBindingKey, void 0), B(s, { provideCodeActions: ({ context: i }) => this._getAskAiCodeActions(i), run: (i) => { this.openArcadeAssistant({ prompt: i ?? this.messages.askarcadeassistantprompt ?? "Fix the errors in my script" }).catch(u(this)); } }), this._askAiBindingKey = s; } _disposeSafely(e) { const s = this._disposables.indexOf(e); s !== -1 && this._disposables.splice(s, 1), e.dispose(); } async _updateArcadeAssistantRemoteState() { const e = this.arcadeAssistant; this.disableAssistant ? this._arcadeAssistantRemoteState = { shouldRender: !1 } : this._arcadeAssistantRemoteState = await Pe(e ?? {}), this._syncAskAiAction(); } renderMainActionBar() { return this._usesBottomExecutionDrawer || !this._canExecute ? null : d`<calcite-action-bar class="main-action-bar" layout=horizontal scale=s expanded expand-disabled slot=top-action-bar><calcite-action-group scale=s><calcite-action .text=${this.messages.run ?? ""} text-enabled icon=play scale=s .loading=${this._preparingArcade} @click=${() => { this._executeScript("run").catch(u(this)); }}></calcite-action>${this._debuggerState.result ? d`<calcite-action .text=${this.messages.lastresults ?? ""} .active=${this._debuggerState.showPanel} text-enabled icon=access-string-results icon-flip-rtl scale=s @click=${this._toggleShowExecutionPanel}></calcite-action>` : null}</calcite-action-group></calcite-action-bar>`; } renderMainPanel() { return d`<arcgis-code-editor slot=editor .editorOptions=${this.editorOptions} .language=${$.languageId} .value=${this.script ?? ""} .modelId=${this._modelId} @arcgisValueChange=${this._onCodeEditorValueChange} ${j(this._codeEditorElt)}></arcgis-code-editor>`; } renderAction({ id: e, label: s, icon: i, active: a, panelName: r, iconFlipRtl: n = !1, onClick: o = this._toggleSidePanel }) { return d`<calcite-action id=${e ?? z} .text=${s} .textEnabled=${this.sideActionBarExpanded} .icon=${i} .active=${a} @click=${o} data-panel-name=${r ?? z} .iconFlipRtl=${n}></calcite-action>${!this.sideActionBarExpanded && d`<calcite-tooltip .referenceElement=${e}><span>${s}</span></calcite-tooltip>` || ""}`; } renderSideActionBar() { return this.hideSideBar ? null : d`<calcite-action-bar slot=side-action-bar class="side-action-bar" .expanded=${this.sideActionBarExpanded} position=end @calciteActionBarToggle=${this._toggleSideActionBarExpanded}><calcite-action-group>${this.renderAction({ id: "profile-variables-action", label: this.messages.profilevariables ?? "", icon: "profile-variables", active: this.openedSidePanel === "variables", panelName: "variables" })}${this.renderAction({ id: "function-action", label: this.messages.constantsandfunctions ?? "", icon: "function", active: this.openedSidePanel === "api", panelName: "api" })}${this.suggestions?.length ? this.renderAction({ id: "suggestions-action", label: this.messages.suggestions ?? "", icon: "lightbulb", active: this.openedSidePanel === "suggestions", panelName: "suggestions" }) : null}${this._arcadeAssistantRemoteState.shouldRender && this.renderAction({ id: "arcade-assistant-action", label: this.messages.arcadeassistant ?? "Arcade assistant", icon: "effects", active: this.openedSidePanel === "arcade-assistant", panelName: "arcade-assistant" }) || ""}${this.customPanels?.map((e) => e.enabled === !1 ? null : this.renderAction({ id: e.id, label: e.name, icon: e.icon, active: this.openedSidePanel === e.id, panelName: e.id }))}${this.hideDocumentationActions ? null : this.renderAction({ id: "developer-website-action", label: this.messages.help ?? "", icon: "question", active: !1, panelName: "none", iconFlipRtl: this.messages._lang === "ar", onClick: this._openArcadeHelp })}</calcite-action-group></calcite-action-bar>`; } renderSidePanel() { if (this.hideSideBar) return null; const { openedSidePanel: e, _arcadeAssistantRemoteState: s } = this; return d`<arcgis-language-api-panel slot=side-panel class=${v(e === "api" ? "" : "hidden")} .loading=${this._preparingArcade} .apiLibrary=${this._apiLibrary} .hideDocumentationActions=${this.hideDocumentationActions} @arcgisInternalItemSelected=${this._insertAsSnippet} @arcgisInternalClosePanel=${this._closeSidePanel} data-panel-name=none .closed=${e !== "api"}></arcgis-language-api-panel><arcgis-editor-variables slot=side-panel class=${v(e === "variables" ? "" : "hidden")} .loading=${this._preparingArcade} .modelId=${this._modelId} @arcgisInternalItemSelected=${this._insertAsText} @arcgisInternalClosePanel=${this._closeSidePanel} data-panel-name=none .variable=${this._editorProfile} .closed=${e !== "variables"} .messageOverrides=${{ profileempty: this.messages.profileempty, profilevariables: this.messages.profilevariables }}></arcgis-editor-variables>${this.suggestions?.length && d`<arcgis-arcade-suggestions slot=side-panel class=${v(e === "suggestions" ? "" : "hidden")} .closed=${e !== "suggestions"} .suggestions=${this.suggestions} @arcgisInternalItemSelected=${this._insertAsText} @arcgisInternalClosePanel=${this._closeSidePanel} data-panel-name=none></arcgis-arcade-suggestions>` || ""}${s?.shouldRender && d`<arcgis-arcade-coding-assistant slot=side-panel class=${v(e === "arcade-assistant" ? "" : "hidden")} .closed=${e !== "arcade-assistant"} .insertText=${this._insertText.bind(this)} .closePanel=${this._closeSidePanel} .portalUrl=${s.portalUrl} .serviceUrl=${"serviceUrl" in s ? s.serviceUrl : void 0} .helpBase=${s.helpBase} .promptingEnabled=${this._canPromptWithArcadeAssistant()} .feedbackServiceUrl=${s.feedbackServiceUrl} .editorRef=${this.el} .appVersion=${this.arcadeAssistant?.appVersion} .disableQuestionAnswerLogging=${this.arcadeAssistant?.disableQuestionAnswerLogging} .diagnostics=${this._diagnostics} ${j(this._arcadeAssistantElt)}></arcgis-arcade-coding-assistant>` || ""}${this.customPanels?.map((i) => d`<calcite-flow slot=side-panel class=${v(e === i.id ? "" : "hidden")}>${i?.useFlows ? i.renderer?.({ closePanel: this._toggleSidePanel, insertText: this._insertText.bind(this), closed: e !== i.id, /** pass this.el instead of "this" as it is what actually gets attached to the dom */ editorRef: this.el }) : d`<calcite-flow-item .heading=${i.name} heading-level=2 closable .closed=${e !== i.id} @calciteFlowItemClose=${this._toggleSidePanel} .description=${i.description}>${i.renderer?.({ closePanel: this._toggleSidePanel, insertText: this._insertText.bind(this), closed: e !== i.id, /** pass this.el instead of "this" as it is what actually gets attached to the dom */ editorRef: this.el })}</calcite-flow-item>`}</calcite-flow>`)}`; } renderResultsPanel() { if (this._usesBottomExecutionDrawer) return this.renderBottomExecutionBody(); if (!this._debuggerState.showPanel) return null; const e = this._debuggerState.openedPanel === "debug-console" ? "output" : this._debuggerState.openedPanel; return d`<arcgis-arcade-results slot=results-panel .openedResultPanel=${e} .loading=${this._debuggerState.isExecuting} .result=${this._debuggerState.runResult} .consoleLogs=${this._debuggerState.consoleLogs} @arcgisInternalOpenedResultPanelChange=${this._onResultPanelChange} @arcgisInternalClosePanel=${this._onExecutionPanelClose}></arcgis-arcade-results>`; } renderBottomExecutionBody() { const { showPanel: e, openedPanel: s, debugResult: i, isExecuting: a, mode: r } = this._debuggerState; if (!e) return null; const n = s === "debug-console" ? "output" : s; return this.enableDebugger && s === "debug-console" ? d`<arcgis-arcade-debugger-console slot=results-panel .modelId=${this._modelId} .debuggerStore=${this._debuggerState}></arcgis-arcade-debugger-console>` : s === "output" && (r === "debug" || i) ? d`<arcgis-arcade-debugger-output .outputTitle=${this.messages.output} slot=results-panel .debuggerStore=${this._debuggerState} .result=${i}></arcgis-arcade-debugger-output>` : d`<arcgis-arcade-results slot=results-panel class="bottom-results" .openedResultPanel=${n} .loading=${s === "console" && this._debuggerState.isPaused ? !1 : a} .result=${this._debuggerState.runResult} .consoleLogs=${this._debuggerState.consoleLogs} hide-header @arcgisInternalOpenedResultPanelChange=${this._onResultPanelChange}></arcgis-arcade-results>`; } renderBottomActionBar() { if (!this._usesBottomExecutionDrawer) return null; const { showPanel: e, hasExecuted: s, openedPanel: i, isDebugging: a, isPaused: r, isExecuting: n } = this._debuggerState, o = this.messages.continue ?? "Continue", b = this.messages.reset ?? "Reset", S = this.messages.stop ?? "Stop"; return d`<div slot=bottom-action-bar class=${`main-action-bar bottom-action-bar ${e ? "" : "is-collapsed"}`}><calcite-action-bar class="bottom-action-bar__actions" layout=horizontal scale=s expand-disabled expanded><calcite-action-group scale=s>${this.enableDebugger && a ? d`<calcite-action id=debugger-continue-action .text=${o} icon=forward scale=s .disabled=${!r} @click=${this._continueDebugSession}></calcite-action><calcite-tooltip reference-element=debugger-continue-action placement=top><span>${o}</span></calcite-tooltip><calcite-action id=debugger-reset-action .text=${b} icon=reset scale=s @click=${this._resetDebugSession}></calcite-action><calcite-tooltip reference-element=debugger-reset-action placement=top><span>${b}</span></calcite-tooltip><calcite-action id=debugger-stop-action .text=${S} icon=circle-stop scale=s @click=${this._stopDebugSession}></calcite-action><calcite-tooltip reference-element=debugger-stop-action placement=top><span>${S}</span></calcite-tooltip>` : d`<calcite-action .text=${this.messages.run ?? ""} text-enabled icon=play scale=s .loading=${this._preparingArcade || n} @click=${() => { this._executeScript("run").catch(u(this)); }}></calcite-action>${this.enableDebugger && d`<calcite-action .disabled=${this._debuggerState.editorBreakpoints.length === 0} .text=${this.messages.runanddebug ?? "Run and Debug"} text-enabled icon=debug-script scale=s .loading=${this._preparingArcade || n} @click=${() => { this._executeScript("debug").catch(u(this)); }}></calcite-action>` || ""}`}</calcite-action-group>${s ? d`<calcite-action-group scale=s><calcite-action .active=${i === "output" && e} .text=${this.messages.output ?? "Output"} text-enabled scale=s icon=list-show-all icon-flip-rtl @click=${() => this._setExecutionPanel("output")}></calcite-action><calcite-action .active=${i === "console" && e} .text=${this.messages.console ?? "Console"} text-enabled scale=s icon=console icon-flip-rtl @click=${() => this._setExecutionPanel("console")}></calcite-action><calcite-action .active=${i === "log" && e} .text=${this.messages.log ?? "Log"} text-enabled scale=s icon=list icon-flip-rtl @click=${() => this._setExecutionPanel("log")} .disabled=${this.enableDebugger && this._debuggerState.mode === "debug"}></calcite-action>${this.enableDebugger && d`<calcite-action .active=${i === "debug-console" && e} .text=${this.messages.debugconsole ?? "Debug Console"} text-enabled scale=s icon=debug-script .disabled=${this._debuggerState.mode !== "debug"} @click=${() => this._setExecutionPanel("debug-console")}></calcite-action>` || ""}</calcite-action-group>` : null}</calcite-action-bar>${e ? d`<calcite-action .text=${this.messages.close ?? "Close"} scale=s icon=x icon-flip-rtl @click=${this._onExecutionPanelClose} slot=actions-end></calcite-action>` : null}</div>`; } render() { return d`<arcgis-code-editor-shell>${this.renderMainActionBar()}${this.renderMainPanel()}${this.renderBottomActionBar()}${this.renderResultsPanel()}${this.renderSidePanel()}${this.renderSideActionBar()}</arcgis-code-editor-shell>`; } } ee("arcgis-arcade-editor", we); export { we as ArcgisArcadeEditor };