claudeup 4.35.1 → 4.36.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.
Files changed (58) hide show
  1. package/package.json +4 -4
  2. package/src/__tests__/scope-squares.test.tsx +165 -0
  3. package/src/__tests__/theme-adaptive-colors.test.ts +307 -0
  4. package/src/__tests__/uppercase-keybindings.test.ts +101 -0
  5. package/src/main.tsx +21 -5
  6. package/src/opentui.d.ts +21 -12
  7. package/src/ui/App.tsx +19 -12
  8. package/src/ui/adapters/pluginsAdapter.ts +174 -168
  9. package/src/ui/adapters/settingsAdapter.ts +119 -116
  10. package/src/ui/adapters/skillsAdapter.ts +203 -196
  11. package/src/ui/components/CategoryHeader.tsx +9 -8
  12. package/src/ui/components/EmptyFilterState.tsx +10 -5
  13. package/src/ui/components/FlagDetailEditor.tsx +0 -0
  14. package/src/ui/components/ScopeIndicator.tsx +10 -6
  15. package/src/ui/components/ScrollableList.tsx +3 -2
  16. package/src/ui/components/SearchInput.tsx +2 -1
  17. package/src/ui/components/StyledText.tsx +5 -4
  18. package/src/ui/components/TabBar.tsx +4 -3
  19. package/src/ui/components/layout/FooterHints.tsx +37 -30
  20. package/src/ui/components/layout/Panel.tsx +6 -5
  21. package/src/ui/components/layout/ProgressBar.tsx +7 -6
  22. package/src/ui/components/layout/ScopeTabs.tsx +6 -5
  23. package/src/ui/components/layout/ScreenLayout.tsx +27 -24
  24. package/src/ui/components/layout/index.ts +3 -3
  25. package/src/ui/components/modals/ConfirmModal.tsx +12 -11
  26. package/src/ui/components/modals/InputModal.tsx +14 -6
  27. package/src/ui/components/modals/LoadingModal.tsx +6 -5
  28. package/src/ui/components/modals/MessageModal.tsx +9 -8
  29. package/src/ui/components/modals/SelectModal.tsx +11 -7
  30. package/src/ui/components/modals/VersionMismatchModal.tsx +14 -16
  31. package/src/ui/components/primitives/ActionHints.tsx +26 -26
  32. package/src/ui/components/primitives/DetailSection.tsx +13 -12
  33. package/src/ui/components/primitives/KeyValueLine.tsx +9 -8
  34. package/src/ui/components/primitives/ListCategoryRow.tsx +25 -27
  35. package/src/ui/components/primitives/MetaText.tsx +3 -3
  36. package/src/ui/components/primitives/ScopeDetail.tsx +48 -48
  37. package/src/ui/components/primitives/ScopeSquares.tsx +47 -22
  38. package/src/ui/components/primitives/SelectableRow.tsx +22 -16
  39. package/src/ui/hooks/useGitignoreModal.ts +78 -74
  40. package/src/ui/registry.ts +11 -11
  41. package/src/ui/renderers/cliToolRenderers.tsx +260 -203
  42. package/src/ui/renderers/gitignoreRenderers.tsx +43 -42
  43. package/src/ui/renderers/mcpRenderers.tsx +121 -117
  44. package/src/ui/renderers/pluginRenderers.tsx +528 -471
  45. package/src/ui/renderers/profileRenderers.tsx +346 -300
  46. package/src/ui/renderers/settingsRenderers.tsx +183 -176
  47. package/src/ui/renderers/skillRenderers.tsx +410 -326
  48. package/src/ui/screens/AliasScreen.tsx +1336 -1309
  49. package/src/ui/screens/CliToolsScreen.tsx +92 -40
  50. package/src/ui/screens/EnvVarsScreen.tsx +19 -13
  51. package/src/ui/screens/GitignoreScreen.tsx +510 -493
  52. package/src/ui/screens/McpRegistryScreen.tsx +28 -21
  53. package/src/ui/screens/McpScreen.tsx +12 -3
  54. package/src/ui/screens/PluginsScreen.tsx +17 -7
  55. package/src/ui/screens/ProfilesScreen.tsx +39 -23
  56. package/src/ui/screens/SkillsScreen.tsx +832 -688
  57. package/src/ui/theme-mode.ts +73 -0
  58. package/src/ui/theme.ts +147 -53
@@ -1,29 +1,30 @@
1
1
  import {
2
- SETTINGS_CATALOG,
3
- type SettingCategory,
4
- type SettingDefinition,
2
+ SETTINGS_CATALOG,
3
+ type SettingCategory,
4
+ type SettingDefinition,
5
5
  } from "../../data/settings-catalog.js";
6
6
  import type { ScopedSettingValues } from "../../services/settings-manager.js";
7
+ import { theme, type UiColor } from "../theme.js";
7
8
 
8
9
  // ─── Item types ────────────────────────────────────────────────────────────────
9
10
 
