clairo 0.2.0 → 0.3.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 (2) hide show
  1. package/dist/cli.js +277 -459
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -4,13 +4,14 @@
4
4
  import meow from "meow";
5
5
 
6
6
  // src/app.tsx
7
- import { useState as useState9 } from "react";
8
- import { Box as Box13, useApp, useInput as useInput11 } from "ink";
7
+ import { useState as useState8 } from "react";
8
+ import { Box as Box12, useApp, useInput as useInput10 } from "ink";
9
9
 
10
10
  // src/components/github/GitHubView.tsx
11
- import { useCallback, useEffect as useEffect3, useState as useState4 } from "react";
11
+ import { exec as exec3 } from "child_process";
12
+ import { useCallback, useEffect as useEffect3, useState as useState3 } from "react";
12
13
  import { TitledBox as TitledBox4 } from "@mishieck/ink-titled-box";
13
- import { Box as Box5, Text as Text5, useInput as useInput5 } from "ink";
14
+ import { Box as Box4, Text as Text4, useInput as useInput4 } from "ink";
14
15
 
15
16
  // src/lib/config/index.ts
16
17
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
@@ -127,8 +128,6 @@ function getCurrentBranch() {
127
128
 
128
129
  // src/lib/github/index.ts
129
130
  import { exec } from "child_process";
130
- import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
131
- import { join as join2 } from "path";
132
131
  import { promisify } from "util";
133
132
  var execAsync = promisify(exec);
134
133
  async function isGhInstalled() {
@@ -241,178 +240,14 @@ async function getPRDetails(prNumber, repo) {
241
240
  };
242
241
  }
243
242
  }
244
- function getPRTemplate(repoPath) {
245
- const templatePaths = [
246
- ".github/PULL_REQUEST_TEMPLATE.md",
247
- ".github/pull_request_template.md",
248
- "PULL_REQUEST_TEMPLATE.md",
249
- "pull_request_template.md",
250
- "docs/PULL_REQUEST_TEMPLATE.md"
251
- ];
252
- for (const templatePath of templatePaths) {
253
- const fullPath = join2(repoPath, templatePath);
254
- if (existsSync2(fullPath)) {
255
- try {
256
- return readFileSync2(fullPath, "utf-8");
257
- } catch {
258
- continue;
259
- }
260
- }
261
- }
262
- return null;
263
- }
264
- async function createPR(repo, title, body, baseBranch) {
265
- if (!await isGhInstalled()) {
266
- return {
267
- success: false,
268
- error: "GitHub CLI (gh) is not installed",
269
- errorType: "not_installed"
270
- };
271
- }
272
- if (!await isGhAuthenticated()) {
273
- return {
274
- success: false,
275
- error: "Not authenticated. Run 'gh auth login'",
276
- errorType: "not_authenticated"
277
- };
278
- }
279
- try {
280
- const baseArg = baseBranch ? `--base "${baseBranch}"` : "";
281
- const fields = "number,title,state,author,createdAt,isDraft";
282
- const escapedTitle = title.replace(/"/g, '\\"');
283
- const escapedBody = body.replace(/"/g, '\\"');
284
- const { stdout } = await execAsync(
285
- `gh pr create --title "${escapedTitle}" --body "${escapedBody}" ${baseArg} --repo "${repo}" --json ${fields}`
286
- );
287
- const pr = JSON.parse(stdout);
288
- return { success: true, data: pr };
289
- } catch (err) {
290
- const message = err instanceof Error ? err.message : "Failed to create PR";
291
- return {
292
- success: false,
293
- error: message,
294
- errorType: "api_error"
295
- };
296
- }
297
- }
298
-
299
- // src/components/github/CreatePRModal.tsx
300
- import { useState } from "react";
301
- import { Box, Text, useInput } from "ink";
302
-
303
- // src/lib/editor.ts
304
- import { spawnSync } from "child_process";
305
- import { mkdtempSync, readFileSync as readFileSync3, rmSync, writeFileSync as writeFileSync2 } from "fs";
306
- import { tmpdir } from "os";
307
- import { join as join3 } from "path";
308
- function openInEditor(content, filename) {
309
- const editor = process.env.VISUAL || process.env.EDITOR || "vi";
310
- const tempDir = mkdtempSync(join3(tmpdir(), "clairo-"));
311
- const tempFile = join3(tempDir, filename);
312
- try {
313
- writeFileSync2(tempFile, content);
314
- const result = spawnSync(editor, [tempFile], {
315
- stdio: "inherit"
316
- });
317
- process.stdout.write("\x1B[2J\x1B[H");
318
- process.stdout.emit("resize");
319
- if (result.status !== 0) {
320
- return null;
321
- }
322
- return readFileSync3(tempFile, "utf-8");
323
- } finally {
324
- try {
325
- rmSync(tempDir, { recursive: true });
326
- } catch {
327
- }
328
- }
329
- }
330
-
331
- // src/components/github/CreatePRModal.tsx
332
- import { jsx, jsxs } from "react/jsx-runtime";
333
- function CreatePRModal({ template, onSubmit, onCancel, loading, error }) {
334
- const [title, setTitle] = useState("");
335
- const [body, setBody] = useState(template ?? "");
336
- const [selectedItem, setSelectedItem] = useState("title");
337
- const items = ["title", "body", "submit"];
338
- useInput(
339
- (input, key) => {
340
- if (loading) return;
341
- if (key.escape) {
342
- onCancel();
343
- return;
344
- }
345
- if (key.upArrow || input === "k") {
346
- setSelectedItem((prev) => {
347
- const idx = items.indexOf(prev);
348
- return items[Math.max(0, idx - 1)];
349
- });
350
- return;
351
- }
352
- if (key.downArrow || input === "j") {
353
- setSelectedItem((prev) => {
354
- const idx = items.indexOf(prev);
355
- return items[Math.min(items.length - 1, idx + 1)];
356
- });
357
- return;
358
- }
359
- if (key.return) {
360
- if (selectedItem === "title") {
361
- const newTitle = openInEditor(title, "PR_TITLE.txt");
362
- if (newTitle !== null) {
363
- setTitle(newTitle.split("\n")[0].trim());
364
- }
365
- } else if (selectedItem === "body") {
366
- const newBody = openInEditor(body, "PR_DESCRIPTION.md");
367
- if (newBody !== null) {
368
- setBody(newBody);
369
- }
370
- } else if (selectedItem === "submit") {
371
- if (title.trim()) {
372
- onSubmit(title.trim(), body);
373
- }
374
- }
375
- }
376
- },
377
- { isActive: !loading }
378
- );
379
- const renderItem = (item, label, value) => {
380
- const isSelected = selectedItem === item;
381
- const prefix = isSelected ? "> " : " ";
382
- const color = isSelected ? "yellow" : void 0;
383
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
384
- /* @__PURE__ */ jsxs(Text, { color, bold: isSelected, children: [
385
- prefix,
386
- label
387
- ] }),
388
- value !== void 0 && /* @__PURE__ */ jsx(Box, { marginLeft: 4, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: value || "(empty - press Enter to edit)" }) })
389
- ] });
390
- };
391
- const truncatedBody = body ? body.split("\n").slice(0, 2).join(" ").slice(0, 60) + (body.length > 60 ? "..." : "") : "";
392
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, paddingY: 1, children: [
393
- /* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "Create Pull Request" }),
394
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Up/Down to select, Enter to edit, Esc to cancel" }),
395
- /* @__PURE__ */ jsx(Box, { marginTop: 1 }),
396
- error && /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { color: "red", children: error }) }),
397
- renderItem("title", "Title", title),
398
- /* @__PURE__ */ jsx(Box, { marginTop: 1 }),
399
- renderItem("body", "Description", truncatedBody),
400
- /* @__PURE__ */ jsx(Box, { marginTop: 1 }),
401
- /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: selectedItem === "submit" ? "green" : void 0, bold: selectedItem === "submit", children: [
402
- selectedItem === "submit" ? "> " : " ",
403
- title.trim() ? "[Submit PR]" : "[Enter title first]"
404
- ] }) }),
405
- loading && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "yellow", children: "Creating PR..." }) })
406
- ] });
407
- }
408
243
 
409
244
  // src/components/github/PRDetailsBox.tsx
410
245
  import { useRef } from "react";
411
246
  import open from "open";
412
247
  import { TitledBox } from "@mishieck/ink-titled-box";
413
- import { Box as Box2, Text as Text2, useInput as useInput2 } from "ink";
248
+ import { Box, Text, useInput } from "ink";
414
249
  import { ScrollView } from "ink-scroll-view";
