@gzeoneth/gov-tracker 0.2.1-alpha.cli-preview.375ef6c → 0.2.1-alpha.cli-preview.99d3341

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.
Files changed (130) hide show
  1. package/README.md +37 -3
  2. package/dist/abis.d.ts.map +1 -1
  3. package/dist/abis.js +22 -1
  4. package/dist/abis.js.map +1 -1
  5. package/dist/cli/cli.js +206 -12
  6. package/dist/cli/cli.js.map +1 -1
  7. package/dist/cli/lib/cli.d.ts +9 -1
  8. package/dist/cli/lib/cli.d.ts.map +1 -1
  9. package/dist/cli/lib/cli.js +80 -4
  10. package/dist/cli/lib/cli.js.map +1 -1
  11. package/dist/cli/tui/hooks/index.d.ts +4 -0
  12. package/dist/cli/tui/hooks/index.d.ts.map +1 -1
  13. package/dist/cli/tui/hooks/index.js +5 -1
  14. package/dist/cli/tui/hooks/index.js.map +1 -1
  15. package/dist/cli/tui/hooks/useElectionData.d.ts +14 -0
  16. package/dist/cli/tui/hooks/useElectionData.d.ts.map +1 -0
  17. package/dist/cli/tui/hooks/useElectionData.js +86 -0
  18. package/dist/cli/tui/hooks/useElectionData.js.map +1 -0
  19. package/dist/cli/tui/hooks/useElectionDetails.d.ts +18 -0
  20. package/dist/cli/tui/hooks/useElectionDetails.d.ts.map +1 -0
  21. package/dist/cli/tui/hooks/useElectionDetails.js +47 -0
  22. package/dist/cli/tui/hooks/useElectionDetails.js.map +1 -0
  23. package/dist/cli/tui/hooks/useNavigation.d.ts.map +1 -1
  24. package/dist/cli/tui/hooks/useNavigation.js +65 -119
  25. package/dist/cli/tui/hooks/useNavigation.js.map +1 -1
  26. package/dist/cli/tui/hooks/useProposals.d.ts.map +1 -1
  27. package/dist/cli/tui/hooks/useProposals.js +74 -80
  28. package/dist/cli/tui/hooks/useProposals.js.map +1 -1
  29. package/dist/cli/tui/hooks/useTracker.d.ts.map +1 -1
  30. package/dist/cli/tui/hooks/useTracker.js +36 -41
  31. package/dist/cli/tui/hooks/useTracker.js.map +1 -1
  32. package/dist/cli/tui/utils/calldata-formatter.d.ts +17 -0
  33. package/dist/cli/tui/utils/calldata-formatter.d.ts.map +1 -0
  34. package/dist/cli/tui/utils/calldata-formatter.js +91 -0
  35. package/dist/cli/tui/utils/calldata-formatter.js.map +1 -0
  36. package/dist/cli/tui/utils/help-data.d.ts +15 -0
  37. package/dist/cli/tui/utils/help-data.d.ts.map +1 -0
  38. package/dist/cli/tui/utils/help-data.js +88 -0
  39. package/dist/cli/tui/utils/help-data.js.map +1 -0
  40. package/dist/cli/tui/utils/index.d.ts +11 -0
  41. package/dist/cli/tui/utils/index.d.ts.map +1 -1
  42. package/dist/cli/tui/utils/index.js +24 -1
  43. package/dist/cli/tui/utils/index.js.map +1 -1
  44. package/dist/cli/tui/utils/markdown-parser.d.ts +11 -0
  45. package/dist/cli/tui/utils/markdown-parser.d.ts.map +1 -0
  46. package/dist/cli/tui/utils/markdown-parser.js +100 -0
  47. package/dist/cli/tui/utils/markdown-parser.js.map +1 -0
  48. package/dist/cli/tui/utils/proposal-detail-helpers.d.ts +17 -0
  49. package/dist/cli/tui/utils/proposal-detail-helpers.d.ts.map +1 -0
  50. package/dist/cli/tui/utils/proposal-detail-helpers.js +46 -0
  51. package/dist/cli/tui/utils/proposal-detail-helpers.js.map +1 -0
  52. package/dist/cli/tui/utils/settings-data.d.ts +36 -0
  53. package/dist/cli/tui/utils/settings-data.d.ts.map +1 -0
  54. package/dist/cli/tui/utils/settings-data.js +220 -0
  55. package/dist/cli/tui/utils/settings-data.js.map +1 -0
  56. package/dist/cli/tui/utils/stage-formatter.d.ts +13 -0
  57. package/dist/cli/tui/utils/stage-formatter.d.ts.map +1 -0
  58. package/dist/cli/tui/utils/stage-formatter.js +100 -0
  59. package/dist/cli/tui/utils/stage-formatter.js.map +1 -0
  60. package/dist/cli/tui/views/CalldataView.d.ts.map +1 -1
  61. package/dist/cli/tui/views/CalldataView.js +50 -117
  62. package/dist/cli/tui/views/CalldataView.js.map +1 -1
  63. package/dist/cli/tui/views/DescriptionView.d.ts.map +1 -1
  64. package/dist/cli/tui/views/DescriptionView.js +1 -85
  65. package/dist/cli/tui/views/DescriptionView.js.map +1 -1
  66. package/dist/cli/tui/views/ElectionView.d.ts.map +1 -1
  67. package/dist/cli/tui/views/ElectionView.js +268 -165
  68. package/dist/cli/tui/views/ElectionView.js.map +1 -1
  69. package/dist/cli/tui/views/HelpView.d.ts.map +1 -1
  70. package/dist/cli/tui/views/HelpView.js +1 -73
  71. package/dist/cli/tui/views/HelpView.js.map +1 -1
  72. package/dist/cli/tui/views/ProposalDetail.d.ts.map +1 -1
  73. package/dist/cli/tui/views/ProposalDetail.js +51 -78
  74. package/dist/cli/tui/views/ProposalDetail.js.map +1 -1
  75. package/dist/cli/tui/views/ProposalList.d.ts.map +1 -1
  76. package/dist/cli/tui/views/ProposalList.js +73 -64
  77. package/dist/cli/tui/views/ProposalList.js.map +1 -1
  78. package/dist/cli/tui/views/SettingsView.d.ts.map +1 -1
  79. package/dist/cli/tui/views/SettingsView.js +67 -122
  80. package/dist/cli/tui/views/SettingsView.js.map +1 -1
  81. package/dist/cli/tui/views/SimulationView.d.ts.map +1 -1
  82. package/dist/cli/tui/views/SimulationView.js +23 -20
  83. package/dist/cli/tui/views/SimulationView.js.map +1 -1
  84. package/dist/cli/tui/views/StageView.d.ts.map +1 -1
  85. package/dist/cli/tui/views/StageView.js +28 -114
  86. package/dist/cli/tui/views/StageView.js.map +1 -1
  87. package/dist/deduplication.d.ts +132 -0
  88. package/dist/deduplication.d.ts.map +1 -0
  89. package/dist/deduplication.js +270 -0
  90. package/dist/deduplication.js.map +1 -0
  91. package/dist/election.d.ts +141 -1
  92. package/dist/election.d.ts.map +1 -1
  93. package/dist/election.js +505 -88
  94. package/dist/election.js.map +1 -1
  95. package/dist/index.d.ts +4 -2
  96. package/dist/index.d.ts.map +1 -1
  97. package/dist/index.js +27 -3
  98. package/dist/index.js.map +1 -1
  99. package/dist/stages/builder.d.ts +4 -0
  100. package/dist/stages/builder.d.ts.map +1 -1
  101. package/dist/stages/builder.js +7 -0
  102. package/dist/stages/builder.js.map +1 -1
  103. package/dist/stages/voting.d.ts.map +1 -1
  104. package/dist/stages/voting.js +5 -4
  105. package/dist/stages/voting.js.map +1 -1
  106. package/dist/tracker/discovery.d.ts +39 -8
  107. package/dist/tracker/discovery.d.ts.map +1 -1
  108. package/dist/tracker/discovery.js +141 -12
  109. package/dist/tracker/discovery.js.map +1 -1
  110. package/dist/tracker.d.ts +24 -4
  111. package/dist/tracker.d.ts.map +1 -1
  112. package/dist/tracker.js +57 -8
  113. package/dist/tracker.js.map +1 -1
  114. package/dist/types/core.d.ts +1 -1
  115. package/dist/types/core.d.ts.map +1 -1
  116. package/dist/types/election.d.ts +88 -0
  117. package/dist/types/election.d.ts.map +1 -1
  118. package/dist/types/index.d.ts +2 -2
  119. package/dist/types/index.d.ts.map +1 -1
  120. package/dist/types/index.js.map +1 -1
  121. package/dist/types/stages.d.ts +6 -0
  122. package/dist/types/stages.d.ts.map +1 -1
  123. package/dist/types/stages.js.map +1 -1
  124. package/dist/types/tracking.d.ts +27 -1
  125. package/dist/types/tracking.d.ts.map +1 -1
  126. package/dist/utils/timing.d.ts +13 -0
  127. package/dist/utils/timing.d.ts.map +1 -1
  128. package/dist/utils/timing.js +35 -0
  129. package/dist/utils/timing.js.map +1 -1
  130. package/package.json +1 -1