10
11
  export interface SettingsCategoryItem {
11
- id: string;
12
- kind: "category";
13
- label: string;
14
- category: SettingCategory;
15
- isDefault: true;
12
+ id: string;
13
+ kind: "category";
14
+ label: string;
15
+ category: SettingCategory;
16
+ isDefault: true;
16
17
  }
17
18
 
18
19
  export interface SettingsSettingItem {
19
- id: string;
20
- kind: "setting";
21
- label: string;
22
- category: SettingCategory;
23
- setting: SettingDefinition;
24
- scopedValues: ScopedSettingValues;
25
- effectiveValue: string | undefined;
26
- isDefault: boolean;
20
+ id: string;
21
+ kind: "setting";
22
+ label: string;
23
+ category: SettingCategory;
24
+ setting: SettingDefinition;
25
+ scopedValues: ScopedSettingValues;
26
+ effectiveValue: string | undefined;
27
+ isDefault: boolean;
27
28
  }
28
29
 
29
30
  export type SettingsBrowserItem = SettingsCategoryItem | SettingsSettingItem;
@@ -31,92 +32,94 @@ export type SettingsBrowserItem = SettingsCategoryItem | SettingsSettingItem;
31
32
  // ─── Constants ─────────────────────────────────────────────────────────────────
32
33
 
33
34
  export const CATEGORY_LABELS: Record<SettingCategory, string> = {
34
- recommended: "Recommended",
35
- agents: "Agents & Teams",
36
- models: "Models & Thinking",
37
- workflow: "Workflow",
38
- terminal: "Terminal & UI",
39
- performance: "Performance",
40
- advanced: "Advanced",
35
+ recommended: "Recommended",
36
+ agents: "Agents & Teams",
37
+ models: "Models & Thinking",
38
+ workflow: "Workflow",
39
+ terminal: "Terminal & UI",
40
+ performance: "Performance",
41
+ advanced: "Advanced",
41
42
  };
42
43
 
43
44
  export const CATEGORY_ORDER: SettingCategory[] = [
44
- "recommended",
45
- "agents",
46
- "models",
47
- "workflow",
48
- "terminal",
49
- "performance",
50
- "advanced",
45
+ "recommended",
46
+ "agents",
47
+ "models",
48
+ "workflow",
49
+ "terminal",
50
+ "performance",
51
+ "advanced",
51
52
  ];
52
53
 
