@statiolake/coc-ui 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 statiolake
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,93 @@
1
+ # coc-ui
2
+
3
+ VS Code-style workbench surfaces for coc.nvim extensions. Extensions contribute
4
+ View Containers to the primary sidebar, secondary sidebar, or panel, then
5
+ contribute one or more Views to each container. The active container is selected
6
+ per surface; all non-hidden Views in that container remain mounted together.
7
+
8
+ The API intentionally mirrors VS Code's `ViewContainer` / `View` separation:
9
+
10
+ ```ts
11
+ const container = ui.registerViewContainer({
12
+ id: "example",
13
+ title: "Example",
14
+ icon: "󰏗",
15
+ location: "primarySidebar",
16
+ });
17
+
18
+ ui.registerView({
19
+ id: "example.items",
20
+ containerId: "example",
21
+ name: "Items",
22
+ order: 1,
23
+ });
24
+
25
+ ui.createTreeView("example.items", {
26
+ treeDataProvider,
27
+ actions: [
28
+ {
29
+ id: "example.rename",
30
+ title: "Rename",
31
+ keys: ["r"],
32
+ handler: (item) => item && rename(item),
33
+ },
34
+ ],
35
+ });
36
+
37
+ ui.registerView({
38
+ id: "example.details",
39
+ containerId: "example",
40
+ name: "Details",
41
+ order: 2,
42
+ visibility: "collapsed",
43
+ });
44
+
45
+ ui.createTreeView("example.details", {
46
+ treeDataProvider: detailsProvider,
47
+ });
48
+ ```
49
+
50
+ This follows VS Code's `viewsContainers` and `views` model:
51
+
52
+ - A workbench surface has one active View Container.
53
+ - A View Container contains multiple ordered Views, not one active View.
54
+ - Views start as `visible`, `collapsed`, or `hidden`.
55
+ - User-chosen visible/collapsed state is restored per workspace.
56
+ - Sidebar Views are stacked vertically. Panel Views are arranged horizontally.
57
+ - The Activity Bar selects the active sidebar container.
58
+
59
+ `registerViewContainer()` and `registerView()` are the runtime equivalents of
60
+ VS Code's `viewsContainers` and `views` contribution points. `createTreeView()`
61
+ uses the VS Code shape: a stable View id followed by provider options.
62
+
63
+ `showContainer()` mounts every non-hidden View in the container. `showView()`
64
+ selects its container, expands that View, and focuses it without closing sibling
65
+ Views. Use `za` or double-click a View title to collapse or expand it.
66
+
67
+ Workbench surfaces have separate show/hide and close lifecycles. Hiding a
68
+ surface removes its windows while preserving the active container, TreeView
69
+ buffers, expansion state, and cursor position. Showing it restores that state;
70
+ only an explicit container close discards the active selection.
71
+
72
+ Locations can also be shown before a ViewContainer is contributed. In that
73
+ state coc-ui renders an empty workbench surface that can receive future views
74
+ instead of treating the location as unavailable.
75
+
76
+ View actions populate the tree item's context menu. Optional view-local keys
77
+ invoke the same action with the element under the cursor, keeping commands,
78
+ menus, and keybindings as one declaration.
79
+
80
+ `coc-ui.switchPrimarySidebar`, `coc-ui.switchSecondarySidebar`, and
81
+ `coc-ui.switchPanel` provide command-driven container selection. Sidebar
82
+ Activity Bar icons provide direct keyboard and mouse selection. Containers on
83
+ distinct surfaces remain mounted concurrently.
84
+
85
+ Tree views retain coc.nvim's native single-click behavior. When
86
+ `coc-ui.mouse.enable` is enabled, right-clicking a tree item opens the actions
87
+ provided by its `TreeDataProvider.resolveActions` implementation.
88
+
89
+ View content currently uses coc.nvim's native TreeView renderer. coc-ui owns the
90
+ workbench model, layout, Activity Bar, container lifecycle, and action
91
+ contributions; it does not duplicate TreeDataProvider rendering.
92
+
93
+ This repository is under local development and is not published yet.
package/lib/index.d.ts ADDED
@@ -0,0 +1,57 @@
1
+ import { Disposable, ExtensionContext, TreeView, TreeViewOptions } from "coc.nvim";
2
+ /** Mirrors VS Code's workbench surfaces. */
3
+ export type ViewLocation = "primarySidebar" | "secondarySidebar" | "panel";
4
+ export type ViewVisibility = "visible" | "collapsed" | "hidden";
5
+ /**
6
+ * Coc equivalent of VS Code's ViewContainerLocation. The string values are
7
+ * intentionally stable because they are also suitable for configuration.
8
+ */
9
+ export declare const ViewContainerLocation: {
10
+ readonly Sidebar: "primarySidebar";
11
+ readonly AuxiliaryBar: "secondarySidebar";
12
+ readonly Panel: "panel";
13
+ };
14
+ export interface ViewContainerRegistration {
15
+ id: string;
16
+ title: string;
17
+ icon?: string;
18
+ location?: ViewLocation;
19
+ order?: number;
20
+ }
21
+ export interface ViewRegistration {
22
+ id: string;
23
+ containerId: string;
24
+ name: string;
25
+ contextualTitle?: string;
26
+ order?: number;
27
+ visibility?: ViewVisibility;
28
+ }
29
+ export interface CocTreeViewOptions<T> extends TreeViewOptions<T> {
30
+ actions?: ViewAction<T>[];
31
+ }
32
+ export interface ViewAction<T> {
33
+ id: string;
34
+ title: string;
35
+ keys?: string[];
36
+ when?: (element: T) => boolean;
37
+ handler: (element: T) => void | Promise<void>;
38
+ }
39
+ export interface ShowViewOptions {
40
+ focus?: boolean;
41
+ }
42
+ export interface CocUiApi {
43
+ registerViewContainer(registration: ViewContainerRegistration): Disposable;
44
+ registerView(registration: ViewRegistration): Disposable;
45
+ createTreeView<T>(id: string, options: CocTreeViewOptions<T>): TreeView<T>;
46
+ showContainer(id: string, options?: ShowViewOptions): Promise<void>;
47
+ showLocation(location: ViewLocation): Promise<void>;
48
+ hideLocation(location: ViewLocation): Promise<void>;
49
+ toggleLocation(location: ViewLocation): Promise<void>;
50
+ switchLocation(location: ViewLocation): Promise<void>;
51
+ showView(id: string, options?: ShowViewOptions): Promise<void>;
52
+ closeContainer(id: string): Promise<void>;
53
+ toggleView(id: string): Promise<void>;
54
+ toggleTreeItem(id: string): Promise<void>;
55
+ openLocation(uri: string, line: number, character: number): Promise<void>;
56
+ }
57
+ export declare function activate(context: ExtensionContext): Promise<CocUiApi>;
package/lib/index.js ADDED
@@ -0,0 +1,945 @@
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
+ ViewContainerLocation: () => ViewContainerLocation,
24
+ activate: () => activate
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+ var import_coc = require("coc.nvim");
28
+ var ViewContainerLocation = {
29
+ Sidebar: "primarySidebar",
30
+ AuxiliaryBar: "secondarySidebar",
31
+ Panel: "panel"
32
+ };
33
+ var CocUi = class {
34
+ constructor(context) {
35
+ this.context = context;
36
+ }
37
+ containers = /* @__PURE__ */ new Map();
38
+ viewRegistrations = /* @__PURE__ */ new Map();
39
+ views = /* @__PURE__ */ new Map();
40
+ surfaces = /* @__PURE__ */ new Map();
41
+ unmountingContainers = /* @__PURE__ */ new Set();
42
+ editorWindowId;
43
+ registerViewContainer(registration) {
44
+ if (this.containers.has(registration.id)) {
45
+ throw new Error(`View container already registered: ${registration.id}`);
46
+ }
47
+ this.containers.set(registration.id, {
48
+ title: registration.title,
49
+ icon: registration.icon ?? "\u2022",
50
+ location: registration.location ?? "primarySidebar",
51
+ order: registration.order ?? 0,
52
+ viewIds: []
53
+ });
54
+ void this.renderActivityBar(registration.location ?? "primarySidebar");
55
+ return import_coc.Disposable.create(() => {
56
+ void this.closeContainer(registration.id);
57
+ this.containers.delete(registration.id);
58
+ });
59
+ }
60
+ registerView(registration) {
61
+ if (this.viewRegistrations.has(registration.id) || this.views.has(registration.id)) {
62
+ throw new Error(`View already registered: ${registration.id}`);
63
+ }
64
+ const container = this.containers.get(registration.containerId);
65
+ if (!container) {
66
+ throw new Error(`Unknown view container: ${registration.containerId}`);
67
+ }
68
+ this.viewRegistrations.set(registration.id, registration);
69
+ return import_coc.Disposable.create(() => {
70
+ this.viewRegistrations.delete(registration.id);
71
+ this.views.delete(registration.id);
72
+ container.viewIds = container.viewIds.filter(
73
+ (id) => id !== registration.id
74
+ );
75
+ });
76
+ }
77
+ createTreeView(id, options) {
78
+ if (this.views.has(id)) {
79
+ throw new Error(`TreeView already created: ${id}`);
80
+ }
81
+ const registration = this.viewRegistrations.get(id);
82
+ if (!registration) {
83
+ throw new Error(`View contribution not registered: ${id}`);
84
+ }
85
+ const container = this.requireContainer(registration.containerId);
86
+ const { actions = [], ...treeOptions } = options;
87
+ const treeDataProvider = withViewActions(
88
+ treeOptions.treeDataProvider,
89
+ actions
90
+ );
91
+ const tree = import_coc.window.createTreeView(id, {
92
+ ...treeOptions,
93
+ treeDataProvider,
94
+ bufhidden: treeOptions.bufhidden ?? "hide"
95
+ });
96
+ const keymappableTree = tree;
97
+ if (typeof keymappableTree.registerLocalKeymap !== "function") {
98
+ throw new Error(
99
+ "Installed coc.nvim does not support TreeView keybindings"
100
+ );
101
+ }
102
+ for (const action of actions) {
103
+ for (const key of action.keys ?? []) {
104
+ keymappableTree.registerLocalKeymap(
105
+ "n",
106
+ key,
107
+ (element) => {
108
+ if (element && (!action.when || action.when(element))) {
109
+ return action.handler(element);
110
+ }
111
+ },
112
+ true
113
+ );
114
+ }
115
+ }
116
+ tree.title = registration.name;
117
+ const registered = {
118
+ containerId: registration.containerId,
119
+ name: registration.name,
120
+ order: registration.order ?? 0,
121
+ visibility: this.context.workspaceState.get(
122
+ this.viewStateKey(id),
123
+ registration.visibility ?? "visible"
124
+ ),
125
+ tree,
126
+ disposables: []
127
+ };
128
+ this.views.set(id, registered);
129
+ container.viewIds.push(id);
130
+ this.sortViews(container);
131
+ registered.disposables.push(
132
+ tree.onDidChangeVisibility(({ visible }) => {
133
+ if (!visible) void this.onViewHidden(id);
134
+ })
135
+ );
136
+ return tree;
137
+ }
138
+ async showContainer(id, options) {
139
+ const container = this.requireContainer(id);
140
+ const visibleViews = this.containerViews(container).filter(
141
+ (view) => view.visibility !== "hidden"
142
+ );
143
+ if (!visibleViews.length) {
144
+ throw new Error(`View container has no views: ${id}`);
145
+ }
146
+ const editorWindowId = await this.findEditorWindow();
147
+ if (editorWindowId) this.editorWindowId = editorWindowId;
148
+ const surface = this.surface(container.location);
149
+ if (surface.activeContainerId && surface.activeContainerId !== id) {
150
+ await this.unmountContainer(surface.activeContainerId);
151
+ }
152
+ surface.activeContainerId = id;
153
+ surface.visible = true;
154
+ await this.closePlaceholder(container.location);
155
+ await this.ensureActivityBar(container.location);
156
+ await this.mountContainer(id);
157
+ await this.layoutContainer(id);
158
+ await this.renderActivityBar(container.location);
159
+ if (options?.focus !== false) {
160
+ const target = visibleViews.find((view) => view.visibility === "visible") ?? visibleViews[0];
161
+ if (target?.tree.windowId) {
162
+ await import_coc.workspace.nvim.call("win_gotoid", [target.tree.windowId]);
163
+ }
164
+ } else if (editorWindowId) {
165
+ await import_coc.workspace.nvim.call("win_gotoid", [editorWindowId]);
166
+ }
167
+ }
168
+ async switchLocation(location) {
169
+ const containers = [...this.containers.entries()].filter(([, container]) => container.location === location).sort(([, left], [, right]) => left.order - right.order);
170
+ if (!containers.length) return;
171
+ const index = await import_coc.window.showQuickpick(
172
+ containers.map(([id, container]) => `${container.title} (${id})`),
173
+ "Select view container"
174
+ );
175
+ if (index >= 0) await this.showContainer(containers[index][0]);
176
+ }
177
+ async showLocation(location) {
178
+ const surface = this.surface(location);
179
+ const containerId = surface.activeContainerId ?? this.firstContainerId(location);
180
+ if (containerId) await this.showContainer(containerId);
181
+ else await this.showEmptyLocation(location);
182
+ }
183
+ async hideLocation(location) {
184
+ const surface = this.surface(location);
185
+ if (surface.activeContainerId) {
186
+ await this.unmountContainer(surface.activeContainerId);
187
+ }
188
+ await this.closePlaceholder(location);
189
+ surface.visible = false;
190
+ await this.closeActivityBar(location);
191
+ }
192
+ async toggleLocation(location) {
193
+ const surface = this.surface(location);
194
+ if (surface.visible && !surface.activeContainerId && !await this.isValidWindow(surface.placeholder?.winid)) {
195
+ surface.visible = false;
196
+ }
197
+ if (surface.visible) await this.hideLocation(location);
198
+ else await this.showLocation(location);
199
+ }
200
+ async selectActivityBar(location) {
201
+ const activityBar = this.surface(location).activityBar;
202
+ if (!activityBar || !await this.isValidWindow(activityBar.winid)) return;
203
+ const [line] = await import_coc.workspace.nvim.call("nvim_win_get_cursor", [
204
+ activityBar.winid
205
+ ]);
206
+ const containerId = activityBar.containerIds[line - 1];
207
+ if (containerId) await this.showContainer(containerId);
208
+ }
209
+ async closeLocation(location) {
210
+ const containerId = this.surface(location).activeContainerId;
211
+ if (containerId) await this.closeContainer(containerId);
212
+ else await this.hideLocation(location);
213
+ }
214
+ async toggleViewAtMouse(id) {
215
+ const view = this.requireView(id);
216
+ const [mouseWindowId, line] = await import_coc.workspace.nvim.call(
217
+ "coc#ui#get_mouse"
218
+ );
219
+ if (mouseWindowId === view.tree.windowId && line === 1) {
220
+ await this.toggleView(id);
221
+ }
222
+ }
223
+ async showView(id, options = {}) {
224
+ const view = this.requireView(id);
225
+ view.visibility = "visible";
226
+ await this.context.workspaceState.update(
227
+ this.viewStateKey(id),
228
+ view.visibility
229
+ );
230
+ await this.showContainer(view.containerId, { focus: false });
231
+ await this.layoutContainer(view.containerId);
232
+ if (options.focus !== false && view.tree.windowId) {
233
+ await import_coc.workspace.nvim.call("win_gotoid", [view.tree.windowId]);
234
+ }
235
+ }
236
+ async closeContainer(id) {
237
+ const container = this.requireContainer(id);
238
+ await this.unmountContainer(id);
239
+ const surface = this.surface(container.location);
240
+ if (surface.activeContainerId === id) {
241
+ surface.activeContainerId = void 0;
242
+ surface.visible = false;
243
+ await this.closeActivityBar(container.location);
244
+ }
245
+ }
246
+ async toggleView(id) {
247
+ const view = this.requireView(id);
248
+ view.visibility = view.visibility === "collapsed" ? "visible" : "collapsed";
249
+ await this.context.workspaceState.update(
250
+ this.viewStateKey(id),
251
+ view.visibility
252
+ );
253
+ await this.showContainer(view.containerId, { focus: false });
254
+ await this.layoutContainer(view.containerId);
255
+ if (view.tree.windowId) {
256
+ await import_coc.workspace.nvim.call("win_gotoid", [view.tree.windowId]);
257
+ }
258
+ }
259
+ async toggleTreeItem(id) {
260
+ const view = this.requireView(id);
261
+ if (!view.tree.windowId) return;
262
+ await import_coc.workspace.nvim.call("win_gotoid", [view.tree.windowId]);
263
+ const key = import_coc.workspace.getConfiguration("tree").get("key.toggle", "t");
264
+ await import_coc.workspace.nvim.input(key);
265
+ }
266
+ async openLocation(uri, line, character) {
267
+ const editorWindowId = await this.findEditorWindow();
268
+ if (editorWindowId) {
269
+ this.editorWindowId = editorWindowId;
270
+ await import_coc.workspace.nvim.call("win_gotoid", [editorWindowId]);
271
+ }
272
+ await import_coc.workspace.jumpTo(uri, import_coc.Position.create(line, character), "edit");
273
+ }
274
+ dispose() {
275
+ for (const view of this.views.values()) {
276
+ for (const disposable of view.disposables) disposable.dispose();
277
+ view.tree.dispose();
278
+ }
279
+ this.views.clear();
280
+ this.viewRegistrations.clear();
281
+ this.containers.clear();
282
+ for (const surface of this.surfaces.values()) {
283
+ if (surface.activityBar) {
284
+ import_coc.workspace.nvim.call(
285
+ "nvim_buf_delete",
286
+ [surface.activityBar.bufnr, { force: true }],
287
+ true
288
+ );
289
+ }
290
+ if (surface.placeholder) {
291
+ import_coc.workspace.nvim.call(
292
+ "nvim_buf_delete",
293
+ [surface.placeholder.bufnr, { force: true }],
294
+ true
295
+ );
296
+ }
297
+ }
298
+ this.surfaces.clear();
299
+ }
300
+ requireContainer(id) {
301
+ const container = this.containers.get(id);
302
+ if (!container) throw new Error(`Unknown view container: ${id}`);
303
+ return container;
304
+ }
305
+ requireView(id) {
306
+ const view = this.views.get(id);
307
+ if (!view) throw new Error(`Unknown view: ${id}`);
308
+ return view;
309
+ }
310
+ viewStateKey(id) {
311
+ return `view.${id}.visibility`;
312
+ }
313
+ sortViews(container) {
314
+ container.viewIds.sort((left, right) => {
315
+ return this.requireView(left).order - this.requireView(right).order;
316
+ });
317
+ }
318
+ containerViews(container) {
319
+ return container.viewIds.map((id) => this.requireView(id));
320
+ }
321
+ surface(location) {
322
+ let surface = this.surfaces.get(location);
323
+ if (!surface) {
324
+ surface = { visible: false };
325
+ this.surfaces.set(location, surface);
326
+ }
327
+ return surface;
328
+ }
329
+ firstContainerId(location) {
330
+ return [...this.containers.entries()].filter(([, container]) => container.location === location).sort(([, left], [, right]) => left.order - right.order)[0]?.[0];
331
+ }
332
+ async mountContainer(id) {
333
+ const container = this.requireContainer(id);
334
+ const entries = container.viewIds.map((viewId) => [viewId, this.requireView(viewId)]).filter(([, view]) => view.visibility !== "hidden");
335
+ let anchorWindowId;
336
+ for (const [viewId, view] of entries) {
337
+ if (await this.isValidWindow(view.tree.windowId)) {
338
+ anchorWindowId = view.tree.windowId;
339
+ continue;
340
+ }
341
+ const targetWindowId = anchorWindowId ?? await this.findEditorWindow();
342
+ if (targetWindowId) {
343
+ await import_coc.workspace.nvim.call("win_gotoid", [targetWindowId]);
344
+ }
345
+ await view.tree.show(
346
+ anchorWindowId ? this.stackSplitCommand(container.location) : this.splitCommand(container.location)
347
+ );
348
+ await this.installViewKeymaps(
349
+ viewId,
350
+ view.containerId,
351
+ view.tree.windowId
352
+ );
353
+ anchorWindowId = view.tree.windowId;
354
+ }
355
+ }
356
+ async unmountContainer(id) {
357
+ const container = this.requireContainer(id);
358
+ this.unmountingContainers.add(id);
359
+ try {
360
+ for (const view of this.containerViews(container)) {
361
+ const winid = view.tree.windowId;
362
+ if (await this.isValidWindow(winid)) {
363
+ await import_coc.workspace.nvim.call("nvim_win_close", [winid, true]);
364
+ }
365
+ }
366
+ } finally {
367
+ this.unmountingContainers.delete(id);
368
+ }
369
+ }
370
+ async onViewHidden(id) {
371
+ const view = this.views.get(id);
372
+ if (!view || this.unmountingContainers.has(view.containerId)) return;
373
+ const container = this.containers.get(view.containerId);
374
+ if (!container) return;
375
+ const surface = this.surface(container.location);
376
+ if (surface.activeContainerId !== view.containerId) return;
377
+ for (const sibling of this.containerViews(container)) {
378
+ if (await this.isValidWindow(sibling.tree.windowId)) {
379
+ await this.layoutContainer(view.containerId);
380
+ return;
381
+ }
382
+ }
383
+ surface.visible = false;
384
+ await this.closeActivityBar(container.location);
385
+ }
386
+ async isValidWindow(winid) {
387
+ if (!winid) return false;
388
+ return await import_coc.workspace.nvim.call("nvim_win_is_valid", [winid]);
389
+ }
390
+ async findEditorWindow() {
391
+ const uiWindowIds = new Set(
392
+ [...this.views.values()].map((view) => view.tree.windowId).filter((winid) => winid != null)
393
+ );
394
+ for (const surface of this.surfaces.values()) {
395
+ if (surface.activityBar?.winid)
396
+ uiWindowIds.add(surface.activityBar.winid);
397
+ if (surface.placeholder?.winid)
398
+ uiWindowIds.add(surface.placeholder.winid);
399
+ }
400
+ const currentWindowId = await import_coc.workspace.nvim.call("win_getid");
401
+ if (!uiWindowIds.has(currentWindowId)) return currentWindowId;
402
+ if (this.editorWindowId) {
403
+ const valid = await import_coc.workspace.nvim.call("nvim_win_is_valid", [
404
+ this.editorWindowId
405
+ ]);
406
+ if (valid) return this.editorWindowId;
407
+ }
408
+ const windowIds = await import_coc.workspace.nvim.call("nvim_list_wins");
409
+ return windowIds.find((winid) => !uiWindowIds.has(winid));
410
+ }
411
+ splitCommand(location) {
412
+ const config = import_coc.workspace.getConfiguration("coc-ui");
413
+ if (location === "panel") {
414
+ const height = Math.max(3, config.get("panel.height", 12));
415
+ return `botright ${height}split`;
416
+ }
417
+ const primary = location === "primarySidebar";
418
+ const position = config.get(
419
+ primary ? "primarySidebar.position" : "secondarySidebar.position",
420
+ primary ? "left" : "right"
421
+ );
422
+ const width = Math.max(
423
+ 10,
424
+ config.get(
425
+ primary ? "primarySidebar.width" : "secondarySidebar.width",
426
+ 40
427
+ )
428
+ );
429
+ return `${position === "left" ? "leftabove" : "rightbelow"} ${width}vsplit`;
430
+ }
431
+ async showEmptyLocation(location) {
432
+ const surface = this.surface(location);
433
+ if (await this.isValidWindow(surface.placeholder?.winid)) {
434
+ surface.visible = true;
435
+ await import_coc.workspace.nvim.call("win_gotoid", [surface.placeholder?.winid]);
436
+ return;
437
+ }
438
+ const editorWindowId = await this.findEditorWindow();
439
+ if (!editorWindowId) return;
440
+ this.editorWindowId = editorWindowId;
441
+ await import_coc.workspace.nvim.call("win_gotoid", [editorWindowId]);
442
+ await import_coc.workspace.nvim.command(this.splitCommand(location));
443
+ const winid = await import_coc.workspace.nvim.call("win_getid");
444
+ const bufnr = await import_coc.workspace.nvim.call("nvim_create_buf", [
445
+ false,
446
+ true
447
+ ]);
448
+ await import_coc.workspace.nvim.call("nvim_buf_set_name", [
449
+ bufnr,
450
+ `coc-ui-placeholder://${location}`
451
+ ]);
452
+ await import_coc.workspace.nvim.call("nvim_win_set_buf", [winid, bufnr]);
453
+ for (const [name, value] of [
454
+ ["buftype", "nofile"],
455
+ ["bufhidden", "wipe"],
456
+ ["swapfile", false],
457
+ ["filetype", "cocui-placeholder"]
458
+ ]) {
459
+ await import_coc.workspace.nvim.call("nvim_buf_set_option", [bufnr, name, value]);
460
+ }
461
+ for (const [name, value] of [
462
+ ["number", false],
463
+ ["relativenumber", false],
464
+ ["wrap", false],
465
+ ["winfixwidth", location !== "panel"],
466
+ ["winfixheight", location === "panel"],
467
+ ["signcolumn", "no"],
468
+ ["statusline", "%!repeat('\u2500',winwidth(g:statusline_winid))"]
469
+ ]) {
470
+ await import_coc.workspace.nvim.call("nvim_win_set_option", [winid, name, value]);
471
+ }
472
+ const rhs = `<Cmd>CocCommand coc-ui.hideLocation ${location}<CR>`;
473
+ const options = { noremap: true, silent: true, nowait: true };
474
+ for (const key of ["q", "<Esc>"]) {
475
+ await import_coc.workspace.nvim.call("nvim_buf_set_keymap", [
476
+ bufnr,
477
+ "n",
478
+ key,
479
+ rhs,
480
+ options
481
+ ]);
482
+ }
483
+ surface.placeholder = { bufnr, winid };
484
+ surface.visible = true;
485
+ }
486
+ async closePlaceholder(location) {
487
+ const surface = this.surface(location);
488
+ const placeholder = surface.placeholder;
489
+ if (!placeholder) return;
490
+ surface.placeholder = void 0;
491
+ const valid = await import_coc.workspace.nvim.call("nvim_buf_is_valid", [
492
+ placeholder.bufnr
493
+ ]);
494
+ if (valid) {
495
+ await import_coc.workspace.nvim.call("nvim_buf_delete", [
496
+ placeholder.bufnr,
497
+ { force: true }
498
+ ]);
499
+ }
500
+ }
501
+ stackSplitCommand(location) {
502
+ return location === "panel" ? "rightbelow vsplit" : "belowright split";
503
+ }
504
+ async layoutContainer(id) {
505
+ const container = this.requireContainer(id);
506
+ const entries = [];
507
+ for (const view of this.containerViews(container)) {
508
+ if (view.visibility === "hidden" || !view.tree.windowId) continue;
509
+ if (await this.isValidWindow(view.tree.windowId)) {
510
+ entries.push([view, view.tree.windowId]);
511
+ }
512
+ }
513
+ if (!entries.length) return;
514
+ const config = import_coc.workspace.getConfiguration("coc-ui");
515
+ if (container.location === "panel") {
516
+ const height = Math.max(3, config.get("panel.height", 12));
517
+ for (const [, winid] of entries) {
518
+ await import_coc.workspace.nvim.call("nvim_win_set_height", [winid, height]);
519
+ }
520
+ const widths = await Promise.all(
521
+ entries.map(
522
+ ([, winid]) => import_coc.workspace.nvim.call("nvim_win_get_width", [winid])
523
+ )
524
+ );
525
+ const totalWidth = widths.reduce((sum, value) => sum + value, 0);
526
+ const expanded2 = entries.filter(
527
+ ([view]) => view.visibility !== "collapsed"
528
+ );
529
+ const collapsed2 = entries.filter(
530
+ ([view]) => view.visibility === "collapsed"
531
+ );
532
+ const collapsedWidth = 12;
533
+ for (const [, winid] of collapsed2) {
534
+ await import_coc.workspace.nvim.call("nvim_win_set_width", [
535
+ winid,
536
+ collapsedWidth
537
+ ]);
538
+ }
539
+ if (expanded2.length) {
540
+ const width2 = Math.max(
541
+ 12,
542
+ Math.floor(
543
+ (totalWidth - collapsed2.length * collapsedWidth) / expanded2.length
544
+ )
545
+ );
546
+ for (const [, winid] of expanded2) {
547
+ await import_coc.workspace.nvim.call("nvim_win_set_width", [winid, width2]);
548
+ }
549
+ }
550
+ return;
551
+ }
552
+ const primary = container.location === "primarySidebar";
553
+ const width = Math.max(
554
+ 10,
555
+ config.get(
556
+ primary ? "primarySidebar.width" : "secondarySidebar.width",
557
+ 40
558
+ )
559
+ );
560
+ for (const [, winid] of entries) {
561
+ await import_coc.workspace.nvim.call("nvim_win_set_width", [winid, width]);
562
+ }
563
+ const heights = await Promise.all(
564
+ entries.map(
565
+ ([, winid]) => import_coc.workspace.nvim.call("nvim_win_get_height", [winid])
566
+ )
567
+ );
568
+ const totalHeight = heights.reduce((sum, height) => sum + height, 0);
569
+ const expanded = entries.filter(
570
+ ([view]) => view.visibility !== "collapsed"
571
+ );
572
+ const collapsed = entries.filter(
573
+ ([view]) => view.visibility === "collapsed"
574
+ );
575
+ for (const [, winid] of collapsed) {
576
+ await import_coc.workspace.nvim.call("nvim_win_set_height", [winid, 1]);
577
+ }
578
+ if (expanded.length) {
579
+ const height = Math.max(
580
+ 2,
581
+ Math.floor((totalHeight - collapsed.length) / expanded.length)
582
+ );
583
+ for (const [, winid] of expanded) {
584
+ await import_coc.workspace.nvim.call("nvim_win_set_height", [winid, height]);
585
+ }
586
+ }
587
+ }
588
+ async ensureActivityBar(location) {
589
+ if (location === "panel") return;
590
+ if (!import_coc.workspace.getConfiguration("coc-ui").get("activityBar.enable", true)) {
591
+ return;
592
+ }
593
+ const surface = this.surface(location);
594
+ if (await this.isValidWindow(surface.activityBar?.winid)) {
595
+ await this.renderActivityBar(location);
596
+ return;
597
+ }
598
+ const editorWindowId = await this.findEditorWindow();
599
+ if (!editorWindowId) return;
600
+ await import_coc.workspace.nvim.call("win_gotoid", [editorWindowId]);
601
+ const config = import_coc.workspace.getConfiguration("coc-ui");
602
+ const primary = location === "primarySidebar";
603
+ const position = config.get(
604
+ primary ? "primarySidebar.position" : "secondarySidebar.position",
605
+ primary ? "left" : "right"
606
+ );
607
+ const width = Math.max(2, config.get("activityBar.width", 3));
608
+ await import_coc.workspace.nvim.command(
609
+ `${position === "left" ? "leftabove" : "rightbelow"} ${width}vsplit`
610
+ );
611
+ const winid = await import_coc.workspace.nvim.call("win_getid");
612
+ const bufnr = await import_coc.workspace.nvim.call("nvim_create_buf", [
613
+ false,
614
+ true
615
+ ]);
616
+ await import_coc.workspace.nvim.call("nvim_buf_set_name", [
617
+ bufnr,
618
+ `coc-ui-activitybar://${location}`
619
+ ]);
620
+ await import_coc.workspace.nvim.call("nvim_win_set_buf", [winid, bufnr]);
621
+ await import_coc.workspace.nvim.call("nvim_buf_set_option", [
622
+ bufnr,
623
+ "buftype",
624
+ "nofile"
625
+ ]);
626
+ await import_coc.workspace.nvim.call("nvim_buf_set_option", [
627
+ bufnr,
628
+ "bufhidden",
629
+ "wipe"
630
+ ]);
631
+ await import_coc.workspace.nvim.call("nvim_buf_set_option", [
632
+ bufnr,
633
+ "swapfile",
634
+ false
635
+ ]);
636
+ await import_coc.workspace.nvim.call("nvim_buf_set_option", [
637
+ bufnr,
638
+ "filetype",
639
+ "cocui-activitybar"
640
+ ]);
641
+ for (const [name, value] of [
642
+ ["number", false],
643
+ ["relativenumber", false],
644
+ ["cursorline", true],
645
+ ["wrap", false],
646
+ ["winfixwidth", true],
647
+ ["signcolumn", "no"],
648
+ ["statusline", "\u2500".repeat(width)]
649
+ ]) {
650
+ await import_coc.workspace.nvim.call("nvim_win_set_option", [winid, name, value]);
651
+ }
652
+ await import_coc.workspace.nvim.call("nvim_win_set_width", [winid, width]);
653
+ const options = { noremap: true, silent: true, nowait: true };
654
+ const select = `<Cmd>CocCommand coc-ui.selectActivityBar ${location}<CR>`;
655
+ await import_coc.workspace.nvim.call("nvim_buf_set_keymap", [
656
+ bufnr,
657
+ "n",
658
+ "<CR>",
659
+ select,
660
+ options
661
+ ]);
662
+ await import_coc.workspace.nvim.call("nvim_buf_set_keymap", [
663
+ bufnr,
664
+ "n",
665
+ "<LeftRelease>",
666
+ select,
667
+ options
668
+ ]);
669
+ await import_coc.workspace.nvim.call("nvim_buf_set_keymap", [
670
+ bufnr,
671
+ "n",
672
+ "<RightMouse>",
673
+ `<Cmd>CocCommand coc-ui.switch${primary ? "PrimarySidebar" : "SecondarySidebar"}<CR>`,
674
+ options
675
+ ]);
676
+ await import_coc.workspace.nvim.call("nvim_buf_set_keymap", [
677
+ bufnr,
678
+ "n",
679
+ "q",
680
+ `<Cmd>CocCommand coc-ui.hideLocation ${location}<CR>`,
681
+ options
682
+ ]);
683
+ surface.activityBar = { bufnr, winid, containerIds: [] };
684
+ await this.renderActivityBar(location);
685
+ }
686
+ async closeActivityBar(location) {
687
+ const surface = this.surface(location);
688
+ const activityBar = surface.activityBar;
689
+ if (!activityBar) return;
690
+ surface.activityBar = void 0;
691
+ const valid = await import_coc.workspace.nvim.call("nvim_buf_is_valid", [
692
+ activityBar.bufnr
693
+ ]);
694
+ if (valid) {
695
+ await import_coc.workspace.nvim.call("nvim_buf_delete", [
696
+ activityBar.bufnr,
697
+ { force: true }
698
+ ]);
699
+ }
700
+ }
701
+ async renderActivityBar(location) {
702
+ if (location === "panel") return;
703
+ const surface = this.surface(location);
704
+ const activityBar = surface.activityBar;
705
+ if (!activityBar || !await this.isValidWindow(activityBar.winid)) return;
706
+ const width = Math.max(
707
+ 2,
708
+ import_coc.workspace.getConfiguration("coc-ui").get("activityBar.width", 3)
709
+ );
710
+ await import_coc.workspace.nvim.call("nvim_win_set_width", [activityBar.winid, width]);
711
+ const containers = [...this.containers.entries()].filter(([, container]) => container.location === location).sort(([, left], [, right]) => left.order - right.order);
712
+ activityBar.containerIds = containers.map(([id]) => id);
713
+ const lines = containers.map(([, container]) => ` ${container.icon}`);
714
+ await import_coc.workspace.nvim.call("nvim_buf_set_option", [
715
+ activityBar.bufnr,
716
+ "modifiable",
717
+ true
718
+ ]);
719
+ await import_coc.workspace.nvim.call("nvim_buf_set_lines", [
720
+ activityBar.bufnr,
721
+ 0,
722
+ -1,
723
+ false,
724
+ lines.length ? lines : [""]
725
+ ]);
726
+ await import_coc.workspace.nvim.call("nvim_buf_set_option", [
727
+ activityBar.bufnr,
728
+ "modifiable",
729
+ false
730
+ ]);
731
+ await import_coc.workspace.nvim.call("nvim_buf_clear_namespace", [
732
+ activityBar.bufnr,
733
+ -1,
734
+ 0,
735
+ -1
736
+ ]);
737
+ const activeLine = activityBar.containerIds.indexOf(
738
+ surface.activeContainerId ?? ""
739
+ );
740
+ if (activeLine >= 0) {
741
+ await import_coc.workspace.nvim.call("nvim_win_set_cursor", [
742
+ activityBar.winid,
743
+ [activeLine + 1, 0]
744
+ ]);
745
+ await import_coc.workspace.nvim.call("nvim_buf_add_highlight", [
746
+ activityBar.bufnr,
747
+ -1,
748
+ "CocUiActivityBarActive",
749
+ activeLine,
750
+ 0,
751
+ -1
752
+ ]);
753
+ }
754
+ }
755
+ async installViewKeymaps(viewId, containerId, windowId) {
756
+ if (!windowId) return;
757
+ const bufferId = await import_coc.workspace.nvim.call("nvim_win_get_buf", [
758
+ windowId
759
+ ]);
760
+ const location = this.requireContainer(containerId).location;
761
+ const rhs = `<Cmd>CocCommand coc-ui.hideLocation ${location}<CR>`;
762
+ const options = { noremap: true, silent: true, nowait: true };
763
+ await import_coc.workspace.nvim.call("nvim_buf_set_keymap", [
764
+ bufferId,
765
+ "n",
766
+ "q",
767
+ rhs,
768
+ options
769
+ ]);
770
+ await import_coc.workspace.nvim.call("nvim_buf_set_keymap", [
771
+ bufferId,
772
+ "n",
773
+ "za",
774
+ `<Cmd>CocCommand coc-ui.toggleView ${viewId}<CR>`,
775
+ options
776
+ ]);
777
+ await import_coc.workspace.nvim.call("nvim_buf_set_keymap", [
778
+ bufferId,
779
+ "n",
780
+ "<2-LeftMouse>",
781
+ `<Cmd>CocCommand coc-ui.toggleViewAtMouse ${viewId}<CR>`,
782
+ options
783
+ ]);
784
+ await import_coc.workspace.nvim.call("nvim_buf_set_keymap", [
785
+ bufferId,
786
+ "n",
787
+ "<Esc>",
788
+ rhs,
789
+ options
790
+ ]);
791
+ if (import_coc.workspace.getConfiguration("coc-ui").get("mouse.enable", true)) {
792
+ const contextMenu = `<Cmd>CocCommand coc-ui.contextMenu ${viewId}<CR>`;
793
+ await import_coc.workspace.nvim.call("nvim_buf_set_keymap", [
794
+ bufferId,
795
+ "n",
796
+ "<RightMouse>",
797
+ contextMenu,
798
+ options
799
+ ]);
800
+ await import_coc.workspace.nvim.call("nvim_buf_set_keymap", [
801
+ bufferId,
802
+ "n",
803
+ "<RightRelease>",
804
+ "<Nop>",
805
+ options
806
+ ]);
807
+ }
808
+ }
809
+ async showContextMenu(id) {
810
+ const view = this.requireView(id);
811
+ const windowId = view.tree.windowId;
812
+ if (!windowId) return;
813
+ const [mouseWindowId, line, column] = await import_coc.workspace.nvim.call(
814
+ "coc#ui#get_mouse"
815
+ );
816
+ if (mouseWindowId !== windowId || line < 1) return;
817
+ await import_coc.workspace.nvim.call("win_gotoid", [windowId]);
818
+ await import_coc.workspace.nvim.call("nvim_win_set_cursor", [
819
+ windowId,
820
+ [line, Math.max(0, column - 1)]
821
+ ]);
822
+ const key = import_coc.workspace.getConfiguration("tree").get("key.actions", "<Tab>");
823
+ await import_coc.workspace.nvim.input(key);
824
+ }
825
+ async routeRightClick() {
826
+ const [mouseWindowId] = await import_coc.workspace.nvim.call("coc#ui#get_mouse");
827
+ const view = [...this.views.entries()].find(
828
+ ([, registered]) => registered.tree.windowId === mouseWindowId
829
+ );
830
+ if (view) {
831
+ await this.showContextMenu(view[0]);
832
+ return;
833
+ }
834
+ const termcodes = await import_coc.workspace.nvim.call("nvim_replace_termcodes", [
835
+ "<RightMouse>",
836
+ true,
837
+ false,
838
+ true
839
+ ]);
840
+ await import_coc.workspace.nvim.feedKeys(termcodes, "n", false);
841
+ }
842
+ };
843
+ function withViewActions(provider, actions) {
844
+ if (!actions.length) return provider;
845
+ return {
846
+ onDidChangeTreeData: provider.onDidChangeTreeData,
847
+ getTreeItem: (element) => provider.getTreeItem(element),
848
+ getChildren: (element) => provider.getChildren(element),
849
+ getParent: provider.getParent ? (element) => provider.getParent?.(element) : void 0,
850
+ resolveTreeItem: provider.resolveTreeItem ? (item, element, token) => provider.resolveTreeItem?.(item, element, token) : void 0,
851
+ resolveActions: async (item, element) => {
852
+ const inherited = provider.resolveActions ? await provider.resolveActions(item, element) ?? [] : [];
853
+ const contributed = actions.filter((action) => !action.when || action.when(element)).map((action) => ({
854
+ title: action.title,
855
+ handler: action.handler
856
+ }));
857
+ return [...inherited, ...contributed];
858
+ }
859
+ };
860
+ }
861
+ async function activate(context) {
862
+ const ui = new CocUi(context);
863
+ context.subscriptions.push(
864
+ ui,
865
+ import_coc.commands.registerCommand("coc-ui.showContainer", (id) => {
866
+ return ui.showContainer(String(id));
867
+ }),
868
+ import_coc.commands.registerCommand("coc-ui.showView", (id) => {
869
+ return ui.showView(String(id));
870
+ }),
871
+ import_coc.commands.registerCommand("coc-ui.closeContainer", (id) => {
872
+ return ui.closeContainer(String(id));
873
+ }),
874
+ import_coc.commands.registerCommand("coc-ui.closeLocation", (location) => {
875
+ return ui.closeLocation(String(location));
876
+ }),
877
+ import_coc.commands.registerCommand("coc-ui.showLocation", (location) => {
878
+ return ui.showLocation(String(location));
879
+ }),
880
+ import_coc.commands.registerCommand("coc-ui.hideLocation", (location) => {
881
+ return ui.hideLocation(String(location));
882
+ }),
883
+ import_coc.commands.registerCommand("coc-ui.toggleLocation", (location) => {
884
+ return ui.toggleLocation(String(location));
885
+ }),
886
+ import_coc.commands.registerCommand("coc-ui.togglePrimarySidebar", () => {
887
+ return ui.toggleLocation("primarySidebar");
888
+ }),
889
+ import_coc.commands.registerCommand("coc-ui.toggleSecondarySidebar", () => {
890
+ return ui.toggleLocation("secondarySidebar");
891
+ }),
892
+ import_coc.commands.registerCommand("coc-ui.togglePanel", () => {
893
+ return ui.toggleLocation("panel");
894
+ }),
895
+ import_coc.commands.registerCommand("coc-ui.toggleView", (id) => {
896
+ return ui.toggleView(String(id));
897
+ }),
898
+ import_coc.commands.registerCommand("coc-ui.toggleViewAtMouse", (id) => {
899
+ return ui.toggleViewAtMouse(String(id));
900
+ }),
901
+ import_coc.commands.registerCommand(
902
+ "coc-ui.selectActivityBar",
903
+ (location) => {
904
+ return ui.selectActivityBar(String(location));
905
+ }
906
+ ),
907
+ import_coc.commands.registerCommand("coc-ui.contextMenu", (id) => {
908
+ return ui.showContextMenu(String(id));
909
+ }),
910
+ import_coc.commands.registerCommand("coc-ui.routeRightMouse", () => {
911
+ return ui.routeRightClick();
912
+ }),
913
+ import_coc.commands.registerCommand("coc-ui.switchPrimarySidebar", () => {
914
+ return ui.switchLocation("primarySidebar");
915
+ }),
916
+ import_coc.commands.registerCommand("coc-ui.switchSecondarySidebar", () => {
917
+ return ui.switchLocation("secondarySidebar");
918
+ }),
919
+ import_coc.commands.registerCommand(
920
+ "coc-ui.switchPanel",
921
+ () => ui.switchLocation("panel")
922
+ )
923
+ );
924
+ await import_coc.workspace.nvim.command(
925
+ "highlight default link CocUiActivityBarActive CursorLine"
926
+ );
927
+ if (import_coc.workspace.getConfiguration("coc-ui").get("mouse.enable", true)) {
928
+ import_coc.workspace.nvim.setKeymap(
929
+ "n",
930
+ "<RightMouse>",
931
+ "<Cmd>CocCommand coc-ui.routeRightMouse<CR>",
932
+ { noremap: true, silent: true, nowait: true }
933
+ );
934
+ context.subscriptions.push(
935
+ import_coc.Disposable.create(() => import_coc.workspace.nvim.deleteKeymap("n", "<RightMouse>"))
936
+ );
937
+ }
938
+ return ui;
939
+ }
940
+ // Annotate the CommonJS export names for ESM import in node:
941
+ 0 && (module.exports = {
942
+ ViewContainerLocation,
943
+ activate
944
+ });
945
+ //# sourceMappingURL=index.js.map
package/package.json ADDED
@@ -0,0 +1,145 @@
1
+ {
2
+ "name": "@statiolake/coc-ui",
3
+ "version": "0.1.0",
4
+ "description": "VS Code-style view containers for coc.nvim extensions",
5
+ "author": "statiolake",
6
+ "license": "MIT",
7
+ "main": "lib/index.js",
8
+ "types": "lib/index.d.ts",
9
+ "engines": {
10
+ "coc": "^0.0.82"
11
+ },
12
+ "scripts": {
13
+ "build": "tsc --project tsconfig.build.json && node esbuild.mjs",
14
+ "prepare": "node esbuild.mjs",
15
+ "typecheck": "tsc --noEmit"
16
+ },
17
+ "activationEvents": [
18
+ "*"
19
+ ],
20
+ "contributes": {
21
+ "commands": [
22
+ {
23
+ "command": "coc-ui.showContainer",
24
+ "title": "Show a Coc UI view container"
25
+ },
26
+ {
27
+ "command": "coc-ui.showView",
28
+ "title": "Show a Coc UI view"
29
+ },
30
+ {
31
+ "command": "coc-ui.closeContainer",
32
+ "title": "Close a Coc UI view container"
33
+ },
34
+ {
35
+ "command": "coc-ui.closeLocation",
36
+ "title": "Close a Coc UI workbench surface"
37
+ },
38
+ {
39
+ "command": "coc-ui.togglePrimarySidebar",
40
+ "title": "Toggle Primary Sidebar"
41
+ },
42
+ {
43
+ "command": "coc-ui.toggleSecondarySidebar",
44
+ "title": "Toggle Secondary Sidebar"
45
+ },
46
+ {
47
+ "command": "coc-ui.togglePanel",
48
+ "title": "Toggle Panel"
49
+ },
50
+ {
51
+ "command": "coc-ui.toggleView",
52
+ "title": "Expand or Collapse a Coc UI view"
53
+ },
54
+ {
55
+ "command": "coc-ui.selectActivityBar",
56
+ "title": "Select an Activity Bar view container"
57
+ },
58
+ {
59
+ "command": "coc-ui.switchPrimarySidebar",
60
+ "title": "Switch Primary Sidebar View Container"
61
+ },
62
+ {
63
+ "command": "coc-ui.switchSecondarySidebar",
64
+ "title": "Switch Secondary Sidebar View Container"
65
+ },
66
+ {
67
+ "command": "coc-ui.switchPanel",
68
+ "title": "Switch Panel View Container"
69
+ }
70
+ ],
71
+ "configuration": {
72
+ "type": "object",
73
+ "title": "Coc UI",
74
+ "properties": {
75
+ "coc-ui.primarySidebar.position": {
76
+ "type": "string",
77
+ "enum": [
78
+ "left",
79
+ "right"
80
+ ],
81
+ "default": "left"
82
+ },
83
+ "coc-ui.primarySidebar.width": {
84
+ "type": "number",
85
+ "default": 40,
86
+ "minimum": 10
87
+ },
88
+ "coc-ui.secondarySidebar.position": {
89
+ "type": "string",
90
+ "enum": [
91
+ "left",
92
+ "right"
93
+ ],
94
+ "default": "right"
95
+ },
96
+ "coc-ui.secondarySidebar.width": {
97
+ "type": "number",
98
+ "default": 40,
99
+ "minimum": 10
100
+ },
101
+ "coc-ui.panel.height": {
102
+ "type": "number",
103
+ "default": 12,
104
+ "minimum": 3
105
+ },
106
+ "coc-ui.activityBar.enable": {
107
+ "type": "boolean",
108
+ "default": true,
109
+ "description": "Show an activity bar for sidebar view containers."
110
+ },
111
+ "coc-ui.activityBar.width": {
112
+ "type": "number",
113
+ "default": 3,
114
+ "minimum": 2
115
+ },
116
+ "coc-ui.mouse.enable": {
117
+ "type": "boolean",
118
+ "default": true,
119
+ "description": "Enable native mouse navigation and context menus in Coc UI tree views."
120
+ }
121
+ }
122
+ }
123
+ },
124
+ "devDependencies": {
125
+ "@types/node": "^16.18.0",
126
+ "coc.nvim": "^0.0.83-next.24",
127
+ "esbuild": "^0.25.0",
128
+ "typescript": "^5.3.3"
129
+ },
130
+ "repository": {
131
+ "type": "git",
132
+ "url": "git+https://github.com/statiolake/coc-ui.git"
133
+ },
134
+ "bugs": {
135
+ "url": "https://github.com/statiolake/coc-ui/issues"
136
+ },
137
+ "homepage": "https://github.com/statiolake/coc-ui#readme",
138
+ "publishConfig": {
139
+ "access": "public"
140
+ },
141
+ "files": [
142
+ "lib/index.js",
143
+ "lib/index.d.ts"
144
+ ]
145
+ }