@scalar/api-client 3.10.2 → 3.10.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/style.css +188 -96
  3. package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-security-schemes.d.ts.map +1 -1
  4. package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-security-schemes.js.map +1 -1
  5. package/dist/v2/blocks/operation-code-sample/index.d.ts +1 -1
  6. package/dist/v2/blocks/operation-code-sample/index.d.ts.map +1 -1
  7. package/dist/v2/blocks/operation-code-sample/index.js +2 -2
  8. package/dist/v2/blocks/request-block/components/RequestTable.vue.d.ts.map +1 -1
  9. package/dist/v2/blocks/request-block/components/RequestTable.vue.js +1 -1
  10. package/dist/v2/blocks/request-block/components/RequestTable.vue.js.map +1 -1
  11. package/dist/v2/blocks/request-block/components/RequestTable.vue.script.js.map +1 -1
  12. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.d.ts.map +1 -1
  13. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.js.map +1 -1
  14. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.script.js +13 -28
  15. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.script.js.map +1 -1
  16. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.d.ts.map +1 -1
  17. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.js +1 -1
  18. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.js.map +1 -1
  19. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.script.js.map +1 -1
  20. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.d.ts +4 -1
  21. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.d.ts.map +1 -1
  22. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.js.map +1 -1
  23. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.script.js +2 -2
  24. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.script.js.map +1 -1
  25. package/dist/v2/blocks/scalar-auth-selector-block/components/OpenIDConnect.vue.d.ts +3 -0
  26. package/dist/v2/blocks/scalar-auth-selector-block/components/OpenIDConnect.vue.d.ts.map +1 -1
  27. package/dist/v2/blocks/scalar-auth-selector-block/components/OpenIDConnect.vue.js.map +1 -1
  28. package/dist/v2/blocks/scalar-auth-selector-block/components/OpenIDConnect.vue.script.js +3 -2
  29. package/dist/v2/blocks/scalar-auth-selector-block/components/OpenIDConnect.vue.script.js.map +1 -1
  30. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.d.ts.map +1 -1
  31. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.js.map +1 -1
  32. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.script.js +0 -1
  33. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.script.js.map +1 -1
  34. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.d.ts.map +1 -1
  35. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.js.map +1 -1
  36. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.script.js +2 -0
  37. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.script.js.map +1 -1
  38. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.d.ts +4 -1
  39. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.d.ts.map +1 -1
  40. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.js +4 -3
  41. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.js.map +1 -1
  42. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.d.ts +7 -2
  43. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.d.ts.map +1 -1
  44. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.js +11 -9
  45. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.js.map +1 -1
  46. package/dist/v2/components/code-input/CodeInput.vue.d.ts.map +1 -1
  47. package/dist/v2/components/code-input/CodeInput.vue.js +1 -1
  48. package/dist/v2/components/code-input/CodeInput.vue.js.map +1 -1
  49. package/dist/v2/components/code-input/CodeInput.vue.script.js +3 -2
  50. package/dist/v2/components/code-input/CodeInput.vue.script.js.map +1 -1
  51. package/dist/v2/components/code-input/CodeInputLite.vue.d.ts +124 -0
  52. package/dist/v2/components/code-input/CodeInputLite.vue.d.ts.map +1 -0
  53. package/dist/v2/components/code-input/CodeInputLite.vue.js +10 -0
  54. package/dist/v2/components/code-input/CodeInputLite.vue.js.map +1 -0
  55. package/dist/v2/components/code-input/CodeInputLite.vue.script.js +631 -0
  56. package/dist/v2/components/code-input/CodeInputLite.vue.script.js.map +1 -0
  57. package/dist/v2/components/code-input/PillTooltipHost.vue.d.ts +3 -0
  58. package/dist/v2/components/code-input/PillTooltipHost.vue.d.ts.map +1 -1
  59. package/dist/v2/components/code-input/PillTooltipHost.vue.js.map +1 -1
  60. package/dist/v2/components/code-input/PillTooltipHost.vue.script.js +23 -11
  61. package/dist/v2/components/code-input/PillTooltipHost.vue.script.js.map +1 -1
  62. package/dist/v2/components/code-input/code-variable-widget.d.ts.map +1 -1
  63. package/dist/v2/components/code-input/code-variable-widget.js +5 -2
  64. package/dist/v2/components/code-input/code-variable-widget.js.map +1 -1
  65. package/dist/v2/components/code-input/helpers/build-pill-context.d.ts +11 -0
  66. package/dist/v2/components/code-input/helpers/build-pill-context.d.ts.map +1 -0
  67. package/dist/v2/components/code-input/helpers/build-pill-context.js +28 -0
  68. package/dist/v2/components/code-input/helpers/build-pill-context.js.map +1 -0
  69. package/dist/v2/components/code-input/helpers/lookup-variable-value.d.ts +11 -0
  70. package/dist/v2/components/code-input/helpers/lookup-variable-value.d.ts.map +1 -0
  71. package/dist/v2/components/code-input/helpers/lookup-variable-value.js +18 -0
  72. package/dist/v2/components/code-input/helpers/lookup-variable-value.js.map +1 -0
  73. package/dist/v2/components/code-input/helpers/pill-signature.d.ts +13 -0
  74. package/dist/v2/components/code-input/helpers/pill-signature.d.ts.map +1 -0
  75. package/dist/v2/components/code-input/helpers/pill-signature.js +25 -0
  76. package/dist/v2/components/code-input/helpers/pill-signature.js.map +1 -0
  77. package/dist/v2/components/code-input/helpers/serialize-value.d.ts +10 -0
  78. package/dist/v2/components/code-input/helpers/serialize-value.d.ts.map +1 -0
  79. package/dist/v2/components/code-input/helpers/serialize-value.js +17 -0
  80. package/dist/v2/components/code-input/helpers/serialize-value.js.map +1 -0
  81. package/dist/v2/components/code-input/index.d.ts +1 -0
  82. package/dist/v2/components/code-input/index.d.ts.map +1 -1
  83. package/dist/v2/components/code-input/index.js +2 -1
  84. package/dist/v2/components/data-table/DataTableInput.vue.d.ts +0 -4
  85. package/dist/v2/components/data-table/DataTableInput.vue.d.ts.map +1 -1
  86. package/dist/v2/components/data-table/DataTableInput.vue.js +1 -1
  87. package/dist/v2/components/data-table/DataTableInput.vue.js.map +1 -1
  88. package/dist/v2/components/data-table/DataTableInput.vue.script.js +2 -19
  89. package/dist/v2/components/data-table/DataTableInput.vue.script.js.map +1 -1
  90. package/dist/v2/constants.js +1 -1
  91. package/dist/v2/features/environments/components/EnvironmentVariablesDropdown.vue.d.ts +9 -0
  92. package/dist/v2/features/environments/components/EnvironmentVariablesDropdown.vue.d.ts.map +1 -1
  93. package/dist/v2/features/environments/components/EnvironmentVariablesDropdown.vue.js.map +1 -1
  94. package/dist/v2/features/environments/components/EnvironmentVariablesDropdown.vue.script.js +59 -28
  95. package/dist/v2/features/environments/components/EnvironmentVariablesDropdown.vue.script.js.map +1 -1
  96. package/dist/v2/features/environments/components/EnvironmentVariablesTable.vue.d.ts.map +1 -1
  97. package/dist/v2/features/environments/components/EnvironmentVariablesTable.vue.js +1 -1
  98. package/dist/v2/features/environments/components/EnvironmentVariablesTable.vue.js.map +1 -1
  99. package/dist/v2/features/environments/components/EnvironmentVariablesTable.vue.script.js +3 -8
  100. package/dist/v2/features/environments/components/EnvironmentVariablesTable.vue.script.js.map +1 -1
  101. package/dist/v2/features/modal/helpers/create-api-client-modal.d.ts.map +1 -1
  102. package/dist/v2/features/modal/helpers/create-api-client-modal.js +12 -1
  103. package/dist/v2/features/modal/helpers/create-api-client-modal.js.map +1 -1
  104. package/dist/v2/features/modal/helpers/resolve-route-parameters.d.ts.map +1 -1
  105. package/dist/v2/features/modal/helpers/resolve-route-parameters.js +6 -1
  106. package/dist/v2/features/modal/helpers/resolve-route-parameters.js.map +1 -1
  107. package/dist/v2/features/search/helpers/create-search-index.d.ts.map +1 -1
  108. package/dist/v2/features/search/helpers/create-search-index.js +2 -1
  109. package/dist/v2/features/search/helpers/create-search-index.js.map +1 -1
  110. package/dist/vue-styles.css +141 -89
  111. package/package.json +11 -11
