@arcgis/coding-components
Version:
Contains components for editing code in different languages. The currently supported languages are html, css, json, TypeScript, JavaScript, and Arcade.
233 lines (232 loc) • 14.3 kB
JavaScript
import { g as u, c as g } from "../../chunks/runtime.js";
import { html as t, nothing as r } from "lit";
import { KeyCode as _ } from "monaco-editor";
import "monaco-editor/esm/vs/editor/standalone/browser/standaloneServices.js";
import "monaco-editor/esm/vs/editor/standalone/common/standaloneTheme.js";
import "monaco-editor/esm/vs/editor/common/languages/supports/tokenization.js";
import { LitElement as m, createEvent as c, noShadowRoot as f, safeClassMap as a } from "@arcgis/lumina";
import { Deferred as x, generateGuid as b } from "@arcgis/components-utils";
import { D as P, e as l } from "../../chunks/arcade-executor.js";
import { s as v } from "../../chunks/setup-monaco.js";
import { b as s } from "../../chunks/arcade-defaults.js";
import { a as $ } from "../../chunks/arcade-service-accessors.js";
import { u as E } from "../../chunks/useT9n.js";
import { createRef as S, ref as A } from "lit-html/directives/ref.js";
import { css as w } from "@lit/reactive-element/css-tag.js";
import { s as y } from "../../chunks/editor.js";
/*! All material copyright Esri, All Rights Reserved, unless otherwise specified.
See https://js.arcgis.com/4.33/esri/copyright.txt for details.
v4.33.14 */
const D = w`{arcgis-arcade-editor{display:flex;flex-direction:column;position:relative;overflow:hidden;border:var(--arcgis-coding-components-border)!important;box-sizing:border-box;background-color:var(--arcgis-coding-components-background-color);height:100%;.sticky{position:sticky;top:0;z-index:10}.notice-container{margin:var(--calcite-spacing-xxs);padding:var(--calcite-spacing-sm);background-color:var(--calcite-color-foreground-1);text-align:center}.main-action-bar{border-bottom:var(--arcgis-coding-components-border)!important;flex:0 0 auto;calcite-action-group{padding-inline-end:var(--calcite-spacing-sm);calcite-action{padding-inline-end:var(--calcite-spacing-sm)}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)}}arcgis-arcade-results{border-top:var(--arcgis-coding-components-border)!important;box-sizing:border-box;max-height:50%;min-height:50%;margin-bottom:-1px}calcite-flow{[slot=footer]{word-break:break-word}}.hidden{display:none}}}`;
class C extends m {
constructor() {
super(...arguments), this._codeEditorElt = S(), this._componentReadyDefer = new x(), this._disposables = [], this._editorProfilePromise = Promise.resolve(void 0), this.messages = E(), this._modelId = b(), this._openArcadeHelp = () => void window.open(P, "Arcade Help"), this._toggleSidePanel = (e) => {
if (!e.target)
return;
const i = e.target?.dataset.panelName ?? "none";
this.openedSidePanel = i === this.openedSidePanel ? "none" : i, this.openedSidePanel === "none" && this._codeEditorElt.value?.setFocus().catch(console.error);
}, this._consoleLogs = [], this._executingScript = !1, this._preparingArcade = !1, this._resultPanel = "output", this._showExecutionPanel = !1, this.hideDocumentationActions = !1, this.hideSideBar = !1, this.openedSidePanel = "none", this.script = "", this.sideActionBarExpanded = !1, this.arcgisDiagnosticsChange = c({ bubbles: !1 }), this.arcgisScriptChange = c({ bubbles: !1 });
}
static {
this.properties = { _apiLibrary: 16, _consoleLogs: 16, _editorProfile: 16, _executingScript: 16, _executionResult: 16, _preparingArcade: 16, _resultPanel: 16, _showExecutionPanel: 16, editorInstance: 32, editorOptions: 0, hideDocumentationActions: 5, hideSideBar: 5, openedSidePanel: 2, profile: 0, script: 1, sideActionBarExpanded: 7, snippets: 0, suggestions: 0, testData: 0, customPanels: 0 };
}
static {
this.shadowRootOptions = f;
}
static {
this.styles = [D, y];
}
get editorInstance() {
return this._codeEditorElt.value?.editorInstance;
}
async getEditorInstance() {
return await this._componentReadyDefer.promise, this._codeEditorElt.value?.editorInstance;
}
async getScript() {
return await this._componentReadyDefer.promise, this._codeEditorElt.value?.value;
}
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 i = this._codeEditorElt.value?.value;
return await l(e.definition, i, this.testData);
}
async setFocus() {
await this._componentReadyDefer.promise, await this._codeEditorElt.value?.setFocus();
}
async load() {
const e = u("./assets");
v(e), await this._updateEditorProfile();
}
willUpdate(e) {
(e.has("messages") || e.has("profile")) && this._updateDataModelDeps(), e.has("testData") && this._testDataChanged(), e.has("snippets") && s.updateApiContextForModel(this._modelId, {
snippets: this.snippets
});
}
async loaded() {
this._componentReadyDefer.resolve(), await this._updateApiLibrary();
const e = await $();
this._disposables.push(e.onDiagnosticsChange((i) => !this._preparingArcade && this.arcgisDiagnosticsChange.emit(i.diagnostics))), this.testData && this._addExecuteScriptAction(), await this._codeEditorElt.value?.setFocus();
}
disconnectedCallback() {
for (super.disconnectedCallback(); this._disposables.length; )
this._disposables.pop()?.dispose();
}
async _updateDataModelDeps() {
await this._updateEditorProfile(), await this._updateApiLibrary();
}
_testDataChanged() {
!this.testData && this._executeScriptAction && (this._disposeSafely(this._executeScriptAction), this._executeScriptAction = void 0), this.testData && !this._executeScriptAction && this._addExecuteScriptAction(), this._showExecutionPanel && this._executeScript().catch(console.error);
}
async _updateEditorProfile() {
this._preparingArcade = !0;
try {
await s.setProfileForModel(this._modelId, this.profile, {
locale: this.messages._t9nLocale,
snippets: this.snippets
}), this._editorProfile = s.getEditorProfileForModel(this._modelId);
} catch {
this._editorProfile = void 0;
} finally {
this._editorProfilePromise = Promise.resolve(this._editorProfile), this._preparingArcade = !1;
}
}
async _updateApiLibrary() {
this._apiLibrary = await s.getApiLibraryForModel(this._modelId);
}
async _executeScript() {
const e = this.testData;
if (!this._codeEditorElt.value || !e)
return;
const i = await this._editorProfilePromise;
if (!i) {
this._executionResult = { type: "error", value: "Missing editor profile", error: null };
return;
}
this._showExecutionPanel = !0, this._executingScript = !0, this._consoleLogs = [], setTimeout(() => void (async () => {
const o = this._codeEditorElt.value?.value;
this._executionResult = await l(i.definition, o, e, (n) => setTimeout(() => this._consoleLogs = [...this._consoleLogs, n], 0)), this._executingScript = !1;
})(), 0);
}
_toggleShowExecutionPanel() {
this._showExecutionPanel = !this._showExecutionPanel;
}
_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(console.error);
}
_insertAsText(e) {
this._insertText(e.detail);
}
_insertText(e) {
this._codeEditorElt.value?.insertText(e).catch(console.error);
}
_onResultPanelChange(e) {
this._resultPanel = e.detail;
}
_onExecutionPanelClose() {
this._showExecutionPanel = !1;
}
_addExecuteScriptAction() {
const e = this.editorInstance?.addAction({
// An unique identifier for the action.
id: "run-script",
label: "Run Arcade Expression",
keybindings: [_.F5],
contextMenuGroupId: "code",
contextMenuOrder: 1,
run: () => {
this.testData && this._executeScript().catch(console.error);
}
});
e && (this._executeScriptAction = e, this._disposables.push(e));
}
_disposeSafely(e) {
const i = this._disposables.indexOf(e);
i !== -1 && this._disposables.splice(i, 1), e.dispose();
}
renderMainActionBar() {
return this.testData ? t`<calcite-action-bar class="main-action-bar" layout=horizontal scale=s expanded expand-disabled><calcite-action-group scale=s><calcite-action .text=${this.messages.run ?? ""} text-enabled icon=play scale=s .loading=${this._preparingArcade} =${() => void this._executeScript().catch(console.error)}></calcite-action>${this._executionResult ? t`<calcite-action .text=${this.messages.lastresults ?? ""} .active=${this._showExecutionPanel} text-enabled icon=access-string-results icon-flip-rtl scale=s =${this._toggleShowExecutionPanel}></calcite-action>` : null}</calcite-action-group></calcite-action-bar>` : null;
}
renderMainPanel() {
return t`<arcgis-code-editor class="flex-adjustable" .editorOptions=${this.editorOptions} .language=${s.languageId} .value=${this.script ?? ""} .modelId=${this._modelId} =${this._onCodeEditorValueChange} ${A(this._codeEditorElt)}></arcgis-code-editor>`;
}
renderAction({ id: e, label: i, icon: o, active: n, panelName: d, iconFlipRtl: h = !1, onClick: p = this._toggleSidePanel }) {
return t`<calcite-action id=${e ?? r} .text=${i} .textEnabled=${this.sideActionBarExpanded} .icon=${o} .active=${n} =${p} data-panel-name=${d ?? r} .iconFlipRtl=${h}></calcite-action>${!this.sideActionBarExpanded && t`<calcite-tooltip .referenceElement=${e}><span>${i}</span></calcite-tooltip>` || ""}`;
}
renderSideActionBar() {
return this.hideSideBar ? null : t`<calcite-action-bar class="side-action-bar border-inline-start" .expanded=${!!this.sideActionBarExpanded} position=end =${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.customPanels?.map((e) => e.enabled ? this.renderAction({
id: e.id,
label: e.name,
icon: e.icon,
active: this.openedSidePanel === e.id,
panelName: e.id
}) : null)}${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 } = this;
return t`<arcgis-language-api-panel class=${a(e === "api" && "side-panel flex-panel border-inline-start")} .loading=${this._preparingArcade} .apiLibrary=${this._apiLibrary} .hideDocumentationActions=${this.hideDocumentationActions} =${this._insertAsSnippet} =${this._toggleSidePanel} data-panel-name=none .closed=${e !== "api"}></arcgis-language-api-panel><arcgis-editor-variables class=${a(e === "variables" && "side-panel flex-panel border-inline-start")} .loading=${this._preparingArcade} .modelId=${this._modelId} =${this._insertAsText} =${this._toggleSidePanel} data-panel-name=none .variable=${this._editorProfile} .closed=${e !== "variables"}></arcgis-editor-variables>${this.suggestions?.length && t`<arcgis-arcade-suggestions class=${a(e === "suggestions" && "side-panel flex-panel border-inline-start")} .closed=${e !== "suggestions"} .suggestions=${this.suggestions} =${this._insertAsText} =${this._toggleSidePanel} data-panel-name=none></arcgis-arcade-suggestions>` || ""}${this.customPanels?.map((i) => (
/** If useFlows is true, we check to make sure the input starts with calcite-flow-item, and if so, we allow them to render custom flow items */
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
}) : t`<calcite-flow class=${a(e === i.id ? "side-panel flex-panel border-inline-start" : "hidden")}><calcite-flow-item .heading=${i.name} closable =${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() {
return this._showExecutionPanel ? t`<arcgis-arcade-results class="flex-adjustable" .openedResultPanel=${this._resultPanel} .loading=${this._executingScript} .result=${this._executionResult} .consoleLogs=${this._consoleLogs} =${this._onResultPanelChange} =${this._onExecutionPanelClose}></arcgis-arcade-results>` : null;
}
render() {
return t`${this.renderMainActionBar()}<div class="flex-row flex-adjustable"><div class="flex-column flex-adjustable">${this.renderMainPanel()}${this.renderResultsPanel()}</div>${this.renderSidePanel()}${this.renderSideActionBar()}</div>`;
}
}
g("arcgis-arcade-editor", C);
export {
C as ArcgisArcadeEditor
};