@@ -19,90 +19,6 @@ function getDescription(proposal) {
19
19
  }
20
20
  return "No description available";
21
21
  }
22
- function parseMarkdown(text, width) {
23
- const result = [];
24
- const lines = text.split("\n");
25
- // Guard against very narrow terminals
26
- const safeWidth = Math.max(20, width);
27
- for (const rawLine of lines) {
28
- const trimmed = rawLine.trim();
29
- // Empty line
30
- if (trimmed.length === 0) {
31
- result.push({ text: "", type: "normal", indent: 0 });
32
- continue;
33
- }
34
- // Horizontal rule
35
- if (/^[-*_]{3,}$/.test(trimmed)) {
36
- result.push({ text: "─".repeat(Math.min(safeWidth - 4, 60)), type: "separator", indent: 0 });
37
- continue;
38
- }
39
- // Headers
40
- if (trimmed.startsWith("### ")) {
41
- result.push({ text: trimmed.slice(4), type: "h3", indent: 0 });
42
- continue;
43
- }
44
- if (trimmed.startsWith("## ")) {
45
- result.push({ text: trimmed.slice(3), type: "h2", indent: 0 });
46
- continue;
47
- }
48
- if (trimmed.startsWith("# ")) {
49
- result.push({ text: trimmed.slice(2), type: "h1", indent: 0 });
50
- continue;
51
- }
52
- // Bullet points
53
- if (/^[-*+] /.test(trimmed)) {
54
- const bulletText = trimmed.slice(2);
55
- wrapTextToLines(bulletText, safeWidth - 6, "bullet", 2, result);
56
- continue;
57
- }
58
- // Numbered lists
59
- if (/^\d+\. /.test(trimmed)) {
60
- const match = trimmed.match(/^(\d+)\. /);
61
- if (match) {
62
- const numText = trimmed.slice(match[0].length);
63
- const textWidth = safeWidth - 6;
64
- result.push({ text: `${match[1]}. ${numText.slice(0, textWidth)}`, type: "bullet", indent: 0 });
65
- if (numText.length > textWidth) {
66
- wrapTextToLines(numText.slice(textWidth), textWidth, "normal", 3, result);
67
- }
68
- continue;
69
- }
70
- }
71
- // Code blocks (just show as-is with code styling)
72
- if (trimmed.startsWith("```")) {
73
- continue; // Skip code fence markers
74
- }
75
- // Links - simplify [text](url) to just text
76
- const processedLine = trimmed.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1");
77
- // Normal paragraph
78
- wrapTextToLines(processedLine, safeWidth - 4, "normal", 0, result);
79
- }
80
- return result;
81
- }
82
- function wrapTextToLines(text, width, type, indent, result) {
83
- const safeWidth = Math.max(10, width);
84
- const words = text.split(/\s+/);
85
- let currentLine = "";
86
- for (const word of words) {
87
- if (currentLine.length === 0) {
88
- currentLine = word;
89
- }
90
- else if (currentLine.length + 1 + word.length <= safeWidth) {
91
- currentLine += " " + word;
92
- }
93
- else {
94
- result.push({ text: currentLine, type, indent });
95
- currentLine = word;
96
- // Continuation lines of bullets get extra indent
97
- if (type === "bullet" && indent === 2) {
98
- indent = 4;
99
- }
100
- }
101
- }
102
- if (currentLine.length > 0) {
103
- result.push({ text: currentLine, type, indent });
104
- }
105
- }
106
22
  const RESERVED_LINES = 8;
