@tuidom/elements 0.5.1 → 0.6.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.
@@ -13,6 +13,12 @@ export interface MenuItemEntry {
13
13
  */
14
14
  id?: string;
15
15
  onSelect?: () => void;
16
+ /**
17
+ * Недоступный пункт (`precondition` эталона VS Code): рисуется
18
+ * `disabledForeground`, стрелки его пропускают, клик, Enter и ховер
19
+ * ничего не делают.
20
+ */
21
+ disabled?: boolean;
16
22
  }
17
23
  export interface MenuSeparatorEntry {
18
24
  type: "separator";
@@ -10,6 +10,10 @@ function isSeparator(entry) {
10
10
  function isSubmenu(entry) {
11
11
  return entry.type === "submenu";
12
12
  }
13
+ /** Строка, на которую можно встать выделением: не разделитель и не недоступный пункт. */
14
+ function isSelectable(entry) {
15
+ return !isSeparator(entry) && (isSubmenu(entry) || entry.disabled !== true);
16
+ }
13
17
  /** Индикатор строки-подменю (рисуется в колонке шортката). */
14
18
  const SUBMENU_INDICATOR = "›";
15
19
  /**
@@ -38,7 +42,7 @@ export class PopupMenuElement extends TUIElement {
38
42
  super();
39
43
  this.style = { fg: "menu.foreground", bg: "menu.background" };
40
44
  this.entries = entries;
41
- this.selectableIndices = entries.map((e, i) => (isSeparator(e) ? -1 : i)).filter((i) => i >= 0);
45
+ this.selectableIndices = entries.map((e, i) => (isSelectable(e) ? i : -1)).filter((i) => i >= 0);
42
46
  this.selectedIndex = this.selectableIndices.length > 0 ? this.selectableIndices[0] : -1;
43
47
  const config = this.computeConfig();
44
48
  this.vstack = new VStackElement();
@@ -63,10 +67,15 @@ export class PopupMenuElement extends TUIElement {
63
67
  }
64
68
  else {
65
69
  const item = new PopupMenuItemElement(entry.label, config, entry.shortcut, entry.icon);
66
- item.onSelect = entry.onSelect;
67
- item.onHover = () => {
68
- this.selectByEntryIndex(entryIndex);
69
- };
70
+ if (entry.disabled === true) {
71
+ item.disabled = true;
72
+ }
73
+ else {
74
+ item.onSelect = entry.onSelect;
75
+ item.onHover = () => {
76
+ this.selectByEntryIndex(entryIndex);
77
+ };
78
+ }
70
79
  this.itemElements.push(item);
71
80
  this.vstack.addChild(item, { width: "stretch", height: 1 });
72
81
  }
@@ -14,6 +14,9 @@ export declare class PopupMenuItemElement extends CompositeElement {
14
14
  constructor(label: string, config: PopupMenuItemConfig, shortcut?: string, icon?: string);
15
15
  get selected(): boolean;
16
16
  set selected(value: boolean);
17
+ /** Недоступный пункт — цвет `disabledForeground` (поведение держит меню). */
18
+ get disabled(): boolean;
19
+ set disabled(value: boolean);
17
20
  }
18
21
  export declare class PopupMenuSeparatorElement extends TUIElement {
19
22
  getMinIntrinsicWidth(_height: number): number;
@@ -29,7 +29,10 @@ export class PopupMenuItemElement extends CompositeElement {
29
29
  // фон раскрытого списка (dropdown.listBackground) одним style на корне
30
30
  // попапа; выделение — when-вариант с токенами menu.selection*.
31
31
  this.style = {
32
- when: [{ states: ["selected"], fg: "menu.selectionForeground", bg: "menu.selectionBackground" }],
32
+ when: [
33
+ { states: ["selected"], fg: "menu.selectionForeground", bg: "menu.selectionBackground" },
34
+ { states: ["disabled"], fg: "disabledForeground" },
35
+ ],
33
36
  };
34
37
  const row = new HFlexElement();
35
38
  if (config.hasIconColumn) {
@@ -49,7 +52,10 @@ export class PopupMenuItemElement extends CompositeElement {
49
52
  const shortcutLabel = new TextLabelElement(" " + this.shortcut);
50
53
  shortcutLabel.style = {
51
54
  fg: "menu.shortcutForeground",
52
- when: [{ states: ["in:selected"], fg: "menu.selectionForeground" }],
55
+ when: [
56
+ { states: ["in:selected"], fg: "menu.selectionForeground" },
57
+ { states: ["in:disabled"], fg: "disabledForeground" },
58
+ ],
53
59
  };
54
60
  row.addChild(shortcutLabel, { width: hflexFit(), height: "fill" });
55
61
  }
@@ -62,6 +68,13 @@ export class PopupMenuItemElement extends CompositeElement {
62
68
  set selected(value) {
63
69
  this.setStyleState("selected", value);
64
70
  }
71
+ /** Недоступный пункт — цвет `disabledForeground` (поведение держит меню). */
72
+ get disabled() {
73
+ return this.hasStyleState("disabled");
74
+ }
75
+ set disabled(value) {
76
+ this.setStyleState("disabled", value);
77
+ }
65
78
  }
66
79
  export class PopupMenuSeparatorElement extends TUIElement {
67
80
  getMinIntrinsicWidth(_height) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tuidom/elements",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
4
4
  "type": "module",
5
5
  "description": "Experimental terminal UI DOM — widgets: lists, trees, menus, inputs, quick pick. API is unstable.",
6
6
  "license": "MIT",
@@ -28,6 +28,6 @@
28
28
  "./*": "./dist/*.js"
29
29
  },
30
30
  "dependencies": {
31
- "@tuidom/core": "0.5.1"
31
+ "@tuidom/core": "0.6.0"
32
32
  }
33
33
  }