@@ -0,0 +1,631 @@
1
+ import DataTableInputSelect_default from "../data-table/DataTableInputSelect.vue.js";
2
+ import EnvironmentVariablesDropdown_default from "../../features/environments/components/EnvironmentVariablesDropdown.vue.js";
3
+ import PillTooltipHost_default from "./PillTooltipHost.vue.js";
4
+ import { lookupVariableValue } from "./helpers/lookup-variable-value.js";
5
+ import { buildPillContext } from "./helpers/build-pill-context.js";
6
+ import { pillSignature } from "./helpers/pill-signature.js";
7
+ import { serializeValue } from "./helpers/serialize-value.js";
8
+ import { Fragment, computed, createApp, createBlock, createCommentVNode, createElementBlock, createElementVNode, defineComponent, mergeProps, nextTick, normalizeClass, onBeforeUnmount, onMounted, openBlock, ref, renderSlot, toDisplayString, unref, useAttrs, useTemplateRef, watch } from "vue";
9
+ import { isDefined } from "@scalar/helpers/array/is-defined";
10
+ import { CONTEXT_FUNCTION_NAMES, getContextFunctionComment, isContextFunctionName } from "@scalar/workspace-store/request-example";
11
+ import { nanoid } from "nanoid";
12
+ import { REGEX } from "@scalar/helpers/regex/regex-helpers";
13
+ //#region src/v2/components/code-input/CodeInputLite.vue?vue&type=script&setup=true&lang.ts
14
+ var _hoisted_1 = { class: "whitespace-nowrap" };
15
+ var _hoisted_2 = ["id"];
16
+ var _hoisted_3 = [
17
+ "aria-activedescendant",
18
+ "aria-autocomplete",
19
+ "aria-controls",
20
+ "aria-expanded",
21
+ "aria-invalid",
22
+ "aria-label",
23
+ "aria-readonly",
24
+ "aria-required",
25
+ "contenteditable",
26
+ "data-placeholder",
27
+ "role"
28
+ ];
29
+ var _hoisted_4 = {
30
+ key: 5,
31
+ class: "centered-y text-orange absolute right-7 text-xs"
32
+ };
33
+ var _hoisted_5 = {
34
+ key: 6,
35
+ class: "centered-y absolute right-0 flex h-full items-center p-1.5 group-has-[.code-input-lite__editor:focus]:z-1"
36
+ };
37
+ var _hoisted_6 = {
38
+ key: 7,
39
+ 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 peer-has-[.code-input-lite__editor:focus]:opacity-0"
40
+ };
41
+ var CodeInputLite_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
42
+ inheritAttrs: false,
43
+ __name: "CodeInputLite",
44
+ props: {
45
+ modelValue: { type: [
46
+ String,
47
+ Number,
48
+ Boolean,
49
+ Array,
50
+ Object
51
+ ] },
52
+ environment: {},
53
+ disabled: {
54
+ type: Boolean,
55
+ default: false
56
+ },
57
+ readOnly: {
58
+ type: Boolean,
59
+ default: false
60
+ },
61
+ error: {
62
+ type: Boolean,
63
+ default: false
64
+ },
65
+ layout: { default: "desktop" },
66
+ placeholder: {},
67
+ required: {
68
+ type: Boolean,
69
+ default: false
70
+ },
71
+ emitOnBlur: {
72
+ type: Boolean,
73
+ default: true
74
+ },
75
+ withVariables: {
76
+ type: Boolean,
77
+ default: true
78
+ },
79
+ withFakeData: {
80
+ type: Boolean,
81
+ default: false
82
+ },
83
+ alwaysEmitChange: {
84
+ type: Boolean,
85
+ default: false
86
+ },
87
+ linethrough: {
88
+ type: Boolean,
89
+ default: false
90
+ },
91
+ type: {},
92
+ enum: {},
93
+ examples: {},
94
+ default: { type: [
95
+ String,
96
+ Number,
97
+ Boolean,
98
+ Array,
99
+ Object
100
+ ] },
101
+ nullable: {
102
+ type: Boolean,
103
+ default: false
104
+ }
105
+ },
106
+ emits: [
107
+ "update:modelValue",
108
+ "submit",
109
+ "blur",
110
+ "navigate"
111
+ ],
112
+ setup(__props, { expose: __expose, emit: __emit }) {
113
+ const emit = __emit;
114
+ const attrs = useAttrs();
115
+ /**
116
+ * The id only matters once the dropdown opens (`aria-controls` /
117
+ * `aria-activedescendant`), so we defer `nanoid()` until first focus to
118
+ * keep idle instances cheap. A consumer-supplied `id` attr is preserved.
119
+ */
120
+ const generatedComponentId = ref(null);
121
+ const componentId = computed(() => attrs.id ?? generatedComponentId.value ?? void 0);
122
+ const ensureComponentId = () => {
123
+ if (!attrs.id && generatedComponentId.value === null) generatedComponentId.value = `id-${nanoid()}`;
124
+ };
125
+ const editorRef = useTemplateRef("editorRef");
126
+ const dropdownRef = ref(null);
127
+ /** Id of the dropdown's `role="listbox"` element, for the combobox wiring. */
128
+ const listboxId = computed(() => componentId.value ? `${componentId.value}-listbox` : void 0);
129
+ /**
130
+ * Id of the option the dropdown currently highlights. Mirrors the dropdown's
131
+ * own selection so the editor can expose it via `aria-activedescendant`.
132
+ */
133
+ const activeOptionId = computed(() => dropdownRef.value?.activeOptionId);
134
+ const isFocused = ref(false);
135
+ const isEmpty = ref(true);
136
+ /**
137
+ * True while an IME composition is in progress. Rebuilding the editor DOM
138
+ * mid-composition (e.g. when `{{` forms a pill) cancels the composition, so we
139
+ * defer those rebuilds until `compositionend`.
140
+ */
141
+ const isComposing = ref(false);
142
+ /**
143
+ * Whether the serialized value should count as empty for placeholder display.
144
+ *
145
+ * `contenteditable` can leave behind invisible residue after some delete
146
+ * sequences — most commonly a non-breaking space (` `) — which makes a
147
+ * visually empty field report a non-zero length and silently drop its
148
+ * placeholder. Trimming covers that case; ` ` counts as whitespace, so a
149
+ * field that only holds editor residue is treated as empty. This affects the
150
+ * placeholder flag only, never the value emitted via `serializeEditor`.
151
+ */
152
+ const isBlankValue = (text) => text.trim().length === 0;
153
+ /** True when the schema type is exactly `boolean` (or includes it in a tuple type). */
154
+ const isBooleanMode = computed(() => {
155
+ if (__props.enum?.length) return false;
156
+ return __props.type === "boolean" || Array.isArray(__props.type) && __props.type.includes("boolean");
157
+ });
158
+ const booleanOptions = computed(() => __props.nullable ? [
159
+ "true",
160
+ "false",
161
+ "null"
162
+ ] : ["true", "false"]);
163
+ /** Default type when the schema is a tuple — picks the first non-null entry. */
164
+ const defaultType = computed(() => {
165
+ if (Array.isArray(__props.type)) return __props.type.find((t) => t !== "null") ?? "string";
166
+ return __props.type;
167
+ });
168
+ const handleSelectChange = (value) => emit("update:modelValue", value);
169
+ let pillTooltipApps = [];
170
+ /**
171
+ * Per-pill tooltips are the heaviest part of the render (a Vue app +
172
+ * `useTooltip` watch + listeners each), so we defer mounting them until
173
+ * the first interaction (focus, pointerover, or dropdown open). Once on,
174
+ * subsequent rebuilds remount tooltips for the new pills.
175
+ */
176
+ let tooltipsActive = false;
177
+ const teardownPillTooltips = () => {
178
+ for (const app of pillTooltipApps) app.unmount();
179
+ pillTooltipApps = [];
180
+ };
181
+ const mountPillTooltips = () => {
182
+ if (!editorRef.value || __props.layout === "modal") return;
183
+ const pills = editorRef.value.querySelectorAll(".scalar-pill");
184
+ for (const pillEl of pills) {
185
+ const app = createApp(PillTooltipHost_default, {
186
+ context: buildPillContext(pillEl.dataset.variable ?? "", __props.environment),
187
+ target: pillEl
188
+ });
189
+ app.mount(document.createElement("div"));
190
+ pillTooltipApps.push(app);
191
+ }
192
+ };
193
+ /**
194
+ * Build a pill `<span>` for the given variable. `contentEditable = 'false'`
195
+ * makes the browser treat it as a single atom (arrow keys jump over it,
196
+ * Backspace deletes it whole); `{{` / `}}` only live in the model string.
197
+ */
198
+ const createPillElement = (name, start, end) => {
199
+ const isCtx = isContextFunctionName(name);
200
+ const span = document.createElement("span");
201
+ span.className = isCtx ? "scalar-pill scalar-pill--context-fn" : "scalar-pill";
202
+ span.contentEditable = "false";
203
+ span.dataset.variable = name;
204
+ span.dataset.pillStart = String(start);
205
+ span.dataset.pillEnd = String(end);
206
+ const color = isCtx ? "var(--scalar-color-3)" : __props.environment?.color || "var(--scalar-color-1)";
207
+ span.style.setProperty("--tw-bg-base", color);
208
+ if (!isCtx && !lookupVariableValue(__props.environment, name)) span.style.opacity = "0.5";
209
+ span.textContent = name;
210
+ return span;
211
+ };
212
+ /** Render a model string into the editor as a mix of text nodes + pills. */
213
+ const renderModel = (text) => {
214
+ const editor = editorRef.value;
215
+ if (!editor) return;
216
+ teardownPillTooltips();
217
+ editor.replaceChildren();
218
+ if (!__props.withVariables || !text.includes("{{")) {
219
+ if (text) editor.appendChild(document.createTextNode(text));
220
+ isEmpty.value = isBlankValue(text);
221
+ return;
222
+ }
223
+ const regex = new RegExp(REGEX.VARIABLES.source, REGEX.VARIABLES.flags);
224
+ let lastIndex = 0;
225
+ let match;
226
+ while ((match = regex.exec(text)) !== null) {
227
+ const start = match.index;
228
+ const end = start + match[0].length;
229
+ if (start > lastIndex) editor.appendChild(document.createTextNode(text.slice(lastIndex, start)));
230
+ editor.appendChild(createPillElement(match[1] ?? "", start, end));
231
+ lastIndex = end;
232
+ }
233
+ if (lastIndex < text.length) editor.appendChild(document.createTextNode(text.slice(lastIndex)));
234
+ isEmpty.value = false;
235
+ if (tooltipsActive) mountPillTooltips();
236
+ };
237
+ /** Length the given child contributes to the serialized model string. */
238
+ const modelLengthOf = (node) => {
239
+ if (node.nodeType === Node.TEXT_NODE) return (node.textContent ?? "").length;
240
+ if (node instanceof HTMLElement && node.classList.contains("scalar-pill")) return `{{${node.dataset.variable ?? ""}}}`.length;
241
+ return (node.textContent ?? "").length;
242
+ };
243
+ /** Read the editor DOM back into a `{{name}}`-bearing model string. */
244
+ const serializeEditor = () => {
245
+ const editor = editorRef.value;
246
+ if (!editor) return "";
247
+ let out = "";
248
+ for (const node of Array.from(editor.childNodes)) if (node.nodeType === Node.TEXT_NODE) out += node.textContent ?? "";
249
+ else if (node instanceof HTMLElement && node.classList.contains("scalar-pill")) out += `{{${node.dataset.variable ?? ""}}}`;
250
+ else if (node instanceof HTMLElement) out += node.textContent ?? "";
251
+ return out;
252
+ };
253
+ let lastPillSignature = null;
254
+ let lastEnvKey = "";
255
+ /**
256
+ * Cache key for the env + `withVariables` state. Includes variable
257
+ * name/value pairs so the watcher notices adds/removes/edits even when
258
+ * `environment.color` is unchanged — without that, pills keep stale
259
+ * `isDefined` opacity and tooltip values until the input itself changes.
260
+ */
261
+ const computeEnvKey = () => {
262
+ const color = __props.environment?.color ?? "";
263
+ const flag = __props.withVariables ? "1" : "0";
264
+ const variables = __props.environment?.variables ?? [];
265
+ let vars = "";
266
+ for (const v of variables) {
267
+ const value = typeof v.value === "string" ? v.value : v.value?.default ?? "";
268
+ vars += `\x1f${v.name}\x1e${value}`;
269
+ }
270
+ return `${color}|${flag}|${vars}`;
271
+ };
272
+ /** Idempotent: first call flips `tooltipsActive` and mounts pill tooltips. */
273
+ const ensureTooltipsActive = () => {
274
+ if (tooltipsActive) return;
275
+ tooltipsActive = true;
276
+ mountPillTooltips();
277
+ };
278
+ /** Selection start as a model-string offset, or `null` if not inside the editor. */
279
+ const getModelCaret = () => {
280
+ const editor = editorRef.value;
281
+ if (!editor) return null;
282
+ const selection = window.getSelection();
283
+ if (!selection || selection.rangeCount === 0) return null;
284
+ const range = selection.getRangeAt(0);
285
+ if (range.startContainer !== editor && !editor.contains(range.startContainer)) return null;
286
+ if (range.startContainer === editor) {
287
+ let pos = 0;
288
+ for (let i = 0; i < range.startOffset && i < editor.childNodes.length; i++) pos += modelLengthOf(editor.childNodes[i]);
289
+ return pos;
290
+ }
291
+ let pos = 0;
292
+ for (const child of Array.from(editor.childNodes)) {
293
+ if (child === range.startContainer) return pos + range.startOffset;
294
+ if (child.contains(range.startContainer)) return range.startOffset === 0 ? pos : pos + modelLengthOf(child);
295
+ pos += modelLengthOf(child);
296
+ }
297
+ return pos;
298
+ };
299
+ /** Place the caret at the given model offset, walking the DOM to find it. */
300
+ const setModelCaret = (target) => {
301
+ const editor = editorRef.value;
302
+ if (!editor) return;
303
+ const range = document.createRange();
304
+ let pos = 0;
305
+ let placed = false;
306
+ for (const child of Array.from(editor.childNodes)) {
307
+ const len = modelLengthOf(child);
308
+ if (pos + len >= target) {
309
+ if (child.nodeType === Node.TEXT_NODE) {
310
+ const into = Math.max(0, Math.min(target - pos, (child.textContent ?? "").length));
311
+ range.setStart(child, into);
312
+ } else if (target - pos <= 0) range.setStartBefore(child);
313
+ else range.setStartAfter(child);
314
+ placed = true;
315
+ break;
316
+ }
317
+ pos += len;
318
+ }
319
+ if (!placed) {
320
+ range.selectNodeContents(editor);
321
+ range.collapse(false);
322
+ } else range.collapse(true);
323
+ const selection = window.getSelection();
324
+ if (!selection) return;
325
+ selection.removeAllRanges();
326
+ selection.addRange(range);
327
+ };
328
+ const showDropdown = ref(false);
329
+ const dropdownQuery = ref("");
330
+ const dropdownPosition = ref({
331
+ left: 0,
332
+ top: 0
333
+ });
334
+ const contextFunctionDropdownItems = computed(() => __props.withFakeData ? CONTEXT_FUNCTION_NAMES.map((key) => ({
335
+ key,
336
+ description: getContextFunctionComment(key)
337
+ })) : []);
338
+ const displayVariablesDropdown = computed(() => showDropdown.value && __props.withVariables && __props.layout !== "modal" && (Boolean(__props.environment) || __props.withFakeData));
339
+ const updateDropdownVisibility = () => {
340
+ if (!editorRef.value) return;
341
+ const caret = getModelCaret();
342
+ if (caret === null) {
343
+ showDropdown.value = false;
344
+ return;
345
+ }
346
+ const text = serializeEditor().slice(0, caret);
347
+ const lastOpen = text.lastIndexOf("{{");
348
+ if (lastOpen <= text.lastIndexOf("}}")) {
349
+ showDropdown.value = false;
350
+ return;
351
+ }
352
+ dropdownQuery.value = text.slice(lastOpen + 2);
353
+ ensureComponentId();
354
+ showDropdown.value = true;
355
+ nextTick(() => {
356
+ const selection = window.getSelection();
357
+ if (!selection || selection.rangeCount === 0 || !editorRef.value) return;
358
+ const r = selection.getRangeAt(0).cloneRange();
359
+ r.collapse(true);
360
+ const rect = r.getBoundingClientRect();
361
+ const editorRect = editorRef.value.getBoundingClientRect();
362
+ dropdownPosition.value = {
363
+ left: rect.left || editorRect.left,
364
+ top: rect.bottom || editorRect.bottom
365
+ };
366
+ });
367
+ };
368
+ const handleDropdownSelect = (item) => {
369
+ if (__props.readOnly) return;
370
+ const caret = getModelCaret() ?? 0;
371
+ const value = serializeEditor();
372
+ const from = Math.max(0, caret - dropdownQuery.value.length - 2);
373
+ const to = caret;
374
+ const next = `${value.slice(0, from)}{{${item}}}${value.slice(to)}`;
375
+ const nextCursor = from + `{{${item}}}`.length;
376
+ lastPillSignature = pillSignature(next, __props.withVariables);
377
+ renderModel(next);
378
+ setModelCaret(nextCursor);
379
+ showDropdown.value = false;
380
+ emitChange(next, { skipDropdownCheck: true });
381
+ };
382
+ const emitChange = (value, opts = {}) => {
383
+ const same = value === serializeValue(__props.modelValue);
384
+ if (__props.alwaysEmitChange || !same) emit("update:modelValue", value);
385
+ if (!opts.skipDropdownCheck) updateDropdownVisibility();
386
+ };
387
+ const handleInput = () => {
388
+ const text = serializeEditor();
389
+ isEmpty.value = isBlankValue(text);
390
+ const sig = pillSignature(text, __props.withVariables);
391
+ if (!isComposing.value && sig !== lastPillSignature) {
392
+ const caret = getModelCaret();
393
+ lastPillSignature = sig;
394
+ renderModel(text);
395
+ if (caret !== null) setModelCaret(caret);
396
+ }
397
+ emitChange(text);
398
+ };
399
+ const handleCompositionStart = () => {
400
+ isComposing.value = true;
401
+ };
402
+ const handleCompositionEnd = () => {
403
+ isComposing.value = false;
404
+ handleInput();
405
+ };
406
+ const handleFocus = () => {
407
+ isFocused.value = true;
408
+ ensureComponentId();
409
+ ensureTooltipsActive();
410
+ };
411
+ const handleBlur = (event) => {
412
+ isFocused.value = false;
413
+ showDropdown.value = false;
414
+ const value = serializeEditor();
415
+ if (__props.emitOnBlur && value) emit("submit", value, event);
416
+ emit("blur", value, event);
417
+ };
418
+ /**
419
+ * Strip rich content on paste; `contenteditable="plaintext-only"` is not
420
+ * reliable cross-browser, so we intercept and use `insertText` to keep undo.
421
+ */
422
+ const handlePaste = (event) => {
423
+ event.preventDefault();
424
+ const text = event.clipboardData?.getData("text/plain") ?? "";
425
+ if (!text) return;
426
+ document.execCommand("insertText", false, text.replace(/\r?\n/g, " "));
427
+ handleInput();
428
+ };
429
+ const handleKeyDown = (event) => {
430
+ if (showDropdown.value) {
431
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
432
+ event.preventDefault();
433
+ event.stopPropagation();
434
+ dropdownRef.value?.handleArrowKey(event.key === "ArrowDown" ? "down" : "up");
435
+ return;
436
+ }
437
+ if (event.key === "Enter") {
438
+ event.preventDefault();
439
+ event.stopPropagation();
440
+ dropdownRef.value?.handleSelect();
441
+ return;
442
+ }
443
+ if (event.key === "Escape") {
444
+ event.preventDefault();
445
+ event.stopPropagation();
446
+ showDropdown.value = false;
447
+ return;
448
+ }
449
+ }
450
+ if (event.key === "Enter") {
451
+ event.preventDefault();
452
+ emit("submit", serializeEditor(), event);
453
+ return;
454
+ }
455
+ };
456
+ /**
457
+ * Clicking a pill selects it whole, so a subsequent Backspace deletes it
458
+ * in one keystroke and typing replaces it — the usual chip/mention model.
459
+ */
460
+ const handleEditorClick = (event) => {
461
+ const target = event.target?.closest(".scalar-pill");
462
+ if (!target) return;
463
+ const editor = editorRef.value;
464
+ if (!editor) return;
465
+ editor.focus();
466
+ const range = document.createRange();
467
+ range.selectNode(target);
468
+ const selection = window.getSelection();
469
+ selection?.removeAllRanges();
470
+ selection?.addRange(range);
471
+ updateDropdownVisibility();
472
+ };
473
+ onMounted(() => {
474
+ const initial = serializeValue(__props.modelValue);
475
+ lastPillSignature = pillSignature(initial, __props.withVariables);
476
+ lastEnvKey = computeEnvKey();
477
+ renderModel(initial);
478
+ isEmpty.value = isBlankValue(initial);
479
+ if (Object.hasOwn(attrs, "autofocus")) editorRef.value?.focus();
480
+ });
481
+ watch(() => __props.modelValue, (next) => {
482
+ const serialized = serializeValue(next);
483
+ isEmpty.value = isBlankValue(serialized);
484
+ if (serializeEditor() === serialized) return;
485
+ lastPillSignature = pillSignature(serialized, __props.withVariables);
486
+ renderModel(serialized);
487
+ });
488
+ watch([() => __props.environment, () => __props.withVariables], () => {
489
+ const envKey = computeEnvKey();
490
+ if (envKey === lastEnvKey) return;
491
+ lastEnvKey = envKey;
492
+ if (lastPillSignature === "") return;
493
+ lastPillSignature = pillSignature(serializeEditor(), __props.withVariables);
494
+ const caret = getModelCaret();
495
+ renderModel(serializeEditor());
496
+ if (caret !== null) setModelCaret(caret);
497
+ }, { deep: true });
498
+ onBeforeUnmount(() => {
499
+ teardownPillTooltips();
500
+ });
501
+ __expose({
502
+ focus: (position) => {
503
+ const editor = editorRef.value;
504
+ if (!editor) return;
505
+ editor.focus();
506
+ if (!isDefined(position)) return;
507
+ const length = serializeEditor().length;
508
+ setModelCaret(position === "start" ? 0 : position === "end" ? length : position);
509
+ },
510
+ setContent: (next = "") => {
511
+ if (serializeEditor() === next) return;
512
+ lastPillSignature = pillSignature(next, __props.withVariables);
513
+ renderModel(next);
514
+ isEmpty.value = isBlankValue(next);
515
+ },
516
+ getValue: () => serializeEditor(),
517
+ cursorPosition: () => {
518
+ const c = getModelCaret();
519
+ return c === null ? void 0 : c;
520
+ },
521
+ isFocused,
522
+ editorRef
523
+ });
524
+ return (_ctx, _cache) => {
525
+ return openBlock(), createElementBlock(Fragment, null, [
526
+ __props.disabled ? (openBlock(), createElementBlock("div", {
527
+ key: 0,
528
+ class: normalizeClass(["text-c-2 flex cursor-default items-center justify-center", {
529
+ "font-code pr-2 pl-1 text-base": __props.layout === "modal",
530
+ "px-2": __props.layout !== "modal",
531
+ "line-through": __props.linethrough
532
+ }]),
533
+ "data-testid": "code-input-lite-disabled"
534
+ }, [createElementVNode("span", _hoisted_1, toDisplayString(__props.modelValue), 1)], 2)) : __props.enum?.length ? (openBlock(), createBlock(DataTableInputSelect_default, {
535
+ key: 1,
536
+ default: __props.default,
537
+ modelValue: __props.modelValue,
538
+ type: defaultType.value,
539
+ value: __props.enum,
540
+ "onUpdate:modelValue": handleSelectChange
541
+ }, null, 8, [
542
+ "default",
543
+ "modelValue",
544
+ "type",
545
+ "value"
546
+ ])) : isBooleanMode.value ? (openBlock(), createBlock(DataTableInputSelect_default, {
547
+ key: 2,
548
+ default: __props.default,
549
+ modelValue: __props.modelValue,
550
+ value: booleanOptions.value,
551
+ "onUpdate:modelValue": handleSelectChange
552
+ }, null, 8, [
553
+ "default",
554
+ "modelValue",
555
+ "value"
556
+ ])) : __props.examples?.length ? (openBlock(), createBlock(DataTableInputSelect_default, {
557
+ key: 3,
558
+ default: __props.default,
559
+ modelValue: __props.modelValue,
560
+ value: __props.examples,
561
+ "onUpdate:modelValue": handleSelectChange
562
+ }, null, 8, [
563
+ "default",
564
+ "modelValue",
565
+ "value"
566
+ ])) : (openBlock(), createElementBlock("div", mergeProps({
567
+ key: 4,
568
+ id: componentId.value
569
+ }, _ctx.$attrs, { class: ["code-input-lite group/code-input-lite peer relative w-full leading-[1.44] -outline-offset-1 has-[:focus-visible]:rounded-[4px] has-[:focus-visible]:outline", {
570
+ "code-input-lite--error": __props.error,
571
+ "code-input-lite--empty": isEmpty.value,
572
+ "line-through": __props.linethrough
573
+ }] }), [createElementVNode("div", {
574
+ ref_key: "editorRef",
575
+ ref: editorRef,
576
+ "aria-activedescendant": displayVariablesDropdown.value ? activeOptionId.value : void 0,
577
+ "aria-autocomplete": __props.withVariables ? "list" : void 0,
578
+ "aria-controls": displayVariablesDropdown.value ? listboxId.value : void 0,
579
+ "aria-expanded": displayVariablesDropdown.value ? "true" : void 0,
580
+ "aria-invalid": __props.error ? "true" : void 0,
581
+ "aria-label": unref(attrs)["aria-label"],
582
+ "aria-readonly": __props.readOnly ? "true" : void 0,
583
+ "aria-required": __props.required ? "true" : void 0,
584
+ class: "code-input-lite__editor",
585
+ contenteditable: __props.readOnly ? "false" : "true",
586
+ "data-placeholder": __props.placeholder,
587
+ role: __props.withVariables ? "combobox" : "textbox",
588
+ spellcheck: "false",
589
+ onBlur: handleBlur,
590
+ onClick: handleEditorClick,
591
+ onCompositionend: handleCompositionEnd,
592
+ onCompositionstart: handleCompositionStart,
593
+ onFocus: handleFocus,
594
+ onInput: handleInput,
595
+ onKeydown: handleKeyDown,
596
+ onPaste: handlePaste,
597
+ onPointerover: ensureTooltipsActive
598
+ }, null, 40, _hoisted_3)], 16, _hoisted_2)),
599
+ _ctx.$slots.warning ? (openBlock(), createElementBlock("div", _hoisted_4, [renderSlot(_ctx.$slots, "warning", {}, void 0, true)])) : createCommentVNode("", true),
600
+ _ctx.$slots.icon ? (openBlock(), createElementBlock("div", _hoisted_5, [renderSlot(_ctx.$slots, "icon", {}, void 0, true)])) : createCommentVNode("", true),
601
+ __props.required ? (openBlock(), createElementBlock("div", _hoisted_6, " Required ")) : createCommentVNode("", true),
602
+ displayVariablesDropdown.value ? (openBlock(), createBlock(EnvironmentVariablesDropdown_default, {
603
+ key: 8,
604
+ ref_key: "dropdownRef",
605
+ ref: dropdownRef,
606
+ contextFunctionItems: contextFunctionDropdownItems.value,
607
+ dropdownPosition: dropdownPosition.value,
608
+ environment: __props.environment,
609
+ listboxId: listboxId.value,
610
+ query: dropdownQuery.value,
611
+ onClose: _cache[0] || (_cache[0] = ($event) => showDropdown.value = false),
612
+ onRedirect: _cache[1] || (_cache[1] = ($event) => emit("navigate", {
613
+ page: "document",
614
+ path: "environment"
615
+ })),
616
+ onSelect: handleDropdownSelect
617
+ }, null, 8, [
618
+ "contextFunctionItems",
619
+ "dropdownPosition",
620
+ "environment",
621
+ "listboxId",
622
+ "query"
623
+ ])) : createCommentVNode("", true)
624
+ ], 64);
625
+ };
626
+ }
627
+ });
628
+ //#endregion
629
+ export { CodeInputLite_vue_vue_type_script_setup_true_lang_default as default };
630
+
631
+ //# sourceMappingURL=CodeInputLite.vue.script.js.map