107
23
  function FormattedLineComponent({ line }) {
108
24
  const indent = " ".repeat(line.indent);
@@ -139,7 +55,7 @@ function DescriptionView({ proposal, navigation, }) {
139
55
  const { state } = navigation;
140
56
  const description = getDescription(proposal);
141
57
  const terminalWidth = process.stdout.columns || 80;
142
- const lines = (0, ink_wrapper_js_1.useMemo)(() => parseMarkdown(description, terminalWidth - 4), [description, terminalWidth]);
58
+ const lines = (0, ink_wrapper_js_1.useMemo)(() => (0, index_js_1.parseMarkdown)(description, terminalWidth - 4), [description, terminalWidth]);
143
59
  const visibleCount = (0, index_js_1.getVisibleRows)(RESERVED_LINES);
144
60
  const visibleLines = lines.slice(state.scrollOffset, state.scrollOffset + visibleCount);
145
61
  (0, ink_wrapper_js_1.useInput)((input, key) => {
@@ -1 +1 @@
1
- {"version":3,"file":"DescriptionView.js","sourceRoot":"","sources":["../../../../src/cli/tui/views/DescriptionView.tsx"],"names":[],"mappings":";AAAA;;GAEG;;AAiLH,0CA+DC;AA9OD,sDAAkF;AAGlF,+DAAyD;AACzD,yEAI0C;AAC1C,gDAAmD;AAanD,SAAS,cAAc,CAAC,QAA0B;IAChD,MAAM,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,eAAe,IAAI,EAAE,CAAC;IACpE,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,kBAAkB,CAAC,CAAC;IAEvE,IAAI,YAAY,EAAE,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,YAAY,CAAC,IAAgC,CAAC;QAC3D,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC,WAAW,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,OAAO,0BAA0B,CAAC;AACpC,CAAC;AAED,SAAS,aAAa,CAAC,IAAY,EAAE,KAAa;IAChD,MAAM,MAAM,GAAoB,EAAE,CAAC;IACnC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,sCAAsC;IACtC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAEtC,KAAK,MAAM,OAAO,IAAI,KAAK,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAE/B,aAAa;QACb,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;YACrD,SAAS;QACX,CAAC;QAED,kBAAkB;QAClB,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAChC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;YAC7F,SAAS;QACX,CAAC;QAED,UAAU;QACV,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/B,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;YAC/D,SAAS;QACX,CAAC;QACD,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;YAC/D,SAAS;QACX,CAAC;QACD,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;YAC/D,SAAS;QACX,CAAC;QAED,gBAAgB;QAChB,IAAI,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACpC,eAAe,CAAC,UAAU,EAAE,SAAS,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;YAChE,SAAS;QACX,CAAC;QAED,iBAAiB;QACjB,IAAI,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YACzC,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;gBAC/C,MAAM,SAAS,GAAG,SAAS,GAAG,CAAC,CAAC;gBAChC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;gBAChG,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;oBAC/B,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;gBAC5E,CAAC;gBACD,SAAS;YACX,CAAC;QACH,CAAC;QAED,kDAAkD;QAClD,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9B,SAAS,CAAC,0BAA0B;QACtC,CAAC;QAED,4CAA4C;QAC5C,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,wBAAwB,EAAE,IAAI,CAAC,CAAC;QAEtE,mBAAmB;QACnB,eAAe,CAAC,aAAa,EAAE,SAAS,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;IACrE,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,eAAe,CACtB,IAAY,EACZ,KAAa,EACb,IAA2B,EAC3B,MAAc,EACd,MAAuB;IAEvB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IACtC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,WAAW,GAAG,EAAE,CAAC;IAErB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,WAAW,GAAG,IAAI,CAAC;QACrB,CAAC;aAAM,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC;YAC7D,WAAW,IAAI,GAAG,GAAG,IAAI,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;YACjD,WAAW,GAAG,IAAI,CAAC;YACnB,iDAAiD;YACjD,IAAI,IAAI,KAAK,QAAQ,IAAI,MAAM,KAAK,CAAC,EAAE,CAAC;gBACtC,MAAM,GAAG,CAAC,CAAC;YACb,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACnD,CAAC;AACH,CAAC;AAED,MAAM,cAAc,GAAG,CAAC,CAAC;AAEzB,SAAS,sBAAsB,CAAC,EAAE,IAAI,EAA2B;IAC/D,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEvC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,IAAI;YACP,OAAO,CACL,qCAAC,qBAAI,IAAC,IAAI,QAAC,KAAK,EAAC,MAAM;gBACpB,MAAM;;gBAAI,IAAI,CAAC,IAAI,CACf,CACR,CAAC;QACJ,KAAK,IAAI;YACP,OAAO,CACL,qCAAC,qBAAI,IAAC,IAAI,QAAC,KAAK,EAAC,QAAQ;gBACtB,MAAM;;gBAAI,IAAI,CAAC,IAAI,CACf,CACR,CAAC;QACJ,KAAK,IAAI;YACP,OAAO,CACL,qCAAC,qBAAI,IAAC,IAAI;gBACP,MAAM;;gBAAI,IAAI,CAAC,IAAI,CACf,CACR,CAAC;QACJ,KAAK,QAAQ;YACX,OAAO,CACL,qCAAC,qBAAI;gBACF,MAAM;;gBAAI,IAAI,CAAC,IAAI,CACf,CACR,CAAC;QACJ,KAAK,WAAW;YACd,OAAO,qCAAC,qBAAI,IAAC,KAAK,EAAC,MAAM,IAAE,IAAI,CAAC,IAAI,CAAQ,CAAC;QAC/C;YACE,OAAO,qCAAC,qBAAI;gBAAE,MAAM;gBAAE,IAAI,CAAC,IAAI,CAAQ,CAAC;IAC5C,CAAC;AACH,CAAC;AAED,SAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,UAAU,GACW;IACrB,MAAM,EAAE,KAAK,EAAE,GAAG,UAAU,CAAC;IAC7B,MAAM,WAAW,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;IACnD,MAAM,KAAK,GAAG,IAAA,wBAAO,EACnB,GAAG,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,aAAa,GAAG,CAAC,CAAC,EACnD,CAAC,WAAW,EAAE,aAAa,CAAC,CAC7B,CAAC;IACF,MAAM,YAAY,GAAG,IAAA,yBAAc,EAAC,cAAc,CAAC,CAAC;IACpD,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,YAAY,GAAG,YAAY,CAAC,CAAC;IAExF,IAAA,yBAAQ,EAAC,CAAC,KAAa,EAAE,GAAa,EAAE,EAAE;QACxC,IAAI,KAAK,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;YAChC,UAAU,CAAC,IAAI,EAAE,CAAC;QACpB,CAAC;aAAM,IAAI,GAAG,CAAC,OAAO,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;YACxC,UAAU,CAAC,MAAM,EAAE,CAAC;QACtB,CAAC;aAAM,IAAI,GAAG,CAAC,SAAS,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;YAC1C,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACpC,CAAC;aAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,KAAK,KAAK,GAAG,CAAC,EAAE,CAAC;YACrD,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAClC,CAAC;aAAM,IAAI,GAAG,CAAC,QAAQ,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,KAAK,KAAK,GAAG,CAAC,EAAE,CAAC;YACvD,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACpC,CAAC;aAAM,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;YACzB,UAAU,CAAC,OAAO,EAAE,CAAC;QACvB,CAAC;aAAM,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;YACzB,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACtC,CAAC;aAAM,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;YACzB,UAAU,CAAC,QAAQ,EAAE,CAAC;QACxB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,EAAE;QAC3C,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK;QACzC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;IAEnB,MAAM,UAAU,GAAG,CAAC,WAAW,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;IAE5D,OAAO,CACL,qCAAC,0BAAU,IAAC,IAAI,EAAC,aAAa,EAAC,KAAK,EAAC,sBAAsB,EAAC,UAAU,EAAE,UAAU;QAC/E,KAAK,CAAC,MAAM,GAAG,YAAY,IAAI,CAC9B,qCAAC,oBAAG,IAAC,YAAY,EAAE,CAAC;YAClB,qCAAC,mCAAc,IACb,YAAY,EAAE,KAAK,CAAC,YAAY,EAChC,WAAW,EAAE,YAAY,EACzB,UAAU,EAAE,KAAK,CAAC,MAAM,GACxB,CACE,CACP;QACD,qCAAC,uCAAkB,IAAC,YAAY,EAAE,KAAK,CAAC,YAAY,EAAE,IAAI,EAAC,OAAO,GAAG;QACpE,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAC7B,qCAAC,sBAAsB,IAAC,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,GAAI,CAC/C,CAAC;QACF,qCAAC,0CAAqB,IACpB,YAAY,EAAE,KAAK,CAAC,YAAY,EAChC,WAAW,EAAE,YAAY,EACzB,UAAU,EAAE,KAAK,CAAC,MAAM,EACxB,IAAI,EAAC,OAAO,GACZ,CACS,CACd,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"DescriptionView.js","sourceRoot":"","sources":["../../../../src/cli/tui/views/DescriptionView.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ElectionView.d.ts","sourceRoot":"","sources":["../../../../src/cli/tui/views/ElectionView.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAKvD,UAAU,iBAAiB;IACzB,UAAU,EAAE,mBAAmB,CAAC;IAChC,SAAS,CAAC,EAAE,cAAc,CAAC;CAC5B;AA8BD,wBAAgB,YAAY,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,iBAAiB,GAAG,KAAK,CAAC,YAAY,CA8J7F"}
1
+ {"version":3,"file":"ElectionView.d.ts","sourceRoot":"","sources":["../../../../src/cli/tui/views/ElectionView.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAiBvD,UAAU,iBAAiB;IACzB,UAAU,EAAE,mBAAmB,CAAC;IAChC,SAAS,CAAC,EAAE,cAAc,CAAC;CAC5B;AA4MD,wBAAgB,YAAY,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,iBAAiB,GAAG,KAAK,CAAC,YAAY,CAsK7F"}
@@ -5,193 +5,296 @@
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.ElectionView = ElectionView;
7
7
  const ink_wrapper_js_1 = require("../ink-wrapper.js");
8
- const react_1 = require("react");
9
8
  const ViewLayout_js_1 = require("../components/ViewLayout.js");
10
- const election_js_1 = require("../../../election.js");
9
+ const ScrollIndicator_js_1 = require("../components/ScrollIndicator.js");
10
+ const index_js_1 = require("../utils/index.js");
11
+ const useElectionData_js_1 = require("../hooks/useElectionData.js");
12
+ const useElectionDetails_js_1 = require("../hooks/useElectionDetails.js");
13
+ const PHASE_COLORS = {
14
+ COMPLETED: "green",
15
+ MEMBER_ELECTION: "yellow",
16
+ NOMINEE_SELECTION: "yellow",
17
+ VETTING_PERIOD: "cyan",
18
+ PENDING_EXECUTION: "magenta",
19
+ NOT_STARTED: "gray",
20
+ };
21
+ const PHASE_ICONS = {
22
+ COMPLETED: "✓",
23
+ MEMBER_ELECTION: "●",
24
+ NOMINEE_SELECTION: "●",
25
+ VETTING_PERIOD: "◐",
26
+ PENDING_EXECUTION: "→",
27
+ NOT_STARTED: "○",
28
+ };
11
29
  function formatTimestamp(ts) {
12
30
  return new Date(ts * 1000).toLocaleString();
13
31
  }
14
- function PhaseIcon({ phase }) {
15
- switch (phase) {
16
- case "COMPLETED":
17
- return ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: "green" }, "\u2713");
18
- case "MEMBER_ELECTION":
19
- case "NOMINEE_SELECTION":
20
- return ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: "yellow" }, "\u25CF");
21
- case "VETTING_PERIOD":
22
- return ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: "cyan" }, "\u25D0");
23
- case "PENDING_EXECUTION":
24
- return ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: "magenta" }, "\u2192");
25
- default:
26
- return ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: "gray" }, "\u25CB");
32
+ function formatVotes(votes) {
33
+ const str = votes.toString();
34
+ const WEI_DECIMALS = 18;
35
+ if (str.length <= WEI_DECIMALS)
36
+ return str;
37
+ const intPart = str.slice(0, str.length - WEI_DECIMALS);
38
+ return intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
39
+ }
40
+ function buildStatusLines(status) {
41
+ const lines = [];
42
+ const cohortName = status.cohort === 0 ? "FIRST" : "SECOND";
43
+ lines.push({ text: "Security Council Election Status", bold: true });
44
+ lines.push({ text: ` Election Count: ${status.electionCount}` });
45
+ lines.push({ text: ` Current Cohort: ${cohortName}`, color: status.cohort === 0 ? "cyan" : "magenta" });
46
+ lines.push({ text: ` Can Create: ${status.canCreateElection ? "Yes" : "No"}`, color: status.canCreateElection ? "green" : "gray" });
47
+ if (!status.canCreateElection) {
48
+ lines.push({ text: ` Next Election: ${formatTimestamp(status.nextElectionTimestamp)} (${status.timeUntilElection})` });
49
+ }
50
+ lines.push({ text: "" });
51
+ return lines;
52
+ }
53
+ function buildListLines(proposals, selectedIndex) {
54
+ const lines = [];
55
+ for (let i = 0; i < proposals.length; i++) {
56
+ const election = proposals[i];
57
+ const isSelected = i === selectedIndex;
58
+ const icon = PHASE_ICONS[election.phase] ?? "○";
59
+ const phaseColor = PHASE_COLORS[election.phase] ?? "gray";
60
+ const prefix = isSelected ? "> " : " ";
61
+ const phaseName = election.phase.replace(/_/g, " ");
62
+ lines.push({
63
+ text: `${prefix}${icon} Election #${election.electionIndex} - ${phaseName}`,
64
+ color: isSelected ? "cyan" : phaseColor,
65
+ bold: isSelected,
66
+ });
67
+ if (isSelected) {
68
+ const cohortName = election.cohort === 0 ? "FIRST" : "SECOND";
69
+ lines.push({ text: ` Cohort: ${cohortName}`, color: "gray" });
70
+ if (election.nomineeProposalId) {
71
+ lines.push({ text: ` Nominee State: ${election.nomineeProposalState}`, color: "gray" });
72
+ }
73
+ if (election.memberProposalId) {
74
+ lines.push({ text: ` Member State: ${election.memberProposalState}`, color: "gray" });
75
+ }
76
+ const nomineeColor = election.compliantNomineeCount >= election.targetNomineeCount ? "green" : "yellow";
77
+ lines.push({
78
+ text: ` Compliant Nominees: ${election.compliantNomineeCount}/${election.targetNomineeCount}`,
79
+ color: nomineeColor,
80
+ });
81
+ if (election.isInVettingPeriod) {
82
+ lines.push({ text: ` In vetting period until block ${election.vettingDeadline}`, color: "cyan" });
83
+ }
84
+ if (election.canProceedToMemberPhase) {
85
+ lines.push({ text: " Ready to trigger member election!", color: "green" });
86
+ }
87
+ if (election.canExecuteMember) {
88
+ lines.push({ text: " Ready to execute member election!", color: "green" });
89
+ }
90
+ }
91
+ }
92
+ return lines;
93
+ }
94
+ function buildDetailLines(election, nomineeDetails, memberDetails) {
95
+ const lines = [];
96
+ const icon = PHASE_ICONS[election.phase] ?? "○";
97
+ const phaseColor = PHASE_COLORS[election.phase] ?? "gray";
98
+ const phaseName = election.phase.replace(/_/g, " ");
99
+ const cohortName = election.cohort === 0 ? "FIRST" : "SECOND";
100
+ lines.push({ text: `${icon} Election #${election.electionIndex} - ${phaseName}`, color: phaseColor, bold: true });
101
+ lines.push({ text: "" });
102
+ lines.push({ text: ` Cohort: ${cohortName}` });
103
+ if (election.nomineeProposalId) {
104
+ lines.push({ text: ` Nominee Proposal ID: ${election.nomineeProposalId}`, dimColor: true });
105
+ }
106
+ if (election.memberProposalId) {
107
+ lines.push({ text: ` Member Proposal ID: ${election.memberProposalId}`, dimColor: true });
108
+ }
109
+ if (nomineeDetails) {
110
+ lines.push({ text: "" });
111
+ lines.push({ text: " ── Nominee Phase ──", color: "cyan", bold: true });
112
+ lines.push({ text: ` Quorum: ${formatVotes(nomineeDetails.quorumThreshold)} votes` });
113
+ lines.push({ text: ` Target: ${nomineeDetails.targetNomineeCount} nominees needed` });
114
+ if (nomineeDetails.contenders.length > 0) {
115
+ lines.push({ text: "" });
116
+ lines.push({ text: ` Contenders (${nomineeDetails.contenders.length})`, color: "yellow" });
117
+ for (const contender of nomineeDetails.contenders.slice(0, 10)) {
118
+ lines.push({ text: ` ${contender.address} (block ${contender.registeredAtBlock})`, color: "gray" });
119
+ }
120
+ if (nomineeDetails.contenders.length > 10) {
121
+ lines.push({ text: ` ... and ${nomineeDetails.contenders.length - 10} more`, color: "gray" });
122
+ }
123
+ }
124
+ if (nomineeDetails.compliantNominees.length > 0) {
125
+ lines.push({ text: "" });
126
+ lines.push({ text: ` Qualified Nominees (${nomineeDetails.compliantNominees.length})`, color: "green" });
127
+ for (const nominee of nomineeDetails.compliantNominees.slice(0, 10)) {
128
+ lines.push({ text: ` ${nominee.address} ${formatVotes(nominee.votesReceived)} votes`, color: "gray" });
129
+ }
130
+ if (nomineeDetails.compliantNominees.length > 10) {
131
+ lines.push({ text: ` ... and ${nomineeDetails.compliantNominees.length - 10} more`, color: "gray" });
132
+ }
133
+ }
134
+ if (nomineeDetails.excludedNominees.length > 0) {
135
+ lines.push({ text: "" });
136
+ lines.push({ text: ` Excluded (${nomineeDetails.excludedNominees.length})`, color: "red" });
137
+ for (const nominee of nomineeDetails.excludedNominees.slice(0, 5)) {
138
+ lines.push({ text: ` ${nominee.address} (excluded)`, color: "gray" });
139
+ }
140
+ if (nomineeDetails.excludedNominees.length > 5) {
141
+ lines.push({ text: ` ... and ${nomineeDetails.excludedNominees.length - 5} more`, color: "gray" });
142
+ }
143
+ }
27
144
  }
145
+ if (memberDetails) {
146
+ lines.push({ text: "" });
147
+ lines.push({ text: " ── Member Phase ──", color: "magenta", bold: true });
148
+ lines.push({ text: ` Full Weight Deadline: block ${memberDetails.fullWeightDeadline}` });
149
+ lines.push({ text: ` Proposal Deadline: block ${memberDetails.proposalDeadline}` });
150
+ if (memberDetails.nominees.length > 0) {
151
+ lines.push({ text: "" });
152
+ lines.push({ text: ` Candidates by Weight (${memberDetails.nominees.length})`, color: "yellow" });
153
+ for (const nominee of memberDetails.nominees.slice(0, 12)) {
154
+ const rank = `#${nominee.rank.toString().padStart(2)}`;
155
+ const winner = nominee.isWinner ? " [WINNER]" : "";
156
+ const color = nominee.isWinner ? "green" : "gray";
157
+ lines.push({ text: ` ${rank} ${nominee.address} ${formatVotes(nominee.weightReceived)}${winner}`, color });
158
+ }
159
+ if (memberDetails.nominees.length > 12) {
160
+ lines.push({ text: ` ... and ${memberDetails.nominees.length - 12} more`, color: "gray" });
161
+ }
162
+ }
163
+ if (memberDetails.winners.length > 0) {
164
+ lines.push({ text: "" });
165
+ lines.push({ text: ` Elected Members (${memberDetails.winners.length})`, color: "green" });
166
+ for (const winner of memberDetails.winners) {
167
+ lines.push({ text: ` ✓ ${winner}`, color: "green" });
168
+ }
169
+ }
170
+ }
171
+ return lines;
28
172
  }
