@openvcs/sdk 0.2.11 → 0.2.13

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.
@@ -5,6 +5,7 @@ export { createDefaultPluginDelegates, createRuntimeDispatcher } from './dispatc
5
5
  export { isPluginFailure, pluginError } from './errors';
6
6
  export { createPluginRuntime } from './factory';
7
7
  export { createHost } from './host';
8
+ export { ModalBuilder } from './modal';
8
9
  export { bootstrapPluginModule, createRegisteredPluginRuntime, } from './registration';
9
10
  export { VcsDelegateBase } from './vcs-delegate-base';
10
11
  export type { VcsDelegateAssignments } from './vcs-delegate-metadata';
@@ -2,7 +2,7 @@
2
2
  // Copyright © 2025-2026 OpenVCS Contributors
3
3
  // SPDX-License-Identifier: GPL-3.0-or-later
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.notify = exports.invoke = exports.registerAction = exports.showMenu = exports.hideMenu = exports.removeMenu = exports.addMenuSeparator = exports.addMenuItem = exports.createMenu = exports.getOrCreateMenu = exports.getMenu = exports.VcsDelegateBase = exports.createRegisteredPluginRuntime = exports.bootstrapPluginModule = exports.createHost = exports.createPluginRuntime = exports.pluginError = exports.isPluginFailure = exports.createRuntimeDispatcher = exports.createDefaultPluginDelegates = void 0;
5
+ exports.notify = exports.invoke = exports.registerAction = exports.showMenu = exports.hideMenu = exports.removeMenu = exports.addMenuSeparator = exports.addMenuItem = exports.createMenu = exports.getOrCreateMenu = exports.getMenu = exports.VcsDelegateBase = exports.createRegisteredPluginRuntime = exports.bootstrapPluginModule = exports.ModalBuilder = exports.createHost = exports.createPluginRuntime = exports.pluginError = exports.isPluginFailure = exports.createRuntimeDispatcher = exports.createDefaultPluginDelegates = void 0;
6
6
  exports.startPluginRuntime = startPluginRuntime;
7
7
  var dispatcher_1 = require("./dispatcher");
8
8
  Object.defineProperty(exports, "createDefaultPluginDelegates", { enumerable: true, get: function () { return dispatcher_1.createDefaultPluginDelegates; } });
@@ -14,6 +14,8 @@ var factory_1 = require("./factory");
14
14
  Object.defineProperty(exports, "createPluginRuntime", { enumerable: true, get: function () { return factory_1.createPluginRuntime; } });
15
15
  var host_1 = require("./host");
16
16
  Object.defineProperty(exports, "createHost", { enumerable: true, get: function () { return host_1.createHost; } });
17
+ var modal_1 = require("./modal");
18
+ Object.defineProperty(exports, "ModalBuilder", { enumerable: true, get: function () { return modal_1.ModalBuilder; } });
17
19
  var registration_1 = require("./registration");
18
20
  Object.defineProperty(exports, "bootstrapPluginModule", { enumerable: true, get: function () { return registration_1.bootstrapPluginModule; } });
19
21
  Object.defineProperty(exports, "createRegisteredPluginRuntime", { enumerable: true, get: function () { return registration_1.createRegisteredPluginRuntime; } });
@@ -5,7 +5,7 @@ type MenubarMenuOptions = {
5
5
  before?: string;
6
6
  after?: string;
7
7
  };
8
- /** Runs one registered action handler by id. */
8
+ /** Runs a registered action handler by id. */
9
9
  export declare function runRegisteredAction(actionId: string, ...args: unknown[]): Promise<boolean>;
