@juanibiapina/pi-extension-settings 0.6.1 → 0.7.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.
@@ -5,7 +5,7 @@
5
5
  * Selected items appear at the top with their position number.
6
6
  * Value is stored as a comma-separated string of selected IDs in order.
7
7
  */
8
- import { type Component } from "@mariozechner/pi-tui";
8
+ import { type Component } from "@earendil-works/pi-tui";
9
9
  import type { OrderedListOption } from "../settings/types.js";
10
10
  import type { SettingsListTheme } from "./settings-list.js";
11
11
  export declare class OrderedMultiSelect implements Component {
@@ -1 +1 @@
1
- {"version":3,"file":"ordered-multi-select.d.ts","sourceRoot":"","sources":["../../src/components/ordered-multi-select.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,KAAK,SAAS,EAA+C,MAAM,sBAAsB,CAAC;AACnG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAS5D,qBAAa,kBAAmB,YAAW,SAAS;IACnD,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,IAAI,CAAmC;gBAG9C,OAAO,EAAE,iBAAiB,EAAE,EAC5B,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,iBAAiB,EACxB,IAAI,EAAE,CAAC,aAAa,CAAC,EAAE,MAAM,KAAK,IAAI;IAWvC,UAAU,IAAI,IAAI;IAElB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAkC/B,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IA2B/B,OAAO,CAAC,iBAAiB;IAsBzB,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,MAAM;IAad,OAAO,CAAC,QAAQ;CAYhB"}
1
+ {"version":3,"file":"ordered-multi-select.d.ts","sourceRoot":"","sources":["../../src/components/ordered-multi-select.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,KAAK,SAAS,EAA+C,MAAM,wBAAwB,CAAC;AACrG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAS5D,qBAAa,kBAAmB,YAAW,SAAS;IACnD,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,IAAI,CAAmC;gBAG9C,OAAO,EAAE,iBAAiB,EAAE,EAC5B,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,iBAAiB,EACxB,IAAI,EAAE,CAAC,aAAa,CAAC,EAAE,MAAM,KAAK,IAAI;IAWvC,UAAU,IAAI,IAAI;IAElB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAkC/B,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IA2B/B,OAAO,CAAC,iBAAiB;IAsBzB,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,MAAM;IAad,OAAO,CAAC,QAAQ;CAYhB"}
@@ -5,7 +5,7 @@
5
5
  * Selected items appear at the top with their position number.
6
6
  * Value is stored as a comma-separated string of selected IDs in order.
7
7
  */
8
- import { getKeybindings, matchesKey, truncateToWidth } from "@mariozechner/pi-tui";
8
+ import { getKeybindings, matchesKey, truncateToWidth } from "@earendil-works/pi-tui";
9
9
  export class OrderedMultiSelect {
10
10
  options;
11
11
  selected;
@@ -1 +1 @@
1
- {"version":3,"file":"ordered-multi-select.js","sourceRoot":"","sources":["../../src/components/ordered-multi-select.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Ordered multi-select component.\n *\n * Displays a list of options that can be toggled on/off and reordered.\n * Selected items appear at the top with their position number.\n * Value is stored as a comma-separated string of selected IDs in order.\n */\n\nimport { type Component, getKeybindings, matchesKey, truncateToWidth } from \"@mariozechner/pi-tui\";\nimport type { OrderedListOption } from \"../settings/types.js\";\nimport type { SettingsListTheme } from \"./settings-list.js\";\n\ninterface DisplayItem {\n\toption: OrderedListOption;\n\tselected: boolean;\n\t/** 1-based position within selected items, or 0 if not selected */\n\tposition: number;\n}\n\nexport class OrderedMultiSelect implements Component {\n\tprivate options: OrderedListOption[];\n\tprivate selected: string[];\n\tprivate cursorIndex = 0;\n\tprivate theme: SettingsListTheme;\n\tprivate done: (selectedValue?: string) => void;\n\n\tconstructor(\n\t\toptions: OrderedListOption[],\n\t\tcurrentValue: string,\n\t\ttheme: SettingsListTheme,\n\t\tdone: (selectedValue?: string) => void,\n\t) {\n\t\tthis.options = options;\n\t\tthis.selected = currentValue\n\t\t\t.split(\",\")\n\t\t\t.map((s) => s.trim())\n\t\t\t.filter(Boolean);\n\t\tthis.theme = theme;\n\t\tthis.done = done;\n\t}\n\n\tinvalidate(): void {}\n\n\trender(width: number): string[] {\n\t\tconst lines: string[] = [];\n\t\tconst items = this.buildDisplayItems();\n\n\t\tfor (let i = 0; i < items.length; i++) {\n\t\t\tconst item = items[i];\n\t\t\tconst isCursor = i === this.cursorIndex;\n\t\t\tconst prefix = isCursor ? this.theme.cursor : \" \";\n\n\t\t\tlet marker: string;\n\t\t\tif (item.selected) {\n\t\t\t\tmarker = this.theme.value(`✓ ${String(item.position).padStart(2)}`, isCursor);\n\t\t\t} else {\n\t\t\t\tmarker = this.theme.label(\" \", isCursor);\n\t\t\t}\n\n\t\t\tconst label = this.theme.label(item.option.label, isCursor);\n\t\t\tconst line = `${prefix}${marker} ${label}`;\n\t\t\tlines.push(truncateToWidth(line, width, \"…\"));\n\t\t}\n\n\t\t// Scroll indicator\n\t\tif (items.length > 0) {\n\t\t\tconst scrollText = ` (${this.cursorIndex + 1}/${items.length})`;\n\t\t\tlines.push(this.theme.hint(scrollText));\n\t\t}\n\n\t\t// Hint line\n\t\tlines.push(\"\");\n\t\tlines.push(this.theme.hint(\" Space toggle · Shift+↑/↓ reorder · Enter confirm · Esc cancel\"));\n\n\t\treturn lines;\n\t}\n\n\thandleInput(data: string): void {\n\t\tconst kb = getKeybindings();\n\t\tconst items = this.buildDisplayItems();\n\t\tif (items.length === 0) {\n\t\t\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\t\tthis.done(undefined);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(data, \"tui.select.up\") || matchesKey(data, \"up\")) {\n\t\t\tthis.cursorIndex = this.cursorIndex === 0 ? items.length - 1 : this.cursorIndex - 1;\n\t\t} else if (kb.matches(data, \"tui.select.down\") || matchesKey(data, \"down\")) {\n\t\t\tthis.cursorIndex = this.cursorIndex === items.length - 1 ? 0 : this.cursorIndex + 1;\n\t\t} else if (data === \" \" || matchesKey(data, \"space\")) {\n\t\t\tthis.toggleCurrent(items);\n\t\t} else if (matchesKey(data, \"shift+up\")) {\n\t\t\tthis.moveUp(items);\n\t\t} else if (matchesKey(data, \"shift+down\")) {\n\t\t\tthis.moveDown(items);\n\t\t} else if (kb.matches(data, \"tui.select.confirm\")) {\n\t\t\tthis.done(this.selected.join(\",\"));\n\t\t} else if (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis.done(undefined);\n\t\t}\n\t}\n\n\tprivate buildDisplayItems(): DisplayItem[] {\n\t\tconst items: DisplayItem[] = [];\n\n\t\t// Selected items first, in order\n\t\tfor (let i = 0; i < this.selected.length; i++) {\n\t\t\tconst id = this.selected[i];\n\t\t\tconst option = this.options.find((o) => o.id === id);\n\t\t\tif (option) {\n\t\t\t\titems.push({ option, selected: true, position: i + 1 });\n\t\t\t}\n\t\t}\n\n\t\t// Unselected items, in original options order\n\t\tfor (const option of this.options) {\n\t\t\tif (!this.selected.includes(option.id)) {\n\t\t\t\titems.push({ option, selected: false, position: 0 });\n\t\t\t}\n\t\t}\n\n\t\treturn items;\n\t}\n\n\tprivate toggleCurrent(items: DisplayItem[]): void {\n\t\tconst item = items[this.cursorIndex];\n\t\tif (!item) return;\n\n\t\tconst id = item.option.id;\n\t\tif (item.selected) {\n\t\t\t// Remove from selected\n\t\t\tthis.selected = this.selected.filter((s) => s !== id);\n\t\t} else {\n\t\t\t// Add to end of selected\n\t\t\tthis.selected.push(id);\n\t\t}\n\t}\n\n\tprivate moveUp(items: DisplayItem[]): void {\n\t\tconst item = items[this.cursorIndex];\n\t\tif (!item?.selected) return;\n\n\t\tconst idx = this.selected.indexOf(item.option.id);\n\t\tif (idx <= 0) return;\n\n\t\t// Swap with previous in selected array\n\t\t[this.selected[idx - 1], this.selected[idx]] = [this.selected[idx], this.selected[idx - 1]];\n\t\t// Move cursor up to follow the item\n\t\tthis.cursorIndex--;\n\t}\n\n\tprivate moveDown(items: DisplayItem[]): void {\n\t\tconst item = items[this.cursorIndex];\n\t\tif (!item?.selected) return;\n\n\t\tconst idx = this.selected.indexOf(item.option.id);\n\t\tif (idx < 0 || idx >= this.selected.length - 1) return;\n\n\t\t// Swap with next in selected array\n\t\t[this.selected[idx], this.selected[idx + 1]] = [this.selected[idx + 1], this.selected[idx]];\n\t\t// Move cursor down to follow the item\n\t\tthis.cursorIndex++;\n\t}\n}\n"]}
1
+ {"version":3,"file":"ordered-multi-select.js","sourceRoot":"","sources":["../../src/components/ordered-multi-select.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAkB,cAAc,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAWrG,MAAM,OAAO,kBAAkB;IACtB,OAAO,CAAsB;IAC7B,QAAQ,CAAW;IACnB,WAAW,GAAG,CAAC,CAAC;IAChB,KAAK,CAAoB;IACzB,IAAI,CAAmC;IAE/C,YACC,OAA4B,EAC5B,YAAoB,EACpB,KAAwB,EACxB,IAAsC;QAEtC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,QAAQ,GAAG,YAAY;aAC1B,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aACpB,MAAM,CAAC,OAAO,CAAC,CAAC;QAClB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IAClB,CAAC;IAED,UAAU,KAAU,CAAC;IAErB,MAAM,CAAC,KAAa;QACnB,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAEvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,MAAM,QAAQ,GAAG,CAAC,KAAK,IAAI,CAAC,WAAW,CAAC;YACxC,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;YAEnD,IAAI,MAAc,CAAC;YACnB,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACnB,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;YAC/E,CAAC;iBAAM,CAAC;gBACP,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YAC9C,CAAC;YAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;YAC5D,MAAM,IAAI,GAAG,GAAG,MAAM,GAAG,MAAM,KAAK,KAAK,EAAE,CAAC;YAC5C,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;QAC/C,CAAC;QAED,mBAAmB;QACnB,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,WAAW,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YACjE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QACzC,CAAC;QAED,YAAY;QACZ,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAC,CAAC;QAE/F,OAAO,KAAK,CAAC;IACd,CAAC;IAED,WAAW,CAAC,IAAY;QACvB,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,mBAAmB,CAAC,EAAE,CAAC;gBAC3C,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACtB,CAAC;YACD,OAAO;QACR,CAAC;QAED,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,eAAe,CAAC,IAAI,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YACjE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;QACrF,CAAC;aAAM,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,iBAAiB,CAAC,IAAI,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC;YAC5E,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;QACrF,CAAC;aAAM,IAAI,IAAI,KAAK,GAAG,IAAI,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;YACtD,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;aAAM,IAAI,UAAU,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,CAAC;YACzC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;aAAM,IAAI,UAAU,CAAC,IAAI,EAAE,YAAY,CAAC,EAAE,CAAC;YAC3C,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;aAAM,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,oBAAoB,CAAC,EAAE,CAAC;YACnD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACpC,CAAC;aAAM,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,mBAAmB,CAAC,EAAE,CAAC;YAClD,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACtB,CAAC;IACF,CAAC;IAEO,iBAAiB;QACxB,MAAM,KAAK,GAAkB,EAAE,CAAC;QAEhC,iCAAiC;QACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/C,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;YACrD,IAAI,MAAM,EAAE,CAAC;gBACZ,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACzD,CAAC;QACF,CAAC;QAED,8CAA8C;QAC9C,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACnC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;gBACxC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;YACtD,CAAC;QACF,CAAC;QAED,OAAO,KAAK,CAAC;IACd,CAAC;IAEO,aAAa,CAAC,KAAoB;QACzC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,uBAAuB;YACvB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QACvD,CAAC;aAAM,CAAC;YACP,yBAAyB;YACzB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxB,CAAC;IACF,CAAC;IAEO,MAAM,CAAC,KAAoB;QAClC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI,EAAE,QAAQ;YAAE,OAAO;QAE5B,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAClD,IAAI,GAAG,IAAI,CAAC;YAAE,OAAO;QAErB,uCAAuC;QACvC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QAC5F,oCAAoC;QACpC,IAAI,CAAC,WAAW,EAAE,CAAC;IACpB,CAAC;IAEO,QAAQ,CAAC,KAAoB;QACpC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI,EAAE,QAAQ;YAAE,OAAO;QAE5B,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAClD,IAAI,GAAG,GAAG,CAAC,IAAI,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO;QAEvD,mCAAmC;QACnC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5F,sCAAsC;QACtC,IAAI,CAAC,WAAW,EAAE,CAAC;IACpB,CAAC;CACD","sourcesContent":["/**\n * Ordered multi-select component.\n *\n * Displays a list of options that can be toggled on/off and reordered.\n * Selected items appear at the top with their position number.\n * Value is stored as a comma-separated string of selected IDs in order.\n */\n\nimport { type Component, getKeybindings, matchesKey, truncateToWidth } from \"@earendil-works/pi-tui\";\nimport type { OrderedListOption } from \"../settings/types.js\";\nimport type { SettingsListTheme } from \"./settings-list.js\";\n\ninterface DisplayItem {\n\toption: OrderedListOption;\n\tselected: boolean;\n\t/** 1-based position within selected items, or 0 if not selected */\n\tposition: number;\n}\n\nexport class OrderedMultiSelect implements Component {\n\tprivate options: OrderedListOption[];\n\tprivate selected: string[];\n\tprivate cursorIndex = 0;\n\tprivate theme: SettingsListTheme;\n\tprivate done: (selectedValue?: string) => void;\n\n\tconstructor(\n\t\toptions: OrderedListOption[],\n\t\tcurrentValue: string,\n\t\ttheme: SettingsListTheme,\n\t\tdone: (selectedValue?: string) => void,\n\t) {\n\t\tthis.options = options;\n\t\tthis.selected = currentValue\n\t\t\t.split(\",\")\n\t\t\t.map((s) => s.trim())\n\t\t\t.filter(Boolean);\n\t\tthis.theme = theme;\n\t\tthis.done = done;\n\t}\n\n\tinvalidate(): void {}\n\n\trender(width: number): string[] {\n\t\tconst lines: string[] = [];\n\t\tconst items = this.buildDisplayItems();\n\n\t\tfor (let i = 0; i < items.length; i++) {\n\t\t\tconst item = items[i];\n\t\t\tconst isCursor = i === this.cursorIndex;\n\t\t\tconst prefix = isCursor ? this.theme.cursor : \" \";\n\n\t\t\tlet marker: string;\n\t\t\tif (item.selected) {\n\t\t\t\tmarker = this.theme.value(`✓ ${String(item.position).padStart(2)}`, isCursor);\n\t\t\t} else {\n\t\t\t\tmarker = this.theme.label(\" \", isCursor);\n\t\t\t}\n\n\t\t\tconst label = this.theme.label(item.option.label, isCursor);\n\t\t\tconst line = `${prefix}${marker} ${label}`;\n\t\t\tlines.push(truncateToWidth(line, width, \"…\"));\n\t\t}\n\n\t\t// Scroll indicator\n\t\tif (items.length > 0) {\n\t\t\tconst scrollText = ` (${this.cursorIndex + 1}/${items.length})`;\n\t\t\tlines.push(this.theme.hint(scrollText));\n\t\t}\n\n\t\t// Hint line\n\t\tlines.push(\"\");\n\t\tlines.push(this.theme.hint(\" Space toggle · Shift+↑/↓ reorder · Enter confirm · Esc cancel\"));\n\n\t\treturn lines;\n\t}\n\n\thandleInput(data: string): void {\n\t\tconst kb = getKeybindings();\n\t\tconst items = this.buildDisplayItems();\n\t\tif (items.length === 0) {\n\t\t\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\t\tthis.done(undefined);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(data, \"tui.select.up\") || matchesKey(data, \"up\")) {\n\t\t\tthis.cursorIndex = this.cursorIndex === 0 ? items.length - 1 : this.cursorIndex - 1;\n\t\t} else if (kb.matches(data, \"tui.select.down\") || matchesKey(data, \"down\")) {\n\t\t\tthis.cursorIndex = this.cursorIndex === items.length - 1 ? 0 : this.cursorIndex + 1;\n\t\t} else if (data === \" \" || matchesKey(data, \"space\")) {\n\t\t\tthis.toggleCurrent(items);\n\t\t} else if (matchesKey(data, \"shift+up\")) {\n\t\t\tthis.moveUp(items);\n\t\t} else if (matchesKey(data, \"shift+down\")) {\n\t\t\tthis.moveDown(items);\n\t\t} else if (kb.matches(data, \"tui.select.confirm\")) {\n\t\t\tthis.done(this.selected.join(\",\"));\n\t\t} else if (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis.done(undefined);\n\t\t}\n\t}\n\n\tprivate buildDisplayItems(): DisplayItem[] {\n\t\tconst items: DisplayItem[] = [];\n\n\t\t// Selected items first, in order\n\t\tfor (let i = 0; i < this.selected.length; i++) {\n\t\t\tconst id = this.selected[i];\n\t\t\tconst option = this.options.find((o) => o.id === id);\n\t\t\tif (option) {\n\t\t\t\titems.push({ option, selected: true, position: i + 1 });\n\t\t\t}\n\t\t}\n\n\t\t// Unselected items, in original options order\n\t\tfor (const option of this.options) {\n\t\t\tif (!this.selected.includes(option.id)) {\n\t\t\t\titems.push({ option, selected: false, position: 0 });\n\t\t\t}\n\t\t}\n\n\t\treturn items;\n\t}\n\n\tprivate toggleCurrent(items: DisplayItem[]): void {\n\t\tconst item = items[this.cursorIndex];\n\t\tif (!item) return;\n\n\t\tconst id = item.option.id;\n\t\tif (item.selected) {\n\t\t\t// Remove from selected\n\t\t\tthis.selected = this.selected.filter((s) => s !== id);\n\t\t} else {\n\t\t\t// Add to end of selected\n\t\t\tthis.selected.push(id);\n\t\t}\n\t}\n\n\tprivate moveUp(items: DisplayItem[]): void {\n\t\tconst item = items[this.cursorIndex];\n\t\tif (!item?.selected) return;\n\n\t\tconst idx = this.selected.indexOf(item.option.id);\n\t\tif (idx <= 0) return;\n\n\t\t// Swap with previous in selected array\n\t\t[this.selected[idx - 1], this.selected[idx]] = [this.selected[idx], this.selected[idx - 1]];\n\t\t// Move cursor up to follow the item\n\t\tthis.cursorIndex--;\n\t}\n\n\tprivate moveDown(items: DisplayItem[]): void {\n\t\tconst item = items[this.cursorIndex];\n\t\tif (!item?.selected) return;\n\n\t\tconst idx = this.selected.indexOf(item.option.id);\n\t\tif (idx < 0 || idx >= this.selected.length - 1) return;\n\n\t\t// Swap with next in selected array\n\t\t[this.selected[idx], this.selected[idx + 1]] = [this.selected[idx + 1], this.selected[idx]];\n\t\t// Move cursor down to follow the item\n\t\tthis.cursorIndex++;\n\t}\n}\n"]}
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Settings list component with support for cycling values and string input.
3
- * Based on @mariozechner/pi-tui SettingsList, extended with string editing.
3
+ * Based on @earendil-works/pi-tui SettingsList, extended with string editing.
4
4
  */
5
- import { type Component } from "@mariozechner/pi-tui";
5
+ import { type Component } from "@earendil-works/pi-tui";
6
6
  export interface SettingItem {
7
7
  /** Unique identifier for this setting */
8
8
  id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"settings-list.d.ts","sourceRoot":"","sources":["../../src/components/settings-list.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,KAAK,SAAS,EAQd,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,WAAW;IAC3B,yCAAyC;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4CAA4C;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,uFAAuF;IACvF,OAAO,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,aAAa,CAAC,EAAE,MAAM,KAAK,IAAI,KAAK,SAAS,CAAC;IACtF,oEAAoE;IACpE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IACjC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,MAAM,CAAC;IACnD,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,MAAM,CAAC;IACnD,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,mBAAmB;IACnC,YAAY,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,qBAAa,YAAa,YAAW,SAAS;IAC7C,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAyC;IACzD,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,WAAW,CAAC,CAAQ;IAC5B,OAAO,CAAC,aAAa,CAAU;IAG/B,OAAO,CAAC,gBAAgB,CAA0B;IAClD,OAAO,CAAC,gBAAgB,CAAuB;IAG/C,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,gBAAgB,CAAuB;gBAG9C,KAAK,EAAE,WAAW,EAAE,EACpB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,iBAAiB,EACxB,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,EAChD,QAAQ,EAAE,MAAM,IAAI,EACpB,OAAO,GAAE,mBAAwB;IAclC,oCAAoC;IACpC,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAO/C,UAAU,IAAI,IAAI;IAIlB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAS/B,OAAO,CAAC,cAAc;IAqFtB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAqC/B,OAAO,CAAC,kBAAkB;IAmB1B,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,YAAY;IAkCpB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,WAAW;CAUnB"}
1
+ {"version":3,"file":"settings-list.d.ts","sourceRoot":"","sources":["../../src/components/settings-list.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,KAAK,SAAS,EAQd,MAAM,wBAAwB,CAAC;AAEhC,MAAM,WAAW,WAAW;IAC3B,yCAAyC;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4CAA4C;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,uFAAuF;IACvF,OAAO,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,aAAa,CAAC,EAAE,MAAM,KAAK,IAAI,KAAK,SAAS,CAAC;IACtF,oEAAoE;IACpE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IACjC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,MAAM,CAAC;IACnD,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,MAAM,CAAC;IACnD,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,mBAAmB;IACnC,YAAY,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,qBAAa,YAAa,YAAW,SAAS;IAC7C,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAyC;IACzD,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,WAAW,CAAC,CAAQ;IAC5B,OAAO,CAAC,aAAa,CAAU;IAG/B,OAAO,CAAC,gBAAgB,CAA0B;IAClD,OAAO,CAAC,gBAAgB,CAAuB;IAG/C,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,gBAAgB,CAAuB;gBAG9C,KAAK,EAAE,WAAW,EAAE,EACpB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,iBAAiB,EACxB,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,EAChD,QAAQ,EAAE,MAAM,IAAI,EACpB,OAAO,GAAE,mBAAwB;IAclC,oCAAoC;IACpC,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAO/C,UAAU,IAAI,IAAI;IAIlB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAS/B,OAAO,CAAC,cAAc;IAqFtB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAqC/B,OAAO,CAAC,kBAAkB;IAmB1B,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,YAAY;IAkCpB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,WAAW;CAUnB"}
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Settings list component with support for cycling values and string input.
3
- * Based on @mariozechner/pi-tui SettingsList, extended with string editing.
3
+ * Based on @earendil-works/pi-tui SettingsList, extended with string editing.
4
4
  */
5
- import { fuzzyFilter, getKeybindings, Input, matchesKey, truncateToWidth, visibleWidth, wrapTextWithAnsi, } from "@mariozechner/pi-tui";
5
+ import { fuzzyFilter, getKeybindings, Input, matchesKey, truncateToWidth, visibleWidth, wrapTextWithAnsi, } from "@earendil-works/pi-tui";
6
6
  export class SettingsList {
7
7
  items;
8
8
  filteredItems;
@@ -1 +1 @@
1
- {"version":3,"file":"settings-list.js","sourceRoot":"","sources":["../../src/components/settings-list.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Settings list component with support for cycling values and string input.\n * Based on @mariozechner/pi-tui SettingsList, extended with string editing.\n */\n\nimport {\n\ttype Component,\n\tfuzzyFilter,\n\tgetKeybindings,\n\tInput,\n\tmatchesKey,\n\ttruncateToWidth,\n\tvisibleWidth,\n\twrapTextWithAnsi,\n} from \"@mariozechner/pi-tui\";\n\nexport interface SettingItem {\n\t/** Unique identifier for this setting */\n\tid: string;\n\t/** Display label (left side) */\n\tlabel: string;\n\t/** Optional description shown when selected */\n\tdescription?: string;\n\t/** Current value to display (right side) */\n\tcurrentValue: string;\n\t/**\n\t * If provided, Enter/Space cycles through these values.\n\t * If undefined/empty, the setting is treated as a string input.\n\t */\n\tvalues?: string[];\n\t/** If provided, Enter opens this submenu. Receives current value and done callback. */\n\tsubmenu?: (currentValue: string, done: (selectedValue?: string) => void) => Component;\n\t/** If false, item is selectable but cannot be edited or changed. */\n\teditable?: boolean;\n}\n\nexport interface SettingsListTheme {\n\tlabel: (text: string, selected: boolean) => string;\n\tvalue: (text: string, selected: boolean) => string;\n\tdescription: (text: string) => string;\n\tcursor: string;\n\thint: (text: string) => string;\n}\n\nexport interface SettingsListOptions {\n\tenableSearch?: boolean;\n}\n\nexport class SettingsList implements Component {\n\tprivate items: SettingItem[];\n\tprivate filteredItems: SettingItem[];\n\tprivate theme: SettingsListTheme;\n\tprivate selectedIndex = 0;\n\tprivate maxVisible: number;\n\tprivate onChange: (id: string, newValue: string) => void;\n\tprivate onCancel: () => void;\n\tprivate searchInput?: Input;\n\tprivate searchEnabled: boolean;\n\n\t// Submenu state\n\tprivate submenuComponent: Component | null = null;\n\tprivate submenuItemIndex: number | null = null;\n\n\t// String editing state\n\tprivate editingInput: Input | null = null;\n\tprivate editingItemIndex: number | null = null;\n\n\tconstructor(\n\t\titems: SettingItem[],\n\t\tmaxVisible: number,\n\t\ttheme: SettingsListTheme,\n\t\tonChange: (id: string, newValue: string) => void,\n\t\tonCancel: () => void,\n\t\toptions: SettingsListOptions = {},\n\t) {\n\t\tthis.items = items;\n\t\tthis.filteredItems = items;\n\t\tthis.maxVisible = maxVisible;\n\t\tthis.theme = theme;\n\t\tthis.onChange = onChange;\n\t\tthis.onCancel = onCancel;\n\t\tthis.searchEnabled = options.enableSearch ?? false;\n\t\tif (this.searchEnabled) {\n\t\t\tthis.searchInput = new Input();\n\t\t}\n\t}\n\n\t/** Update an item's currentValue */\n\tupdateValue(id: string, newValue: string): void {\n\t\tconst item = this.items.find((i) => i.id === id);\n\t\tif (item) {\n\t\t\titem.currentValue = newValue;\n\t\t}\n\t}\n\n\tinvalidate(): void {\n\t\tthis.submenuComponent?.invalidate?.();\n\t}\n\n\trender(width: number): string[] {\n\t\t// If submenu is active, render it instead\n\t\tif (this.submenuComponent) {\n\t\t\treturn this.submenuComponent.render(width);\n\t\t}\n\n\t\treturn this.renderMainList(width);\n\t}\n\n\tprivate renderMainList(width: number): string[] {\n\t\tconst lines: string[] = [];\n\n\t\tif (this.searchEnabled && this.searchInput && !this.editingInput) {\n\t\t\tlines.push(...this.searchInput.render(width));\n\t\t\tlines.push(\"\");\n\t\t}\n\n\t\tif (this.items.length === 0) {\n\t\t\tlines.push(this.theme.hint(\" No settings available\"));\n\t\t\tif (this.searchEnabled) {\n\t\t\t\tthis.addHintLine(lines);\n\t\t\t}\n\t\t\treturn lines;\n\t\t}\n\n\t\tconst displayItems = this.searchEnabled ? this.filteredItems : this.items;\n\t\tif (displayItems.length === 0) {\n\t\t\tlines.push(this.theme.hint(\" No matching settings\"));\n\t\t\tthis.addHintLine(lines);\n\t\t\treturn lines;\n\t\t}\n\n\t\t// Calculate visible range with scrolling\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.selectedIndex - Math.floor(this.maxVisible / 2), displayItems.length - this.maxVisible),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + this.maxVisible, displayItems.length);\n\n\t\t// Calculate max label width for alignment\n\t\tconst maxLabelWidth = Math.min(30, Math.max(...this.items.map((item) => visibleWidth(item.label))));\n\n\t\t// Render visible items\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst item = displayItems[i];\n\t\t\tif (!item) continue;\n\n\t\t\tconst isSelected = i === this.selectedIndex;\n\t\t\tconst isEditing = this.editingInput && this.editingItemIndex === i;\n\t\t\tconst prefix = isSelected ? this.theme.cursor : \" \";\n\t\t\tconst prefixWidth = visibleWidth(prefix);\n\n\t\t\t// Pad label to align values\n\t\t\tconst labelPadded = item.label + \" \".repeat(Math.max(0, maxLabelWidth - visibleWidth(item.label)));\n\t\t\tconst labelText = this.theme.label(labelPadded, isSelected);\n\n\t\t\t// Calculate space for value\n\t\t\tconst separator = \" \";\n\t\t\tconst usedWidth = prefixWidth + maxLabelWidth + visibleWidth(separator);\n\t\t\tconst valueMaxWidth = width - usedWidth - 2;\n\n\t\t\tif (isEditing && this.editingInput) {\n\t\t\t\t// Render inline input for string editing\n\t\t\t\tconst inputLines = this.editingInput.render(valueMaxWidth);\n\t\t\t\tconst inputLine = inputLines[0] ?? \"\";\n\t\t\t\tlines.push(prefix + labelText + separator + inputLine);\n\t\t\t} else {\n\t\t\t\tconst valueText = this.theme.value(truncateToWidth(item.currentValue, valueMaxWidth, \"\"), isSelected);\n\t\t\t\tlines.push(prefix + labelText + separator + valueText);\n\t\t\t}\n\t\t}\n\n\t\t// Add scroll indicator if needed\n\t\tif (startIndex > 0 || endIndex < displayItems.length) {\n\t\t\tconst scrollText = ` (${this.selectedIndex + 1}/${displayItems.length})`;\n\t\t\tlines.push(this.theme.hint(truncateToWidth(scrollText, width - 2, \"\")));\n\t\t}\n\n\t\t// Add description for selected item\n\t\tconst selectedItem = displayItems[this.selectedIndex];\n\t\tif (selectedItem?.description && !this.editingInput) {\n\t\t\tlines.push(\"\");\n\t\t\tconst wrappedDesc = wrapTextWithAnsi(selectedItem.description, width - 4);\n\t\t\tfor (const line of wrappedDesc) {\n\t\t\t\tlines.push(this.theme.description(` ${line}`));\n\t\t\t}\n\t\t}\n\n\t\t// Add hint\n\t\tthis.addHintLine(lines);\n\n\t\treturn lines;\n\t}\n\n\thandleInput(data: string): void {\n\t\t// If editing a string value, handle input for the editor\n\t\tif (this.editingInput) {\n\t\t\tthis.handleEditingInput(data);\n\t\t\treturn;\n\t\t}\n\n\t\t// If submenu is active, delegate all input to it\n\t\tif (this.submenuComponent) {\n\t\t\tthis.submenuComponent.handleInput?.(data);\n\t\t\treturn;\n\t\t}\n\n\t\t// Main list input handling\n\t\tconst kb = getKeybindings();\n\t\tconst displayItems = this.searchEnabled ? this.filteredItems : this.items;\n\n\t\tif (kb.matches(data, \"tui.select.up\")) {\n\t\t\tif (displayItems.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === 0 ? displayItems.length - 1 : this.selectedIndex - 1;\n\t\t} else if (kb.matches(data, \"tui.select.down\")) {\n\t\t\tif (displayItems.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === displayItems.length - 1 ? 0 : this.selectedIndex + 1;\n\t\t} else if (kb.matches(data, \"tui.select.confirm\") || data === \" \") {\n\t\t\tthis.activateItem();\n\t\t} else if (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis.onCancel();\n\t\t} else if (this.searchEnabled && this.searchInput) {\n\t\t\tconst sanitized = data.replace(/ /g, \"\");\n\t\t\tif (!sanitized) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.searchInput.handleInput(sanitized);\n\t\t\tthis.applyFilter(this.searchInput.getValue());\n\t\t}\n\t}\n\n\tprivate handleEditingInput(data: string): void {\n\t\tif (!this.editingInput) return;\n\n\t\t// Enter: confirm edit\n\t\tif (matchesKey(data, \"enter\")) {\n\t\t\tthis.confirmEdit();\n\t\t\treturn;\n\t\t}\n\n\t\t// Escape: cancel edit\n\t\tif (matchesKey(data, \"escape\")) {\n\t\t\tthis.cancelEdit();\n\t\t\treturn;\n\t\t}\n\n\t\t// Pass other input to the editor\n\t\tthis.editingInput.handleInput(data);\n\t}\n\n\tprivate confirmEdit(): void {\n\t\tif (!this.editingInput || this.editingItemIndex === null) return;\n\n\t\tconst displayItems = this.searchEnabled ? this.filteredItems : this.items;\n\t\tconst item = displayItems[this.editingItemIndex];\n\t\tif (item) {\n\t\t\tconst newValue = this.editingInput.getValue();\n\t\t\titem.currentValue = newValue;\n\t\t\tthis.onChange(item.id, newValue);\n\t\t}\n\n\t\tthis.editingInput = null;\n\t\tthis.editingItemIndex = null;\n\t}\n\n\tprivate cancelEdit(): void {\n\t\tthis.editingInput = null;\n\t\tthis.editingItemIndex = null;\n\t}\n\n\tprivate activateItem(): void {\n\t\tconst displayItems = this.searchEnabled ? this.filteredItems : this.items;\n\t\tconst item = displayItems[this.selectedIndex];\n\t\tif (!item) return;\n\n\t\tif (item.editable === false) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (item.submenu) {\n\t\t\t// Open submenu, passing current value so it can pre-select correctly\n\t\t\tthis.submenuItemIndex = this.selectedIndex;\n\t\t\tthis.submenuComponent = item.submenu(item.currentValue, (selectedValue?: string) => {\n\t\t\t\tif (selectedValue !== undefined) {\n\t\t\t\t\titem.currentValue = selectedValue;\n\t\t\t\t\tthis.onChange(item.id, selectedValue);\n\t\t\t\t}\n\t\t\t\tthis.closeSubmenu();\n\t\t\t});\n\t\t} else if (item.values && item.values.length > 0) {\n\t\t\t// Cycle through values\n\t\t\tconst currentIndex = item.values.indexOf(item.currentValue);\n\t\t\tconst nextIndex = (currentIndex + 1) % item.values.length;\n\t\t\tconst newValue = item.values[nextIndex];\n\t\t\titem.currentValue = newValue;\n\t\t\tthis.onChange(item.id, newValue);\n\t\t} else {\n\t\t\t// String input - start editing\n\t\t\tthis.editingItemIndex = this.selectedIndex;\n\t\t\tthis.editingInput = new Input();\n\t\t\tthis.editingInput.setValue(item.currentValue);\n\t\t}\n\t}\n\n\tprivate closeSubmenu(): void {\n\t\tthis.submenuComponent = null;\n\t\t// Restore selection to the item that opened the submenu\n\t\tif (this.submenuItemIndex !== null) {\n\t\t\tthis.selectedIndex = this.submenuItemIndex;\n\t\t\tthis.submenuItemIndex = null;\n\t\t}\n\t}\n\n\tprivate applyFilter(query: string): void {\n\t\tthis.filteredItems = fuzzyFilter(this.items, query, (item) => item.label);\n\t\tthis.selectedIndex = 0;\n\t}\n\n\tprivate addHintLine(lines: string[]): void {\n\t\tlines.push(\"\");\n\t\tif (this.editingInput) {\n\t\t\tlines.push(this.theme.hint(\" Enter to confirm · Esc to cancel\"));\n\t\t} else if (this.searchEnabled) {\n\t\t\tlines.push(this.theme.hint(\" Type to search · Enter/Space to change · Esc to cancel\"));\n\t\t} else {\n\t\t\tlines.push(this.theme.hint(\" Enter/Space to change · Esc to cancel\"));\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"settings-list.js","sourceRoot":"","sources":["../../src/components/settings-list.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Settings list component with support for cycling values and string input.\n * Based on @earendil-works/pi-tui SettingsList, extended with string editing.\n */\n\nimport {\n\ttype Component,\n\tfuzzyFilter,\n\tgetKeybindings,\n\tInput,\n\tmatchesKey,\n\ttruncateToWidth,\n\tvisibleWidth,\n\twrapTextWithAnsi,\n} from \"@earendil-works/pi-tui\";\n\nexport interface SettingItem {\n\t/** Unique identifier for this setting */\n\tid: string;\n\t/** Display label (left side) */\n\tlabel: string;\n\t/** Optional description shown when selected */\n\tdescription?: string;\n\t/** Current value to display (right side) */\n\tcurrentValue: string;\n\t/**\n\t * If provided, Enter/Space cycles through these values.\n\t * If undefined/empty, the setting is treated as a string input.\n\t */\n\tvalues?: string[];\n\t/** If provided, Enter opens this submenu. Receives current value and done callback. */\n\tsubmenu?: (currentValue: string, done: (selectedValue?: string) => void) => Component;\n\t/** If false, item is selectable but cannot be edited or changed. */\n\teditable?: boolean;\n}\n\nexport interface SettingsListTheme {\n\tlabel: (text: string, selected: boolean) => string;\n\tvalue: (text: string, selected: boolean) => string;\n\tdescription: (text: string) => string;\n\tcursor: string;\n\thint: (text: string) => string;\n}\n\nexport interface SettingsListOptions {\n\tenableSearch?: boolean;\n}\n\nexport class SettingsList implements Component {\n\tprivate items: SettingItem[];\n\tprivate filteredItems: SettingItem[];\n\tprivate theme: SettingsListTheme;\n\tprivate selectedIndex = 0;\n\tprivate maxVisible: number;\n\tprivate onChange: (id: string, newValue: string) => void;\n\tprivate onCancel: () => void;\n\tprivate searchInput?: Input;\n\tprivate searchEnabled: boolean;\n\n\t// Submenu state\n\tprivate submenuComponent: Component | null = null;\n\tprivate submenuItemIndex: number | null = null;\n\n\t// String editing state\n\tprivate editingInput: Input | null = null;\n\tprivate editingItemIndex: number | null = null;\n\n\tconstructor(\n\t\titems: SettingItem[],\n\t\tmaxVisible: number,\n\t\ttheme: SettingsListTheme,\n\t\tonChange: (id: string, newValue: string) => void,\n\t\tonCancel: () => void,\n\t\toptions: SettingsListOptions = {},\n\t) {\n\t\tthis.items = items;\n\t\tthis.filteredItems = items;\n\t\tthis.maxVisible = maxVisible;\n\t\tthis.theme = theme;\n\t\tthis.onChange = onChange;\n\t\tthis.onCancel = onCancel;\n\t\tthis.searchEnabled = options.enableSearch ?? false;\n\t\tif (this.searchEnabled) {\n\t\t\tthis.searchInput = new Input();\n\t\t}\n\t}\n\n\t/** Update an item's currentValue */\n\tupdateValue(id: string, newValue: string): void {\n\t\tconst item = this.items.find((i) => i.id === id);\n\t\tif (item) {\n\t\t\titem.currentValue = newValue;\n\t\t}\n\t}\n\n\tinvalidate(): void {\n\t\tthis.submenuComponent?.invalidate?.();\n\t}\n\n\trender(width: number): string[] {\n\t\t// If submenu is active, render it instead\n\t\tif (this.submenuComponent) {\n\t\t\treturn this.submenuComponent.render(width);\n\t\t}\n\n\t\treturn this.renderMainList(width);\n\t}\n\n\tprivate renderMainList(width: number): string[] {\n\t\tconst lines: string[] = [];\n\n\t\tif (this.searchEnabled && this.searchInput && !this.editingInput) {\n\t\t\tlines.push(...this.searchInput.render(width));\n\t\t\tlines.push(\"\");\n\t\t}\n\n\t\tif (this.items.length === 0) {\n\t\t\tlines.push(this.theme.hint(\" No settings available\"));\n\t\t\tif (this.searchEnabled) {\n\t\t\t\tthis.addHintLine(lines);\n\t\t\t}\n\t\t\treturn lines;\n\t\t}\n\n\t\tconst displayItems = this.searchEnabled ? this.filteredItems : this.items;\n\t\tif (displayItems.length === 0) {\n\t\t\tlines.push(this.theme.hint(\" No matching settings\"));\n\t\t\tthis.addHintLine(lines);\n\t\t\treturn lines;\n\t\t}\n\n\t\t// Calculate visible range with scrolling\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.selectedIndex - Math.floor(this.maxVisible / 2), displayItems.length - this.maxVisible),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + this.maxVisible, displayItems.length);\n\n\t\t// Calculate max label width for alignment\n\t\tconst maxLabelWidth = Math.min(30, Math.max(...this.items.map((item) => visibleWidth(item.label))));\n\n\t\t// Render visible items\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst item = displayItems[i];\n\t\t\tif (!item) continue;\n\n\t\t\tconst isSelected = i === this.selectedIndex;\n\t\t\tconst isEditing = this.editingInput && this.editingItemIndex === i;\n\t\t\tconst prefix = isSelected ? this.theme.cursor : \" \";\n\t\t\tconst prefixWidth = visibleWidth(prefix);\n\n\t\t\t// Pad label to align values\n\t\t\tconst labelPadded = item.label + \" \".repeat(Math.max(0, maxLabelWidth - visibleWidth(item.label)));\n\t\t\tconst labelText = this.theme.label(labelPadded, isSelected);\n\n\t\t\t// Calculate space for value\n\t\t\tconst separator = \" \";\n\t\t\tconst usedWidth = prefixWidth + maxLabelWidth + visibleWidth(separator);\n\t\t\tconst valueMaxWidth = width - usedWidth - 2;\n\n\t\t\tif (isEditing && this.editingInput) {\n\t\t\t\t// Render inline input for string editing\n\t\t\t\tconst inputLines = this.editingInput.render(valueMaxWidth);\n\t\t\t\tconst inputLine = inputLines[0] ?? \"\";\n\t\t\t\tlines.push(prefix + labelText + separator + inputLine);\n\t\t\t} else {\n\t\t\t\tconst valueText = this.theme.value(truncateToWidth(item.currentValue, valueMaxWidth, \"\"), isSelected);\n\t\t\t\tlines.push(prefix + labelText + separator + valueText);\n\t\t\t}\n\t\t}\n\n\t\t// Add scroll indicator if needed\n\t\tif (startIndex > 0 || endIndex < displayItems.length) {\n\t\t\tconst scrollText = ` (${this.selectedIndex + 1}/${displayItems.length})`;\n\t\t\tlines.push(this.theme.hint(truncateToWidth(scrollText, width - 2, \"\")));\n\t\t}\n\n\t\t// Add description for selected item\n\t\tconst selectedItem = displayItems[this.selectedIndex];\n\t\tif (selectedItem?.description && !this.editingInput) {\n\t\t\tlines.push(\"\");\n\t\t\tconst wrappedDesc = wrapTextWithAnsi(selectedItem.description, width - 4);\n\t\t\tfor (const line of wrappedDesc) {\n\t\t\t\tlines.push(this.theme.description(` ${line}`));\n\t\t\t}\n\t\t}\n\n\t\t// Add hint\n\t\tthis.addHintLine(lines);\n\n\t\treturn lines;\n\t}\n\n\thandleInput(data: string): void {\n\t\t// If editing a string value, handle input for the editor\n\t\tif (this.editingInput) {\n\t\t\tthis.handleEditingInput(data);\n\t\t\treturn;\n\t\t}\n\n\t\t// If submenu is active, delegate all input to it\n\t\tif (this.submenuComponent) {\n\t\t\tthis.submenuComponent.handleInput?.(data);\n\t\t\treturn;\n\t\t}\n\n\t\t// Main list input handling\n\t\tconst kb = getKeybindings();\n\t\tconst displayItems = this.searchEnabled ? this.filteredItems : this.items;\n\n\t\tif (kb.matches(data, \"tui.select.up\")) {\n\t\t\tif (displayItems.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === 0 ? displayItems.length - 1 : this.selectedIndex - 1;\n\t\t} else if (kb.matches(data, \"tui.select.down\")) {\n\t\t\tif (displayItems.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === displayItems.length - 1 ? 0 : this.selectedIndex + 1;\n\t\t} else if (kb.matches(data, \"tui.select.confirm\") || data === \" \") {\n\t\t\tthis.activateItem();\n\t\t} else if (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis.onCancel();\n\t\t} else if (this.searchEnabled && this.searchInput) {\n\t\t\tconst sanitized = data.replace(/ /g, \"\");\n\t\t\tif (!sanitized) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.searchInput.handleInput(sanitized);\n\t\t\tthis.applyFilter(this.searchInput.getValue());\n\t\t}\n\t}\n\n\tprivate handleEditingInput(data: string): void {\n\t\tif (!this.editingInput) return;\n\n\t\t// Enter: confirm edit\n\t\tif (matchesKey(data, \"enter\")) {\n\t\t\tthis.confirmEdit();\n\t\t\treturn;\n\t\t}\n\n\t\t// Escape: cancel edit\n\t\tif (matchesKey(data, \"escape\")) {\n\t\t\tthis.cancelEdit();\n\t\t\treturn;\n\t\t}\n\n\t\t// Pass other input to the editor\n\t\tthis.editingInput.handleInput(data);\n\t}\n\n\tprivate confirmEdit(): void {\n\t\tif (!this.editingInput || this.editingItemIndex === null) return;\n\n\t\tconst displayItems = this.searchEnabled ? this.filteredItems : this.items;\n\t\tconst item = displayItems[this.editingItemIndex];\n\t\tif (item) {\n\t\t\tconst newValue = this.editingInput.getValue();\n\t\t\titem.currentValue = newValue;\n\t\t\tthis.onChange(item.id, newValue);\n\t\t}\n\n\t\tthis.editingInput = null;\n\t\tthis.editingItemIndex = null;\n\t}\n\n\tprivate cancelEdit(): void {\n\t\tthis.editingInput = null;\n\t\tthis.editingItemIndex = null;\n\t}\n\n\tprivate activateItem(): void {\n\t\tconst displayItems = this.searchEnabled ? this.filteredItems : this.items;\n\t\tconst item = displayItems[this.selectedIndex];\n\t\tif (!item) return;\n\n\t\tif (item.editable === false) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (item.submenu) {\n\t\t\t// Open submenu, passing current value so it can pre-select correctly\n\t\t\tthis.submenuItemIndex = this.selectedIndex;\n\t\t\tthis.submenuComponent = item.submenu(item.currentValue, (selectedValue?: string) => {\n\t\t\t\tif (selectedValue !== undefined) {\n\t\t\t\t\titem.currentValue = selectedValue;\n\t\t\t\t\tthis.onChange(item.id, selectedValue);\n\t\t\t\t}\n\t\t\t\tthis.closeSubmenu();\n\t\t\t});\n\t\t} else if (item.values && item.values.length > 0) {\n\t\t\t// Cycle through values\n\t\t\tconst currentIndex = item.values.indexOf(item.currentValue);\n\t\t\tconst nextIndex = (currentIndex + 1) % item.values.length;\n\t\t\tconst newValue = item.values[nextIndex];\n\t\t\titem.currentValue = newValue;\n\t\t\tthis.onChange(item.id, newValue);\n\t\t} else {\n\t\t\t// String input - start editing\n\t\t\tthis.editingItemIndex = this.selectedIndex;\n\t\t\tthis.editingInput = new Input();\n\t\t\tthis.editingInput.setValue(item.currentValue);\n\t\t}\n\t}\n\n\tprivate closeSubmenu(): void {\n\t\tthis.submenuComponent = null;\n\t\t// Restore selection to the item that opened the submenu\n\t\tif (this.submenuItemIndex !== null) {\n\t\t\tthis.selectedIndex = this.submenuItemIndex;\n\t\t\tthis.submenuItemIndex = null;\n\t\t}\n\t}\n\n\tprivate applyFilter(query: string): void {\n\t\tthis.filteredItems = fuzzyFilter(this.items, query, (item) => item.label);\n\t\tthis.selectedIndex = 0;\n\t}\n\n\tprivate addHintLine(lines: string[]): void {\n\t\tlines.push(\"\");\n\t\tif (this.editingInput) {\n\t\t\tlines.push(this.theme.hint(\" Enter to confirm · Esc to cancel\"));\n\t\t} else if (this.searchEnabled) {\n\t\t\tlines.push(this.theme.hint(\" Type to search · Enter/Space to change · Esc to cancel\"));\n\t\t} else {\n\t\t\tlines.push(this.theme.hint(\" Enter/Space to change · Esc to cancel\"));\n\t\t}\n\t}\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Pi extension that provides /extension-settings command.
3
3
  */
4
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
4
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
5
5
  export default function piLibExtension(pi: ExtensionAPI): void;
6
6
  //# sourceMappingURL=extension.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAalE,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,EAAE,EAAE,YAAY,QA2GtD"}
1
+ {"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAapE,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,EAAE,EAAE,YAAY,QA2GtD"}
package/dist/extension.js CHANGED
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Pi extension that provides /extension-settings command.
3
3
  */
4
- import { getSettingsListTheme } from "@mariozechner/pi-coding-agent";
5
- import { Container, Text } from "@mariozechner/pi-tui";
4
+ import { getSettingsListTheme } from "@earendil-works/pi-coding-agent";
5
+ import { Container, Text } from "@earendil-works/pi-tui";
6
6
  import { OrderedMultiSelect } from "./components/ordered-multi-select.js";
7
7
  import { SettingsList } from "./components/settings-list.js";
8
8
  import { getSetting, setSetting } from "./settings/storage.js";
@@ -1 +1 @@
1
- {"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pi extension that provides /extension-settings command.\n */\n\nimport type { ExtensionAPI } from \"@mariozechner/pi-coding-agent\";\nimport { getSettingsListTheme } from \"@mariozechner/pi-coding-agent\";\nimport { Container, Text } from \"@mariozechner/pi-tui\";\nimport { OrderedMultiSelect } from \"./components/ordered-multi-select.js\";\nimport { type SettingItem, SettingsList } from \"./components/settings-list.js\";\nimport { getSetting, setSetting } from \"./settings/storage.js\";\nimport type { SettingDefinition } from \"./settings/types.js\";\n\ninterface RegistrationPayload {\n\tname: string;\n\tsettings: SettingDefinition[];\n}\n\nexport default function piLibExtension(pi: ExtensionAPI) {\n\t// Local registry - stores settings registered via events\n\tconst registry = new Map<string, SettingDefinition[]>();\n\n\t// Listen for registration events from other extensions\n\tpi.events.on(\"pi-extension-settings:register\", (data) => {\n\t\tconst { name, settings } = data as RegistrationPayload;\n\t\tregistry.set(name, settings);\n\t});\n\n\tpi.registerCommand(\"extension-settings\", {\n\t\tdescription: \"Configure settings for all extensions\",\n\t\thandler: async (_args, ctx) => {\n\t\t\tif (registry.size === 0) {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\"No extensions have registered settings. Ensure pi-extension-settings is listed before consumer extensions in your packages array in ~/.pi/settings.json.\",\n\t\t\t\t\t\"info\",\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Sort extensions by name\n\t\t\tconst sortedExtensions = Array.from(registry.entries()).sort(([a], [b]) => a.localeCompare(b));\n\n\t\t\tawait ctx.ui.custom((tui, theme, _kb, done) => {\n\t\t\t\tconst container = new Container();\n\n\t\t\t\t// Title\n\t\t\t\tcontainer.addChild(new Text(theme.fg(\"accent\", theme.bold(\"Extension Settings\")), 1, 1));\n\n\t\t\t\t// Build items grouped by extension\n\t\t\t\tconst items: SettingItem[] = [];\n\n\t\t\t\tfor (const [extName, settings] of sortedExtensions) {\n\t\t\t\t\t// Add extension header as a non-interactive item\n\t\t\t\t\titems.push({\n\t\t\t\t\t\tid: `__header__${extName}`,\n\t\t\t\t\t\tlabel: theme.bold(extName),\n\t\t\t\t\t\tcurrentValue: \"\",\n\t\t\t\t\t\tvalues: undefined, // No cycling - acts as header\n\t\t\t\t\t\teditable: false,\n\t\t\t\t\t});\n\n\t\t\t\t\t// Add each setting\n\t\t\t\t\tfor (const setting of settings) {\n\t\t\t\t\t\tconst currentValue = getSetting(extName, setting.id, setting.defaultValue) ?? setting.defaultValue;\n\n\t\t\t\t\t\tif (setting.options && setting.options.length > 0) {\n\t\t\t\t\t\t\t// Ordered multi-select: opens a submenu\n\t\t\t\t\t\t\titems.push({\n\t\t\t\t\t\t\t\tid: `${extName}::${setting.id}`,\n\t\t\t\t\t\t\t\tlabel: ` ${setting.label}`,\n\t\t\t\t\t\t\t\tdescription: setting.description,\n\t\t\t\t\t\t\t\tcurrentValue,\n\t\t\t\t\t\t\t\tsubmenu: (val, submenuDone) => {\n\t\t\t\t\t\t\t\t\treturn new OrderedMultiSelect(setting.options!, val, getSettingsListTheme(), submenuDone);\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\titems.push({\n\t\t\t\t\t\t\t\tid: `${extName}::${setting.id}`,\n\t\t\t\t\t\t\t\tlabel: ` ${setting.label}`,\n\t\t\t\t\t\t\t\tdescription: setting.description,\n\t\t\t\t\t\t\t\tcurrentValue,\n\t\t\t\t\t\t\t\tvalues: setting.values,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst settingsList = new SettingsList(\n\t\t\t\t\titems,\n\t\t\t\t\tMath.min(items.length + 2, 20),\n\t\t\t\t\tgetSettingsListTheme(),\n\t\t\t\t\t(id, newValue) => {\n\t\t\t\t\t\t// Skip headers\n\t\t\t\t\t\tif (id.startsWith(\"__header__\")) return;\n\n\t\t\t\t\t\t// Parse extension::settingId\n\t\t\t\t\t\tconst [extensionName, settingId] = id.split(\"::\");\n\t\t\t\t\t\tif (extensionName && settingId) {\n\t\t\t\t\t\t\tsetSetting(extensionName, settingId, newValue);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t() => {\n\t\t\t\t\t\tdone(undefined);\n\t\t\t\t\t},\n\t\t\t\t\t{ enableSearch: true },\n\t\t\t\t);\n\n\t\t\t\tcontainer.addChild(settingsList);\n\n\t\t\t\treturn {\n\t\t\t\t\trender(width: number) {\n\t\t\t\t\t\treturn container.render(width);\n\t\t\t\t\t},\n\t\t\t\t\tinvalidate() {\n\t\t\t\t\t\tcontainer.invalidate();\n\t\t\t\t\t},\n\t\t\t\t\thandleInput(data: string) {\n\t\t\t\t\t\tsettingsList.handleInput?.(data);\n\t\t\t\t\t\ttui.requestRender();\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\t});\n}\n"]}
1
+ {"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pi extension that provides /extension-settings command.\n */\n\nimport type { ExtensionAPI } from \"@earendil-works/pi-coding-agent\";\nimport { getSettingsListTheme } from \"@earendil-works/pi-coding-agent\";\nimport { Container, Text } from \"@earendil-works/pi-tui\";\nimport { OrderedMultiSelect } from \"./components/ordered-multi-select.js\";\nimport { type SettingItem, SettingsList } from \"./components/settings-list.js\";\nimport { getSetting, setSetting } from \"./settings/storage.js\";\nimport type { SettingDefinition } from \"./settings/types.js\";\n\ninterface RegistrationPayload {\n\tname: string;\n\tsettings: SettingDefinition[];\n}\n\nexport default function piLibExtension(pi: ExtensionAPI) {\n\t// Local registry - stores settings registered via events\n\tconst registry = new Map<string, SettingDefinition[]>();\n\n\t// Listen for registration events from other extensions\n\tpi.events.on(\"pi-extension-settings:register\", (data) => {\n\t\tconst { name, settings } = data as RegistrationPayload;\n\t\tregistry.set(name, settings);\n\t});\n\n\tpi.registerCommand(\"extension-settings\", {\n\t\tdescription: \"Configure settings for all extensions\",\n\t\thandler: async (_args, ctx) => {\n\t\t\tif (registry.size === 0) {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\"No extensions have registered settings. Ensure pi-extension-settings is listed before consumer extensions in your packages array in ~/.pi/settings.json.\",\n\t\t\t\t\t\"info\",\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Sort extensions by name\n\t\t\tconst sortedExtensions = Array.from(registry.entries()).sort(([a], [b]) => a.localeCompare(b));\n\n\t\t\tawait ctx.ui.custom((tui, theme, _kb, done) => {\n\t\t\t\tconst container = new Container();\n\n\t\t\t\t// Title\n\t\t\t\tcontainer.addChild(new Text(theme.fg(\"accent\", theme.bold(\"Extension Settings\")), 1, 1));\n\n\t\t\t\t// Build items grouped by extension\n\t\t\t\tconst items: SettingItem[] = [];\n\n\t\t\t\tfor (const [extName, settings] of sortedExtensions) {\n\t\t\t\t\t// Add extension header as a non-interactive item\n\t\t\t\t\titems.push({\n\t\t\t\t\t\tid: `__header__${extName}`,\n\t\t\t\t\t\tlabel: theme.bold(extName),\n\t\t\t\t\t\tcurrentValue: \"\",\n\t\t\t\t\t\tvalues: undefined, // No cycling - acts as header\n\t\t\t\t\t\teditable: false,\n\t\t\t\t\t});\n\n\t\t\t\t\t// Add each setting\n\t\t\t\t\tfor (const setting of settings) {\n\t\t\t\t\t\tconst currentValue = getSetting(extName, setting.id, setting.defaultValue) ?? setting.defaultValue;\n\n\t\t\t\t\t\tif (setting.options && setting.options.length > 0) {\n\t\t\t\t\t\t\t// Ordered multi-select: opens a submenu\n\t\t\t\t\t\t\titems.push({\n\t\t\t\t\t\t\t\tid: `${extName}::${setting.id}`,\n\t\t\t\t\t\t\t\tlabel: ` ${setting.label}`,\n\t\t\t\t\t\t\t\tdescription: setting.description,\n\t\t\t\t\t\t\t\tcurrentValue,\n\t\t\t\t\t\t\t\tsubmenu: (val, submenuDone) => {\n\t\t\t\t\t\t\t\t\treturn new OrderedMultiSelect(setting.options!, val, getSettingsListTheme(), submenuDone);\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\titems.push({\n\t\t\t\t\t\t\t\tid: `${extName}::${setting.id}`,\n\t\t\t\t\t\t\t\tlabel: ` ${setting.label}`,\n\t\t\t\t\t\t\t\tdescription: setting.description,\n\t\t\t\t\t\t\t\tcurrentValue,\n\t\t\t\t\t\t\t\tvalues: setting.values,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst settingsList = new SettingsList(\n\t\t\t\t\titems,\n\t\t\t\t\tMath.min(items.length + 2, 20),\n\t\t\t\t\tgetSettingsListTheme(),\n\t\t\t\t\t(id, newValue) => {\n\t\t\t\t\t\t// Skip headers\n\t\t\t\t\t\tif (id.startsWith(\"__header__\")) return;\n\n\t\t\t\t\t\t// Parse extension::settingId\n\t\t\t\t\t\tconst [extensionName, settingId] = id.split(\"::\");\n\t\t\t\t\t\tif (extensionName && settingId) {\n\t\t\t\t\t\t\tsetSetting(extensionName, settingId, newValue);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t() => {\n\t\t\t\t\t\tdone(undefined);\n\t\t\t\t\t},\n\t\t\t\t\t{ enableSearch: true },\n\t\t\t\t);\n\n\t\t\t\tcontainer.addChild(settingsList);\n\n\t\t\t\treturn {\n\t\t\t\t\trender(width: number) {\n\t\t\t\t\t\treturn container.render(width);\n\t\t\t\t\t},\n\t\t\t\t\tinvalidate() {\n\t\t\t\t\t\tcontainer.invalidate();\n\t\t\t\t\t},\n\t\t\t\t\thandleInput(data: string) {\n\t\t\t\t\t\tsettingsList.handleInput?.(data);\n\t\t\t\t\t\ttui.requestRender();\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\t});\n}\n"]}
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
5
5
  import { dirname, join } from "node:path";
6
- import { getAgentDir } from "@mariozechner/pi-coding-agent";
6
+ import { getAgentDir } from "@earendil-works/pi-coding-agent";
7
7
  const SETTINGS_FILE_NAME = "settings-extensions.json";
8
8
  /**
9
9
  * Get the global settings file path.
@@ -1 +1 @@
1
- {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/settings/storage.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAE5D,MAAM,kBAAkB,GAAG,0BAA0B,CAAC;AAItD;;GAEG;AACH,SAAS,qBAAqB;IAC7B,OAAO,IAAI,CAAC,WAAW,EAAE,EAAE,kBAAkB,CAAC,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAC,IAAY;IACrC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,CAAC;IACX,CAAC;IACD,IAAI,CAAC;QACJ,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAiB,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,EAAE,CAAC;IACX,CAAC;AACF,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAC,IAAY,EAAE,QAAsB;IAC7D,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrC,CAAC;IACD,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,aAAqB,EAAE,SAAiB,EAAE,YAAqB;IACzF,MAAM,UAAU,GAAG,qBAAqB,EAAE,CAAC;IAC3C,MAAM,QAAQ,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAE9C,gCAAgC;IAChC,MAAM,WAAW,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAC;IAC5C,IAAI,WAAW,IAAI,SAAS,IAAI,WAAW,EAAE,CAAC;QAC7C,OAAO,WAAW,CAAC,SAAS,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,YAAY,CAAC;AACrB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,aAAqB,EAAE,SAAiB,EAAE,KAAa;IACjF,MAAM,UAAU,GAAG,qBAAqB,EAAE,CAAC;IAC3C,MAAM,QAAQ,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAE9C,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QAC9B,QAAQ,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC;IAC9B,CAAC;IACD,QAAQ,CAAC,aAAa,CAAC,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC;IAE3C,gBAAgB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;AACxC,CAAC","sourcesContent":["/**\n * Read/write extension settings to JSON files.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { getAgentDir } from \"@mariozechner/pi-coding-agent\";\n\nconst SETTINGS_FILE_NAME = \"settings-extensions.json\";\n\ntype SettingsFile = Record<string, Record<string, string>>;\n\n/**\n * Get the global settings file path.\n */\nfunction getGlobalSettingsPath(): string {\n\treturn join(getAgentDir(), SETTINGS_FILE_NAME);\n}\n\n/**\n * Load the settings file. Returns empty object if file doesn't exist or is invalid.\n */\nfunction loadSettingsFile(path: string): SettingsFile {\n\tif (!existsSync(path)) {\n\t\treturn {};\n\t}\n\ttry {\n\t\tconst content = readFileSync(path, \"utf-8\");\n\t\treturn JSON.parse(content) as SettingsFile;\n\t} catch {\n\t\treturn {};\n\t}\n}\n\n/**\n * Save settings to the global file.\n */\nfunction saveSettingsFile(path: string, settings: SettingsFile): void {\n\tconst dir = dirname(path);\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true });\n\t}\n\twriteFileSync(path, JSON.stringify(settings, null, \"\\t\"));\n}\n\n/**\n * Get a setting value for an extension.\n * Returns the stored value, or the provided default, or undefined.\n *\n * @param extensionName - Extension name\n * @param settingId - Setting ID within the extension\n * @param defaultValue - Default value if setting is not found\n * @returns The setting value\n */\nexport function getSetting(extensionName: string, settingId: string, defaultValue?: string): string | undefined {\n\tconst globalPath = getGlobalSettingsPath();\n\tconst settings = loadSettingsFile(globalPath);\n\n\t// Check if value exists in file\n\tconst extSettings = settings[extensionName];\n\tif (extSettings && settingId in extSettings) {\n\t\treturn extSettings[settingId];\n\t}\n\n\treturn defaultValue;\n}\n\n/**\n * Set a setting value for an extension.\n * Always writes to the global settings file.\n *\n * @param extensionName - Extension name\n * @param settingId - Setting ID within the extension\n * @param value - Value to set\n */\nexport function setSetting(extensionName: string, settingId: string, value: string): void {\n\tconst globalPath = getGlobalSettingsPath();\n\tconst settings = loadSettingsFile(globalPath);\n\n\tif (!settings[extensionName]) {\n\t\tsettings[extensionName] = {};\n\t}\n\tsettings[extensionName][settingId] = value;\n\n\tsaveSettingsFile(globalPath, settings);\n}\n"]}
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/settings/storage.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAE9D,MAAM,kBAAkB,GAAG,0BAA0B,CAAC;AAItD;;GAEG;AACH,SAAS,qBAAqB;IAC7B,OAAO,IAAI,CAAC,WAAW,EAAE,EAAE,kBAAkB,CAAC,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAC,IAAY;IACrC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,CAAC;IACX,CAAC;IACD,IAAI,CAAC;QACJ,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAiB,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,EAAE,CAAC;IACX,CAAC;AACF,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAC,IAAY,EAAE,QAAsB;IAC7D,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrC,CAAC;IACD,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,aAAqB,EAAE,SAAiB,EAAE,YAAqB;IACzF,MAAM,UAAU,GAAG,qBAAqB,EAAE,CAAC;IAC3C,MAAM,QAAQ,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAE9C,gCAAgC;IAChC,MAAM,WAAW,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAC;IAC5C,IAAI,WAAW,IAAI,SAAS,IAAI,WAAW,EAAE,CAAC;QAC7C,OAAO,WAAW,CAAC,SAAS,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,YAAY,CAAC;AACrB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,aAAqB,EAAE,SAAiB,EAAE,KAAa;IACjF,MAAM,UAAU,GAAG,qBAAqB,EAAE,CAAC;IAC3C,MAAM,QAAQ,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAE9C,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QAC9B,QAAQ,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC;IAC9B,CAAC;IACD,QAAQ,CAAC,aAAa,CAAC,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC;IAE3C,gBAAgB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;AACxC,CAAC","sourcesContent":["/**\n * Read/write extension settings to JSON files.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { getAgentDir } from \"@earendil-works/pi-coding-agent\";\n\nconst SETTINGS_FILE_NAME = \"settings-extensions.json\";\n\ntype SettingsFile = Record<string, Record<string, string>>;\n\n/**\n * Get the global settings file path.\n */\nfunction getGlobalSettingsPath(): string {\n\treturn join(getAgentDir(), SETTINGS_FILE_NAME);\n}\n\n/**\n * Load the settings file. Returns empty object if file doesn't exist or is invalid.\n */\nfunction loadSettingsFile(path: string): SettingsFile {\n\tif (!existsSync(path)) {\n\t\treturn {};\n\t}\n\ttry {\n\t\tconst content = readFileSync(path, \"utf-8\");\n\t\treturn JSON.parse(content) as SettingsFile;\n\t} catch {\n\t\treturn {};\n\t}\n}\n\n/**\n * Save settings to the global file.\n */\nfunction saveSettingsFile(path: string, settings: SettingsFile): void {\n\tconst dir = dirname(path);\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true });\n\t}\n\twriteFileSync(path, JSON.stringify(settings, null, \"\\t\"));\n}\n\n/**\n * Get a setting value for an extension.\n * Returns the stored value, or the provided default, or undefined.\n *\n * @param extensionName - Extension name\n * @param settingId - Setting ID within the extension\n * @param defaultValue - Default value if setting is not found\n * @returns The setting value\n */\nexport function getSetting(extensionName: string, settingId: string, defaultValue?: string): string | undefined {\n\tconst globalPath = getGlobalSettingsPath();\n\tconst settings = loadSettingsFile(globalPath);\n\n\t// Check if value exists in file\n\tconst extSettings = settings[extensionName];\n\tif (extSettings && settingId in extSettings) {\n\t\treturn extSettings[settingId];\n\t}\n\n\treturn defaultValue;\n}\n\n/**\n * Set a setting value for an extension.\n * Always writes to the global settings file.\n *\n * @param extensionName - Extension name\n * @param settingId - Setting ID within the extension\n * @param value - Value to set\n */\nexport function setSetting(extensionName: string, settingId: string, value: string): void {\n\tconst globalPath = getGlobalSettingsPath();\n\tconst settings = loadSettingsFile(globalPath);\n\n\tif (!settings[extensionName]) {\n\t\tsettings[extensionName] = {};\n\t}\n\tsettings[extensionName][settingId] = value;\n\n\tsaveSettingsFile(globalPath, settings);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juanibiapina/pi-extension-settings",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "description": "Pi extension for centralized settings management across extensions",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -39,14 +39,14 @@
39
39
  "node": ">=20.0.0"
40
40
  },
41
41
  "peerDependencies": {
42
- "@mariozechner/pi-coding-agent": "*",
43
- "@mariozechner/pi-tui": "*"
42
+ "@earendil-works/pi-coding-agent": "*",
43
+ "@earendil-works/pi-tui": "*"
44
44
  },
45
45
  "devDependencies": {
46
- "@biomejs/biome": "2.4.9",
47
- "@mariozechner/pi-coding-agent": "^0.64.0",
48
- "@types/node": "^25.5.0",
49
- "tsx": "^4.20.3",
50
- "typescript": "^6.0.2"
46
+ "@biomejs/biome": "2.4.15",
47
+ "@earendil-works/pi-coding-agent": "^0.75.3",
48
+ "@types/node": "^25.9.1",
49
+ "tsx": "^4.22.3",
50
+ "typescript": "^6.0.3"
51
51
  }
52
52
  }