53
- export const CATEGORY_BG: Record<SettingCategory, string> = {
54
- recommended: "#2e7d32",
55
- agents: "#00838f",
56
- models: "#4527a0",
57
- workflow: "#1565c0",
58
- terminal: "#4e342e",
59
- performance: "#6a1b9a",
60
- advanced: "#e65100",
54
+ export const CATEGORY_BG: Record<SettingCategory, UiColor> = {
55
+ recommended: theme.colors.success,
56
+ agents: theme.colors.info,
57
+ models: theme.colors.accent,
58
+ workflow: theme.colors.link,
59
+ terminal: theme.colors.warning,
60
+ performance: theme.colors.accent,
61
+ advanced: theme.colors.warning,
61
62
  };
62
63
 
63
- export const CATEGORY_COLOR: Record<SettingCategory, string> = {
64
- recommended: "green",
65
- agents: "cyan",
66
- models: "cyan",
67
- workflow: "blue",
68
- terminal: "blue",
69
- performance: "magentaBright",
70
- advanced: "yellow",
64
+ export const CATEGORY_COLOR: Record<SettingCategory, UiColor> = {
65
+ recommended: theme.colors.success,
66
+ agents: theme.colors.info,
67
+ models: theme.colors.info,
68
+ workflow: theme.colors.link,
69
+ terminal: theme.colors.link,
70
+ performance: "magentaBright",
71
+ advanced: theme.colors.warning,
71
72
  };
72
73
 
73
74
  export const CATEGORY_DESCRIPTIONS: Record<SettingCategory, string> = {
74
- recommended: "Most impactful settings every user should know.",
75
- agents: "Agent teams, task lists, and subagent configuration.",
76
- models: "Model selection, extended thinking, and effort.",
77
- workflow: "Git, plans, permissions, output style, and languages.",
78
- terminal: "Shell, spinners, progress bars, voice, and UI behavior.",
79
- performance: "Compaction, token limits, timeouts, and caching.",
80
- advanced: "Telemetry, updates, debugging, and internal controls.",
75
+ recommended: "Most impactful settings every user should know.",
76
+ agents: "Agent teams, task lists, and subagent configuration.",
77
+ models: "Model selection, extended thinking, and effort.",
78
+ workflow: "Git, plans, permissions, output style, and languages.",
79
+ terminal: "Shell, spinners, progress bars, voice, and UI behavior.",
80
+ performance: "Compaction, token limits, timeouts, and caching.",
81
+ advanced: "Telemetry, updates, debugging, and internal controls.",
81
82
  };
82
83
 
83
84
  // ─── Helpers ───────────────────────────────────────────────────────────────────
84
85
 
85
86
  /** Get the effective value (project overrides user) */
86
87
  export function getEffectiveValue(
87
- scoped: ScopedSettingValues,
88
+ scoped: ScopedSettingValues,
88
89
  ): string | undefined {
89
- return scoped.project !== undefined ? scoped.project : scoped.user;
90
+ return scoped.project !== undefined ? scoped.project : scoped.user;
90
91
  }
91
92
 
92
93
  export function formatValue(
93
- setting: SettingDefinition,
94
- value: string | undefined,
94
+ setting: SettingDefinition,
95
+ value: string | undefined,
95
96
  ): string {
96
- if (value === undefined || value === "") {
97
- if (setting.type === "boolean" && setting.defaultValue !== undefined) {
98
- return setting.defaultValue === "true" ? "on" : "off";
99
- }
100
- if (setting.type === "select" && setting.defaultValue !== undefined) {
101
- const opt = setting.options?.find((o) => o.value === setting.defaultValue);
102
- return opt ? opt.label : setting.defaultValue;
103
- }
104
- return "—";
105
- }
106
-
107
- if (setting.type === "boolean") {
108
- return value === "true" || value === "1" ? "on" : "off";
109
- }
110
-
111
- if (setting.type === "select" && setting.options) {
112
- const opt = setting.options.find((o) => o.value === value);
113
- return opt ? opt.label : value;
114
- }
115
-
116
- if (value.length > 12) {
117
- return value.slice(0, 12) + "…";
118
- }
119
- return value;
97
+ if (value === undefined || value === "") {
98
+ if (setting.type === "boolean" && setting.defaultValue !== undefined) {
99
+ return setting.defaultValue === "true" ? "on" : "off";
100
+ }
101
+ if (setting.type === "select" && setting.defaultValue !== undefined) {
102
+ const opt = setting.options?.find(
103
+ (o) => o.value === setting.defaultValue,
104
+ );
105
+ return opt ? opt.label : setting.defaultValue;
106
+ }
107
+ return "—";
108
+ }
109
+
110
+ if (setting.type === "boolean") {
111
+ return value === "true" || value === "1" ? "on" : "off";
112
+ }
113
+
114
+ if (setting.type === "select" && setting.options) {
115
+ const opt = setting.options.find((o) => o.value === value);
116
+ return opt ? opt.label : value;
117
+ }
118
+
119
+ if (value.length > 12) {
120
+ return value.slice(0, 12) + "…";
121
+ }
122
+ return value;
120
123
  }
121
124
 
122
125
  // ─── Adapter ───────────────────────────────────────────────────────────────────
@@ -126,40 +129,40 @@ export function formatValue(
126
129
  * Extracted from SettingsScreen so it can be tested independently.
127
130
  */
128
131
  export function buildSettingsBrowserItems(
129
- values: Map<string, ScopedSettingValues>,
132
+ values: Map<string, ScopedSettingValues>,
130
133
  ): SettingsBrowserItem[] {
131
- const items: SettingsBrowserItem[] = [];
132
-
133
- for (const category of CATEGORY_ORDER) {
134
- items.push({
135
- id: `cat:${category}`,
136
- kind: "category",
137
- label: CATEGORY_LABELS[category],
138
- category,
139
- isDefault: true,
140
- });
141
-
142
- const categorySettings = SETTINGS_CATALOG.filter(
143
- (s) => s.category === category,
144
- );
145
- for (const setting of categorySettings) {
146
- const scoped = values.get(setting.id) || {
147
- user: undefined,
148
- project: undefined,
149
- };
150
- const effective = getEffectiveValue(scoped);
151
- items.push({
152
- id: `setting:${setting.id}`,
153
- kind: "setting",
154
- label: setting.name,
155
- category,
156
- setting,
157
- scopedValues: scoped,
158
- effectiveValue: effective,
159
- isDefault: effective === undefined || effective === "",
160
- });
161
- }
162
- }
163
-
164
- return items;
134
+ const items: SettingsBrowserItem[] = [];
135
+
136
+ for (const category of CATEGORY_ORDER) {
137
+ items.push({
138
+ id: `cat:${category}`,
139
+ kind: "category",
140
+ label: CATEGORY_LABELS[category],
141
+ category,
142
+ isDefault: true,
143
+ });
144
+
145
+ const categorySettings = SETTINGS_CATALOG.filter(
146
+ (s) => s.category === category,
147
+ );
148
+ for (const setting of categorySettings) {
149
+ const scoped = values.get(setting.id) || {
150
+ user: undefined,
151
+ project: undefined,
152
+ };
153
+ const effective = getEffectiveValue(scoped);
154
+ items.push({
155
+ id: `setting:${setting.id}`,
156
+ kind: "setting",
157
+ label: setting.name,
158
+ category,
159
+ setting,
160
+ scopedValues: scoped,
161
+ effectiveValue: effective,
162
+ isDefault: effective === undefined || effective === "",
163
+ });
164
+ }
165
+ }
166
+
167
+ return items;
165
168
  }