@scalar/api-client
Version:
the open source API testing client
220 lines (219 loc) • 9.31 kB
JavaScript
import { defineComponent as W, useAttrs as j, ref as d, computed as s, toRef as r, watch as H, createElementBlock as i, openBlock as o, Fragment as Q, createBlock as c, createCommentVNode as f, normalizeClass as G, createElementVNode as w, toDisplayString as J, mergeProps as X, unref as F, withKeys as b, withModifiers as T, createTextVNode as V, renderSlot as $ } from "vue";
import { isDefined as Y } from "@scalar/helpers/array/is-defined";
import { useCodeMirror as Z, useDropdown as _, colorPicker as ee } from "@scalar/use-codemirror";
import { nanoid as te } from "nanoid";
import B from "../data-table/DataTableInputSelect.vue.js";
import le from "../../features/environments/components/EnvironmentVariablesDropdown.vue.js";
import { pillPlugin as ne, backspaceCommand as oe } from "./code-variable-widget.js";
const ae = { class: "whitespace-nowrap" }, re = ["id"], ie = {
key: 0,
class: "z-context text-c-2 absolute right-1.5 bottom-1 hidden font-sans group-has-[:focus-visible]/input:block",
role: "alert"
}, ue = {
key: 5,
class: "centered-y text-orange absolute right-7 text-xs"
}, de = {
key: 6,
class: "centered-y absolute right-0 flex h-full items-center p-1.5 group-has-[.cm-focused]:z-1"
}, se = {
key: 7,
class: "required centered-y text-xxs text-c-3 group-[.error]:text-red bg-b-1 pointer-events-none absolute right-0 mr-0.5 pt-px pr-2 opacity-100 shadow-[-8px_0_4px_var(--scalar-background-1)] transition-opacity duration-150 group-[.alert]:bg-transparent group-[.alert]:shadow-none group-[.error]:bg-transparent group-[.error]:shadow-none peer-has-[.cm-focused]:opacity-0"
}, fe = {
inheritAttrs: !1
}, ve = /* @__PURE__ */ W({
...fe,
__name: "CodeInput",
props: {
modelValue: { type: [String, Number, Boolean] },
environment: {},
type: {},
disabled: { type: Boolean, default: !1 },
error: { type: Boolean, default: !1 },
layout: { default: "desktop" },
enum: {},
examples: {},
default: { type: [String, Number, Boolean] },
nullable: { type: Boolean, default: !1 },
placeholder: {},
required: { type: Boolean },
colorPicker: { type: Boolean, default: !1 },
lineNumbers: { type: Boolean, default: !1 },
lint: { type: Boolean, default: !1 },
lineWrapping: { type: Boolean, default: !1 },
language: {},
extensions: { default: () => [] },
disableTabIndent: { type: Boolean, default: !1 },
disableEnter: { type: Boolean, default: !1 },
disableCloseBrackets: { type: Boolean, default: !1 },
emitOnBlur: { type: Boolean, default: !0 },
withVariables: { type: Boolean, default: !0 },
importCurl: { type: Boolean, default: !1 },
alwaysEmitChange: { type: Boolean, default: !1 },
handleFieldChange: { type: Function },
handleFieldSubmit: { type: Function }
},
emits: ["update:modelValue", "submit", "blur", "curl", "redirectToEnvironment"],
setup(t, { expose: I, emit: M }) {
const u = M, k = j(), N = k.id || `id-${te()}`, y = d(!1), R = s(() => t.enum?.length ? !1 : t.type === "boolean" || Array.isArray(t.type) && t.type.includes("boolean")), x = s(() => t.nullable ? ["true", "false", "null"] : ["true", "false"]), q = s(() => Array.isArray(t.type) ? t.type.find((e) => e !== "null") ?? "string" : t.type), C = (e) => {
if (!(!t.alwaysEmitChange && e === t.modelValue)) {
if (t.importCurl && e.trim().toLowerCase().startsWith("curl")) {
u("curl", e), n.value && n.value.dispatch({
changes: {
from: 0,
to: n.value.state.doc.length,
insert: String(t.modelValue)
}
});
return;
}
t.handleFieldChange ? t.handleFieldChange(e) : u("update:modelValue", e);
}
}, h = (e) => {
t.handleFieldSubmit ? t.handleFieldSubmit(e) : u("submit", e);
}, S = (e) => {
y.value = !1, t.emitOnBlur && t.modelValue && h(e), u("blur", e);
}, g = (e) => {
u("update:modelValue", e);
}, A = () => {
const e = [...t.extensions];
return t.colorPicker && e.push(ee), e;
}, O = s(
() => ne({
environment: t.environment,
isReadOnly: t.layout === "modal"
})
), z = s(() => [
...A(),
O.value,
oe
]), E = d(null), { codeMirror: n } = Z({
content: r(() => String(t.modelValue ?? "")),
onChange: (e) => {
C(e), L();
},
onFocus: () => {
y.value = !0;
},
onBlur: S,
codeMirrorRef: E,
disableTabIndent: r(() => t.disableTabIndent),
disableEnter: r(() => t.disableEnter),
disableCloseBrackets: r(() => t.disableCloseBrackets),
lineNumbers: r(() => t.lineNumbers),
language: r(() => t.language),
lint: r(() => t.lint),
extensions: z,
placeholder: r(() => t.placeholder)
});
H(n, () => {
n.value && Object.hasOwn(k, "autofocus") && n.value.focus();
});
const p = d(!1), P = d(""), D = d({ left: 0, top: 0 }), v = d(null), { handleDropdownSelect: K, updateDropdownVisibility: L } = _({
codeMirror: n,
query: P,
showDropdown: p,
dropdownPosition: D
}), U = s(() => p.value && t.withVariables && t.layout !== "modal" && !!t.environment), m = (e, l) => {
if (p.value) {
e === "down" || e === "up" ? (l.preventDefault(), v.value?.handleArrowKey(e)) : e === "enter" && (l.preventDefault(), v.value?.handleSelect());
return;
}
e === "escape" && !t.disableTabIndent && l.stopPropagation(), e === "enter" && l.target instanceof HTMLDivElement && h(l.target.textContent ?? "");
};
return I({
/**
* Focus the codemirror element
*
* @param cursorAtEnd boolean place the cursor at the end of the input
*/
focus: (e) => {
if (!n.value || (n.value.focus(), !Y(e)))
return;
const l = e === "start" ? 0 : e === "end" ? n.value.state.doc.length : e;
n.value.dispatch({
selection: { anchor: l },
scrollIntoView: !0
});
},
isFocused: y,
handleChange: C,
handleSubmit: h,
handleBlur: S,
booleanOptions: x,
codeMirror: n,
modelValue: t.modelValue,
cursorPosition: () => n.value?.state.selection.main.head
}), (e, l) => (o(), i(Q, null, [
e.disabled ? (o(), i("div", {
key: 0,
class: G(["text-c-2 flex cursor-default items-center justify-center", e.layout === "modal" ? "font-code pr-2 pl-1 text-base" : "px-2"]),
"data-testid": "code-input-disabled"
}, [
w("span", ae, J(e.modelValue), 1)
], 2)) : t.enum?.length ? (o(), c(B, {
key: 1,
default: t.default,
modelValue: e.modelValue,
type: q.value,
value: t.enum,
"onUpdate:modelValue": g
}, null, 8, ["default", "modelValue", "type", "value"])) : R.value ? (o(), c(B, {
key: 2,
default: t.default,
modelValue: e.modelValue,
value: x.value,
"onUpdate:modelValue": g
}, null, 8, ["default", "modelValue", "value"])) : e.examples?.length ? (o(), c(B, {
key: 3,
default: t.default,
modelValue: e.modelValue,
value: e.examples,
"onUpdate:modelValue": g
}, null, 8, ["default", "modelValue", "value"])) : (o(), i("div", X({
key: 4,
id: F(N)
}, e.$attrs, {
ref_key: "codeMirrorRef",
ref: E,
class: ["group/input group-[.alert]:outline-orange group-[.error]:outline-red font-code peer relative w-full overflow-hidden text-xs leading-[1.44] whitespace-nowrap -outline-offset-1 has-[:focus-visible]:rounded-[4px] has-[:focus-visible]:outline", {
"line-wrapping has-[:focus-visible]:bg-b-1 has-[:focus-visible]:absolute has-[:focus-visible]:z-1": e.lineWrapping,
"flow-code-input--error": e.error
}],
onKeydown: [
l[0] || (l[0] = b(T((a) => m("down", a), ["stop"]), ["down"])),
l[1] || (l[1] = b((a) => m("enter", a), ["enter"])),
l[2] || (l[2] = b((a) => m("escape", a), ["escape"])),
l[3] || (l[3] = b(T((a) => m("up", a), ["stop"]), ["up"]))
]
}), [
e.disableTabIndent ? f("", !0) : (o(), i("div", ie, [...l[5] || (l[5] = [
V(" Press ", -1),
w("kbd", { class: "-mx-0.25 rounded border px-0.5 font-mono" }, "Esc", -1),
V(" then ", -1),
w("kbd", { class: "-mx-0.25 rounded border px-0.5 font-mono" }, "Tab", -1),
V(" to exit ", -1)
])]))
], 16, re)),
e.$slots.warning ? (o(), i("div", ue, [
$(e.$slots, "warning", {}, void 0, !0)
])) : f("", !0),
e.$slots.icon ? (o(), i("div", de, [
$(e.$slots, "icon", {}, void 0, !0)
])) : f("", !0),
e.required ? (o(), i("div", se, " Required ")) : f("", !0),
U.value && e.environment ? (o(), c(le, {
key: 8,
ref_key: "dropdownRef",
ref: v,
dropdownPosition: D.value,
environment: e.environment,
query: P.value,
onRedirect: l[4] || (l[4] = (a) => u("redirectToEnvironment")),
onSelect: F(K)
}, null, 8, ["dropdownPosition", "environment", "query", "onSelect"])) : f("", !0)
], 64));
}
});
export {
ve as default
};