173
+ const RESERVED_LINES = 8;
29
174
  function ElectionView({ navigation, providers }) {
30
- const [data, setData] = (0, react_1.useState)({
31
- status: null,
32
- proposals: [],
33
- loading: true,
34
- error: null,
35
- warning: null,
36
- });
37
- const [selectedIndex, setSelectedIndex] = (0, react_1.useState)(0);
38
- // Reset selection when proposals change to avoid out-of-bounds index
39
- (0, react_1.useEffect)(() => {
175
+ const data = (0, useElectionData_js_1.useElectionData)(providers);
176
+ const { details, loadDetails, clearDetails } = (0, useElectionDetails_js_1.useElectionDetails)(providers);
177
+ const [selectedIndex, setSelectedIndex] = (0, ink_wrapper_js_1.useState)(0);
178
+ const [showDetails, setShowDetails] = (0, ink_wrapper_js_1.useState)(false);
179
+ const [scrollOffset, setScrollOffset] = (0, ink_wrapper_js_1.useState)(0);
180
+ (0, ink_wrapper_js_1.useEffect)(() => {
40
181
  setSelectedIndex(0);
41
- }, [data.proposals.length]);
42
- (0, react_1.useEffect)(() => {
43
- if (!providers) {
44
- setData({
45
- status: null,
46
- proposals: [],
47
- loading: false,
48
- error: "RPC providers required. Use --l2-rpc and --l1-rpc options.",
49
- warning: null,
50
- });
51
- return;
182
+ setShowDetails(false);
183
+ setScrollOffset(0);
184
+ clearDetails();
185
+ }, [data.proposals.length, clearDetails]);
186
+ const selectedElection = data.proposals[selectedIndex];
187
+ const lines = (0, ink_wrapper_js_1.useMemo)(() => {
188
+ const result = [];
189
+ const selected = data.proposals[selectedIndex];
190
+ if (data.status) {
191
+ result.push(...buildStatusLines(data.status));
52
192
  }
53
- let cancelled = false;
54
- const loadElectionData = async () => {
55
- try {
56
- setData((prev) => ({ ...prev, loading: true, error: null }));
57
- const status = await (0, election_js_1.checkElectionStatus)(providers.l2Provider, providers.l1Provider);
58
- if (cancelled)
59
- return;
60
- const proposals = [];
61
- let failedCount = 0;
62
- if (status.electionCount > 0) {
63
- const startIndex = Math.max(1, status.electionCount - 2);
64
- for (let i = status.electionCount; i >= startIndex; i--) {
65
- if (cancelled)
66
- return;
67
- try {
68
- const proposal = await (0, election_js_1.trackElectionProposal)(i, providers.l2Provider, providers.l1Provider);
69
- proposals.push(proposal);
70
- }
71
- catch {
72
- failedCount++;
73
- }
74
- }
75
- }
76
- if (!cancelled) {
77
- setData({
78
- status,
79
- proposals,
80
- loading: false,
81
- error: failedCount > 0 && proposals.length === 0
82
- ? `Failed to load ${failedCount} election(s)`
83
- : null,
84
- warning: failedCount > 0 && proposals.length > 0
85
- ? `Loaded ${proposals.length} election(s), ${failedCount} failed`
86
- : null,
87
- });
88
- }
89
- }
90
- catch (err) {
91
- if (!cancelled) {
92
- setData({
93
- status: null,
94
- proposals: [],
95
- loading: false,
96
- error: err instanceof Error ? err.message : String(err),
97
- warning: null,
98
- });
99
- }
100
- }
101
- };
102
- loadElectionData();
103
- return () => {
104
- cancelled = true;
105
- };
106
- }, [providers]);
107
- (0, ink_wrapper_js_1.useInput)((input, key) => {
108
- if (input === "b" || key.escape) {
193
+ const headerText = showDetails ? "Recent Elections • Press b to go back" : "Recent Elections • Press Enter for details";
194
+ result.push({ text: headerText, bold: true });
195
+ result.push({ text: "" });
196
+ if (data.proposals.length === 0) {
197
+ result.push({ text: " No elections found", color: "gray" });
198
+ }
199
+ else if (showDetails && selected) {
200
+ if (details.loading) {
201
+ result.push({ text: " Loading election details...", color: "cyan" });
202
+ }
203
+ else if (details.error) {
204
+ result.push({ text: ` Error: ${details.error}`, color: "red" });
205
+ }
206
+ else {
207
+ result.push(...buildDetailLines(selected, details.nomineeDetails, details.memberDetails));
208
+ }
209
+ }
210
+ else {
211
+ result.push(...buildListLines(data.proposals, selectedIndex));
212
+ }
213
+ return result;
214
+ }, [data.status, data.proposals, selectedIndex, showDetails, details]);
215
+ const visibleCount = (0, index_js_1.getVisibleRows)(RESERVED_LINES);
216
+ const visibleLines = lines.slice(scrollOffset, scrollOffset + visibleCount);
217
+ const hasMore = scrollOffset + visibleCount < lines.length;
218
+ const hasLess = scrollOffset > 0;
219
+ const handleBackOrEscape = () => {
220
+ if (showDetails) {
221
+ setShowDetails(false);
222
+ setScrollOffset(0);
223
+ clearDetails();
224
+ }
225
+ else {
109
226
  navigation.back();
110
227
  }
111
- else if (key.upArrow || input === "k") {
228
+ };
229
+ const handleDetailScroll = (input, key) => {
230
+ const maxOffset = Math.max(0, lines.length - visibleCount);
231
+ const PAGE_SIZE = 10;
232
+ if (key.upArrow || input === "k") {
233
+ setScrollOffset((prev) => Math.max(0, prev - 1));
234
+ }
235
+ else if (key.downArrow || input === "j") {
236
+ setScrollOffset((prev) => Math.min(maxOffset, prev + 1));
237
+ }
238
+ else if (key.pageUp || (key.ctrl && input === "u")) {
239
+ setScrollOffset((prev) => Math.max(0, prev - PAGE_SIZE));
240
+ }
241
+ else if (key.pageDown || (key.ctrl && input === "d")) {
242
+ setScrollOffset((prev) => Math.min(maxOffset, prev + PAGE_SIZE));
243
+ }
244
+ else if (input === "g") {
245
+ setScrollOffset(0);
246
+ }
247
+ else if (input === "G") {
248
+ setScrollOffset(maxOffset);
249
+ }
250
+ };
251
+ const handleListNavigation = (input, key) => {
252
+ if (data.proposals.length === 0)
253
+ return;
254
+ const maxIndex = data.proposals.length - 1;
255
+ if (key.upArrow || input === "k") {
112
256
  setSelectedIndex((prev) => Math.max(0, prev - 1));
113
257
  }
114
- else if ((key.downArrow || input === "j") && data.proposals.length > 0) {
115
- setSelectedIndex((prev) => Math.min(data.proposals.length - 1, prev + 1));
258
+ else if (key.downArrow || input === "j") {
259
+ setSelectedIndex((prev) => Math.min(maxIndex, prev + 1));
116
260
  }
117
261
  else if (input === "g") {
118
262
  setSelectedIndex(0);
119
263
  }
120
- else if (input === "G" && data.proposals.length > 0) {
121
- setSelectedIndex(data.proposals.length - 1);
264
+ else if (input === "G") {
265
+ setSelectedIndex(maxIndex);
266
+ }
267
+ else if ((key.return || input === "l") && selectedElection && providers) {
268
+ setShowDetails(true);
269
+ setScrollOffset(0);
270
+ loadDetails(selectedElection.electionIndex);
271
+ }
272
+ };
273
+ (0, ink_wrapper_js_1.useInput)((input, key) => {
274
+ if (input === "b" || key.escape) {
275
+ handleBackOrEscape();
276
+ return;
122
277
  }
123
- else if (input === "?") {
278
+ if (input === "?") {
124
279
  navigation.goToHelp();
280
+ return;
281
+ }
282
+ if (showDetails) {
283
+ handleDetailScroll(input, key);
284
+ }
285
+ else {
286
+ handleListNavigation(input, key);
125
287
  }
126
288
  });
127
- const { status, proposals, warning } = data;
128
- return (ink_wrapper_js_1.React.createElement(ViewLayout_js_1.ViewLayout, { view: "election", hasProviders: !!providers, isTracking: data.loading, loading: data.loading, loadingText: "Loading election status...", skeletonType: "detail", error: data.error },
129
- warning && (ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Box, { marginBottom: 1 },
289
+ return (ink_wrapper_js_1.React.createElement(ViewLayout_js_1.ViewLayout, { view: "election", hasProviders: !!providers, isTracking: data.loading || details.loading, loading: data.loading, loadingText: "Loading election status...", skeletonType: "detail", error: data.error },
290
+ data.warning && (ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Box, { marginBottom: 1 },
130
291
  ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: "yellow" },
131
292
  "[Warning] ",
132
- warning))),
133
- status && (ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Box, { flexDirection: "column", marginBottom: 1 },
134
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { bold: true }, "Security Council Election Status"),
135
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Box, { marginLeft: 1, flexDirection: "column" },
136
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Box, null,
137
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: "gray" }, "Election Count: "),
138
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, null, status.electionCount)),
139
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Box, null,
140
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: "gray" }, "Current Cohort: "),
141
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: status.cohort === 0 ? "cyan" : "magenta" }, status.cohort === 0 ? "FIRST" : "SECOND")),
142
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Box, null,
143
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: "gray" }, "Can Create Election: "),
144
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: status.canCreateElection ? "green" : "gray" }, status.canCreateElection ? "Yes" : "No")),
145
- !status.canCreateElection && (ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Box, null,
146
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: "gray" }, "Next Election: "),
147
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, null, formatTimestamp(status.nextElectionTimestamp)),
148
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: "gray" },
149
- " (",
150
- status.timeUntilElection,
151
- ")")))))),
152
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Box, { flexDirection: "column" },
153
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { bold: true }, "Recent Elections"),
154
- proposals.length === 0 ? (ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: "gray", marginLeft: 1 }, "No elections found")) : (proposals.map((election, i) => (ink_wrapper_js_1.React.createElement(ElectionItem, { key: election.electionIndex, election: election, isSelected: i === selectedIndex })))))));
155
- }
156
- function getPhaseColor(phase) {
157
- if (phase === "COMPLETED")
158
- return "green";
159
- if (phase === "NOT_STARTED")
160
- return "gray";
161
- return "yellow";
162
- }
163
- function ElectionItem({ election, isSelected }) {
164
- return (ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Box, { marginLeft: 1, flexDirection: "column" },
165
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Box, null,
166
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: isSelected ? "cyan" : undefined }, isSelected ? "> " : " "),
167
- ink_wrapper_js_1.React.createElement(PhaseIcon, { phase: election.phase }),
168
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, null, " "),
169
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: isSelected ? "cyan" : undefined, bold: isSelected },
170
- "Election #",
171
- election.electionIndex),
172
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: "gray" }, " - "),
173
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: getPhaseColor(election.phase) }, election.phase.replace(/_/g, " "))),
174
- isSelected && (ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Box, { marginLeft: 4, flexDirection: "column" },
175
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Box, null,
176
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: "gray" }, "Cohort: "),
177
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, null, election.cohort === 0 ? "FIRST" : "SECOND")),
178
- election.nomineeProposalId && (ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Box, null,
179
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: "gray" }, "Nominee State: "),
180
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, null, election.nomineeProposalState))),
181
- election.memberProposalId && (ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Box, null,
182
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: "gray" }, "Member State: "),
183
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, null, election.memberProposalState))),
184
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Box, null,
185
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: "gray" }, "Compliant Nominees: "),
186
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: election.compliantNomineeCount >= election.targetNomineeCount ? "green" : "yellow" },
187
- election.compliantNomineeCount,
188
- "/",
189
- election.targetNomineeCount)),
190
- election.isInVettingPeriod && (ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Box, null,
191
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: "cyan" },
192
- "In vetting period until block ",
193
- election.vettingDeadline))),
194
- election.canProceedToMemberPhase && (ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Box, null,
195
- ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { color: "green" }, "Ready to trigger member election!")))))));
293
+ data.warning))),
294
+ lines.length > visibleCount && (ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Box, { marginBottom: 1 },
295
+ ink_wrapper_js_1.React.createElement(ScrollIndicator_js_1.ScrollPosition, { scrollOffset: scrollOffset, visibleRows: visibleCount, totalItems: lines.length }))),
296
+ hasLess && ink_wrapper_js_1.React.createElement(ScrollIndicator_js_1.ScrollIndicatorTop, { scrollOffset: scrollOffset, unit: "lines" }),
297
+ visibleLines.map((line, i) => (ink_wrapper_js_1.React.createElement(ink_wrapper_js_1.Text, { key: i, color: line.color, bold: line.bold, dimColor: line.dimColor }, line.text))),
298
+ hasMore && (ink_wrapper_js_1.React.createElement(ScrollIndicator_js_1.ScrollIndicatorBottom, { scrollOffset: scrollOffset, visibleRows: visibleCount, totalItems: lines.length, unit: "lines" }))));
196
299
  }
197
300
  //# sourceMappingURL=ElectionView.js.map