@qodalis/vue-cli 2.0.0-beta.1 → 2.0.0-beta.11

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.
package/dist/index.js ADDED
@@ -0,0 +1,1284 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Cli: () => Cli,
24
+ CliConfigKey: () => CliConfigKey,
25
+ CliConfigProvider: () => CliConfigProvider,
26
+ CliEngine: () => import_cli3.CliEngine,
27
+ CliInjectionKey: () => CliInjectionKey,
28
+ CliPanel: () => CliPanel,
29
+ CliProvider: () => CliProvider,
30
+ useCli: () => useCli,
31
+ useCliEngine: () => useCliEngine
32
+ });
33
+ module.exports = __toCommonJS(index_exports);
34
+
35
+ // src/Cli.ts
36
+ var import_vue2 = require("vue");
37
+ var import_cli = require("@qodalis/cli");
38
+
39
+ // src/cliInjection.ts
40
+ var CliInjectionKey = /* @__PURE__ */ Symbol("qodalis-cli");
41
+
42
+ // src/CliConfigProvider.ts
43
+ var import_vue = require("vue");
44
+ var CliConfigKey = /* @__PURE__ */ Symbol("qodalis-cli-config");
45
+ var CliConfigProvider = (0, import_vue.defineComponent)({
46
+ name: "CliConfigProvider",
47
+ props: {
48
+ modules: {
49
+ type: Array,
50
+ default: void 0
51
+ },
52
+ processors: {
53
+ type: Array,
54
+ default: void 0
55
+ },
56
+ options: {
57
+ type: Object,
58
+ default: void 0
59
+ },
60
+ services: {
61
+ type: Object,
62
+ default: void 0
63
+ }
64
+ },
65
+ setup(props, { slots }) {
66
+ (0, import_vue.provide)(CliConfigKey, {
67
+ modules: props.modules,
68
+ processors: props.processors,
69
+ options: props.options,
70
+ services: props.services
71
+ });
72
+ return () => slots.default?.();
73
+ }
74
+ });
75
+
76
+ // src/Cli.ts
77
+ var Cli = (0, import_vue2.defineComponent)({
78
+ name: "Cli",
79
+ props: {
80
+ modules: {
81
+ type: Array,
82
+ default: void 0
83
+ },
84
+ processors: {
85
+ type: Array,
86
+ default: void 0
87
+ },
88
+ options: {
89
+ type: Object,
90
+ default: void 0
91
+ },
92
+ services: {
93
+ type: Object,
94
+ default: void 0
95
+ },
96
+ snapshot: {
97
+ type: Object,
98
+ default: void 0
99
+ },
100
+ style: {
101
+ type: Object,
102
+ default: void 0
103
+ },
104
+ class: {
105
+ type: String,
106
+ default: void 0
107
+ }
108
+ },
109
+ emits: ["ready"],
110
+ setup(props, { emit }) {
111
+ const containerRef = (0, import_vue2.ref)(null);
112
+ const ctx = (0, import_vue2.inject)(CliInjectionKey, null);
113
+ const config = (0, import_vue2.inject)(CliConfigKey, null);
114
+ let engine = null;
115
+ if (ctx) {
116
+ return () => null;
117
+ }
118
+ const modules = props.modules ?? config?.modules;
119
+ const processors = props.processors ?? config?.processors;
120
+ const options = props.options ?? config?.options;
121
+ const services = props.services ?? config?.services;
122
+ (0, import_vue2.onMounted)(async () => {
123
+ if (!containerRef.value) return;
124
+ const engineOptions = props.snapshot ? { ...options, snapshot: props.snapshot } : options;
125
+ engine = new import_cli.CliEngine(containerRef.value, engineOptions);
126
+ engine.registerService("cli-framework", "Vue");
127
+ if (services) {
128
+ for (const [token, value] of Object.entries(services)) {
129
+ engine.registerService(token, value);
130
+ }
131
+ }
132
+ if (modules) {
133
+ engine.registerModules(modules);
134
+ }
135
+ if (processors) {
136
+ engine.registerProcessors(processors);
137
+ }
138
+ await engine.start();
139
+ emit("ready", engine);
140
+ });
141
+ (0, import_vue2.onBeforeUnmount)(() => {
142
+ engine?.destroy();
143
+ engine = null;
144
+ });
145
+ return () => (0, import_vue2.h)("div", {
146
+ ref: containerRef,
147
+ style: { height: "100%", ...props.style },
148
+ class: props.class
149
+ });
150
+ }
151
+ });
152
+
153
+ // src/CliPanel.ts
154
+ var import_vue3 = require("vue");
155
+ var import_cli_core = require("@qodalis/cli-core");
156
+ var MIN_PANE_WIDTH_PERCENT = 10;
157
+ function normalizePanes(panes) {
158
+ const total = panes.reduce((s, p) => s + p.widthPercent, 0);
159
+ if (total === 0) return;
160
+ const scale = 100 / total;
161
+ panes.forEach((p) => {
162
+ p.widthPercent *= scale;
163
+ });
164
+ }
165
+ var svgAttrs = {
166
+ width: "20",
167
+ height: "20",
168
+ viewBox: "0 0 24 24",
169
+ fill: "none",
170
+ stroke: "currentColor",
171
+ "stroke-width": "1.8",
172
+ "stroke-linecap": "round",
173
+ "stroke-linejoin": "round"
174
+ };
175
+ var terminalIcon = () => (0, import_vue3.h)("svg", { ...svgAttrs, width: "22", height: "22", "stroke-width": "2" }, [
176
+ (0, import_vue3.h)("polyline", { points: "4 17 10 11 4 5" }),
177
+ (0, import_vue3.h)("line", { x1: "12", y1: "19", x2: "20", y2: "19" })
178
+ ]);
179
+ var maximizeIcon = () => (0, import_vue3.h)("svg", svgAttrs, [
180
+ (0, import_vue3.h)("polyline", { points: "15 3 21 3 21 9" }),
181
+ (0, import_vue3.h)("polyline", { points: "9 21 3 21 3 15" }),
182
+ (0, import_vue3.h)("line", { x1: "21", y1: "3", x2: "14", y2: "10" }),
183
+ (0, import_vue3.h)("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
184
+ ]);
185
+ var restoreIcon = () => (0, import_vue3.h)("svg", svgAttrs, [
186
+ (0, import_vue3.h)("polyline", { points: "4 14 10 14 10 20" }),
187
+ (0, import_vue3.h)("polyline", { points: "20 10 14 10 14 4" }),
188
+ (0, import_vue3.h)("line", { x1: "14", y1: "10", x2: "21", y2: "3" }),
189
+ (0, import_vue3.h)("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
190
+ ]);
191
+ var closeIcon = () => (0, import_vue3.h)("svg", svgAttrs, [
192
+ (0, import_vue3.h)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
193
+ (0, import_vue3.h)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
194
+ ]);
195
+ var hideIcon = () => (0, import_vue3.h)("svg", svgAttrs, [
196
+ (0, import_vue3.h)("line", { x1: "5", y1: "18", x2: "19", y2: "18" }),
197
+ (0, import_vue3.h)("polyline", { points: "9 14 12 17 15 14" })
198
+ ]);
199
+ function collapseChevron(position, isCollapsed) {
200
+ let points;
201
+ switch (position) {
202
+ case "top":
203
+ points = isCollapsed ? "6 9 12 15 18 9" : "18 15 12 9 6 15";
204
+ break;
205
+ case "left":
206
+ points = isCollapsed ? "9 18 15 12 9 6" : "15 6 9 12 15 18";
207
+ break;
208
+ case "right":
209
+ points = isCollapsed ? "15 6 9 12 15 18" : "9 18 15 12 9 6";
210
+ break;
211
+ default:
212
+ points = isCollapsed ? "18 15 12 9 6 15" : "6 9 12 15 18 9";
213
+ break;
214
+ }
215
+ return (0, import_vue3.h)("svg", svgAttrs, [(0, import_vue3.h)("polyline", { points })]);
216
+ }
217
+ function hideTabChevron(position) {
218
+ let points;
219
+ switch (position) {
220
+ case "top":
221
+ points = "6 9 12 15 18 9";
222
+ break;
223
+ case "left":
224
+ points = "9 18 15 12 9 6";
225
+ break;
226
+ case "right":
227
+ points = "15 6 9 12 15 18";
228
+ break;
229
+ default:
230
+ points = "18 15 12 9 6 15";
231
+ break;
232
+ }
233
+ return (0, import_vue3.h)("svg", { class: "cli-panel-hide-tab-arrow", ...svgAttrs, width: "14", height: "14", "stroke-width": "2.5" }, [
234
+ (0, import_vue3.h)("polyline", { points })
235
+ ]);
236
+ }
237
+ function positionIcon(pos, size = 20) {
238
+ let fillRect;
239
+ switch (pos) {
240
+ case "top":
241
+ fillRect = (0, import_vue3.h)("rect", { x: "4", y: "4", width: "16", height: "5", rx: "1", fill: "currentColor", stroke: "none", opacity: "0.5" });
242
+ break;
243
+ case "left":
244
+ fillRect = (0, import_vue3.h)("rect", { x: "4", y: "4", width: "5", height: "16", rx: "1", fill: "currentColor", stroke: "none", opacity: "0.5" });
245
+ break;
246
+ case "right":
247
+ fillRect = (0, import_vue3.h)("rect", { x: "15", y: "4", width: "5", height: "16", rx: "1", fill: "currentColor", stroke: "none", opacity: "0.5" });
248
+ break;
249
+ default:
250
+ fillRect = (0, import_vue3.h)("rect", { x: "4", y: "15", width: "16", height: "5", rx: "1", fill: "currentColor", stroke: "none", opacity: "0.5" });
251
+ break;
252
+ }
253
+ return (0, import_vue3.h)("svg", { ...svgAttrs, width: String(size), height: String(size) }, [
254
+ (0, import_vue3.h)("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }),
255
+ fillRect
256
+ ]);
257
+ }
258
+ var CliPanel = (0, import_vue3.defineComponent)({
259
+ name: "CliPanel",
260
+ props: {
261
+ options: {
262
+ type: Object,
263
+ default: void 0
264
+ },
265
+ modules: { type: Array, default: void 0 },
266
+ processors: {
267
+ type: Array,
268
+ default: void 0
269
+ },
270
+ services: {
271
+ type: Object,
272
+ default: void 0
273
+ },
274
+ onClose: {
275
+ type: Function,
276
+ default: void 0
277
+ },
278
+ collapsed: { type: Boolean, default: void 0 },
279
+ hidden: { type: Boolean, default: void 0 },
280
+ maximized: { type: Boolean, default: void 0 },
281
+ activeTabId: { type: Number, default: void 0 },
282
+ position: { type: String, default: void 0 },
283
+ height: { type: Number, default: void 0 },
284
+ width: { type: Number, default: void 0 },
285
+ style: {
286
+ type: Object,
287
+ default: void 0
288
+ },
289
+ class: { type: String, default: void 0 }
290
+ },
291
+ emits: [
292
+ "update:collapsed",
293
+ "update:hidden",
294
+ "update:maximized",
295
+ "update:activeTabId",
296
+ "update:position",
297
+ "update:height",
298
+ "update:width",
299
+ "close",
300
+ "tab-added",
301
+ "tab-closed",
302
+ "pane-split",
303
+ "pane-closed"
304
+ ],
305
+ setup(props, { expose, emit }) {
306
+ const config = (0, import_vue3.inject)(CliConfigKey, null);
307
+ const mergedOptions = (0, import_vue3.computed)(() => props.options ?? config?.options);
308
+ const mergedModules = (0, import_vue3.computed)(() => props.modules ?? config?.modules);
309
+ const mergedProcessors = (0, import_vue3.computed)(() => props.processors ?? config?.processors);
310
+ const mergedServices = (0, import_vue3.computed)(() => props.services ?? config?.services);
311
+ const visible = (0, import_vue3.ref)(true);
312
+ const internalCollapsed = (0, import_vue3.ref)(mergedOptions.value?.isCollapsed ?? true);
313
+ const internalMaximized = (0, import_vue3.ref)(false);
314
+ const internalHeight = (0, import_vue3.ref)(600);
315
+ const internalWidth = (0, import_vue3.ref)(400);
316
+ const prevHeight = (0, import_vue3.ref)(600);
317
+ const prevWidth = (0, import_vue3.ref)(400);
318
+ const initialized = (0, import_vue3.ref)(false);
319
+ const internalHidden = (0, import_vue3.ref)(props.options?.isHidden ?? false);
320
+ let preHideCollapsed = true;
321
+ const internalActiveTabId = (0, import_vue3.ref)(0);
322
+ const internalPosition = (0, import_vue3.ref)(
323
+ (0, import_cli_core.loadPanelPosition)() ?? mergedOptions.value?.position ?? "bottom"
324
+ );
325
+ const resolvedCollapsed = (0, import_vue3.computed)(() => props.collapsed !== void 0 ? props.collapsed : internalCollapsed.value);
326
+ const resolvedHidden = (0, import_vue3.computed)(() => props.hidden !== void 0 ? props.hidden : internalHidden.value);
327
+ const resolvedMaximized = (0, import_vue3.computed)(() => props.maximized !== void 0 ? props.maximized : internalMaximized.value);
328
+ const resolvedActiveTabId = (0, import_vue3.computed)(() => props.activeTabId !== void 0 ? props.activeTabId : internalActiveTabId.value);
329
+ const resolvedHeight = (0, import_vue3.computed)(() => props.height !== void 0 ? props.height : internalHeight.value);
330
+ const resolvedWidth = (0, import_vue3.computed)(() => props.width !== void 0 ? props.width : internalWidth.value);
331
+ const resolvedPosition = (0, import_vue3.computed)(() => props.position !== void 0 ? props.position : internalPosition.value);
332
+ function updateCollapsed(value) {
333
+ internalCollapsed.value = value;
334
+ emit("update:collapsed", value);
335
+ }
336
+ function updateHidden(value) {
337
+ internalHidden.value = value;
338
+ emit("update:hidden", value);
339
+ }
340
+ function updateMaximized(value) {
341
+ internalMaximized.value = value;
342
+ emit("update:maximized", value);
343
+ }
344
+ function updateActiveTabId(value) {
345
+ internalActiveTabId.value = value;
346
+ emit("update:activeTabId", value);
347
+ }
348
+ function updateHeight(value) {
349
+ internalHeight.value = value;
350
+ emit("update:height", value);
351
+ }
352
+ function updateWidth(value) {
353
+ internalWidth.value = value;
354
+ emit("update:width", value);
355
+ }
356
+ function updatePosition(value) {
357
+ internalPosition.value = value;
358
+ (0, import_cli_core.savePanelPosition)(value);
359
+ emit("update:position", value);
360
+ }
361
+ const closable = (0, import_vue3.computed)(() => mergedOptions.value?.closable ?? true);
362
+ const resizable = (0, import_vue3.computed)(() => mergedOptions.value?.resizable ?? true);
363
+ const isHorizontal = (0, import_vue3.computed)(() => resolvedPosition.value === "left" || resolvedPosition.value === "right");
364
+ const hideable = (0, import_vue3.computed)(() => mergedOptions.value?.hideable ?? true);
365
+ const hideAlignment = (0, import_vue3.computed)(() => mergedOptions.value?.hideAlignment ?? "center");
366
+ const syncTheme = (0, import_vue3.computed)(() => mergedOptions.value?.syncTheme ?? false);
367
+ const themeStyles = (0, import_vue3.ref)({});
368
+ const tabs = (0, import_vue3.ref)([]);
369
+ const activePaneId = (0, import_vue3.ref)(0);
370
+ let nextTabId = 1;
371
+ let nextPaneId = 1;
372
+ const contextMenu = (0, import_vue3.ref)({
373
+ visible: false,
374
+ x: 0,
375
+ y: 0,
376
+ tabId: 0
377
+ });
378
+ const engineMap = /* @__PURE__ */ new Map();
379
+ const paneResizing = (0, import_vue3.ref)(false);
380
+ let paneResizeState = {
381
+ tabId: 0,
382
+ dividerIndex: 0,
383
+ startX: 0,
384
+ startWidths: [],
385
+ containerWidth: 0
386
+ };
387
+ const panelResizing = (0, import_vue3.ref)(false);
388
+ let panelResizeState = { startY: 0, startHeight: 0, startX: 0, startWidth: 0 };
389
+ function addTab(title) {
390
+ const tabId = nextTabId++;
391
+ const paneId = nextPaneId++;
392
+ tabs.value = [...tabs.value, {
393
+ id: tabId,
394
+ title: title ?? `Terminal ${tabId}`,
395
+ isEditing: false,
396
+ panes: [{ id: paneId, widthPercent: 100 }]
397
+ }];
398
+ updateActiveTabId(tabId);
399
+ activePaneId.value = paneId;
400
+ emit("tab-added", { tabId });
401
+ return tabId;
402
+ }
403
+ let themeObserver;
404
+ function syncThemeFromEngine() {
405
+ const engine = engineMap.values().next().value;
406
+ if (!engine) return;
407
+ const theme = engine.getTerminal().options.theme;
408
+ if (theme) themeStyles.value = (0, import_cli_core.derivePanelThemeStyles)(theme);
409
+ }
410
+ function setupThemeSync() {
411
+ if (!syncTheme.value) return;
412
+ setTimeout(() => {
413
+ syncThemeFromEngine();
414
+ const container = document.querySelector(".cli-panel-wrapper .terminal-container");
415
+ if (!container) return;
416
+ themeObserver?.disconnect();
417
+ themeObserver = new MutationObserver(syncThemeFromEngine);
418
+ themeObserver.observe(container, { attributes: true, attributeFilter: ["style"] });
419
+ }, 200);
420
+ }
421
+ (0, import_vue3.onMounted)(() => {
422
+ document.addEventListener("click", closePositionDropdown);
423
+ });
424
+ (0, import_vue3.onBeforeUnmount)(() => {
425
+ themeObserver?.disconnect();
426
+ document.removeEventListener("click", closePositionDropdown);
427
+ });
428
+ function toggle() {
429
+ const newVal = !resolvedCollapsed.value;
430
+ updateCollapsed(newVal);
431
+ if (!newVal && !initialized.value) {
432
+ initialized.value = true;
433
+ addTab();
434
+ setupThemeSync();
435
+ }
436
+ }
437
+ function closeTab(id) {
438
+ const idx = tabs.value.findIndex((t) => t.id === id);
439
+ if (idx === -1) return;
440
+ tabs.value.splice(idx, 1);
441
+ emit("tab-closed", { tabId: id });
442
+ if (tabs.value.length === 0) {
443
+ initialized.value = false;
444
+ updateCollapsed(true);
445
+ return;
446
+ }
447
+ if (resolvedActiveTabId.value === id) {
448
+ const newIdx = Math.min(idx, tabs.value.length - 1);
449
+ selectTab(tabs.value[newIdx].id);
450
+ }
451
+ }
452
+ function selectTab(id) {
453
+ updateActiveTabId(id);
454
+ const tab = tabs.value.find((t) => t.id === id);
455
+ if (tab && tab.panes.length > 0) {
456
+ activePaneId.value = tab.panes[0].id;
457
+ }
458
+ }
459
+ function splitPane(tabId) {
460
+ const targetTabId = tabId ?? resolvedActiveTabId.value;
461
+ const paneId = nextPaneId++;
462
+ tabs.value = tabs.value.map((t) => {
463
+ if (t.id !== targetTabId) return t;
464
+ const newPanes = [...t.panes, { id: paneId, widthPercent: 0 }];
465
+ normalizePanes(newPanes);
466
+ return { ...t, panes: newPanes };
467
+ });
468
+ activePaneId.value = paneId;
469
+ emit("pane-split", { paneId, tabId: targetTabId });
470
+ return paneId;
471
+ }
472
+ function closePane(paneId) {
473
+ for (const tab of tabs.value) {
474
+ const idx = tab.panes.findIndex((p) => p.id === paneId);
475
+ if (idx === -1) continue;
476
+ if (tab.panes.length <= 1) {
477
+ closeTab(tab.id);
478
+ return;
479
+ }
480
+ engineMap.get(paneId)?.destroy();
481
+ engineMap.delete(paneId);
482
+ const newPanes = tab.panes.filter((p) => p.id !== paneId);
483
+ normalizePanes(newPanes);
484
+ if (activePaneId.value === paneId) {
485
+ activePaneId.value = newPanes[Math.min(idx, newPanes.length - 1)].id;
486
+ }
487
+ emit("pane-closed", { paneId });
488
+ tabs.value = tabs.value.map(
489
+ (t) => t.id === tab.id ? { ...t, panes: newPanes } : t
490
+ );
491
+ return;
492
+ }
493
+ }
494
+ function renameTab(tabId, title) {
495
+ tabs.value = tabs.value.map((t) => t.id === tabId ? { ...t, title } : t);
496
+ }
497
+ function startRename(tabId) {
498
+ tabs.value.forEach((t) => {
499
+ t.isEditing = t.id === tabId;
500
+ });
501
+ }
502
+ function commitRename(tabId, value) {
503
+ const trimmed = value.trim();
504
+ const tab = tabs.value.find((t) => t.id === tabId);
505
+ if (tab) {
506
+ if (trimmed) tab.title = trimmed;
507
+ tab.isEditing = false;
508
+ }
509
+ }
510
+ function closeContextMenu() {
511
+ contextMenu.value = { ...contextMenu.value, visible: false };
512
+ }
513
+ function onDocClick() {
514
+ if (contextMenu.value.visible) closeContextMenu();
515
+ }
516
+ (0, import_vue3.onMounted)(() => document.addEventListener("click", onDocClick));
517
+ (0, import_vue3.onBeforeUnmount)(
518
+ () => document.removeEventListener("click", onDocClick)
519
+ );
520
+ function onPanelResizeStart(e) {
521
+ if (!resizable.value) return;
522
+ e.preventDefault();
523
+ if (resolvedCollapsed.value) toggle();
524
+ panelResizing.value = true;
525
+ panelResizeState = {
526
+ startY: e.clientY,
527
+ startHeight: resolvedHeight.value,
528
+ startX: e.clientX,
529
+ startWidth: resolvedWidth.value
530
+ };
531
+ }
532
+ function onPanelResizeMove(e) {
533
+ if (!panelResizing.value) return;
534
+ if (isHorizontal.value) {
535
+ const deltaX = resolvedPosition.value === "left" ? e.clientX - panelResizeState.startX : panelResizeState.startX - e.clientX;
536
+ let next = Math.max(100, panelResizeState.startWidth + deltaX);
537
+ if (next > window.innerWidth) next = window.innerWidth;
538
+ updateWidth(next);
539
+ } else {
540
+ const deltaY = resolvedPosition.value === "top" ? e.clientY - panelResizeState.startY : panelResizeState.startY - e.clientY;
541
+ let next = Math.max(100, panelResizeState.startHeight + deltaY);
542
+ if (next > window.innerHeight) next = window.innerHeight;
543
+ updateHeight(next);
544
+ }
545
+ }
546
+ function onPanelResizeEnd() {
547
+ panelResizing.value = false;
548
+ }
549
+ (0, import_vue3.onMounted)(() => {
550
+ document.addEventListener("mousemove", onPanelResizeMove);
551
+ document.addEventListener("mouseup", onPanelResizeEnd);
552
+ });
553
+ (0, import_vue3.onBeforeUnmount)(() => {
554
+ document.removeEventListener("mousemove", onPanelResizeMove);
555
+ document.removeEventListener("mouseup", onPanelResizeEnd);
556
+ });
557
+ function onPaneResizeStart(e, tabId, dividerIndex) {
558
+ e.preventDefault();
559
+ const tab = tabs.value.find((t) => t.id === tabId);
560
+ if (!tab) return;
561
+ paneResizing.value = true;
562
+ const container = e.target.closest(
563
+ ".cli-panel-panes-container"
564
+ );
565
+ paneResizeState = {
566
+ tabId,
567
+ dividerIndex,
568
+ startX: e.clientX,
569
+ startWidths: tab.panes.map((p) => p.widthPercent),
570
+ containerWidth: container ? container.clientWidth : 1
571
+ };
572
+ document.body.classList.add("cli-pane-resizing");
573
+ }
574
+ function onPaneResizeMove(e) {
575
+ if (!paneResizing.value) return;
576
+ const s = paneResizeState;
577
+ const deltaPct = (e.clientX - s.startX) / s.containerWidth * 100;
578
+ const i = s.dividerIndex;
579
+ let leftW = s.startWidths[i] + deltaPct;
580
+ let rightW = s.startWidths[i + 1] - deltaPct;
581
+ if (leftW < MIN_PANE_WIDTH_PERCENT) {
582
+ leftW = MIN_PANE_WIDTH_PERCENT;
583
+ rightW = s.startWidths[i] + s.startWidths[i + 1] - MIN_PANE_WIDTH_PERCENT;
584
+ }
585
+ if (rightW < MIN_PANE_WIDTH_PERCENT) {
586
+ rightW = MIN_PANE_WIDTH_PERCENT;
587
+ leftW = s.startWidths[i] + s.startWidths[i + 1] - MIN_PANE_WIDTH_PERCENT;
588
+ }
589
+ const tab = tabs.value.find((t) => t.id === s.tabId);
590
+ if (tab) {
591
+ tab.panes[i].widthPercent = leftW;
592
+ tab.panes[i + 1].widthPercent = rightW;
593
+ }
594
+ }
595
+ function onPaneResizeEnd() {
596
+ if (!paneResizing.value) return;
597
+ paneResizing.value = false;
598
+ document.body.classList.remove("cli-pane-resizing");
599
+ }
600
+ (0, import_vue3.onMounted)(() => {
601
+ document.addEventListener("mousemove", onPaneResizeMove);
602
+ document.addEventListener("mouseup", onPaneResizeEnd);
603
+ });
604
+ (0, import_vue3.onBeforeUnmount)(() => {
605
+ document.removeEventListener("mousemove", onPaneResizeMove);
606
+ document.removeEventListener("mouseup", onPaneResizeEnd);
607
+ });
608
+ function toggleMaximize() {
609
+ if (!resolvedMaximized.value) {
610
+ if (isHorizontal.value) {
611
+ prevWidth.value = resolvedWidth.value;
612
+ updateWidth(window.innerWidth);
613
+ } else {
614
+ prevHeight.value = resolvedHeight.value;
615
+ updateHeight(window.innerHeight);
616
+ }
617
+ } else {
618
+ if (isHorizontal.value) {
619
+ updateWidth(prevWidth.value);
620
+ } else {
621
+ updateHeight(prevHeight.value);
622
+ }
623
+ }
624
+ updateMaximized(!resolvedMaximized.value);
625
+ }
626
+ function handleClose() {
627
+ visible.value = false;
628
+ emit("close");
629
+ props.onClose?.();
630
+ }
631
+ function handleHide() {
632
+ preHideCollapsed = resolvedCollapsed.value;
633
+ updateHidden(true);
634
+ }
635
+ function handleUnhide() {
636
+ updateHidden(false);
637
+ updateCollapsed(preHideCollapsed);
638
+ }
639
+ const positionDropdownOpen = (0, import_vue3.ref)(false);
640
+ function closePositionDropdown() {
641
+ positionDropdownOpen.value = false;
642
+ }
643
+ function togglePositionDropdown(e) {
644
+ e.stopPropagation();
645
+ positionDropdownOpen.value = !positionDropdownOpen.value;
646
+ }
647
+ function selectPosition(pos) {
648
+ positionDropdownOpen.value = false;
649
+ updatePosition(pos);
650
+ }
651
+ function getEngine(paneId) {
652
+ const targetId = paneId ?? activePaneId.value;
653
+ return engineMap.get(targetId);
654
+ }
655
+ function getState() {
656
+ return {
657
+ collapsed: resolvedCollapsed.value,
658
+ hidden: resolvedHidden.value,
659
+ maximized: resolvedMaximized.value,
660
+ position: resolvedPosition.value,
661
+ height: resolvedHeight.value,
662
+ width: resolvedWidth.value,
663
+ activeTabId: resolvedActiveTabId.value,
664
+ activePaneId: activePaneId.value,
665
+ tabs: tabs.value.map((t) => ({
666
+ id: t.id,
667
+ title: t.title,
668
+ panes: t.panes.map((p) => ({ id: p.id, widthPercent: p.widthPercent }))
669
+ }))
670
+ };
671
+ }
672
+ expose({
673
+ open: () => {
674
+ if (!visible.value) {
675
+ visible.value = true;
676
+ }
677
+ if (resolvedHidden.value) {
678
+ updateHidden(false);
679
+ }
680
+ if (resolvedCollapsed.value) {
681
+ updateCollapsed(false);
682
+ if (!initialized.value) {
683
+ initialized.value = true;
684
+ addTab();
685
+ setupThemeSync();
686
+ }
687
+ }
688
+ },
689
+ collapse: () => {
690
+ if (!resolvedCollapsed.value) updateCollapsed(true);
691
+ },
692
+ toggleCollapse: () => {
693
+ if (resolvedCollapsed.value) {
694
+ updateCollapsed(false);
695
+ if (!initialized.value) {
696
+ initialized.value = true;
697
+ addTab();
698
+ setupThemeSync();
699
+ }
700
+ } else {
701
+ updateCollapsed(true);
702
+ }
703
+ },
704
+ hide: () => {
705
+ if (!resolvedHidden.value) updateHidden(true);
706
+ },
707
+ unhide: () => {
708
+ if (resolvedHidden.value) updateHidden(false);
709
+ },
710
+ toggleHide: () => {
711
+ updateHidden(!resolvedHidden.value);
712
+ },
713
+ close: handleClose,
714
+ maximize: () => {
715
+ if (!resolvedMaximized.value) updateMaximized(true);
716
+ },
717
+ restore: () => {
718
+ if (resolvedMaximized.value) updateMaximized(false);
719
+ },
720
+ toggleMaximize: () => {
721
+ updateMaximized(!resolvedMaximized.value);
722
+ },
723
+ resize: (dims) => {
724
+ if (dims.height !== void 0) updateHeight(dims.height);
725
+ if (dims.width !== void 0) updateWidth(dims.width);
726
+ },
727
+ setPosition: updatePosition,
728
+ addTab,
729
+ closeTab,
730
+ selectTab,
731
+ renameTab,
732
+ splitPane,
733
+ closePane,
734
+ getEngine,
735
+ getState
736
+ });
737
+ return () => {
738
+ if (!visible.value) return null;
739
+ const wrapperClass = [
740
+ "cli-panel-wrapper",
741
+ resolvedCollapsed.value && "collapsed",
742
+ resolvedMaximized.value && "maximized",
743
+ panelResizing.value && "resizing",
744
+ props.class
745
+ ].filter(Boolean).join(" ");
746
+ const wrapperStyle = {
747
+ ...isHorizontal.value ? { width: `${resolvedWidth.value}px` } : { height: `${resolvedHeight.value}px` },
748
+ ...resolvedHidden.value ? { display: "none" } : {},
749
+ ...themeStyles.value,
750
+ ...props.style
751
+ };
752
+ const headerEl = (0, import_vue3.h)("div", { class: "cli-panel-header" }, [
753
+ (0, import_vue3.h)(
754
+ "div",
755
+ {
756
+ class: "cli-panel-resize-bar",
757
+ onMousedown: onPanelResizeStart
758
+ },
759
+ [(0, import_vue3.h)("div", { class: "cli-panel-resize-grip" })]
760
+ ),
761
+ (0, import_vue3.h)("div", { class: "cli-panel-header-content" }, [
762
+ (0, import_vue3.h)("p", { class: "cli-panel-title" }, [
763
+ (0, import_vue3.h)("span", { class: "cli-panel-title-icon" }, [
764
+ terminalIcon()
765
+ ]),
766
+ "CLI"
767
+ ]),
768
+ (0, import_vue3.h)("div", { class: "cli-panel-action-buttons" }, [
769
+ (0, import_vue3.h)("div", {
770
+ class: "cli-panel-btn-position-wrapper",
771
+ onClick: (e) => e.stopPropagation()
772
+ }, [
773
+ (0, import_vue3.h)("button", {
774
+ class: "cli-panel-btn cli-panel-btn-position",
775
+ title: "Move panel",
776
+ onClick: togglePositionDropdown
777
+ }, [positionIcon(resolvedPosition.value)]),
778
+ positionDropdownOpen.value ? (0, import_vue3.h)(
779
+ "div",
780
+ { class: "cli-panel-position-dropdown" },
781
+ ["bottom", "top", "left", "right"].map(
782
+ (pos) => (0, import_vue3.h)("button", {
783
+ class: ["cli-panel-position-dropdown-item", resolvedPosition.value === pos ? "active" : ""].filter(Boolean).join(" "),
784
+ onClick: () => selectPosition(pos)
785
+ }, [
786
+ positionIcon(pos, 16),
787
+ pos.charAt(0).toUpperCase() + pos.slice(1)
788
+ ])
789
+ )
790
+ ) : null
791
+ ]),
792
+ hideable.value ? (0, import_vue3.h)("button", {
793
+ class: "cli-panel-btn cli-panel-btn-hide",
794
+ title: "Hide",
795
+ onClick: handleHide
796
+ }, [hideIcon()]) : null,
797
+ (0, import_vue3.h)(
798
+ "button",
799
+ {
800
+ class: "cli-panel-btn",
801
+ title: resolvedMaximized.value ? "Restore" : "Maximize",
802
+ disabled: resolvedCollapsed.value,
803
+ onClick: toggleMaximize
804
+ },
805
+ [resolvedMaximized.value ? restoreIcon() : maximizeIcon()]
806
+ ),
807
+ (0, import_vue3.h)(
808
+ "button",
809
+ {
810
+ class: "cli-panel-btn",
811
+ title: resolvedCollapsed.value ? "Expand" : "Collapse",
812
+ onClick: toggle
813
+ },
814
+ [collapseChevron(resolvedPosition.value, resolvedCollapsed.value)]
815
+ ),
816
+ closable.value ? (0, import_vue3.h)(
817
+ "button",
818
+ {
819
+ class: "cli-panel-btn cli-panel-btn-close",
820
+ title: "Close",
821
+ onClick: handleClose
822
+ },
823
+ [closeIcon()]
824
+ ) : null
825
+ ])
826
+ ])
827
+ ]);
828
+ const contentEl = initialized.value ? (0, import_vue3.h)("div", { class: "cli-panel-content", style: resolvedCollapsed.value ? { display: "none" } : void 0 }, [
829
+ // Tab bar
830
+ (0, import_vue3.h)("div", { class: "cli-panel-tabs" }, [
831
+ (0, import_vue3.h)(
832
+ "ul",
833
+ { class: "cli-panel-tab-list" },
834
+ tabs.value.map(
835
+ (tab) => (0, import_vue3.h)(
836
+ "li",
837
+ {
838
+ key: tab.id,
839
+ class: [
840
+ "cli-panel-tab",
841
+ tab.id === resolvedActiveTabId.value && "active"
842
+ ].filter(Boolean).join(" "),
843
+ onClick: () => selectTab(tab.id),
844
+ onDblclick: () => startRename(tab.id),
845
+ onContextmenu: (e) => {
846
+ e.preventDefault();
847
+ e.stopPropagation();
848
+ contextMenu.value = {
849
+ visible: true,
850
+ x: e.clientX,
851
+ y: e.clientY,
852
+ tabId: tab.id
853
+ };
854
+ }
855
+ },
856
+ tab.isEditing ? [
857
+ (0, import_vue3.h)("input", {
858
+ class: "cli-panel-tab-rename-input",
859
+ type: "text",
860
+ value: tab.title,
861
+ onKeydown: (e) => {
862
+ if (e.key === "Enter")
863
+ commitRename(
864
+ tab.id,
865
+ e.target.value
866
+ );
867
+ else if (e.key === "Escape") {
868
+ tab.isEditing = false;
869
+ }
870
+ },
871
+ onBlur: (e) => commitRename(
872
+ tab.id,
873
+ e.target.value
874
+ ),
875
+ onClick: (e) => e.stopPropagation(),
876
+ onDblclick: (e) => e.stopPropagation()
877
+ })
878
+ ] : [
879
+ (0, import_vue3.h)(
880
+ "span",
881
+ {
882
+ class: "cli-panel-tab-title"
883
+ },
884
+ tab.title
885
+ ),
886
+ (0, import_vue3.h)(
887
+ "button",
888
+ {
889
+ class: "cli-panel-tab-close-btn",
890
+ title: "Close tab",
891
+ onClick: (e) => {
892
+ e.stopPropagation();
893
+ closeTab(
894
+ tab.id
895
+ );
896
+ }
897
+ },
898
+ "\xD7"
899
+ )
900
+ ]
901
+ )
902
+ )
903
+ ),
904
+ (0, import_vue3.h)(
905
+ "button",
906
+ {
907
+ class: "cli-panel-add-tab",
908
+ title: "New terminal",
909
+ onClick: addTab
910
+ },
911
+ "+"
912
+ )
913
+ ]),
914
+ // Terminal instances
915
+ (0, import_vue3.h)(
916
+ "div",
917
+ { class: "cli-panel-instances" },
918
+ tabs.value.map(
919
+ (tab) => (0, import_vue3.h)(
920
+ "div",
921
+ {
922
+ key: tab.id,
923
+ class: "cli-panel-instance",
924
+ style: {
925
+ display: tab.id === resolvedActiveTabId.value ? void 0 : "none"
926
+ }
927
+ },
928
+ [
929
+ (0, import_vue3.h)(
930
+ "div",
931
+ {
932
+ class: [
933
+ "cli-panel-panes-container",
934
+ paneResizing.value && "resizing"
935
+ ].filter(Boolean).join(" ")
936
+ },
937
+ tab.panes.flatMap((pane, i) => {
938
+ const nodes = [];
939
+ if (i > 0) {
940
+ nodes.push(
941
+ (0, import_vue3.h)(
942
+ "div",
943
+ {
944
+ class: "cli-panel-pane-divider",
945
+ onMousedown: (e) => onPaneResizeStart(
946
+ e,
947
+ tab.id,
948
+ i - 1
949
+ )
950
+ },
951
+ [
952
+ (0, import_vue3.h)("div", {
953
+ class: "cli-panel-pane-divider-grip"
954
+ })
955
+ ]
956
+ )
957
+ );
958
+ }
959
+ nodes.push(
960
+ (0, import_vue3.h)(
961
+ "div",
962
+ {
963
+ class: [
964
+ "cli-panel-pane",
965
+ pane.id === activePaneId.value && tab.id === resolvedActiveTabId.value && "active-pane"
966
+ ].filter(
967
+ Boolean
968
+ ).join(" "),
969
+ style: {
970
+ flex: `${pane.widthPercent} 1 0`
971
+ },
972
+ onClick: () => {
973
+ activePaneId.value = pane.id;
974
+ updateActiveTabId(tab.id);
975
+ }
976
+ },
977
+ [
978
+ tab.panes.length > 1 ? (0, import_vue3.h)(
979
+ "button",
980
+ {
981
+ class: "cli-panel-pane-close-btn",
982
+ title: "Close pane",
983
+ onClick: (e) => {
984
+ e.stopPropagation();
985
+ closePane(
986
+ pane.id
987
+ );
988
+ }
989
+ },
990
+ "\xD7"
991
+ ) : null,
992
+ (0, import_vue3.h)(Cli, {
993
+ options: mergedOptions.value,
994
+ modules: mergedModules.value,
995
+ processors: mergedProcessors.value,
996
+ services: mergedServices.value,
997
+ snapshot: pane.snapshot,
998
+ style: {
999
+ height: "100%"
1000
+ },
1001
+ onReady: (engine) => {
1002
+ engineMap.set(pane.id, engine);
1003
+ }
1004
+ })
1005
+ ]
1006
+ )
1007
+ );
1008
+ return nodes;
1009
+ })
1010
+ )
1011
+ ]
1012
+ )
1013
+ )
1014
+ )
1015
+ ]) : null;
1016
+ const contextMenuEl = contextMenu.value.visible ? (0, import_vue3.h)(
1017
+ "div",
1018
+ {
1019
+ class: "cli-panel-context-menu",
1020
+ style: {
1021
+ left: `${contextMenu.value.x}px`,
1022
+ top: `${contextMenu.value.y}px`
1023
+ },
1024
+ onClick: (e) => e.stopPropagation()
1025
+ },
1026
+ [
1027
+ (0, import_vue3.h)(
1028
+ "button",
1029
+ {
1030
+ class: "cli-panel-context-menu-item",
1031
+ onClick: () => {
1032
+ closeContextMenu();
1033
+ startRename(contextMenu.value.tabId);
1034
+ }
1035
+ },
1036
+ "Rename"
1037
+ ),
1038
+ (0, import_vue3.h)(
1039
+ "button",
1040
+ {
1041
+ class: "cli-panel-context-menu-item",
1042
+ onClick: () => {
1043
+ const tab = tabs.value.find(
1044
+ (t) => t.id === contextMenu.value.tabId
1045
+ );
1046
+ closeContextMenu();
1047
+ if (!tab) return;
1048
+ const sourceEngine = engineMap.get(tab.panes[0]?.id);
1049
+ const snapshot = sourceEngine?.snapshot();
1050
+ const paneId = nextPaneId++;
1051
+ const tabId = nextTabId++;
1052
+ const idx = tabs.value.indexOf(tab);
1053
+ tabs.value.splice(idx + 1, 0, {
1054
+ id: tabId,
1055
+ title: `${tab.title} (copy)`,
1056
+ isEditing: false,
1057
+ panes: [
1058
+ { id: paneId, widthPercent: 100, snapshot }
1059
+ ]
1060
+ });
1061
+ updateActiveTabId(tabId);
1062
+ activePaneId.value = paneId;
1063
+ }
1064
+ },
1065
+ "Duplicate"
1066
+ ),
1067
+ (0, import_vue3.h)(
1068
+ "button",
1069
+ {
1070
+ class: "cli-panel-context-menu-item",
1071
+ onClick: () => {
1072
+ closeContextMenu();
1073
+ splitPane(contextMenu.value.tabId);
1074
+ }
1075
+ },
1076
+ "Split Right"
1077
+ ),
1078
+ (0, import_vue3.h)("div", {
1079
+ class: "cli-panel-context-menu-separator"
1080
+ }),
1081
+ (0, import_vue3.h)(
1082
+ "button",
1083
+ {
1084
+ class: "cli-panel-context-menu-item",
1085
+ onClick: () => {
1086
+ closeContextMenu();
1087
+ closeTab(contextMenu.value.tabId);
1088
+ }
1089
+ },
1090
+ "Close"
1091
+ ),
1092
+ (0, import_vue3.h)(
1093
+ "button",
1094
+ {
1095
+ class: "cli-panel-context-menu-item",
1096
+ disabled: tabs.value.length <= 1,
1097
+ onClick: () => {
1098
+ const id = contextMenu.value.tabId;
1099
+ closeContextMenu();
1100
+ tabs.value = tabs.value.filter(
1101
+ (t) => t.id === id
1102
+ );
1103
+ updateActiveTabId(id);
1104
+ }
1105
+ },
1106
+ "Close Others"
1107
+ ),
1108
+ (0, import_vue3.h)(
1109
+ "button",
1110
+ {
1111
+ class: "cli-panel-context-menu-item",
1112
+ onClick: () => {
1113
+ const id = contextMenu.value.tabId;
1114
+ closeContextMenu();
1115
+ const idx = tabs.value.findIndex(
1116
+ (t) => t.id === id
1117
+ );
1118
+ if (idx !== -1)
1119
+ tabs.value = tabs.value.slice(
1120
+ 0,
1121
+ idx + 1
1122
+ );
1123
+ }
1124
+ },
1125
+ "Close to the Right"
1126
+ ),
1127
+ (0, import_vue3.h)("div", {
1128
+ class: "cli-panel-context-menu-separator"
1129
+ }),
1130
+ (0, import_vue3.h)(
1131
+ "button",
1132
+ {
1133
+ class: "cli-panel-context-menu-item destructive",
1134
+ onClick: () => {
1135
+ closeContextMenu();
1136
+ tabs.value = [];
1137
+ initialized.value = false;
1138
+ updateCollapsed(true);
1139
+ }
1140
+ },
1141
+ "Close All"
1142
+ )
1143
+ ]
1144
+ ) : null;
1145
+ const hideTabEl = resolvedHidden.value ? (0, import_vue3.h)("button", {
1146
+ class: "cli-panel-hide-tab",
1147
+ "data-position": resolvedPosition.value,
1148
+ "data-hide-align": hideAlignment.value,
1149
+ style: themeStyles.value,
1150
+ title: "Show CLI",
1151
+ onClick: handleUnhide
1152
+ }, [
1153
+ (0, import_vue3.h)("svg", { class: "cli-panel-hide-tab-icon", ...svgAttrs, width: "16", height: "16", "stroke-width": "2" }, [
1154
+ (0, import_vue3.h)("polyline", { points: "4 17 10 11 4 5" }),
1155
+ (0, import_vue3.h)("line", { x1: "12", y1: "19", x2: "20", y2: "19" })
1156
+ ]),
1157
+ (0, import_vue3.h)("span", { class: "cli-panel-hide-tab-label" }, "CLI"),
1158
+ hideTabChevron(resolvedPosition.value)
1159
+ ]) : null;
1160
+ return (0, import_vue3.h)("div", {}, [
1161
+ hideTabEl,
1162
+ (0, import_vue3.h)(
1163
+ "div",
1164
+ {
1165
+ class: wrapperClass,
1166
+ style: wrapperStyle,
1167
+ "data-position": resolvedPosition.value,
1168
+ "data-resizable": String(resizable.value),
1169
+ "data-closable": String(closable.value),
1170
+ "data-hideable": String(hideable.value)
1171
+ },
1172
+ [headerEl, contentEl]
1173
+ ),
1174
+ contextMenuEl
1175
+ ]);
1176
+ };
1177
+ }
1178
+ });
1179
+
1180
+ // src/CliProvider.ts
1181
+ var import_vue5 = require("vue");
1182
+
1183
+ // src/useCliEngine.ts
1184
+ var import_vue4 = require("vue");
1185
+ var import_cli2 = require("@qodalis/cli");
1186
+ function useCliEngine(containerRef, config) {
1187
+ const engine = (0, import_vue4.shallowRef)(null);
1188
+ (0, import_vue4.onMounted)(async () => {
1189
+ if (!containerRef.value) return;
1190
+ const e = new import_cli2.CliEngine(containerRef.value, config?.options);
1191
+ e.registerService("cli-framework", "Vue");
1192
+ if (config?.services) {
1193
+ for (const [token, value] of Object.entries(config.services)) {
1194
+ e.registerService(token, value);
1195
+ }
1196
+ }
1197
+ if (config?.modules) {
1198
+ e.registerModules(config.modules);
1199
+ }
1200
+ if (config?.processors) {
1201
+ e.registerProcessors(config.processors);
1202
+ }
1203
+ await e.start();
1204
+ engine.value = e;
1205
+ });
1206
+ (0, import_vue4.onBeforeUnmount)(() => {
1207
+ engine.value?.destroy();
1208
+ engine.value = null;
1209
+ });
1210
+ return engine;
1211
+ }
1212
+
1213
+ // src/CliProvider.ts
1214
+ var CliProvider = (0, import_vue5.defineComponent)({
1215
+ name: "CliProvider",
1216
+ props: {
1217
+ modules: {
1218
+ type: Array,
1219
+ default: void 0
1220
+ },
1221
+ processors: {
1222
+ type: Array,
1223
+ default: void 0
1224
+ },
1225
+ options: {
1226
+ type: Object,
1227
+ default: void 0
1228
+ },
1229
+ services: {
1230
+ type: Object,
1231
+ default: void 0
1232
+ },
1233
+ style: {
1234
+ type: Object,
1235
+ default: void 0
1236
+ }
1237
+ },
1238
+ emits: ["ready"],
1239
+ setup(props, { slots, emit }) {
1240
+ const containerRef = (0, import_vue5.ref)(null);
1241
+ const engine = useCliEngine(containerRef, {
1242
+ modules: props.modules,
1243
+ processors: props.processors,
1244
+ options: props.options,
1245
+ services: props.services
1246
+ });
1247
+ (0, import_vue5.provide)(CliInjectionKey, { engine });
1248
+ return () => (0, import_vue5.h)("div", { style: { height: "100%" } }, [
1249
+ (0, import_vue5.h)("div", {
1250
+ ref: containerRef,
1251
+ style: { height: "100%", ...props.style }
1252
+ }),
1253
+ slots.default?.()
1254
+ ]);
1255
+ }
1256
+ });
1257
+
1258
+ // src/useCli.ts
1259
+ var import_vue6 = require("vue");
1260
+ function useCli() {
1261
+ const ctx = (0, import_vue6.inject)(CliInjectionKey);
1262
+ if (!ctx) {
1263
+ throw new Error(
1264
+ "useCli() must be used inside a <CliProvider> component"
1265
+ );
1266
+ }
1267
+ return ctx;
1268
+ }
1269
+
1270
+ // src/index.ts
1271
+ var import_cli3 = require("@qodalis/cli");
1272
+ // Annotate the CommonJS export names for ESM import in node:
1273
+ 0 && (module.exports = {
1274
+ Cli,
1275
+ CliConfigKey,
1276
+ CliConfigProvider,
1277
+ CliEngine,
1278
+ CliInjectionKey,
1279
+ CliPanel,
1280
+ CliProvider,
1281
+ useCli,
1282
+ useCliEngine
1283
+ });
1284
+ //# sourceMappingURL=index.js.map