415
- import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
250
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
416
251
  function getCheckColor(check) {
417
252
  const conclusion = check.conclusion ?? check.state;
418
253
  if (conclusion === "SUCCESS") return "green";
@@ -450,7 +285,7 @@ function PRDetailsBox({ pr, loading, error, isFocused }) {
450
285
  return { text: pr.mergeable ?? "UNKNOWN", color: "yellow" };
451
286
  };
452
287
  const mergeDisplay = getMergeDisplay();
453
- useInput2(
288
+ useInput(
454
289
  (input, key) => {
455
290
  var _a2, _b2;
456
291
  if (key.upArrow || input === "k") {
@@ -466,36 +301,36 @@ function PRDetailsBox({ pr, loading, error, isFocused }) {
466
301
  },
467
302
  { isActive: isFocused }
468
303
  );
469
- return /* @__PURE__ */ jsx2(TitledBox, { borderStyle: "round", titles: [displayTitle], borderColor, flexGrow: 2, children: /* @__PURE__ */ jsx2(Box2, { flexGrow: 1, overflow: "hidden", children: /* @__PURE__ */ jsx2(ScrollView, { ref: scrollRef, flexGrow: 1, children: /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingX: 1, children: [
470
- loading && /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Loading details..." }),
471
- error && /* @__PURE__ */ jsx2(Text2, { color: "red", children: error }),
472
- !loading && !error && !pr && /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Select a PR to view details" }),
473
- !loading && !error && pr && /* @__PURE__ */ jsxs2(Fragment, { children: [
474
- /* @__PURE__ */ jsx2(Text2, { bold: true, children: pr.title }),
475
- /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
304
+ return /* @__PURE__ */ jsx(TitledBox, { borderStyle: "round", titles: [displayTitle], borderColor, flexGrow: 2, children: /* @__PURE__ */ jsx(Box, { flexGrow: 1, overflow: "hidden", children: /* @__PURE__ */ jsx(ScrollView, { ref: scrollRef, flexGrow: 1, children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
305
+ loading && /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Loading details..." }),
306
+ error && /* @__PURE__ */ jsx(Text, { color: "red", children: error }),
307
+ !loading && !error && !pr && /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Select a PR to view details" }),
308
+ !loading && !error && pr && /* @__PURE__ */ jsxs(Fragment, { children: [
309
+ /* @__PURE__ */ jsx(Text, { bold: true, children: pr.title }),
310
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
476
311
  "by ",
477
312
  ((_a = pr.author) == null ? void 0 : _a.login) ?? "unknown",
478
313
  " | ",
479
314
  ((_b = pr.commits) == null ? void 0 : _b.length) ?? 0,
480
315
  " commits"
481
316
  ] }),
482
- /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, children: [
483
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Review: " }),
484
- /* @__PURE__ */ jsx2(Text2, { color: reviewColor, children: reviewStatus }),
485
- /* @__PURE__ */ jsx2(Text2, { children: " | " }),
486
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Status: " }),
487
- /* @__PURE__ */ jsx2(Text2, { color: mergeDisplay.color, children: mergeDisplay.text })
317
+ /* @__PURE__ */ jsxs(Box, { marginTop: 1, children: [
318
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Review: " }),
319
+ /* @__PURE__ */ jsx(Text, { color: reviewColor, children: reviewStatus }),
320
+ /* @__PURE__ */ jsx(Text, { children: " | " }),
321
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Status: " }),
322
+ /* @__PURE__ */ jsx(Text, { color: mergeDisplay.color, children: mergeDisplay.text })
488
323
  ] }),
489
- (((_c = pr.assignees) == null ? void 0 : _c.length) ?? 0) > 0 && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, children: [
490
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Assignees: " }),
491
- /* @__PURE__ */ jsx2(Text2, { children: pr.assignees.map((a) => a.login).join(", ") })
324
+ (((_c = pr.assignees) == null ? void 0 : _c.length) ?? 0) > 0 && /* @__PURE__ */ jsxs(Box, { marginTop: 1, children: [
325
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Assignees: " }),
326
+ /* @__PURE__ */ jsx(Text, { children: pr.assignees.map((a) => a.login).join(", ") })
492
327
  ] }),
493
- (((_d = pr.reviews) == null ? void 0 : _d.length) ?? 0) > 0 && /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
494
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Reviews:" }),
328
+ (((_d = pr.reviews) == null ? void 0 : _d.length) ?? 0) > 0 && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
329
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Reviews:" }),
495
330
  pr.reviews.map((review, idx) => {
496
331
  const color = review.state === "APPROVED" ? "green" : review.state === "CHANGES_REQUESTED" ? "red" : review.state === "COMMENTED" ? "blue" : "yellow";
497
332
  const icon = review.state === "APPROVED" ? "\u2713" : review.state === "CHANGES_REQUESTED" ? "\u2717" : review.state === "COMMENTED" ? "\u{1F4AC}" : "\u25CB";
498
- return /* @__PURE__ */ jsxs2(Text2, { color, children: [
333
+ return /* @__PURE__ */ jsxs(Text, { color, children: [
499
334
  " ",
500
335
  icon,
501
336
  " ",
@@ -503,31 +338,31 @@ function PRDetailsBox({ pr, loading, error, isFocused }) {
503
338
  ] }, idx);
504
339
  })
505
340
  ] }),
506
- (((_e = pr.reviewRequests) == null ? void 0 : _e.length) ?? 0) > 0 && /* @__PURE__ */ jsxs2(Box2, { children: [
507
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Pending: " }),
508
- /* @__PURE__ */ jsx2(Text2, { color: "yellow", children: pr.reviewRequests.map((r) => r.login ?? r.name ?? r.slug ?? "Team").join(", ") })
341
+ (((_e = pr.reviewRequests) == null ? void 0 : _e.length) ?? 0) > 0 && /* @__PURE__ */ jsxs(Box, { children: [
342
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Pending: " }),
343
+ /* @__PURE__ */ jsx(Text, { color: "yellow", children: pr.reviewRequests.map((r) => r.login ?? r.name ?? r.slug ?? "Team").join(", ") })
509
344
  ] }),
510
- (((_f = pr.statusCheckRollup) == null ? void 0 : _f.length) ?? 0) > 0 && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, flexDirection: "column", children: [
511
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Checks:" }),
512
- (_g = pr.statusCheckRollup) == null ? void 0 : _g.map((check, idx) => /* @__PURE__ */ jsxs2(Text2, { color: getCheckColor(check), children: [
345
+ (((_f = pr.statusCheckRollup) == null ? void 0 : _f.length) ?? 0) > 0 && /* @__PURE__ */ jsxs(Box, { marginTop: 1, flexDirection: "column", children: [
346
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Checks:" }),
347
+ (_g = pr.statusCheckRollup) == null ? void 0 : _g.map((check, idx) => /* @__PURE__ */ jsxs(Text, { color: getCheckColor(check), children: [
513
348
  " ",
514
349
  getCheckIcon(check),
515
350
  " ",
516
351
  check.name ?? check.context
517
352
  ] }, idx))
518
353
  ] }),
519
- pr.body && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, flexDirection: "column", children: [
520
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Description:" }),
521
- /* @__PURE__ */ jsx2(Text2, { children: pr.body })
354
+ pr.body && /* @__PURE__ */ jsxs(Box, { marginTop: 1, flexDirection: "column", children: [
355
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Description:" }),
356
+ /* @__PURE__ */ jsx(Text, { children: pr.body })
522
357
  ] })
523
358
  ] })
524
359
  ] }) }) }) });
525
360
  }
526
361
 
527
362
  // src/components/github/PullRequestsBox.tsx
528
- import { useEffect, useState as useState2 } from "react";
363
+ import { useEffect, useState } from "react";
529
364
  import { TitledBox as TitledBox2 } from "@mishieck/ink-titled-box";
530
- import { Box as Box3, Text as Text3, useInput as useInput3 } from "ink";
365
+ import { Box as Box2, Text as Text2, useInput as useInput2 } from "ink";
531
366
 
532
367
  // src/lib/clipboard.ts
533
368
  import { exec as exec2 } from "child_process";
@@ -551,7 +386,7 @@ async function copyToClipboard(text) {
551
386
  }
552
387
 
553
388
  // src/components/github/PullRequestsBox.tsx
554
- import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
389
+ import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
555
390
  function PullRequestsBox({
556
391
  prs,
557
392
  selectedPR,
@@ -563,13 +398,13 @@ function PullRequestsBox({
563
398
  repoSlug,
564
399
  isFocused
565
400
  }) {
566
- const [highlightedIndex, setHighlightedIndex] = useState2(0);
401
+ const [highlightedIndex, setHighlightedIndex] = useState(0);
567
402
  const totalItems = prs.length + 1;
568
403
  useEffect(() => {
569
404
  const idx = prs.findIndex((p) => p.number === (selectedPR == null ? void 0 : selectedPR.number));
570
405
  if (idx >= 0) setHighlightedIndex(idx);
571
406
  }, [selectedPR, prs]);
572
- useInput3(
407
+ useInput2(
573
408
  (input, key) => {
574
409
  if (!isFocused) return;
575
410
  if (key.upArrow || input === "k") {
@@ -596,16 +431,16 @@ function PullRequestsBox({
596
431
  const title = "[2] Pull Requests";
597
432
  const subtitle = branch ? ` (${branch})` : "";
598
433
  const borderColor = isFocused ? "yellow" : void 0;
599
- return /* @__PURE__ */ jsx3(TitledBox2, { borderStyle: "round", titles: [`${title}${subtitle}`], borderColor, flexShrink: 0, children: /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", paddingX: 1, overflow: "hidden", children: [
600
- loading && /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "Loading PRs..." }),
601
- error && /* @__PURE__ */ jsx3(Text3, { color: "red", children: error }),
602
- !loading && !error && /* @__PURE__ */ jsxs3(Fragment2, { children: [
603
- prs.length === 0 && /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "No PRs for this branch" }),
434
+ return /* @__PURE__ */ jsx2(TitledBox2, { borderStyle: "round", titles: [`${title}${subtitle}`], borderColor, flexShrink: 0, children: /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingX: 1, overflow: "hidden", children: [
435
+ loading && /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Loading PRs..." }),
436
+ error && /* @__PURE__ */ jsx2(Text2, { color: "red", children: error }),
437
+ !loading && !error && /* @__PURE__ */ jsxs2(Fragment2, { children: [
438
+ prs.length === 0 && /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "No PRs for this branch" }),
604
439
  prs.map((pr, idx) => {
605
440
  const isHighlighted = isFocused && idx === highlightedIndex;
606
441
  const isSelected = pr.number === (selectedPR == null ? void 0 : selectedPR.number);
607
442
  const prefix = isHighlighted ? "> " : isSelected ? "\u25CF " : " ";
608
- return /* @__PURE__ */ jsxs3(Text3, { color: isSelected ? "green" : void 0, children: [
443
+ return /* @__PURE__ */ jsxs2(Text2, { color: isSelected ? "green" : void 0, children: [
609
444
  prefix,
610
445
  "#",
611
446
  pr.number,
@@ -614,7 +449,7 @@ function PullRequestsBox({
614
449
  pr.title
615
450
  ] }, pr.number);
616
451
  }),
617
- /* @__PURE__ */ jsxs3(Text3, { color: "blue", children: [
452
+ /* @__PURE__ */ jsxs2(Text2, { color: "blue", children: [
618
453
  isFocused && highlightedIndex === prs.length ? "> " : " ",
619
454
  "+ Create new PR"
620
455
  ] })
@@ -623,17 +458,17 @@ function PullRequestsBox({
623
458
  }
624
459
 
625
460
  // src/components/github/RemotesBox.tsx
626
- import { useEffect as useEffect2, useState as useState3 } from "react";
461
+ import { useEffect as useEffect2, useState as useState2 } from "react";
627
462
  import { TitledBox as TitledBox3 } from "@mishieck/ink-titled-box";
628
- import { Box as Box4, Text as Text4, useInput as useInput4 } from "ink";
629
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
463
+ import { Box as Box3, Text as Text3, useInput as useInput3 } from "ink";
464
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
630
465
  function RemotesBox({ remotes, selectedRemote, onSelect, loading, error, isFocused }) {
631
- const [highlightedIndex, setHighlightedIndex] = useState3(0);
466
+ const [highlightedIndex, setHighlightedIndex] = useState2(0);
632
467
  useEffect2(() => {
633
468
  const idx = remotes.findIndex((r) => r.name === selectedRemote);
634
469
  if (idx >= 0) setHighlightedIndex(idx);
635
470
  }, [selectedRemote, remotes]);
636
- useInput4(
471
+ useInput3(
637
472
  (input, key) => {
638
473
  if (!isFocused || remotes.length === 0) return;
639
474
  if (key.upArrow || input === "k") {
@@ -650,15 +485,15 @@ function RemotesBox({ remotes, selectedRemote, onSelect, loading, error, isFocus
650
485
  );
651
486
  const title = "[1] Remotes";
652
487
  const borderColor = isFocused ? "yellow" : void 0;
653
- return /* @__PURE__ */ jsx4(TitledBox3, { borderStyle: "round", titles: [title], borderColor, flexShrink: 0, children: /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingX: 1, overflow: "hidden", children: [
654
- loading && /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "Loading..." }),
655
- error && /* @__PURE__ */ jsx4(Text4, { color: "red", children: error }),
656
- !loading && !error && remotes.length === 0 && /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "No remotes configured" }),
488
+ return /* @__PURE__ */ jsx3(TitledBox3, { borderStyle: "round", titles: [title], borderColor, flexShrink: 0, children: /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", paddingX: 1, overflow: "hidden", children: [
489
+ loading && /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "Loading..." }),
490
+ error && /* @__PURE__ */ jsx3(Text3, { color: "red", children: error }),
491
+ !loading && !error && remotes.length === 0 && /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "No remotes configured" }),
657
492
  !loading && !error && remotes.map((remote, idx) => {
658
493
  const isHighlighted = isFocused && idx === highlightedIndex;
659
494
  const isSelected = remote.name === selectedRemote;
660
495
  const prefix = isHighlighted ? "> " : isSelected ? "\u25CF " : " ";
661
- return /* @__PURE__ */ jsxs4(Text4, { color: isSelected ? "green" : void 0, children: [
496
+ return /* @__PURE__ */ jsxs3(Text3, { color: isSelected ? "green" : void 0, children: [
662
497
  prefix,
663
498
  remote.name,
664
499
  " (",
@@ -670,38 +505,26 @@ function RemotesBox({ remotes, selectedRemote, onSelect, loading, error, isFocus
670
505
  }
671
506
 
672
507
  // src/components/github/GitHubView.tsx
673
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
674
- function GitHubView({ isFocused, onModalChange, onKeybindingsChange }) {
675
- const [isRepo, setIsRepo] = useState4(null);
676
- const [repoPath, setRepoPath] = useState4(null);
677
- const [remotes, setRemotes] = useState4([]);
678
- const [currentBranch, setCurrentBranch] = useState4(null);
679
- const [currentRepoSlug, setCurrentRepoSlug] = useState4(null);
680
- const [selectedRemote, setSelectedRemote] = useState4(null);
681
- const [selectedPR, setSelectedPR] = useState4(null);
682
- const [prs, setPrs] = useState4([]);
683
- const [prDetails, setPrDetails] = useState4(null);
684
- const [loading, setLoading] = useState4({
508
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
509
+ function GitHubView({ isFocused, onKeybindingsChange }) {
510
+ const [isRepo, setIsRepo] = useState3(null);
511
+ const [repoPath, setRepoPath] = useState3(null);
512
+ const [remotes, setRemotes] = useState3([]);
513
+ const [currentBranch, setCurrentBranch] = useState3(null);
514
+ const [currentRepoSlug, setCurrentRepoSlug] = useState3(null);
515
+ const [selectedRemote, setSelectedRemote] = useState3(null);
516
+ const [selectedPR, setSelectedPR] = useState3(null);
517
+ const [prs, setPrs] = useState3([]);
518
+ const [prDetails, setPrDetails] = useState3(null);
519
+ const [loading, setLoading] = useState3({
685
520
  remotes: true,
686
521
  prs: false,
687
- details: false,
688
- createPR: false
522
+ details: false
689
523
  });
690
- const [errors, setErrors] = useState4({});
691
- const [showCreatePR, setShowCreatePR] = useState4(false);
692
- const [prTemplate, setPrTemplate] = useState4(null);
693
- const [focusedBox, setFocusedBox] = useState4("remotes");
524
+ const [errors, setErrors] = useState3({});
525
+ const [focusedBox, setFocusedBox] = useState3("remotes");
694
526
  useEffect3(() => {
695
527
  if (!isFocused) {
696
- setShowCreatePR(false);
697
- setErrors((prev) => ({ ...prev, createPR: void 0 }));
698
- }
699
- }, [isFocused]);
700
- useEffect3(() => {
701
- onModalChange == null ? void 0 : onModalChange(showCreatePR);
702
- }, [showCreatePR, onModalChange]);
703
- useEffect3(() => {
704
- if (!isFocused || showCreatePR) {
705
528
  onKeybindingsChange == null ? void 0 : onKeybindingsChange([]);
706
529
  return;
707
530
  }
@@ -710,13 +533,15 @@ function GitHubView({ isFocused, onModalChange, onKeybindingsChange }) {
710
533
  bindings.push({ key: "Enter", label: "Select Remote" });
711
534
  } else if (focusedBox === "prs") {
712
535
  bindings.push({ key: "n", label: "New PR", color: "green" });
536
+ bindings.push({ key: "r", label: "Refresh" });
713
537
  bindings.push({ key: "o", label: "Open", color: "green" });
714
538
  bindings.push({ key: "y", label: "Copy Link" });
715
539
  } else if (focusedBox === "details") {
540
+ bindings.push({ key: "r", label: "Refresh" });
716
541
  bindings.push({ key: "o", label: "Open", color: "green" });
717
542
  }
718
543
  onKeybindingsChange == null ? void 0 : onKeybindingsChange(bindings);
719
- }, [isFocused, focusedBox, showCreatePR, onKeybindingsChange]);
544
+ }, [isFocused, focusedBox, onKeybindingsChange]);
720
545
  useEffect3(() => {
721
546
  const gitRepoCheck = isGitRepo();
722
547
  setIsRepo(gitRepoCheck);
@@ -728,8 +553,6 @@ function GitHubView({ isFocused, onModalChange, onKeybindingsChange }) {
728
553
  const rootResult = getRepoRoot();
729
554
  if (rootResult.success) {
730
555
  setRepoPath(rootResult.data);
731
- const template = getPRTemplate(rootResult.data);
732
- setPrTemplate(template);
733
556
  }
734
557
  const branchResult = getCurrentBranch();
735
558
  if (branchResult.success) {
@@ -746,6 +569,43 @@ function GitHubView({ isFocused, onModalChange, onKeybindingsChange }) {
746
569
  }
747
570
  setLoading((prev) => ({ ...prev, remotes: false }));
748
571
  }, []);
572
+ const refreshPRs = useCallback(async () => {
573
+ if (!currentBranch || !currentRepoSlug) return;
574
+ setLoading((prev) => ({ ...prev, prs: true }));
575
+ try {
576
+ const result = await listPRsForBranch(currentBranch, currentRepoSlug);
577
+ if (result.success) {
578
+ setPrs(result.data);
579
+ if (result.data.length > 0) {
580
+ setSelectedPR((prev) => prev ?? result.data[0]);
581
+ }
582
+ setErrors((prev) => ({ ...prev, prs: void 0 }));
583
+ } else {
584
+ setErrors((prev) => ({ ...prev, prs: result.error }));
585
+ }
586
+ } catch (err) {
587
+ setErrors((prev) => ({ ...prev, prs: String(err) }));
588
+ } finally {
589
+ setLoading((prev) => ({ ...prev, prs: false }));
590
+ }
591
+ }, [currentBranch, currentRepoSlug]);
592
+ const refreshDetails = useCallback(async () => {
593
+ if (!selectedPR || !currentRepoSlug) return;
594
+ setLoading((prev) => ({ ...prev, details: true }));
595
+ try {
596
+ const result = await getPRDetails(selectedPR.number, currentRepoSlug);
597
+ if (result.success) {
598
+ setPrDetails(result.data);
599
+ setErrors((prev) => ({ ...prev, details: void 0 }));
600
+ } else {
601
+ setErrors((prev) => ({ ...prev, details: result.error }));
602
+ }
603
+ } catch (err) {
604
+ setErrors((prev) => ({ ...prev, details: String(err) }));
605
+ } finally {
606
+ setLoading((prev) => ({ ...prev, details: false }));
607
+ }
608
+ }, [selectedPR, currentRepoSlug]);
749
609
  useEffect3(() => {
750
610
  if (!selectedRemote || !currentBranch) return;
751
611
  const remote = remotes.find((r) => r.name === selectedRemote);
@@ -753,52 +613,21 @@ function GitHubView({ isFocused, onModalChange, onKeybindingsChange }) {
753
613
  const repo = getRepoFromRemote(remote.url);
754
614
  if (!repo) return;
755
615
  setCurrentRepoSlug(repo);
756
- setLoading((prev) => ({ ...prev, prs: true }));
757
616
  setPrs([]);
758
617
  setSelectedPR(null);
759
- const fetchPRs = async () => {
760
- try {
761
- const result = await listPRsForBranch(currentBranch, repo);
762
- if (result.success) {
763
- setPrs(result.data);
764
- if (result.data.length > 0) {
765
- setSelectedPR(result.data[0]);
766
- }
767
- setErrors((prev) => ({ ...prev, prs: void 0 }));
768
- } else {
769
- setErrors((prev) => ({ ...prev, prs: result.error }));
770
- }
771
- } catch (err) {
772
- setErrors((prev) => ({ ...prev, prs: String(err) }));
773
- } finally {
774
- setLoading((prev) => ({ ...prev, prs: false }));
775
- }
776
- };
777
- fetchPRs();
778
618
  }, [selectedRemote, currentBranch, remotes]);
619
+ useEffect3(() => {
620
+ if (currentRepoSlug && currentBranch) {
621
+ refreshPRs();
622
+ }
623
+ }, [currentRepoSlug, currentBranch, refreshPRs]);
779
624
  useEffect3(() => {
780
625
  if (!selectedPR || !currentRepoSlug) {
781
626
  setPrDetails(null);
782
627
  return;
783
628
  }
784
- setLoading((prev) => ({ ...prev, details: true }));
785
- const fetchDetails = async () => {
786
- try {
787
- const result = await getPRDetails(selectedPR.number, currentRepoSlug);
788
- if (result.success) {
789
- setPrDetails(result.data);
790
- setErrors((prev) => ({ ...prev, details: void 0 }));
791
- } else {
792
- setErrors((prev) => ({ ...prev, details: result.error }));
793
- }
794
- } catch (err) {
795
- setErrors((prev) => ({ ...prev, details: String(err) }));
796
- } finally {
797
- setLoading((prev) => ({ ...prev, details: false }));
798
- }
799
- };
800
- fetchDetails();
801
- }, [selectedPR, currentRepoSlug]);
629
+ refreshDetails();
630
+ }, [selectedPR, currentRepoSlug, refreshDetails]);
802
631
  const handleRemoteSelect = useCallback(
803
632
  (remoteName) => {
804
633
  setSelectedRemote(remoteName);
@@ -812,57 +641,27 @@ function GitHubView({ isFocused, onModalChange, onKeybindingsChange }) {
812
641
  setSelectedPR(pr);
813
642
  }, []);
814
643
  const handleCreatePR = useCallback(() => {
815
- setShowCreatePR(true);
816
- setErrors((prev) => ({ ...prev, createPR: void 0 }));
817
- }, []);
818
- const handleCreatePRSubmit = useCallback(
819
- async (title, body) => {
820
- if (!currentRepoSlug) return;
821
- setLoading((prev) => ({ ...prev, createPR: true }));
822
- setErrors((prev) => ({ ...prev, createPR: void 0 }));
823
- try {
824
- const result = await createPR(currentRepoSlug, title, body);
825
- if (result.success) {
826
- setShowCreatePR(false);
827
- if (currentBranch) {
828
- const prsResult = await listPRsForBranch(currentBranch, currentRepoSlug);
829
- if (prsResult.success) {
830
- setPrs(prsResult.data);
831
- const newPR = prsResult.data.find((p) => p.number === result.data.number);
832
- if (newPR) {
833
- setSelectedPR(newPR);
834
- }
835
- }
836
- }
837
- } else {
838
- setErrors((prev) => ({ ...prev, createPR: result.error }));
839
- }
840
- } catch (err) {
841
- setErrors((prev) => ({ ...prev, createPR: String(err) }));
842
- } finally {
843
- setLoading((prev) => ({ ...prev, createPR: false }));
844
- }
845
- },
846
- [currentRepoSlug, currentBranch]
847
- );
848
- const handleCreatePRCancel = useCallback(() => {
849
- setShowCreatePR(false);
850
- setErrors((prev) => ({ ...prev, createPR: void 0 }));
644
+ exec3("gh pr create --web", () => {
645
+ process.stdout.emit("resize");
646
+ });
851
647
  }, []);
852
- useInput5(
648
+ useInput4(
853
649
  (input) => {
854
- if (showCreatePR) return;
855
650
  if (input === "1") setFocusedBox("remotes");
856
651
  if (input === "2") setFocusedBox("prs");
857
652
  if (input === "3") setFocusedBox("details");
653
+ if (input === "r") {
654
+ if (focusedBox === "prs") refreshPRs();
655
+ if (focusedBox === "details") refreshDetails();
656
+ }
858
657
  },
859
- { isActive: isFocused && !showCreatePR }
658
+ { isActive: isFocused }
860
659
  );
861
660
  if (isRepo === false) {
862
- return /* @__PURE__ */ jsx5(TitledBox4, { borderStyle: "round", titles: ["Error"], flexGrow: 1, children: /* @__PURE__ */ jsx5(Text5, { color: "red", children: "Current directory is not a git repository" }) });
661
+ return /* @__PURE__ */ jsx4(TitledBox4, { borderStyle: "round", titles: ["Error"], flexGrow: 1, children: /* @__PURE__ */ jsx4(Text4, { color: "red", children: "Current directory is not a git repository" }) });
863
662
  }
864
- return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", flexGrow: 1, children: [
865
- /* @__PURE__ */ jsx5(
663
+ return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", flexGrow: 1, children: [
664
+ /* @__PURE__ */ jsx4(
866
665
  RemotesBox,
867
666
  {
868
667
  remotes,
@@ -870,10 +669,10 @@ function GitHubView({ isFocused, onModalChange, onKeybindingsChange }) {
870
669
  onSelect: handleRemoteSelect,
871
670
  loading: loading.remotes,
872
671
  error: errors.remotes,
873
- isFocused: isFocused && !showCreatePR && focusedBox === "remotes"
672
+ isFocused: isFocused && focusedBox === "remotes"
874
673
  }
875
674
  ),
876
- /* @__PURE__ */ jsx5(
675
+ /* @__PURE__ */ jsx4(
877
676
  PullRequestsBox,
878
677
  {
879
678
  prs,
@@ -884,36 +683,26 @@ function GitHubView({ isFocused, onModalChange, onKeybindingsChange }) {
884
683
  error: errors.prs,
885
684
  branch: currentBranch,
886
685
  repoSlug: currentRepoSlug,
887
- isFocused: isFocused && !showCreatePR && focusedBox === "prs"
686
+ isFocused: isFocused && focusedBox === "prs"
888
687
  }
889
688
  ),
890
- showCreatePR && /* @__PURE__ */ jsx5(
891
- CreatePRModal,
892
- {
893
- template: prTemplate,
894
- onSubmit: handleCreatePRSubmit,
895
- onCancel: handleCreatePRCancel,
896
- loading: loading.createPR,
897
- error: errors.createPR
898
- }
899
- ),
900
- /* @__PURE__ */ jsx5(
689
+ /* @__PURE__ */ jsx4(
901
690
  PRDetailsBox,
902
691
  {
903
692
  pr: prDetails,
904
693
  loading: loading.details,
905
694
  error: errors.details,
906
- isFocused: isFocused && !showCreatePR && focusedBox === "details"
695
+ isFocused: isFocused && focusedBox === "details"
907
696
  }
908
697
  )
909
698
  ] });
910
699
  }
911
700
 
912
701
  // src/components/jira/JiraView.tsx
913
- import { useCallback as useCallback2, useEffect as useEffect5, useState as useState8 } from "react";
702
+ import { useCallback as useCallback2, useEffect as useEffect5, useState as useState7 } from "react";
914
703
  import open2 from "open";
915
704
  import { TitledBox as TitledBox5 } from "@mishieck/ink-titled-box";
916
- import { Box as Box11, Text as Text11, useInput as useInput10 } from "ink";
705
+ import { Box as Box10, Text as Text10, useInput as useInput9 } from "ink";
917
706
 
918
707
  // src/lib/jira/parser.ts
919
708
  var TICKET_KEY_PATTERN = /^[A-Z][A-Z0-9]+-\d+$/;
@@ -1139,15 +928,15 @@ async function applyTransition(auth, ticketKey, transitionId) {
1139
928
  }
1140
929
 
1141
930
  // src/components/jira/ChangeStatusModal.tsx
1142
- import { useEffect as useEffect4, useState as useState5 } from "react";
1143
- import { Box as Box6, Text as Text6, useInput as useInput6 } from "ink";
931
+ import { useEffect as useEffect4, useState as useState4 } from "react";
932
+ import { Box as Box5, Text as Text5, useInput as useInput5 } from "ink";
1144
933
  import SelectInput from "ink-select-input";
1145
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
934
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1146
935
  function ChangeStatusModal({ repoPath, ticketKey, currentStatus, onComplete, onCancel }) {
1147
- const [transitions, setTransitions] = useState5([]);
1148
- const [loading, setLoading] = useState5(true);
1149
- const [applying, setApplying] = useState5(false);
1150
- const [error, setError] = useState5(null);
936
+ const [transitions, setTransitions] = useState4([]);
937
+ const [loading, setLoading] = useState4(true);
938
+ const [applying, setApplying] = useState4(false);
939
+ const [error, setError] = useState4(null);
1151
940
  useEffect4(() => {
1152
941
  const fetchTransitions = async () => {
1153
942
  const siteUrl = getJiraSiteUrl(repoPath);
@@ -1189,7 +978,7 @@ function ChangeStatusModal({ repoPath, ticketKey, currentStatus, onComplete, onC
1189
978
  setApplying(false);
1190
979
  }
1191
980
  };
1192
- useInput6(
981
+ useInput5(
1193
982
  (_input, key) => {
1194
983
  if (key.escape && !applying) {
1195
984
  onCancel();
@@ -1202,24 +991,54 @@ function ChangeStatusModal({ repoPath, ticketKey, currentStatus, onComplete, onC
1202
991
  value: t.id
1203
992
  }));
1204
993
  const initialIndex = Math.max(0, transitions.findIndex((t) => t.to.name === currentStatus));
1205
- return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, paddingY: 1, children: [
1206
- /* @__PURE__ */ jsxs6(Text6, { bold: true, color: "yellow", children: [
994
+ return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, paddingY: 1, children: [
995
+ /* @__PURE__ */ jsxs5(Text5, { bold: true, color: "yellow", children: [
1207
996
  "Change Status: ",
1208
997
  ticketKey
1209
998
  ] }),
1210
- loading && /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Loading transitions..." }),
1211
- error && /* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { color: "red", children: error }) }),
1212
- !loading && !error && transitions.length === 0 && /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "No available transitions" }),
1213
- !loading && !error && transitions.length > 0 && !applying && /* @__PURE__ */ jsx6(Box6, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx6(SelectInput, { items, initialIndex, onSelect: handleSelect }) }),
1214
- applying && /* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { color: "yellow", children: "Updating status..." }) }),
1215
- /* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Esc to cancel" }) })
999
+ loading && /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "Loading transitions..." }),
1000
+ error && /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text5, { color: "red", children: error }) }),
1001
+ !loading && !error && transitions.length === 0 && /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "No available transitions" }),
1002
+ !loading && !error && transitions.length > 0 && !applying && /* @__PURE__ */ jsx5(Box5, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx5(SelectInput, { items, initialIndex, onSelect: handleSelect }) }),
1003
+ applying && /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text5, { color: "yellow", children: "Updating status..." }) }),
1004
+ /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "Esc to cancel" }) })
1216
1005
  ] });
1217
1006
  }
1218
1007
 
1219
1008
  // src/components/jira/ConfigureJiraSiteModal.tsx
1220
- import { useState as useState6 } from "react";
1221
- import { Box as Box7, Text as Text7, useInput as useInput7 } from "ink";
1222
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1009
+ import { useState as useState5 } from "react";
1010
+ import { Box as Box6, Text as Text6, useInput as useInput6 } from "ink";
1011
+
1012
+ // src/lib/editor.ts
1013
+ import { spawnSync } from "child_process";
1014
+ import { mkdtempSync, readFileSync as readFileSync2, rmSync, writeFileSync as writeFileSync2 } from "fs";
1015
+ import { tmpdir } from "os";
1016
+ import { join as join2 } from "path";
1017
+ function openInEditor(content, filename) {
1018
+ const editor = process.env.VISUAL || process.env.EDITOR || "vi";
1019
+ const tempDir = mkdtempSync(join2(tmpdir(), "clairo-"));
1020
+ const tempFile = join2(tempDir, filename);
1021
+ try {
1022
+ writeFileSync2(tempFile, content);
1023
+ const result = spawnSync(editor, [tempFile], {
1024
+ stdio: "inherit"
1025
+ });
1026
+ process.stdout.write("\x1B[2J\x1B[H");
1027
+ process.stdout.emit("resize");
1028
+ if (result.status !== 0) {
1029
+ return null;
1030
+ }
1031
+ return readFileSync2(tempFile, "utf-8");
1032
+ } finally {
1033
+ try {
1034
+ rmSync(tempDir, { recursive: true });
1035
+ } catch {
1036
+ }
1037
+ }
1038
+ }
1039
+
1040
+ // src/components/jira/ConfigureJiraSiteModal.tsx
1041
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1223
1042
  function ConfigureJiraSiteModal({
1224
1043
  initialSiteUrl,
1225
1044
  initialEmail,
@@ -1228,13 +1047,13 @@ function ConfigureJiraSiteModal({
1228
1047
  loading,
1229
1048
  error
1230
1049
  }) {
1231
- const [siteUrl, setSiteUrl] = useState6(initialSiteUrl ?? "");
1232
- const [email, setEmail] = useState6(initialEmail ?? "");
1233
- const [apiToken, setApiToken] = useState6("");
1234
- const [selectedItem, setSelectedItem] = useState6("siteUrl");
1050
+ const [siteUrl, setSiteUrl] = useState5(initialSiteUrl ?? "");
1051
+ const [email, setEmail] = useState5(initialEmail ?? "");
1052
+ const [apiToken, setApiToken] = useState5("");
1053
+ const [selectedItem, setSelectedItem] = useState5("siteUrl");
1235
1054
  const items = ["siteUrl", "email", "apiToken", "submit"];
1236
1055
  const canSubmit = siteUrl.trim() && email.trim() && apiToken.trim();
1237
- useInput7(
1056
+ useInput6(
1238
1057
  (input, key) => {
1239
1058
  if (loading) return;
1240
1059
  if (key.escape) {
@@ -1283,43 +1102,43 @@ function ConfigureJiraSiteModal({
1283
1102
  const prefix = isSelected ? "> " : " ";
1284
1103
  const color = isSelected ? "yellow" : void 0;
1285
1104
  const displayValue = isSensitive && value ? "*".repeat(Math.min(value.length, 20)) : value;
1286
- return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
1287
- /* @__PURE__ */ jsxs7(Text7, { color, bold: isSelected, children: [
1105
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
1106
+ /* @__PURE__ */ jsxs6(Text6, { color, bold: isSelected, children: [
1288
1107
  prefix,
1289
1108
  label
1290
1109
  ] }),
1291
- value !== void 0 && /* @__PURE__ */ jsx7(Box7, { marginLeft: 4, children: /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: displayValue || "(empty - press Enter to edit)" }) })
1110
+ value !== void 0 && /* @__PURE__ */ jsx6(Box6, { marginLeft: 4, children: /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: displayValue || "(empty - press Enter to edit)" }) })
1292
1111
  ] });
1293
1112
  };
1294
- return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, paddingY: 1, children: [
1295
- /* @__PURE__ */ jsx7(Text7, { bold: true, color: "cyan", children: "Configure Jira Site" }),
1296
- /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Up/Down to select, Enter to edit, Esc to cancel" }),
1297
- /* @__PURE__ */ jsx7(Box7, { marginTop: 1 }),
1298
- error && /* @__PURE__ */ jsx7(Box7, { marginBottom: 1, children: /* @__PURE__ */ jsx7(Text7, { color: "red", children: error }) }),
1113
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, paddingY: 1, children: [
1114
+ /* @__PURE__ */ jsx6(Text6, { bold: true, color: "cyan", children: "Configure Jira Site" }),
1115
+ /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Up/Down to select, Enter to edit, Esc to cancel" }),
1116
+ /* @__PURE__ */ jsx6(Box6, { marginTop: 1 }),
1117
+ error && /* @__PURE__ */ jsx6(Box6, { marginBottom: 1, children: /* @__PURE__ */ jsx6(Text6, { color: "red", children: error }) }),
1299
1118
  renderItem("siteUrl", "Site URL (e.g., https://company.atlassian.net)", siteUrl),
1300
- /* @__PURE__ */ jsx7(Box7, { marginTop: 1 }),
1119
+ /* @__PURE__ */ jsx6(Box6, { marginTop: 1 }),
1301
1120
  renderItem("email", "Email", email),
1302
- /* @__PURE__ */ jsx7(Box7, { marginTop: 1 }),
1121
+ /* @__PURE__ */ jsx6(Box6, { marginTop: 1 }),
1303
1122
  renderItem("apiToken", "API Token", apiToken, true),
1304
- /* @__PURE__ */ jsx7(Box7, { marginTop: 1 }),
1305
- /* @__PURE__ */ jsx7(Box7, { children: /* @__PURE__ */ jsxs7(Text7, { color: selectedItem === "submit" ? "green" : void 0, bold: selectedItem === "submit", children: [
1123
+ /* @__PURE__ */ jsx6(Box6, { marginTop: 1 }),
1124
+ /* @__PURE__ */ jsx6(Box6, { children: /* @__PURE__ */ jsxs6(Text6, { color: selectedItem === "submit" ? "green" : void 0, bold: selectedItem === "submit", children: [
1306
1125
  selectedItem === "submit" ? "> " : " ",
1307
1126
  canSubmit ? "[Save Configuration]" : "[Fill all fields first]"
1308
1127
  ] }) }),
1309
- loading && /* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text7, { color: "yellow", children: "Validating credentials..." }) }),
1310
- /* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Get your API token from: https://id.atlassian.com/manage-profile/security/api-tokens" }) })
1128
+ loading && /* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { color: "yellow", children: "Validating credentials..." }) }),
1129
+ /* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Get your API token from: https://id.atlassian.com/manage-profile/security/api-tokens" }) })
1311
1130
  ] });
1312
1131
  }
1313
1132
 
1314
1133
  // src/components/jira/LinkTicketModal.tsx
1315
- import { useState as useState7 } from "react";
1316
- import { Box as Box9, Text as Text9, useInput as useInput9 } from "ink";
1134
+ import { useState as useState6 } from "react";
1135
+ import { Box as Box8, Text as Text8, useInput as useInput8 } from "ink";
1317
1136
 
1318
1137
  // src/components/ui/TextInput.tsx
1319
- import { Box as Box8, Text as Text8, useInput as useInput8 } from "ink";
1320
- import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
1138
+ import { Box as Box7, Text as Text7, useInput as useInput7 } from "ink";
1139
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1321
1140
  function TextInput({ value, onChange, placeholder, isActive, mask }) {
1322
- useInput8(
1141
+ useInput7(
1323
1142
  (input, key) => {
1324
1143
  if (key.backspace || key.delete) {
1325
1144
  if (value.length > 0) {
@@ -1338,18 +1157,18 @@ function TextInput({ value, onChange, placeholder, isActive, mask }) {
1338
1157
  );
1339
1158
  const displayValue = mask ? "*".repeat(value.length) : value;
1340
1159
  const showPlaceholder = value.length === 0 && placeholder;
1341
- return /* @__PURE__ */ jsx8(Box8, { children: /* @__PURE__ */ jsxs8(Text8, { children: [
1342
- showPlaceholder ? /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: placeholder }) : /* @__PURE__ */ jsx8(Text8, { children: displayValue }),
1343
- isActive && /* @__PURE__ */ jsx8(Text8, { backgroundColor: "yellow", children: " " })
1160
+ return /* @__PURE__ */ jsx7(Box7, { children: /* @__PURE__ */ jsxs7(Text7, { children: [
1161
+ showPlaceholder ? /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: placeholder }) : /* @__PURE__ */ jsx7(Text7, { children: displayValue }),
1162
+ isActive && /* @__PURE__ */ jsx7(Text7, { backgroundColor: "yellow", children: " " })
1344
1163
  ] }) });
1345
1164
  }
1346
1165
 
1347
1166
  // src/components/jira/LinkTicketModal.tsx
1348
- import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
1167
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
1349
1168
  function LinkTicketModal({ onSubmit, onCancel, loading, error }) {
1350
- const [ticketInput, setTicketInput] = useState7("");
1169
+ const [ticketInput, setTicketInput] = useState6("");
1351
1170
  const canSubmit = ticketInput.trim().length > 0;
1352
- useInput9(
1171
+ useInput8(
1353
1172
  (_input, key) => {
1354
1173
  if (loading) return;
1355
1174
  if (key.escape) {
@@ -1362,14 +1181,14 @@ function LinkTicketModal({ onSubmit, onCancel, loading, error }) {
1362
1181
  },
1363
1182
  { isActive: !loading }
1364
1183
  );
1365
- return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, paddingY: 1, children: [
1366
- /* @__PURE__ */ jsx9(Text9, { bold: true, color: "yellow", children: "Link Jira Ticket" }),
1367
- /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "Type ticket ID, Enter to submit, Esc to cancel" }),
1368
- /* @__PURE__ */ jsx9(Box9, { marginTop: 1 }),
1369
- error && /* @__PURE__ */ jsx9(Box9, { marginBottom: 1, children: /* @__PURE__ */ jsx9(Text9, { color: "red", children: error }) }),
1370
- /* @__PURE__ */ jsxs9(Box9, { children: [
1371
- /* @__PURE__ */ jsx9(Text9, { color: "blue", children: "Ticket: " }),
1372
- /* @__PURE__ */ jsx9(
1184
+ return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, paddingY: 1, children: [
1185
+ /* @__PURE__ */ jsx8(Text8, { bold: true, color: "yellow", children: "Link Jira Ticket" }),
1186
+ /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: "Type ticket ID, Enter to submit, Esc to cancel" }),
1187
+ /* @__PURE__ */ jsx8(Box8, { marginTop: 1 }),
1188
+ error && /* @__PURE__ */ jsx8(Box8, { marginBottom: 1, children: /* @__PURE__ */ jsx8(Text8, { color: "red", children: error }) }),
1189
+ /* @__PURE__ */ jsxs8(Box8, { children: [
1190
+ /* @__PURE__ */ jsx8(Text8, { color: "blue", children: "Ticket: " }),
1191
+ /* @__PURE__ */ jsx8(
1373
1192
  TextInput,
1374
1193
  {
1375
1194
  value: ticketInput,
@@ -1379,23 +1198,23 @@ function LinkTicketModal({ onSubmit, onCancel, loading, error }) {
1379
1198
  }
1380
1199
  )
1381
1200
  ] }),
1382
- loading && /* @__PURE__ */ jsx9(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text9, { color: "yellow", children: "Fetching ticket..." }) }),
1383
- /* @__PURE__ */ jsx9(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "Examples: PROJ-123 or https://company.atlassian.net/browse/PROJ-123" }) })
1201
+ loading && /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(Text8, { color: "yellow", children: "Fetching ticket..." }) }),
1202
+ /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: "Examples: PROJ-123 or https://company.atlassian.net/browse/PROJ-123" }) })
1384
1203
  ] });
1385
1204
  }
1386
1205
 
1387
1206
  // src/components/jira/TicketItem.tsx
1388
- import { Box as Box10, Text as Text10 } from "ink";
1389
- import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
1207
+ import { Box as Box9, Text as Text9 } from "ink";
1208
+ import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
1390
1209
  function TicketItem({ ticketKey, summary, status, isHighlighted, isSelected }) {
1391
1210
  const prefix = isHighlighted ? "> " : isSelected ? "\u25CF " : " ";
1392
1211
  const textColor = isSelected ? "green" : void 0;
1393
- return /* @__PURE__ */ jsx10(Box10, { children: /* @__PURE__ */ jsxs10(Text10, { color: textColor, children: [
1212
+ return /* @__PURE__ */ jsx9(Box9, { children: /* @__PURE__ */ jsxs9(Text9, { color: textColor, children: [
1394
1213
  prefix,
1395
- /* @__PURE__ */ jsx10(Text10, { bold: true, color: "blue", children: ticketKey }),
1214
+ /* @__PURE__ */ jsx9(Text9, { bold: true, color: "blue", children: ticketKey }),
1396
1215
  " ",
1397
1216
  summary,
1398
- status && /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
1217
+ status && /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
1399
1218
  " [",
1400
1219
  status,
1401
1220
  "]"
@@ -1404,19 +1223,19 @@ function TicketItem({ ticketKey, summary, status, isHighlighted, isSelected }) {
1404
1223
  }
1405
1224
 
1406
1225
  // src/components/jira/JiraView.tsx
1407
- import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
1226
+ import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
1408
1227
  function JiraView({ isFocused, onModalChange, onKeybindingsChange }) {
1409
- const [repoPath, setRepoPath] = useState8(null);
1410
- const [currentBranch, setCurrentBranch] = useState8(null);
1411
- const [isRepo, setIsRepo] = useState8(null);
1412
- const [jiraState, setJiraState] = useState8("not_configured");
1413
- const [tickets, setTickets] = useState8([]);
1414
- const [highlightedIndex, setHighlightedIndex] = useState8(0);
1415
- const [showConfigureModal, setShowConfigureModal] = useState8(false);
1416
- const [showLinkModal, setShowLinkModal] = useState8(false);
1417
- const [showStatusModal, setShowStatusModal] = useState8(false);
1418
- const [loading, setLoading] = useState8({ configure: false, link: false });
1419
- const [errors, setErrors] = useState8({});
1228
+ const [repoPath, setRepoPath] = useState7(null);
1229
+ const [currentBranch, setCurrentBranch] = useState7(null);
1230
+ const [isRepo, setIsRepo] = useState7(null);
1231
+ const [jiraState, setJiraState] = useState7("not_configured");
1232
+ const [tickets, setTickets] = useState7([]);
1233
+ const [highlightedIndex, setHighlightedIndex] = useState7(0);
1234
+ const [showConfigureModal, setShowConfigureModal] = useState7(false);
1235
+ const [showLinkModal, setShowLinkModal] = useState7(false);
1236
+ const [showStatusModal, setShowStatusModal] = useState7(false);
1237
+ const [loading, setLoading] = useState7({ configure: false, link: false });
1238
+ const [errors, setErrors] = useState7({});
1420
1239
  useEffect5(() => {
1421
1240
  if (!isFocused) {
1422
1241
  setShowConfigureModal(false);
@@ -1579,7 +1398,7 @@ function JiraView({ isFocused, onModalChange, onKeybindingsChange }) {
1579
1398
  });
1580
1399
  }
1581
1400
  }, [repoPath, tickets, highlightedIndex]);
1582
- useInput10(
1401
+ useInput9(
1583
1402
  (input, key) => {
1584
1403
  if (showConfigureModal || showLinkModal || showStatusModal) return;
1585
1404
  if (input === "c" && jiraState === "not_configured") {
@@ -1619,12 +1438,12 @@ function JiraView({ isFocused, onModalChange, onKeybindingsChange }) {
1619
1438
  { isActive: isFocused && !showConfigureModal && !showLinkModal && !showStatusModal }
1620
1439
  );
1621
1440
  if (isRepo === false) {
1622
- return /* @__PURE__ */ jsx11(TitledBox5, { borderStyle: "round", titles: ["Jira"], flexShrink: 0, children: /* @__PURE__ */ jsx11(Text11, { color: "red", children: "Not a git repository" }) });
1441
+ return /* @__PURE__ */ jsx10(TitledBox5, { borderStyle: "round", titles: ["Jira"], flexShrink: 0, children: /* @__PURE__ */ jsx10(Text10, { color: "red", children: "Not a git repository" }) });
1623
1442
  }
1624
1443
  if (showConfigureModal) {
1625
1444
  const siteUrl = repoPath ? getJiraSiteUrl(repoPath) : void 0;
1626
1445
  const creds = repoPath ? getJiraCredentials(repoPath) : { email: null, apiToken: null };
1627
- return /* @__PURE__ */ jsx11(Box11, { flexDirection: "column", flexShrink: 0, children: /* @__PURE__ */ jsx11(
1446
+ return /* @__PURE__ */ jsx10(Box10, { flexDirection: "column", flexShrink: 0, children: /* @__PURE__ */ jsx10(
1628
1447
  ConfigureJiraSiteModal,
1629
1448
  {
1630
1449
  initialSiteUrl: siteUrl ?? void 0,
@@ -1640,7 +1459,7 @@ function JiraView({ isFocused, onModalChange, onKeybindingsChange }) {
1640
1459
  ) });
1641
1460
  }
1642
1461
  if (showLinkModal) {
1643
- return /* @__PURE__ */ jsx11(Box11, { flexDirection: "column", flexShrink: 0, children: /* @__PURE__ */ jsx11(
1462
+ return /* @__PURE__ */ jsx10(Box10, { flexDirection: "column", flexShrink: 0, children: /* @__PURE__ */ jsx10(
1644
1463
  LinkTicketModal,
1645
1464
  {
1646
1465
  onSubmit: handleLinkSubmit,
@@ -1655,7 +1474,7 @@ function JiraView({ isFocused, onModalChange, onKeybindingsChange }) {
1655
1474
  }
1656
1475
  if (showStatusModal && repoPath && currentBranch && tickets[highlightedIndex]) {
1657
1476
  const ticket = tickets[highlightedIndex];
1658
- return /* @__PURE__ */ jsx11(Box11, { flexDirection: "column", flexShrink: 0, children: /* @__PURE__ */ jsx11(
1477
+ return /* @__PURE__ */ jsx10(Box10, { flexDirection: "column", flexShrink: 0, children: /* @__PURE__ */ jsx10(
1659
1478
  ChangeStatusModal,
1660
1479
  {
1661
1480
  repoPath,
@@ -1672,10 +1491,10 @@ function JiraView({ isFocused, onModalChange, onKeybindingsChange }) {
1672
1491
  }
1673
1492
  const title = "[4] Jira";
1674
1493
  const borderColor = isFocused ? "yellow" : void 0;
1675
- return /* @__PURE__ */ jsx11(TitledBox5, { borderStyle: "round", titles: [title], borderColor, flexShrink: 0, children: /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", paddingX: 1, children: [
1676
- jiraState === "not_configured" && /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "No Jira site configured" }),
1677
- jiraState === "no_tickets" && /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "No tickets linked to this branch" }),
1678
- jiraState === "has_tickets" && tickets.map((ticket, idx) => /* @__PURE__ */ jsx11(
1494
+ return /* @__PURE__ */ jsx10(TitledBox5, { borderStyle: "round", titles: [title], borderColor, flexShrink: 0, children: /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", paddingX: 1, children: [
1495
+ jiraState === "not_configured" && /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: "No Jira site configured" }),
1496
+ jiraState === "no_tickets" && /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: "No tickets linked to this branch" }),
1497
+ jiraState === "has_tickets" && tickets.map((ticket, idx) => /* @__PURE__ */ jsx10(
1679
1498
  TicketItem,
1680
1499
  {
1681
1500
  ticketKey: ticket.key,
@@ -1689,8 +1508,8 @@ function JiraView({ isFocused, onModalChange, onKeybindingsChange }) {
1689
1508
  }
1690
1509
 
1691
1510
  // src/components/ui/KeybindingsBar.tsx
1692
- import { Box as Box12, Text as Text12 } from "ink";
1693
- import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
1511
+ import { Box as Box11, Text as Text11 } from "ink";
1512
+ import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
1694
1513
  var globalBindings = [
1695
1514
  { key: "1-4", label: "Focus" },
1696
1515
  { key: "j/k", label: "Navigate" },
@@ -1701,20 +1520,20 @@ var modalBindings = [
1701
1520
  ];
1702
1521
  function KeybindingsBar({ contextBindings = [], modalOpen = false }) {
1703
1522
  const allBindings = modalOpen ? [...contextBindings, ...modalBindings] : [...contextBindings, ...globalBindings];
1704
- return /* @__PURE__ */ jsx12(Box12, { flexShrink: 0, paddingX: 1, gap: 2, children: allBindings.map((binding) => /* @__PURE__ */ jsxs12(Box12, { gap: 1, children: [
1705
- /* @__PURE__ */ jsx12(Text12, { bold: true, color: binding.color ?? "yellow", children: binding.key }),
1706
- /* @__PURE__ */ jsx12(Text12, { dimColor: true, children: binding.label })
1523
+ return /* @__PURE__ */ jsx11(Box11, { flexShrink: 0, paddingX: 1, gap: 2, children: allBindings.map((binding) => /* @__PURE__ */ jsxs11(Box11, { gap: 1, children: [
1524
+ /* @__PURE__ */ jsx11(Text11, { bold: true, color: binding.color ?? "yellow", children: binding.key }),
1525
+ /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: binding.label })
1707
1526
  ] }, binding.key)) });
1708
1527
  }
1709
1528
 
1710
1529
  // src/app.tsx
1711
- import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
1530
+ import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
1712
1531
  function App() {
1713
1532
  const { exit } = useApp();
1714
- const [focusedView, setFocusedView] = useState9("github");
1715
- const [modalOpen, setModalOpen] = useState9(false);
1716
- const [contextBindings, setContextBindings] = useState9([]);
1717
- useInput11(
1533
+ const [focusedView, setFocusedView] = useState8("github");
1534
+ const [modalOpen, setModalOpen] = useState8(false);
1535
+ const [contextBindings, setContextBindings] = useState8([]);
1536
+ useInput10(
1718
1537
  (input, key) => {
1719
1538
  if (key.ctrl && input === "c") {
1720
1539
  exit();
@@ -1728,16 +1547,15 @@ function App() {
1728
1547
  },
1729
1548
  { isActive: !modalOpen }
1730
1549
  );
1731
- return /* @__PURE__ */ jsxs13(Box13, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: [
1732
- /* @__PURE__ */ jsx13(
1550
+ return /* @__PURE__ */ jsxs12(Box12, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: [
1551
+ /* @__PURE__ */ jsx12(
1733
1552
  GitHubView,
1734
1553
  {
1735
1554
  isFocused: focusedView === "github",
1736
- onModalChange: setModalOpen,
1737
1555
  onKeybindingsChange: focusedView === "github" ? setContextBindings : void 0
1738
1556
  }
1739
1557
  ),
1740
- /* @__PURE__ */ jsx13(
1558
+ /* @__PURE__ */ jsx12(
1741
1559
  JiraView,
1742
1560
  {
1743
1561
  isFocused: focusedView === "jira",
@@ -1745,7 +1563,7 @@ function App() {
1745
1563
  onKeybindingsChange: focusedView === "jira" ? setContextBindings : void 0
1746
1564
  }
1747
1565
  ),
1748
- /* @__PURE__ */ jsx13(KeybindingsBar, { contextBindings, modalOpen })
1566
+ /* @__PURE__ */ jsx12(KeybindingsBar, { contextBindings, modalOpen })
1749
1567
  ] });
1750
1568
  }
1751
1569
 
@@ -1753,16 +1571,16 @@ function App() {
1753
1571
  import { render as inkRender } from "ink";
1754
1572
 
1755
1573
  // src/lib/Screen.tsx
1756
- import { Box as Box14, useStdout } from "ink";
1757
- import { useCallback as useCallback3, useEffect as useEffect6, useState as useState10 } from "react";
1758
- import { jsx as jsx14 } from "react/jsx-runtime";
1574
+ import { Box as Box13, useStdout } from "ink";
1575
+ import { useCallback as useCallback3, useEffect as useEffect6, useState as useState9 } from "react";
1576
+ import { jsx as jsx13 } from "react/jsx-runtime";
1759
1577
  function Screen({ children }) {
1760
1578
  const { stdout } = useStdout();
1761
1579
  const getSize = useCallback3(
1762
1580
  () => ({ height: stdout.rows, width: stdout.columns }),
1763
1581
  [stdout]
1764
1582
  );
1765
- const [size, setSize] = useState10(getSize);
1583
+ const [size, setSize] = useState9(getSize);
1766
1584
  useEffect6(() => {
1767
1585
  const onResize = () => setSize(getSize());
1768
1586
  stdout.on("resize", onResize);
@@ -1770,17 +1588,17 @@ function Screen({ children }) {
1770
1588
  stdout.off("resize", onResize);
1771
1589
  };
1772
1590
  }, [stdout, getSize]);
1773
- return /* @__PURE__ */ jsx14(Box14, { height: size.height, width: size.width, children });
1591
+ return /* @__PURE__ */ jsx13(Box13, { height: size.height, width: size.width, children });
1774
1592
  }
1775
1593
 
1776
1594
  // src/lib/render.tsx
1777
- import { jsx as jsx15 } from "react/jsx-runtime";
1595
+ import { jsx as jsx14 } from "react/jsx-runtime";
1778
1596
  var ENTER_ALT_BUFFER = "\x1B[?1049h";
1779
1597
  var EXIT_ALT_BUFFER = "\x1B[?1049l";
1780
1598
  var CLEAR_SCREEN = "\x1B[2J\x1B[H";
1781
1599
  function render(node, options) {
1782
1600
  process.stdout.write(ENTER_ALT_BUFFER + CLEAR_SCREEN);
1783
- const element = /* @__PURE__ */ jsx15(Screen, { children: node });
1601
+ const element = /* @__PURE__ */ jsx14(Screen, { children: node });
1784
1602
  const instance = inkRender(element, options);
1785
1603
  setImmediate(() => instance.rerender(element));
1786
1604
  const cleanup = () => process.stdout.write(EXIT_ALT_BUFFER);
@@ -1801,7 +1619,7 @@ function render(node, options) {
1801
1619
  }
1802
1620
 
1803
1621
  // src/cli.tsx
1804
- import { jsx as jsx16 } from "react/jsx-runtime";
1622
+ import { jsx as jsx15 } from "react/jsx-runtime";
1805
1623
  meow(
1806
1624
  `
1807
1625
  Usage
@@ -1823,4 +1641,4 @@ meow(
1823
1641
  }
1824
1642
  }
1825
1643
  );
1826
- render(/* @__PURE__ */ jsx16(App, {}));
1644
+ render(/* @__PURE__ */ jsx15(App, {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clairo",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",