10
10
  export interface MenuHandle {
11
11
  id: string;
@@ -17,26 +17,26 @@ export interface MenuHandle {
17
17
  }
18
18
  /** Returns a menu by id, or null when it does not exist. */
19
19
  export declare function getMenu(menuId: string): MenuHandle | null;
20
- /** Returns a menu by id, creating it when necessary. */
20
+ /** Returns a menu by id, creating it if needed. */
21
21
  export declare function getOrCreateMenu(menuId: string, label: string): MenuHandle | null;
22
- /** Creates a menu at a specific insertion point. */
22
+ /** Creates a menu at a specific position. */
23
23
  export declare function createMenu(menuId: string, label: string, options?: MenubarMenuOptions): MenuHandle | null;
24
- /** Adds one action item to a menu. */
24
+ /** Adds one item to a menu. */
25
25
  export declare function addMenuItem(menuId: string, item: MenubarItem): void;
26
- /** Adds one separator item to a menu. */
26
+ /** Adds one separator to a menu. */
27
27
  export declare function addMenuSeparator(menuId: string, beforeAction?: string): void;
28
- /** Removes one menu entirely. */
28
+ /** Removes one menu from the registry. */
29
29
  export declare function removeMenu(menuId: string): void;
30
- /** Hides one menu from the host UI. */
30
+ /** Hides one menu from the registry. */
31
31
  export declare function hideMenu(menuId: string): void;
32
- /** Shows one previously hidden menu. */
32
+ /** Shows one menu from the registry. */
33
33
  export declare function showMenu(menuId: string): void;
34
34
  /** Registers an action handler by id. */
35
35
  export declare function registerAction(id: string, handler: (...args: unknown[]) => unknown): void;
36
- /** Invokes a host command when the host exposes a direct invoke helper. */
36
+ /** Invokes a host command when a host helper is available. */
37
37
  export declare function invoke<T = unknown>(cmd: string, args?: unknown): Promise<T>;
38
- /** Emits a user notification when the host exposes one. */
38
+ /** Emits a notification when the host helper is available. */
39
39
  export declare function notify(msg: string): void;
40
- /** Builds the SDK plugin delegates contributed by the menu registry. */
40
+ /** Builds SDK delegates from the local menu/action registries. */
41
41
  export declare function createMenuPluginDelegates(): PluginDelegates<PluginRuntimeContext>;
42
42
  export {};
@@ -18,31 +18,35 @@ exports.createMenuPluginDelegates = createMenuPluginDelegates;
18
18
  const menus = new Map();
19
19
  const menuOrder = [];
20
20
  const actionHandlers = new Map();
21
- let nextSyntheticId = 0;
22
- /** Returns the OpenVCS global, when the host exposes one. */
21
+ let syntheticId = 0;
22
+ /** Returns the host-side OpenVCS helper, when the environment provides one. */
23
23
  function getOpenVCS() {
24
24
  return globalThis.OpenVCS;
25
25
  }
26
- /** Normalizes menu ids for stable map lookups. */
26
+ /** Normalizes a menu id for stable map lookup. */
27
27
  function normalizeMenuId(menuId) {
28
28
  return String(menuId || '').trim();
29
29
  }
30
- /** Allocates a stable synthetic id for a generated menu item. */
30
+ /** Allocates a stable synthetic id for generated menu entries. */
31
31
  function allocateSyntheticId(prefix) {
32
- nextSyntheticId += 1;
33
- return `${prefix}-${nextSyntheticId}`;
32
+ syntheticId += 1;
33
+ return `${prefix}-${syntheticId}`;
34
34
  }
35
- /** Returns a stored menu state or null if it does not exist. */
35
+ /** Returns the stored menu state for one id, if present. */
36
36
  function getStoredMenu(menuId) {
37
37
  return menus.get(normalizeMenuId(menuId)) || null;
38
38
  }
39
- /** Inserts a menu id into the ordering list. */
39
+ /** Removes one menu id from the ordering list. */
40
+ function removeMenuId(menuId) {
41
+ const id = normalizeMenuId(menuId);
42
+ const index = menuOrder.indexOf(id);
43
+ if (index >= 0)
44
+ menuOrder.splice(index, 1);
45
+ }
46
+ /** Inserts one menu id into the ordering list. */
40
47
  function placeMenuId(menuId, options) {
41
48
  const id = normalizeMenuId(menuId);
42
- const existingIndex = menuOrder.indexOf(id);
43
- if (existingIndex >= 0) {
44
- menuOrder.splice(existingIndex, 1);
45
- }
49
+ removeMenuId(id);
46
50
  const beforeId = normalizeMenuId(options?.before || '');
47
51
  const afterId = normalizeMenuId(options?.after || '');
48
52
  if (afterId) {
@@ -61,7 +65,7 @@ function placeMenuId(menuId, options) {
61
65
  }
62
66
  menuOrder.push(id);
63
67
  }
64
- /** Ensures a menu record exists for the provided id. */
68
+ /** Ensures a menu record exists for one id. */
65
69
  function ensureStoredMenu(menuId, label, options) {
66
70
  const id = normalizeMenuId(menuId);
67
71
  const safeLabel = String(label || '').trim() || id;
@@ -69,46 +73,47 @@ function ensureStoredMenu(menuId, label, options) {
69
73
  if (!menu) {
70
74
  menu = { id, label: safeLabel, items: [] };
71
75
  menus.set(id, menu);
72
- placeMenuId(id, options);
73
- return menu;
74
76
  }
75
- menu.label = safeLabel;
77
+ else {
78
+ menu.label = safeLabel;
79
+ }
76
80
  placeMenuId(id, options);
77
81
  return menu;
78
82
  }
79
- /** Finds one menu item by action id. */
80
- function findMenuItem(menu, actionId) {
83
+ /** Finds a stored item by action id. */
84
+ function findStoredItem(menu, actionId) {
81
85
  const id = normalizeMenuId(actionId);
82
86
  return menu.items.find((item) => item.action === id) || null;
83
87
  }
84
- /** Inserts a menu item relative to before/after anchors when provided. */
88
+ /** Inserts a menu item at the requested position. */
85
89
  function insertMenuItem(menu, item, before, after) {
86
90
  const beforeId = normalizeMenuId(before || '');
87
91
  const afterId = normalizeMenuId(after || '');
88
- const insertAt = (index) => {
89
- const existingIndex = menu.items.findIndex((entry) => entry.id === item.id || entry.action === item.action);
90
- if (existingIndex >= 0) {
91
- menu.items.splice(existingIndex, 1);
92
- }
93
- menu.items.splice(index, 0, item);
92
+ const removeExisting = () => {
93
+ const index = menu.items.findIndex((entry) => entry.id === item.id || entry.action === item.action);
94
+ if (index >= 0)
95
+ menu.items.splice(index, 1);
94
96
  };
95
97
  if (beforeId) {
96
98
  const beforeIndex = menu.items.findIndex((entry) => entry.action === beforeId);
97
99
  if (beforeIndex >= 0) {
98
- insertAt(beforeIndex);
100
+ removeExisting();
101
+ menu.items.splice(beforeIndex, 0, item);
99
102
  return;
100
103
  }
101
104
  }
102
105
  if (afterId) {
103
106
  const afterIndex = menu.items.findIndex((entry) => entry.action === afterId);
104
107
  if (afterIndex >= 0) {
105
- insertAt(afterIndex + 1);
108
+ removeExisting();
109
+ menu.items.splice(afterIndex + 1, 0, item);
106
110
  return;
107
111
  }
108
112
  }
109
- insertAt(menu.items.length);
113
+ removeExisting();
114
+ menu.items.push(item);
110
115
  }
111
- /** Converts one stored menu item into a serializable plugin payload element. */
116
+ /** Converts one stored item into a serializable menu payload element. */
112
117
  function serializeMenuItem(item) {
113
118
  if (item.hidden)
114
119
  return null;
@@ -132,7 +137,7 @@ function serializeMenuItem(item) {
132
137
  label: item.label,
133
138
  };
134
139
  }
135
- /** Serializes the current menu registry for the host runtime. */
140
+ /** Serializes the local registry into plugin menu payloads. */
136
141
  function serializeMenus() {
137
142
  return menuOrder
138
143
  .map((menuId, index) => {
@@ -150,7 +155,7 @@ function serializeMenus() {
150
155
  })
151
156
  .filter((menu) => Boolean(menu));
152
157
  }
153
- /** Runs one registered action handler by id. */
158
+ /** Runs a registered action handler by id. */
154
159
  async function runRegisteredAction(actionId, ...args) {
155
160
  const id = String(actionId || '').trim();
156
161
  if (!id)
@@ -161,45 +166,33 @@ async function runRegisteredAction(actionId, ...args) {
161
166
  await handler(...args);
162
167
  return true;
163
168
  }
164
- /** Creates a stable, mutation-based handle for one menu id. */
169
+ /** Creates a stable handle for one stored menu. */
165
170
  function createMenuHandle(menuId) {
166
171
  const id = normalizeMenuId(menuId);
167
172
  return {
168
173
  id,
169
174
  addItem(item) {
170
- const menu = getStoredMenu(this.id) || ensureStoredMenu(this.id, this.id);
171
175
  const label = String(item?.label || '').trim();
172
176
  const action = String(item?.action || '').trim();
173
177
  if (!label || !action)
174
178
  return;
175
- const entry = {
179
+ const menu = getStoredMenu(this.id) || ensureStoredMenu(this.id, this.id);
180
+ insertMenuItem(menu, {
176
181
  kind: 'button',
177
182
  id: action,
178
183
  label,
179
184
  title: item.title,
180
185
  action,
181
- };
182
- insertMenuItem(menu, entry, item.before, item.after);
183
- const openvcs = getOpenVCS();
184
- if (!openvcs?.menus)
185
- return;
186
- openvcs.menus.getOrCreate(menu.id, menu.label);
187
- openvcs.menus.addMenuItem(menu.id, item);
186
+ }, item.before, item.after);
188
187
  },
189
188
  addSeparator(beforeAction) {
190
189
  const menu = getStoredMenu(this.id) || ensureStoredMenu(this.id, this.id);
191
- const entry = {
190
+ insertMenuItem(menu, {
192
191
  kind: 'separator',
193
192
  id: allocateSyntheticId(`${menu.id}-separator`),
194
193
  label: 'Separator',
195
194
  content: '—',
196
- };
197
- insertMenuItem(menu, entry, beforeAction);
198
- const openvcs = getOpenVCS();
199
- if (!openvcs?.menus)
200
- return;
201
- openvcs.menus.getOrCreate(menu.id, menu.label);
202
- openvcs.menus.addMenuSeparator(menu.id, beforeAction);
195
+ }, beforeAction);
203
196
  },
204
197
  removeItem(actionId) {
205
198
  const menu = getStoredMenu(this.id);
@@ -207,37 +200,22 @@ function createMenuHandle(menuId) {
207
200
  return;
208
201
  const idToRemove = normalizeMenuId(actionId);
209
202
  menu.items = menu.items.filter((item) => item.action !== idToRemove);
210
- const openvcs = getOpenVCS();
211
- if (openvcs?.menus) {
212
- const handle = openvcs.menus.get(this.id);
213
- handle?.removeItem(idToRemove);
214
- }
215
203
  },
216
204
  hideItem(actionId) {
217
205
  const menu = getStoredMenu(this.id);
218
206
  if (!menu)
219
207
  return;
220
- const item = findMenuItem(menu, actionId);
208
+ const item = findStoredItem(menu, actionId);
221
209
  if (item)
222
210
  item.hidden = true;
223
- const openvcs = getOpenVCS();
224
- if (!openvcs?.menus)
225
- return;
226
- const handle = openvcs.menus.get(this.id);
227
- handle?.hideItem(actionId);
228
211
  },
229
212
  showItem(actionId) {
230
213
  const menu = getStoredMenu(this.id);
231
214
  if (!menu)
232
215
  return;
233
- const item = findMenuItem(menu, actionId);
216
+ const item = findStoredItem(menu, actionId);
234
217
  if (item)
235
218
  item.hidden = false;
236
- const openvcs = getOpenVCS();
237
- if (!openvcs?.menus)
238
- return;
239
- const handle = openvcs.menus.get(this.id);
240
- handle?.showItem(actionId);
241
219
  },
242
220
  };
243
221
  }
@@ -248,53 +226,41 @@ function getMenu(menuId) {
248
226
  return null;
249
227
  return createMenuHandle(stored.id);
250
228
  }
251
- /** Returns a menu by id, creating it when necessary. */
229
+ /** Returns a menu by id, creating it if needed. */
252
230
  function getOrCreateMenu(menuId, label) {
253
231
  const stored = ensureStoredMenu(menuId, label);
254
232
  return createMenuHandle(stored.id);
255
233
  }
256
- /** Creates a menu at a specific insertion point. */
234
+ /** Creates a menu at a specific position. */
257
235
  function createMenu(menuId, label, options) {
258
236
  const stored = ensureStoredMenu(menuId, label, options);
259
237
  return createMenuHandle(stored.id);
260
238
  }
261
- /** Adds one action item to a menu. */
239
+ /** Adds one item to a menu. */
262
240
  function addMenuItem(menuId, item) {
263
- const menu = getStoredMenu(menuId) || ensureStoredMenu(menuId, menuId);
264
- const handle = createMenuHandle(menu.id);
265
- handle.addItem(item);
241
+ createMenuHandle(menuId).addItem(item);
266
242
  }
267
- /** Adds one separator item to a menu. */
243
+ /** Adds one separator to a menu. */
268
244
  function addMenuSeparator(menuId, beforeAction) {
269
- const menu = getStoredMenu(menuId) || ensureStoredMenu(menuId, menuId);
270
- const handle = createMenuHandle(menu.id);
271
- handle.addSeparator(beforeAction);
245
+ createMenuHandle(menuId).addSeparator(beforeAction);
272
246
  }
273
- /** Removes one menu entirely. */
247
+ /** Removes one menu from the registry. */
274
248
  function removeMenu(menuId) {
275
249
  const id = normalizeMenuId(menuId);
276
250
  menus.delete(id);
277
- const index = menuOrder.indexOf(id);
278
- if (index >= 0)
279
- menuOrder.splice(index, 1);
280
- const openvcs = getOpenVCS();
281
- openvcs?.menus?.remove(id);
251
+ removeMenuId(id);
282
252
  }
283
- /** Hides one menu from the host UI. */
253
+ /** Hides one menu from the registry. */
284
254
  function hideMenu(menuId) {
285
255
  const menu = getStoredMenu(menuId);
286
256
  if (menu)
287
257
  menu.hidden = true;
288
- const openvcs = getOpenVCS();
289
- openvcs?.menus?.hide(normalizeMenuId(menuId));
290
258
  }
291
- /** Shows one previously hidden menu. */
259
+ /** Shows one menu from the registry. */
292
260
  function showMenu(menuId) {
293
261
  const menu = getStoredMenu(menuId);
294
262
  if (menu)
295
263
  menu.hidden = false;
296
- const openvcs = getOpenVCS();
297
- openvcs?.menus?.show(normalizeMenuId(menuId));
298
264
  }
299
265
  /** Registers an action handler by id. */
300
266
  function registerAction(id, handler) {
@@ -302,23 +268,21 @@ function registerAction(id, handler) {
302
268
  if (!key)
303
269
  return;
304
270
  actionHandlers.set(key, handler);
305
- const openvcs = getOpenVCS();
306
- openvcs?.registerAction(key, handler);
307
271
  }
308
- /** Invokes a host command when the host exposes a direct invoke helper. */
272
+ /** Invokes a host command when a host helper is available. */
309
273
  function invoke(cmd, args) {
310
274
  const openvcs = getOpenVCS();
311
275
  if (!openvcs) {
312
- return Promise.reject(new Error('OpenVCS not available'));
276
+ return Promise.reject(new Error('OpenVCS host is not available in this runtime'));
313
277
  }
314
278
  return openvcs.invoke(cmd, args);
315
279
  }
316
- /** Emits a user notification when the host exposes one. */
280
+ /** Emits a notification when the host helper is available. */
317
281
  function notify(msg) {
318
282
  const openvcs = getOpenVCS();
319
283
  openvcs?.notify(msg);
320
284
  }
321
- /** Builds the SDK plugin delegates contributed by the menu registry. */
285
+ /** Builds SDK delegates from the local menu/action registries. */
322
286
  function createMenuPluginDelegates() {
323
287
  return {
324
288
  async 'plugin.get_menus'() {
@@ -326,9 +290,9 @@ function createMenuPluginDelegates() {
326
290
  },
327
291
  async 'plugin.handle_action'(params) {
328
292
  const actionId = String(params?.action_id || '').trim();
329
- if (!actionId)
330
- return null;
331
- await runRegisteredAction(actionId);
293
+ if (actionId) {
294
+ await runRegisteredAction(actionId, params?.payload);
295
+ }
332
296
  return null;
333
297
  },
334
298
  };
@@ -0,0 +1,74 @@
1
+ import type { ModalButtonVariant, ModalContentAlign, ModalInputKind, ModalListRowDefinition, ModalSelectOptionDefinition, PluginModalDefinition } from '../types/modal.js';
2
+ /** Describes the options accepted by `ModalBuilder.button()`. */
3
+ export interface ModalBuilderButtonOptions {
4
+ /** Stores the optional tooltip text. */
5
+ title?: string;
6
+ /** Stores the visual button variant. */
7
+ variant?: ModalButtonVariant;
8
+ /** Stores the alignment hint. */
9
+ align?: ModalContentAlign;
10
+ /** Stores a static payload merged into the action payload. */
11
+ payload?: Record<string, unknown>;
12
+ }
13
+ /** Describes the options accepted by `ModalBuilder.text()`. */
14
+ export interface ModalBuilderTextOptions {
15
+ /** Stores the optional tooltip text. */
16
+ title?: string;
17
+ /** Stores the alignment hint. */
18
+ align?: ModalContentAlign;
19
+ }
20
+ /** Describes the options accepted by `ModalBuilder.input()`. */
21
+ export interface ModalBuilderInputOptions {
22
+ /** Stores the input kind. */
23
+ kind?: ModalInputKind;
24
+ /** Stores the default value. */
25
+ value?: string;
26
+ /** Stores the placeholder text. */
27
+ placeholder?: string;
28
+ /** Stores whether the field is required. */
29
+ required?: boolean;
30
+ /** Stores the alignment hint. */
31
+ align?: ModalContentAlign;
32
+ }
33
+ /** Describes the options accepted by `ModalBuilder.select()`. */
34
+ export interface ModalBuilderSelectOptions {
35
+ /** Stores the available options. */
36
+ options: ModalSelectOptionDefinition[];
37
+ /** Stores the default value. */
38
+ value?: string;
39
+ /** Stores the alignment hint. */
40
+ align?: ModalContentAlign;
41
+ }
42
+ /** Describes the options accepted by `ModalBuilder.list()`. */
43
+ export interface ModalBuilderListOptions {
44
+ /** Stores the list label. */
45
+ label?: string;
46
+ /** Stores the empty-state text. */
47
+ emptyText?: string;
48
+ /** Stores the alignment hint. */
49
+ align?: ModalContentAlign;
50
+ /** Stores the list rows. */
51
+ items: ModalListRowDefinition[];
52
+ }
53
+ /** Builds a structured modal definition with a fluent class API. */
54
+ export declare class ModalBuilder {
55
+ private readonly definition;
56
+ /** Creates a new modal builder with the provided title. */
57
+ constructor(title: string);
58
+ /** Adds a text block to the modal body. */
59
+ text(content: string, options?: ModalBuilderTextOptions): this;
60
+ /** Adds a separator to the modal body. */
61
+ separator(): this;
62
+ /** Adds a button to the modal body. */
63
+ button(id: string, content: string, options?: ModalBuilderButtonOptions): this;
64
+ /** Adds a text input to the modal body. */
65
+ input(id: string, label: string, options?: ModalBuilderInputOptions): this;
66
+ /** Adds a select field to the modal body. */
67
+ select(id: string, label: string, options: ModalBuilderSelectOptions): this;
68
+ /** Adds a list block to the modal body. */
69
+ list(id: string, options: ModalBuilderListOptions): this;
70
+ /** Returns the serialized modal payload. */
71
+ build(): PluginModalDefinition;
72
+ /** Requests the host to open the modal with the current definition. */
73
+ open(): Promise<void>;
74
+ }
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ // Copyright © 2025-2026 OpenVCS Contributors
3
+ // SPDX-License-Identifier: GPL-3.0-or-later
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.ModalBuilder = void 0;
6
+ const menu_js_1 = require("./menu.js");
7
+ /** Builds a structured modal definition with a fluent class API. */
8
+ class ModalBuilder {
9
+ definition;
10
+ /** Creates a new modal builder with the provided title. */
11
+ constructor(title) {
12
+ this.definition = {
13
+ title: String(title || '').trim(),
14
+ content: [],
15
+ };
16
+ }
17
+ /** Adds a text block to the modal body. */
18
+ text(content, options = {}) {
19
+ this.definition.content.push({
20
+ type: 'text',
21
+ content: String(content || ''),
22
+ ...(options.title ? { title: options.title } : {}),
23
+ ...(options.align ? { align: options.align } : {}),
24
+ });
25
+ return this;
26
+ }
27
+ /** Adds a separator to the modal body. */
28
+ separator() {
29
+ this.definition.content.push({ type: 'separator' });
30
+ return this;
31
+ }
32
+ /** Adds a button to the modal body. */
33
+ button(id, content, options = {}) {
34
+ this.definition.content.push({
35
+ type: 'button',
36
+ id: String(id || '').trim(),
37
+ content: String(content || ''),
38
+ ...(options.title ? { title: options.title } : {}),
39
+ ...(options.variant && options.variant !== 'default' ? { variant: options.variant } : {}),
40
+ ...(options.align ? { align: options.align } : {}),
41
+ ...(options.payload ? { payload: options.payload } : {}),
42
+ });
43
+ return this;
44
+ }
45
+ /** Adds a text input to the modal body. */
46
+ input(id, label, options = {}) {
47
+ this.definition.content.push({
48
+ type: 'input',
49
+ id: String(id || '').trim(),
50
+ label: String(label || '').trim(),
51
+ ...(options.kind ? { kind: options.kind } : {}),
52
+ ...(options.value !== undefined ? { value: options.value } : {}),
53
+ ...(options.placeholder ? { placeholder: options.placeholder } : {}),
54
+ ...(options.required ? { required: true } : {}),
55
+ ...(options.align ? { align: options.align } : {}),
56
+ });
57
+ return this;
58
+ }
59
+ /** Adds a select field to the modal body. */
60
+ select(id, label, options) {
61
+ this.definition.content.push({
62
+ type: 'select',
63
+ id: String(id || '').trim(),
64
+ label: String(label || '').trim(),
65
+ options: Array.isArray(options.options) ? options.options : [],
66
+ ...(options.value !== undefined ? { value: options.value } : {}),
67
+ ...(options.align ? { align: options.align } : {}),
68
+ });
69
+ return this;
70
+ }
71
+ /** Adds a list block to the modal body. */
72
+ list(id, options) {
73
+ this.definition.content.push({
74
+ type: 'list',
75
+ id: String(id || '').trim(),
76
+ ...(options.label ? { label: options.label } : {}),
77
+ ...(options.emptyText ? { emptyText: options.emptyText } : {}),
78
+ ...(options.align ? { align: options.align } : {}),
79
+ items: Array.isArray(options.items) ? options.items : [],
80
+ });
81
+ return this;
82
+ }
83
+ /** Returns the serialized modal payload. */
84
+ build() {
85
+ return {
86
+ title: this.definition.title,
87
+ content: this.definition.content.map((item) => ({ ...item })),
88
+ };
89
+ }
90
+ /** Requests the host to open the modal with the current definition. */
91
+ async open() {
92
+ await (0, menu_js_1.invoke)('open_plugin_modal', { modal: this.build() });
93
+ }
94
+ }
95
+ exports.ModalBuilder = ModalBuilder;
@@ -1,4 +1,5 @@
1
1
  export * from './host';
2
+ export * from './modal';
2
3
  export * from './menubar';
3
4
  export * from './plugin';
4
5
  export * from './protocol';
@@ -17,6 +17,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
17
17
  };
18
18
  Object.defineProperty(exports, "__esModule", { value: true });
19
19
  __exportStar(require("./host"), exports);
20
+ __exportStar(require("./modal"), exports);
20
21
  __exportStar(require("./menubar"), exports);
21
22
  __exportStar(require("./plugin"), exports);
22
23
  __exportStar(require("./protocol"), exports);