@sushant-kum/ccstatus 0.1.2 → 0.2.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.
@@ -15,7 +15,7 @@ import {
15
15
  saveConfigFile,
16
16
  snapshotPath,
17
17
  writeLinkedLines
18
- } from "./chunk-BCBGMRHQ.js";
18
+ } from "./chunk-EUAY5IC6.js";
19
19
 
20
20
  // src/app.tsx
21
21
  import { Box as Box12, Text as Text12, useApp, useInput as useInput10 } from "ink";
@@ -310,45 +310,21 @@ function Import({
310
310
  // src/screens/items.tsx
311
311
  import { Box as Box5, Text as Text5, useInput as useInput3 } from "ink";
312
312
  import { useState as useState3 } from "react";
313
-
314
- // src/named-colors.ts
315
- var all = [...COLORS];
316
- var NAMED_COLORS = [
317
- "(none)",
318
- ...all.filter((c) => !c.startsWith("bg")),
319
- ...all.filter((c) => c.startsWith("bg"))
320
- ];
321
-
322
- // src/screens/items.tsx
323
313
  import { Fragment, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
324
314
  var SURFACES = LINKABLE;
325
- var FIELDS2 = ["fg", "bg", "raw", "merge", "align"];
315
+ var FIELDS2 = ["raw", "merge", "align"];
326
316
  var ALIGNS = ["left", "center", "right"];
327
- var FG = NAMED_COLORS.filter((c) => !c.startsWith("bg"));
328
- var BG = ["(none)", ...NAMED_COLORS.filter((c) => c.startsWith("bg"))];
329
317
  var WIDGETS = Object.values(registry);
330
318
  var wrap = (i, n) => (i + n) % n;
331
319
  var makeId = (type) => `${type}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
332
320
  var isStylable = (item) => item.type !== "flex-separator";
333
321
  function Chip({ item, selected }) {
334
- const fg = isStylable(item) ? item.fg : void 0;
335
- const bg = isStylable(item) ? item.bg : void 0;
336
- return /* @__PURE__ */ jsxs4(Text5, { inverse: selected, color: inkColor(fg), backgroundColor: inkBg(bg), children: [
322
+ return /* @__PURE__ */ jsxs4(Text5, { inverse: selected, children: [
337
323
  "[ ",
338
324
  item.type,
339
325
  " ]"
340
326
  ] });
341
327
  }
342
- function Swatch({ name, bg }) {
343
- if (!name) {
344
- return /* @__PURE__ */ jsx4(Text5, { dimColor: true, children: "(none)" });
345
- }
346
- return /* @__PURE__ */ jsxs4(Text5, { color: bg ? void 0 : inkColor(name), backgroundColor: bg ? inkBg(name) : void 0, children: [
347
- " ",
348
- name,
349
- " "
350
- ] });
351
- }
352
328
  function Items({ config, setConfig, goHome }) {
353
329
  const [surface, setSurface] = useState3("band");
354
330
  const [sel, setSel] = useState3(0);
@@ -377,20 +353,12 @@ function Items({ config, setConfig, goHome }) {
377
353
  }
378
354
  commit(items.map((it, i) => i === idx ? item : it));
379
355
  };
380
- const cycleColor = (list, cur2, dir) => {
381
- const n = list[wrap(Math.max(0, list.indexOf(cur2 ?? "(none)")) + dir + list.length, list.length)] ?? "(none)";
382
- return n === "(none)" ? void 0 : n;
383
- };
384
356
  const change = (dir) => {
385
357
  if (!cur || !isStylable(cur)) {
386
358
  return;
387
359
  }
388
360
  const f = FIELDS2[field];
389
- if (f === "fg") {
390
- patch({ fg: cycleColor(FG, cur.fg, dir) });
391
- } else if (f === "bg") {
392
- patch({ bg: cycleColor(BG, cur.bg, dir) });
393
- } else if (f === "raw") {
361
+ if (f === "raw") {
394
362
  patch({ rawValue: !cur.rawValue });
395
363
  } else if (f === "merge") {
396
364
  patch({ merge: !cur.merge });
@@ -601,11 +569,9 @@ function Items({ config, setConfig, goHome }) {
601
569
  "type: ",
602
570
  cur.type
603
571
  ] }),
604
- row(0, "fg", /* @__PURE__ */ jsx4(Swatch, { name: cur.fg })),
605
- row(1, "bg", /* @__PURE__ */ jsx4(Swatch, { name: cur.bg, bg: true })),
606
- row(2, "raw", /* @__PURE__ */ jsx4(Text5, { children: cur.rawValue ? "on" : "off" })),
607
- row(3, "merge", /* @__PURE__ */ jsx4(Text5, { children: cur.merge ? "on" : "off" })),
608
- row(4, "align", /* @__PURE__ */ jsx4(Text5, { children: cur.align ?? "left" }))
572
+ row(0, "raw", /* @__PURE__ */ jsx4(Text5, { children: cur.rawValue ? "on" : "off" })),
573
+ row(1, "merge", /* @__PURE__ */ jsx4(Text5, { children: cur.merge ? "on" : "off" })),
574
+ row(2, "align", /* @__PURE__ */ jsx4(Text5, { children: cur.align ?? "left" }))
609
575
  ] }) : /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", marginTop: 1, borderStyle: "round", paddingX: 1, children: [
610
576
  /* @__PURE__ */ jsxs4(Text5, { children: [
611
577
  "type: ",
@@ -1169,9 +1135,19 @@ function Surfaces({ config, setConfig, goHome }) {
1169
1135
  // src/screens/themes.tsx
1170
1136
  import { Box as Box11, Text as Text11, useInput as useInput9 } from "ink";
1171
1137
  import { useState as useState9 } from "react";
1138
+
1139
+ // src/named-colors.ts
1140
+ var all = [...COLORS];
1141
+ var NAMED_COLORS = [
1142
+ "(none)",
1143
+ ...all.filter((c) => !c.startsWith("bg")),
1144
+ ...all.filter((c) => c.startsWith("bg"))
1145
+ ];
1146
+
1147
+ // src/screens/themes.tsx
1172
1148
  import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
1173
- var FG2 = NAMED_COLORS.filter((c) => !c.startsWith("bg"));
1174
- var BG2 = NAMED_COLORS.filter((c) => c.startsWith("bg"));
1149
+ var FG = NAMED_COLORS.filter((c) => !c.startsWith("bg"));
1150
+ var BG = ["(none)", ...NAMED_COLORS.filter((c) => c.startsWith("bg"))];
1175
1151
  var FIELDS3 = ["fg", "bg"];
1176
1152
  function uniqueName(base, themes) {
1177
1153
  if (!(base in themes)) {
@@ -1187,15 +1163,20 @@ function Themes({ config, setConfig, goHome }) {
1187
1163
  const names = Object.keys(config.themes);
1188
1164
  const [sel, setSel] = useState9(Math.max(0, names.indexOf(config.theme)));
1189
1165
  const [mode, setMode] = useState9("list");
1190
- const [w, setW] = useState9(0);
1166
+ const [slot, setSlot] = useState9(0);
1191
1167
  const [field, setField] = useState9(0);
1192
1168
  const [pick, setPick] = useState9(0);
1193
1169
  const name = names[Math.min(sel, names.length - 1)];
1194
- const theme = name && config.themes[name] || {};
1195
- const widgets = Object.keys(theme);
1196
- const widget = widgets[Math.min(w, widgets.length - 1)];
1197
- const list = FIELDS3[field] === "fg" ? FG2 : BG2;
1170
+ const theme = name && config.themes[name] || [];
1171
+ const count = theme.length;
1172
+ const slotIdx = Math.min(slot, count - 1);
1173
+ const list = FIELDS3[field] === "fg" ? FG : BG;
1198
1174
  const setThemes = (themes, active = config.theme) => setConfig({ ...config, theme: active, themes });
1175
+ const writeSlot = (index, entry) => {
1176
+ if (name) {
1177
+ setThemes({ ...config.themes, [name]: theme.map((s, i) => i === index ? entry : s) });
1178
+ }
1179
+ };
1199
1180
  useInput9((input, key) => {
1200
1181
  if (mode === "list") {
1201
1182
  if (key.escape) {
@@ -1209,49 +1190,65 @@ function Themes({ config, setConfig, goHome }) {
1209
1190
  setConfig({ ...config, theme: name });
1210
1191
  }
1211
1192
  } else if (key.rightArrow) {
1212
- if (widgets.length) {
1213
- setW(0);
1214
- setMode("colors");
1193
+ if (count) {
1194
+ setSlot(0);
1195
+ setMode("slots");
1215
1196
  }
1216
1197
  } else if (input === "n") {
1217
1198
  const n = uniqueName("custom", config.themes);
1218
- setThemes({ ...config.themes, [n]: {} });
1199
+ setThemes({ ...config.themes, [n]: [] });
1219
1200
  setSel(names.length);
1220
1201
  } else if (input === "d" && name) {
1221
1202
  const n = uniqueName(`${name}-copy`, config.themes);
1222
1203
  setThemes({ ...config.themes, [n]: structuredClone(theme) });
1223
1204
  setSel(names.length);
1224
1205
  }
1225
- } else if (mode === "colors") {
1206
+ } else if (mode === "slots") {
1226
1207
  if (key.escape || key.leftArrow && field === 0) {
1227
1208
  setMode("list");
1228
1209
  } else if (key.upArrow) {
1229
- setW((i) => Math.max(0, i - 1));
1210
+ setSlot(Math.max(0, slotIdx - 1));
1230
1211
  } else if (key.downArrow) {
1231
- setW((i) => Math.min(widgets.length - 1, i + 1));
1212
+ setSlot(Math.min(count - 1, slotIdx + 1));
1232
1213
  } else if (key.leftArrow) {
1233
1214
  setField(0);
1234
1215
  } else if (key.rightArrow) {
1235
1216
  setField(1);
1236
- } else if (key.return && widget) {
1237
- const cur = theme[widget]?.[FIELDS3[field] ?? "fg"];
1238
- setPick(Math.max(0, list.indexOf(cur ?? "")));
1217
+ } else if (key.return && slotIdx >= 0) {
1218
+ const cur = theme[slotIdx]?.[FIELDS3[field] ?? "fg"];
1219
+ setPick(Math.max(0, list.indexOf(cur ?? "(none)")));
1239
1220
  setMode("picker");
1221
+ } else if (input === "a" && name) {
1222
+ setThemes({ ...config.themes, [name]: [...theme, {}] });
1223
+ setSlot(count);
1224
+ } else if (input === "x" && name && slotIdx >= 0) {
1225
+ const next = theme.filter((_, i) => i !== slotIdx);
1226
+ setThemes({ ...config.themes, [name]: next });
1227
+ if (next.length === 0) {
1228
+ setMode("list");
1229
+ } else {
1230
+ setSlot(Math.min(slotIdx, next.length - 1));
1231
+ }
1240
1232
  }
1241
1233
  } else {
1242
1234
  if (key.escape) {
1243
- setMode("colors");
1235
+ setMode("slots");
1244
1236
  } else if (key.upArrow) {
1245
1237
  setPick((p) => Math.max(0, p - 1));
1246
1238
  } else if (key.downArrow) {
1247
1239
  setPick((p) => Math.min(list.length - 1, p + 1));
1248
- } else if (key.return && name && widget) {
1240
+ } else if (key.return && slotIdx >= 0) {
1249
1241
  const f = FIELDS3[field] ?? "fg";
1250
1242
  const chosen = list[pick];
1251
1243
  if (chosen) {
1252
- const entry = { ...theme[widget], [f]: chosen };
1253
- setThemes({ ...config.themes, [name]: { ...theme, [widget]: entry } });
1254
- setMode("colors");
1244
+ const entry = { ...theme[slotIdx] };
1245
+ if (chosen === "(none)") {
1246
+ delete entry[f];
1247
+ } else {
1248
+ entry[f] = chosen;
1249
+ }
1250
+ writeSlot(slotIdx, entry);
1251
+ setMode("slots");
1255
1252
  }
1256
1253
  }
1257
1254
  }
@@ -1265,14 +1262,14 @@ function Themes({ config, setConfig, goHome }) {
1265
1262
  ] }, n)),
1266
1263
  /* @__PURE__ */ jsxs10(Text11, { dimColor: true, children: [
1267
1264
  name,
1268
- " colors:"
1265
+ " palette slots:"
1269
1266
  ] }),
1270
- widgets.map((wt, i) => {
1271
- const c = theme[wt] ?? {};
1272
- const on = mode !== "list" && i === w;
1267
+ count === 0 && /* @__PURE__ */ jsx10(Text11, { dimColor: true, children: "(empty palette)" }),
1268
+ theme.map((c, i) => {
1269
+ const on = mode !== "list" && i === slotIdx;
1273
1270
  return /* @__PURE__ */ jsxs10(Text11, { children: [
1274
1271
  on ? "\u25B8 " : " ",
1275
- wt.padEnd(20),
1272
+ String(i).padEnd(4),
1276
1273
  /* @__PURE__ */ jsxs10(Text11, { color: inkColor(c.fg), inverse: on && field === 0, children: [
1277
1274
  " ",
1278
1275
  c.fg ?? "(none)",
@@ -1283,14 +1280,14 @@ function Themes({ config, setConfig, goHome }) {
1283
1280
  c.bg ?? "(none)",
1284
1281
  " "
1285
1282
  ] })
1286
- ] }, wt);
1283
+ ] }, i);
1287
1284
  }),
1288
1285
  mode === "picker" && /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", children: [
1289
1286
  /* @__PURE__ */ jsxs10(Text11, { bold: true, children: [
1290
1287
  "Pick ",
1291
1288
  FIELDS3[field],
1292
- " for ",
1293
- widget
1289
+ " for slot ",
1290
+ slotIdx
1294
1291
  ] }),
1295
1292
  list.map((c, i) => /* @__PURE__ */ jsxs10(Text11, { color: i === pick ? "cyan" : void 0, children: [
1296
1293
  i === pick ? "\u25B8 " : " ",
@@ -1308,7 +1305,7 @@ function Themes({ config, setConfig, goHome }) {
1308
1305
  )
1309
1306
  ] }, c))
1310
1307
  ] }),
1311
- /* @__PURE__ */ jsx10(Text11, { dimColor: true, children: mode === "list" ? "\u2191/\u2193 select \xB7 \u23CE activate \xB7 \u2192 colors \xB7 n new \xB7 d duplicate \xB7 esc back" : mode === "colors" ? "\u2191/\u2193 widget \xB7 \u2190/\u2192 fg/bg \xB7 \u23CE pick \xB7 esc back" : "\u2191/\u2193 choose \xB7 \u23CE set \xB7 esc cancel" })
1308
+ /* @__PURE__ */ jsx10(Text11, { dimColor: true, children: mode === "list" ? "\u2191/\u2193 select \xB7 \u23CE activate \xB7 \u2192 slots \xB7 n new \xB7 d duplicate \xB7 esc back" : mode === "slots" ? "\u2191/\u2193 slot \xB7 \u2190/\u2192 fg/bg \xB7 \u23CE pick \xB7 a add \xB7 x remove \xB7 esc back" : "\u2191/\u2193 choose \xB7 \u23CE set \xB7 esc cancel" })
1312
1309
  ] });
1313
1310
  }
1314
1311
 
@@ -5,128 +5,6 @@ var __export = (target, all) => {
5
5
  __defProp(target, name, { get: all[name], enumerable: true });
6
6
  };
7
7
 
8
- // ../core/src/theme/themes.ts
9
- function resolveColors(item, config) {
10
- const themeEntry = config.themes[config.theme]?.[item.type];
11
- const fg2 = item.type === "flex-separator" ? void 0 : item.fg;
12
- const bg2 = item.type === "flex-separator" ? void 0 : item.bg;
13
- return {
14
- fg: fg2 ?? themeEntry?.fg,
15
- bg: bg2 ?? themeEntry?.bg
16
- };
17
- }
18
- var WIDGETS = [
19
- "model",
20
- "version",
21
- "context-percentage",
22
- "git-branch",
23
- "git-changes",
24
- "tokens-input",
25
- "tokens-output",
26
- "tokens-total"
27
- ];
28
- var mk = (rows) => {
29
- const t = {};
30
- WIDGETS.forEach((w, i) => {
31
- const row = rows[i];
32
- if (!row) {
33
- throw new Error(`theme definition is missing a color row for widget "${w}"`);
34
- }
35
- const [fg2, bg2] = row;
36
- t[w] = { fg: fg2, bg: bg2 };
37
- });
38
- return t;
39
- };
40
- var builtinThemes = {
41
- default: {
42
- model: { fg: "black", bg: "bgCyan" },
43
- version: { fg: "white", bg: "bgBlue" },
44
- "context-percentage": { fg: "black", bg: "bgBrightYellow" },
45
- "git-branch": { fg: "black", bg: "bgCyan" },
46
- "git-changes": { fg: "white", bg: "bgBrightBlack" }
47
- },
48
- classic: mk([
49
- ["black", "bgYellow"],
50
- ["black", "bgWhite"],
51
- ["black", "bgGreen"],
52
- ["white", "bgBlue"],
53
- ["black", "bgMagenta"],
54
- ["black", "bgCyan"],
55
- ["black", "bgBrightYellow"],
56
- ["white", "bgRed"]
57
- ]),
58
- nord: mk([
59
- ["black", "bgBrightCyan"],
60
- ["black", "bgCyan"],
61
- ["black", "bgBlue"],
62
- ["white", "bgBrightBlack"],
63
- ["black", "bgBrightBlue"],
64
- ["black", "bgGreen"],
65
- ["black", "bgYellow"],
66
- ["white", "bgBlack"]
67
- ]),
68
- dracula: mk([
69
- ["black", "bgMagenta"],
70
- ["black", "bgBrightMagenta"],
71
- ["black", "bgBrightGreen"],
72
- ["black", "bgBrightCyan"],
73
- ["black", "bgBrightYellow"],
74
- ["black", "bgBrightRed"],
75
- ["white", "bgBrightBlack"],
76
- ["white", "bgMagenta"]
77
- ]),
78
- gruvbox: mk([
79
- ["black", "bgYellow"],
80
- ["black", "bgBrightYellow"],
81
- ["black", "bgGreen"],
82
- ["black", "bgCyan"],
83
- ["black", "bgRed"],
84
- ["black", "bgMagenta"],
85
- ["white", "bgBrightBlack"],
86
- ["white", "bgBlack"]
87
- ]),
88
- monokai: mk([
89
- ["black", "bgBrightGreen"],
90
- ["black", "bgBrightYellow"],
91
- ["black", "bgBrightMagenta"],
92
- ["black", "bgBrightCyan"],
93
- ["black", "bgBrightRed"],
94
- ["white", "bgBrightBlack"],
95
- ["black", "bgYellow"],
96
- ["white", "bgBlack"]
97
- ]),
98
- "one-dark": mk([
99
- ["black", "bgBlue"],
100
- ["black", "bgBrightBlue"],
101
- ["black", "bgGreen"],
102
- ["black", "bgMagenta"],
103
- ["black", "bgYellow"],
104
- ["black", "bgCyan"],
105
- ["white", "bgBrightBlack"],
106
- ["white", "bgBlack"]
107
- ]),
108
- solarized: mk([
109
- ["white", "bgBlue"],
110
- ["black", "bgCyan"],
111
- ["black", "bgYellow"],
112
- ["white", "bgGreen"],
113
- ["white", "bgMagenta"],
114
- ["white", "bgRed"],
115
- ["white", "bgBrightBlack"],
116
- ["white", "bgBlack"]
117
- ]),
118
- "tokyo-night": mk([
119
- ["black", "bgBrightBlue"],
120
- ["black", "bgBlue"],
121
- ["black", "bgBrightGreen"],
122
- ["black", "bgBrightMagenta"],
123
- ["black", "bgBrightYellow"],
124
- ["black", "bgBrightCyan"],
125
- ["white", "bgBrightBlack"],
126
- ["white", "bgBlack"]
127
- ])
128
- };
129
-
130
8
  // ../core/src/widgets/registry.ts
131
9
  var registry = {};
132
10
  function register(def) {
@@ -145,9 +23,8 @@ function itemToCell(item, config, snapshot, commandOutputs) {
145
23
  }
146
24
  const flex = item.type === "flex-separator";
147
25
  const pad = flex ? "" : " ".repeat(Math.max(0, Math.floor(config.defaults.padding)));
148
- const { fg: fg2, bg: bg2 } = resolveColors(item, config);
149
26
  const merge = item.type === "flex-separator" ? false : item.merge ?? false;
150
- return { text: flex ? "" : `${pad}${value}${pad}`, fg: fg2, bg: bg2, merge, flex };
27
+ return { text: flex ? "" : `${pad}${value}${pad}`, merge, flex };
151
28
  }
152
29
  function lineToCells(items, config, snapshot, commandOutputs) {
153
30
  return items.map((it) => itemToCell(it, config, snapshot, commandOutputs)).filter((c) => c !== null);
@@ -250,6 +127,55 @@ function composeLine(cells, mode, width, glyph = "\u2592") {
250
127
  return truncate(segs, width);
251
128
  }
252
129
 
130
+ // ../core/src/theme/contrast.ts
131
+ var LIGHT_BG = /* @__PURE__ */ new Set([
132
+ "green",
133
+ "yellow",
134
+ "cyan",
135
+ "white",
136
+ "brightGreen",
137
+ "brightYellow",
138
+ "brightCyan",
139
+ "brightWhite"
140
+ ]);
141
+ var baseColor = (bg2) => {
142
+ if (!bg2.startsWith("bg")) {
143
+ return bg2;
144
+ }
145
+ const rest = bg2.slice(2);
146
+ return rest.charAt(0).toLowerCase() + rest.slice(1);
147
+ };
148
+ function contrastFg(bg2) {
149
+ return LIGHT_BG.has(baseColor(bg2)) ? "black" : "white";
150
+ }
151
+
152
+ // ../core/src/layout/palette.ts
153
+ function assignPaletteColors(cells, theme) {
154
+ if (theme.length === 0) {
155
+ return cells.map((c) => ({ ...c }));
156
+ }
157
+ const out = [];
158
+ let slot = -1;
159
+ let prev;
160
+ for (const c of cells) {
161
+ if (c.flex) {
162
+ out.push({ ...c });
163
+ prev = c;
164
+ continue;
165
+ }
166
+ const continuation = c.merge === true && prev !== void 0 && !prev.flex;
167
+ if (!continuation) {
168
+ slot += 1;
169
+ }
170
+ const pal = theme[slot % theme.length];
171
+ const bg2 = pal?.bg;
172
+ const fg2 = pal?.fg ?? (bg2 !== void 0 ? contrastFg(bg2) : void 0);
173
+ out.push({ ...c, fg: fg2, bg: bg2 });
174
+ prev = c;
175
+ }
176
+ return out;
177
+ }
178
+
253
179
  // ../core/src/format.ts
254
180
  function fmtNum(n) {
255
181
  const trim = (v, suffix) => `${v.toFixed(1).replace(/\.0$/, "")}${suffix}`;
@@ -525,7 +451,8 @@ function render(config, snapshot, opts) {
525
451
  return { lines: [] };
526
452
  }
527
453
  const outputs = opts.commandOutputs ?? {};
528
- const lines = surface.lines.map((items) => lineToCells(items, config, snapshot, outputs)).filter((cells) => cells.length > 0).map((cells) => ({
454
+ const theme = Object.hasOwn(config.themes, config.theme) ? config.themes[config.theme] ?? [] : [];
455
+ const lines = surface.lines.map((items) => lineToCells(items, config, snapshot, outputs)).filter((cells) => cells.length > 0).map((cells) => assignPaletteColors(cells, theme)).map((cells) => ({
529
456
  segments: composeLine(cells, config.defaults.separator, opts.width, config.defaults.glyph)
530
457
  }));
531
458
  return { lines };
@@ -609,6 +536,98 @@ function isColor(x) {
609
536
  return typeof x === "string" && COLORS.has(x);
610
537
  }
611
538
 
539
+ // ../core/src/theme/themes.ts
540
+ var mk = (rows) => rows.map(([fg2, bg2]) => ({ fg: fg2, bg: bg2 }));
541
+ var builtinThemes = {
542
+ default: [
543
+ { fg: "black", bg: "bgCyan" },
544
+ { fg: "white", bg: "bgBlue" },
545
+ { fg: "black", bg: "bgBrightYellow" },
546
+ { fg: "white", bg: "bgBrightBlack" },
547
+ { fg: "black", bg: "bgGreen" }
548
+ ],
549
+ classic: mk([
550
+ ["black", "bgYellow"],
551
+ ["black", "bgWhite"],
552
+ ["black", "bgGreen"],
553
+ ["white", "bgBlue"],
554
+ ["black", "bgMagenta"],
555
+ ["black", "bgCyan"],
556
+ ["black", "bgBrightYellow"],
557
+ ["white", "bgRed"]
558
+ ]),
559
+ nord: mk([
560
+ ["black", "bgBrightCyan"],
561
+ ["black", "bgCyan"],
562
+ ["black", "bgBlue"],
563
+ ["white", "bgBrightBlack"],
564
+ ["black", "bgBrightBlue"],
565
+ ["black", "bgGreen"],
566
+ ["black", "bgYellow"],
567
+ ["white", "bgBlack"]
568
+ ]),
569
+ dracula: mk([
570
+ ["black", "bgMagenta"],
571
+ ["black", "bgBrightMagenta"],
572
+ ["black", "bgBrightGreen"],
573
+ ["black", "bgBrightCyan"],
574
+ ["black", "bgBrightYellow"],
575
+ ["black", "bgBrightRed"],
576
+ ["white", "bgBrightBlack"],
577
+ ["white", "bgMagenta"]
578
+ ]),
579
+ gruvbox: mk([
580
+ ["black", "bgYellow"],
581
+ ["black", "bgBrightYellow"],
582
+ ["black", "bgGreen"],
583
+ ["black", "bgCyan"],
584
+ ["black", "bgRed"],
585
+ ["black", "bgMagenta"],
586
+ ["white", "bgBrightBlack"],
587
+ ["white", "bgBlack"]
588
+ ]),
589
+ monokai: mk([
590
+ ["black", "bgBrightGreen"],
591
+ ["black", "bgBrightYellow"],
592
+ ["black", "bgBrightMagenta"],
593
+ ["black", "bgBrightCyan"],
594
+ ["black", "bgBrightRed"],
595
+ ["white", "bgBrightBlack"],
596
+ ["black", "bgYellow"],
597
+ ["white", "bgBlack"]
598
+ ]),
599
+ "one-dark": mk([
600
+ ["black", "bgBlue"],
601
+ ["black", "bgBrightBlue"],
602
+ ["black", "bgGreen"],
603
+ ["black", "bgMagenta"],
604
+ ["black", "bgYellow"],
605
+ ["black", "bgCyan"],
606
+ ["white", "bgBrightBlack"],
607
+ ["white", "bgBlack"]
608
+ ]),
609
+ solarized: mk([
610
+ ["white", "bgBlue"],
611
+ ["black", "bgCyan"],
612
+ ["black", "bgYellow"],
613
+ ["white", "bgGreen"],
614
+ ["white", "bgMagenta"],
615
+ ["white", "bgRed"],
616
+ ["white", "bgBrightBlack"],
617
+ ["white", "bgBlack"]
618
+ ]),
619
+ "tokyo-night": mk([
620
+ ["black", "bgBrightBlue"],
621
+ ["black", "bgBlue"],
622
+ ["black", "bgBrightGreen"],
623
+ ["black", "bgBrightMagenta"],
624
+ ["black", "bgBrightYellow"],
625
+ ["black", "bgBrightCyan"],
626
+ ["white", "bgBrightBlack"],
627
+ ["white", "bgBlack"]
628
+ ])
629
+ };
630
+
612
631
  // ../core/src/toast.ts
613
632
  var TOAST_FIELDS = {
614
633
  ctxPct: (s) => s.ctxPct,
@@ -4771,7 +4790,7 @@ var toastRuleSchema = external_exports.object({
4771
4790
  var configSchema = external_exports.object({
4772
4791
  version: external_exports.literal(1).catch(1),
4773
4792
  theme: external_exports.string().default("default"),
4774
- themes: external_exports.record(external_exports.record(external_exports.object({ fg: external_exports.string().optional(), bg: external_exports.string().optional() }))).default({}),
4793
+ themes: external_exports.record(external_exports.unknown()).default({}),
4775
4794
  defaults: external_exports.object({
4776
4795
  separator: sep,
4777
4796
  padding: external_exports.number().int().min(0).catch(1),
@@ -4841,16 +4860,8 @@ function cleanStyle(raw, type, warn) {
4841
4860
  if (raw.rawValue !== void 0) {
4842
4861
  style.rawValue = raw.rawValue;
4843
4862
  }
4844
- for (const key of ["fg", "bg"]) {
4845
- const v = raw[key];
4846
- if (v === void 0) {
4847
- continue;
4848
- }
4849
- if (isColor(v)) {
4850
- style[key] = v;
4851
- } else {
4852
- warn(`stripped unknown color "${v}" on a ${type} item`);
4853
- }
4863
+ if (raw.fg !== void 0 || raw.bg !== void 0) {
4864
+ warn(`dropped per-item color on a ${type} item; colors now come from the theme palette`);
4854
4865
  }
4855
4866
  return style;
4856
4867
  }
@@ -4883,22 +4894,36 @@ function cleanItem(raw, warn) {
4883
4894
  return { id, type, ...style };
4884
4895
  }
4885
4896
  function cleanThemes(themes, warn) {
4886
- const cleaned = {};
4887
- for (const [themeName, themeEntries] of Object.entries(themes)) {
4888
- const cleanedEntries = {};
4889
- for (const [widgetName, entry] of Object.entries(themeEntries)) {
4890
- const cleanedEntry = { ...entry };
4897
+ const cleaned = /* @__PURE__ */ Object.create(null);
4898
+ for (const [name, value] of Object.entries(themes)) {
4899
+ if (!Array.isArray(value)) {
4900
+ const message = value !== null && typeof value === "object" ? `theme "${name}" uses the old per-widget format and was dropped; colors are now a positional palette` : `theme "${name}" is not a palette array and was dropped; colors are now a positional palette`;
4901
+ warn(message);
4902
+ continue;
4903
+ }
4904
+ const slots = [];
4905
+ value.forEach((rawSlot, i) => {
4906
+ if (!rawSlot || typeof rawSlot !== "object") {
4907
+ warn(`replaced invalid slot ${i} in theme "${name}" with an empty slot`);
4908
+ slots.push({});
4909
+ return;
4910
+ }
4911
+ const entry = rawSlot;
4912
+ const slot = {};
4891
4913
  for (const key of ["fg", "bg"]) {
4892
- if (cleanedEntry[key] !== void 0 && !isColor(cleanedEntry[key])) {
4893
- warn(
4894
- `stripped unknown color "${cleanedEntry[key]}" in theme "${themeName}" (${widgetName})`
4895
- );
4896
- cleanedEntry[key] = void 0;
4914
+ const v = entry[key];
4915
+ if (v === void 0) {
4916
+ continue;
4917
+ }
4918
+ if (typeof v === "string" && isColor(v)) {
4919
+ slot[key] = v;
4920
+ } else {
4921
+ warn(`stripped unknown color "${String(v)}" in theme "${name}" (slot ${i})`);
4897
4922
  }
4898
4923
  }
4899
- cleanedEntries[widgetName] = cleanedEntry;
4900
- }
4901
- cleaned[themeName] = cleanedEntries;
4924
+ slots.push(slot);
4925
+ });
4926
+ cleaned[name] = slots;
4902
4927
  }
4903
4928
  return cleaned;
4904
4929
  }
@@ -4948,11 +4973,20 @@ function loadConfig(raw) {
4948
4973
  }
4949
4974
  return layout;
4950
4975
  };
4951
- const themesToUse = Object.keys(p.themes).length ? p.themes : clone2(defaultConfig.themes);
4976
+ const cleaned = cleanThemes(p.themes, warn);
4977
+ const themes = Object.keys(cleaned).length ? cleaned : clone2(builtinThemes);
4978
+ if (!Object.hasOwn(themes, "default")) {
4979
+ themes["default"] = clone2(builtinThemes["default"] ?? []);
4980
+ }
4981
+ let theme = p.theme;
4982
+ if (!Object.hasOwn(themes, theme)) {
4983
+ warn(`theme "${theme}" not found; using "default"`);
4984
+ theme = "default";
4985
+ }
4952
4986
  const config = {
4953
4987
  version: 1,
4954
- theme: p.theme,
4955
- themes: cleanThemes(themesToUse, warn),
4988
+ theme,
4989
+ themes,
4956
4990
  defaults: { ...defaultConfig.defaults, ...p.defaults },
4957
4991
  surfaces: {
4958
4992
  band: surf("band"),
@@ -5057,7 +5091,6 @@ var UNSUPPORTED = {
5057
5091
  function baseStyle(raw, idFallback) {
5058
5092
  return {
5059
5093
  id: String(raw["id"] ?? `${idFallback}-${Math.random().toString(36).slice(2)}`),
5060
- bg: typeof raw["backgroundColor"] === "string" ? raw["backgroundColor"] : void 0,
5061
5094
  rawValue: raw["rawValue"] === true || void 0,
5062
5095
  merge: raw["merge"] === true || void 0
5063
5096
  };
package/dist/index.js CHANGED
@@ -4,10 +4,10 @@
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  var sub = process.argv[2];
6
6
  if (sub === "statusline") {
7
- const { runStatusline } = await import("./statusline-cmd-2YHMLVSM.js");
7
+ const { runStatusline } = await import("./statusline-cmd-5XRA4JYE.js");
8
8
  await runStatusline();
9
9
  } else {
10
10
  const { render } = await import("ink");
11
- const { App } = await import("./app-WR7CHOQI.js");
11
+ const { App } = await import("./app-DVVWJH7H.js");
12
12
  render(/* @__PURE__ */ jsx(App, {}));
13
13
  }
@@ -6,7 +6,7 @@ import {
6
6
  render,
7
7
  snapshotPath,
8
8
  toAnsi
9
- } from "./chunk-BCBGMRHQ.js";
9
+ } from "./chunk-EUAY5IC6.js";
10
10
 
11
11
  // src/statusline-cmd.ts
12
12
  function renderStatuslineAnsi(config, snapshot) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sushant-kum/ccstatus",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "Interactive configurator (npx @sushant-kum/ccstatus) for the ccstatus Claude Code status bar — band, status line, pane, and threshold toasts from one config.",
5
5
  "license": "MIT",
6
6
  "author": "Sushant Kumar",