clairo 0.3.0 → 0.4.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 +240 -129
  2. package/package.json +4 -1
package/dist/cli.js CHANGED
@@ -5,13 +5,13 @@ import meow from "meow";
5
5
 
6
6
  // src/app.tsx
7
7
  import { useState as useState8 } from "react";
8
- import { Box as Box12, useApp, useInput as useInput10 } from "ink";
8
+ import { Box as Box13, useApp, useInput as useInput10 } from "ink";
9
9
 
10
10
  // src/components/github/GitHubView.tsx
11
11
  import { exec as exec3 } from "child_process";
12
12
  import { useCallback, useEffect as useEffect3, useState as useState3 } from "react";
13
13
  import { TitledBox as TitledBox4 } from "@mishieck/ink-titled-box";
14
- import { Box as Box4, Text as Text4, useInput as useInput4 } from "ink";
14
+ import { Box as Box5, Text as Text5, useInput as useInput4 } from "ink";
15
15
 
16
16
  // src/lib/config/index.ts
17
17
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
@@ -245,9 +245,120 @@ async function getPRDetails(prNumber, repo) {
245
245
  import { useRef } from "react";
246
246
  import open from "open";
247
247
  import { TitledBox } from "@mishieck/ink-titled-box";
248
- import { Box, Text, useInput } from "ink";
248
+ import { Box as Box2, Text as Text2, useInput } from "ink";
249
249
  import { ScrollView } from "ink-scroll-view";
250
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
250
+
251
+ // src/components/ui/Markdown.tsx
252
+ import { Box, Text } from "ink";
253
+ import Link from "ink-link";
254
+ import { marked } from "marked";
255
+ import Table from "cli-table3";
256
+ import { jsx, jsxs } from "react/jsx-runtime";
257
+ function Markdown({ children }) {
258
+ const tokens = marked.lexer(children);
259
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: tokens.map((token, idx) => /* @__PURE__ */ jsx(TokenRenderer, { token }, idx)) });
260
+ }
261
+ function TokenRenderer({ token }) {
262
+ var _a, _b;
263
+ switch (token.type) {
264
+ case "heading":
265
+ return /* @__PURE__ */ jsx(Box, { marginTop: token.depth === 1 ? 0 : 1, children: /* @__PURE__ */ jsx(Text, { bold: true, underline: token.depth === 1, children: renderInline(token.tokens) }) });
266
+ case "paragraph": {
267
+ const hasLinks = (_a = token.tokens) == null ? void 0 : _a.some((t) => {
268
+ var _a2;
269
+ return t.type === "link" || t.type === "strong" && "tokens" in t && ((_a2 = t.tokens) == null ? void 0 : _a2.some((st) => st.type === "link"));
270
+ });
271
+ if (hasLinks) {
272
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "row", flexWrap: "wrap", children: renderInline(token.tokens) });
273
+ }
274
+ return /* @__PURE__ */ jsx(Text, { children: renderInline(token.tokens) });
275
+ }
276
+ case "code":
277
+ return /* @__PURE__ */ jsx(Box, { marginY: 1, paddingX: 1, borderStyle: "single", borderColor: "gray", children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: token.text }) });
278
+ case "blockquote":
279
+ return /* @__PURE__ */ jsxs(Box, { marginLeft: 2, children: [
280
+ /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u2502 " }),
281
+ /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: (_b = token.tokens) == null ? void 0 : _b.map((t, idx) => /* @__PURE__ */ jsx(TokenRenderer, { token: t }, idx)) })
282
+ ] });
283
+ case "list":
284
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginY: 1, children: token.items.map((item, idx) => /* @__PURE__ */ jsxs(Box, { children: [
285
+ /* @__PURE__ */ jsx(Text, { children: token.ordered ? `${idx + 1}. ` : "\u2022 " }),
286
+ /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: item.tokens.map((t, i) => /* @__PURE__ */ jsx(TokenRenderer, { token: t }, i)) })
287
+ ] }, idx)) });
288
+ case "table":
289
+ return /* @__PURE__ */ jsx(TableRenderer, { token });
290
+ case "hr":
291
+ return /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500".repeat(40) });
292
+ case "space":
293
+ return null;
294
+ default:
295
+ if ("text" in token && typeof token.text === "string") {
296
+ return /* @__PURE__ */ jsx(Text, { children: token.text });
297
+ }
298
+ return null;
299
+ }
300
+ }
301
+ function TableRenderer({ token }) {
302
+ const table = new Table({
303
+ head: token.header.map((cell) => renderInlineToString(cell.tokens)),
304
+ style: { head: ["cyan"], border: ["gray"] }
305
+ });
306
+ for (const row of token.rows) {
307
+ table.push(row.map((cell) => renderInlineToString(cell.tokens)));
308
+ }
309
+ return /* @__PURE__ */ jsx(Text, { children: table.toString() });
310
+ }
311
+ function renderInline(tokens) {
312
+ if (!tokens) return null;
313
+ return tokens.map((token, idx) => {
314
+ switch (token.type) {
315
+ case "text":
316
+ return /* @__PURE__ */ jsx(Text, { children: token.text }, idx);
317
+ case "strong":
318
+ return /* @__PURE__ */ jsx(Text, { bold: true, children: renderInline(token.tokens) }, idx);
319
+ case "em":
320
+ return /* @__PURE__ */ jsx(Text, { italic: true, children: renderInline(token.tokens) }, idx);
321
+ case "codespan":
322
+ return /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
323
+ "`",
324
+ token.text,
325
+ "`"
326
+ ] }, idx);
327
+ case "link":
328
+ return /* @__PURE__ */ jsx(Link, { url: token.href, children: /* @__PURE__ */ jsx(Text, { color: "blue", children: renderInlineToString(token.tokens) }) }, idx);
329
+ case "image":
330
+ return /* @__PURE__ */ jsxs(Text, { color: "blue", children: [
331
+ "[Image: ",
332
+ token.text || token.href,
333
+ "]"
334
+ ] }, idx);
335
+ case "br":
336
+ return /* @__PURE__ */ jsx(Text, { children: "\n" }, idx);
337
+ case "del":
338
+ return /* @__PURE__ */ jsx(Text, { strikethrough: true, children: renderInline(token.tokens) }, idx);
339
+ default:
340
+ if ("text" in token && typeof token.text === "string") {
341
+ return /* @__PURE__ */ jsx(Text, { children: token.text }, idx);
342
+ }
343
+ return null;
344
+ }
345
+ });
346
+ }
347
+ function renderInlineToString(tokens) {
348
+ if (!tokens) return "";
349
+ return tokens.map((token) => {
350
+ if ("text" in token && typeof token.text === "string") {
351
+ return token.text;
352
+ }
353
+ if ("tokens" in token && Array.isArray(token.tokens)) {
354
+ return renderInlineToString(token.tokens);
355
+ }
356
+ return "";
357
+ }).join("");
358
+ }
359
+
360
+ // src/components/github/PRDetailsBox.tsx
361
+ import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
251
362
  function getCheckColor(check) {
252
363
  const conclusion = check.conclusion ?? check.state;
253
364
  if (conclusion === "SUCCESS") return "green";
@@ -301,36 +412,36 @@ function PRDetailsBox({ pr, loading, error, isFocused }) {
301
412
  },
302
413
  { isActive: isFocused }
303
414
  );
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: [
415
+ return /* @__PURE__ */ jsx2(TitledBox, { borderStyle: "round", titles: [displayTitle], borderColor, flexGrow: 1, children: /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", flexGrow: 1, children: /* @__PURE__ */ jsx2(ScrollView, { ref: scrollRef, children: /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingX: 1, children: [
416
+ loading && /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Loading details..." }),
417
+ error && /* @__PURE__ */ jsx2(Text2, { color: "red", children: error }),
418
+ !loading && !error && !pr && /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Select a PR to view details" }),
419
+ !loading && !error && pr && /* @__PURE__ */ jsxs2(Fragment, { children: [
420
+ /* @__PURE__ */ jsx2(Text2, { bold: true, children: pr.title }),
421
+ /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
311
422
  "by ",
312
423
  ((_a = pr.author) == null ? void 0 : _a.login) ?? "unknown",
313
424
  " | ",
314
425
  ((_b = pr.commits) == null ? void 0 : _b.length) ?? 0,
315
426
  " commits"
316
427
  ] }),
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 })
428
+ /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, children: [
429
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Review: " }),
430
+ /* @__PURE__ */ jsx2(Text2, { color: reviewColor, children: reviewStatus }),
431
+ /* @__PURE__ */ jsx2(Text2, { children: " | " }),
432
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Status: " }),
433
+ /* @__PURE__ */ jsx2(Text2, { color: mergeDisplay.color, children: mergeDisplay.text })
323
434
  ] }),
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(", ") })
435
+ (((_c = pr.assignees) == null ? void 0 : _c.length) ?? 0) > 0 && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, children: [
436
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Assignees: " }),
437
+ /* @__PURE__ */ jsx2(Text2, { children: pr.assignees.map((a) => a.login).join(", ") })
327
438
  ] }),
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:" }),
439
+ (((_d = pr.reviews) == null ? void 0 : _d.length) ?? 0) > 0 && /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
440
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Reviews:" }),
330
441
  pr.reviews.map((review, idx) => {
331
442
  const color = review.state === "APPROVED" ? "green" : review.state === "CHANGES_REQUESTED" ? "red" : review.state === "COMMENTED" ? "blue" : "yellow";
332
443
  const icon = review.state === "APPROVED" ? "\u2713" : review.state === "CHANGES_REQUESTED" ? "\u2717" : review.state === "COMMENTED" ? "\u{1F4AC}" : "\u25CB";
333
- return /* @__PURE__ */ jsxs(Text, { color, children: [
444
+ return /* @__PURE__ */ jsxs2(Text2, { color, children: [
334
445
  " ",
335
446
  icon,
336
447
  " ",
@@ -338,22 +449,22 @@ function PRDetailsBox({ pr, loading, error, isFocused }) {
338
449
  ] }, idx);
339
450
  })
340
451
  ] }),
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(", ") })
452
+ (((_e = pr.reviewRequests) == null ? void 0 : _e.length) ?? 0) > 0 && /* @__PURE__ */ jsxs2(Box2, { children: [
453
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Pending: " }),
454
+ /* @__PURE__ */ jsx2(Text2, { color: "yellow", children: pr.reviewRequests.map((r) => r.login ?? r.name ?? r.slug ?? "Team").join(", ") })
344
455
  ] }),
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: [
456
+ (((_f = pr.statusCheckRollup) == null ? void 0 : _f.length) ?? 0) > 0 && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, flexDirection: "column", children: [
457
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Checks:" }),
458
+ (_g = pr.statusCheckRollup) == null ? void 0 : _g.map((check, idx) => /* @__PURE__ */ jsxs2(Text2, { color: getCheckColor(check), children: [
348
459
  " ",
349
460
  getCheckIcon(check),
350
461
  " ",
351
462
  check.name ?? check.context
352
463
  ] }, idx))
353
464
  ] }),
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 })
465
+ pr.body && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, flexDirection: "column", children: [
466
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Description:" }),
467
+ /* @__PURE__ */ jsx2(Markdown, { children: pr.body })
357
468
  ] })
358
469
  ] })
359
470
  ] }) }) }) });
@@ -362,7 +473,7 @@ function PRDetailsBox({ pr, loading, error, isFocused }) {
362
473
  // src/components/github/PullRequestsBox.tsx
363
474
  import { useEffect, useState } from "react";
364
475
  import { TitledBox as TitledBox2 } from "@mishieck/ink-titled-box";
365
- import { Box as Box2, Text as Text2, useInput as useInput2 } from "ink";
476
+ import { Box as Box3, Text as Text3, useInput as useInput2 } from "ink";
366
477
 
367
478
  // src/lib/clipboard.ts
368
479
  import { exec as exec2 } from "child_process";
@@ -386,7 +497,7 @@ async function copyToClipboard(text) {
386
497
  }
387
498
 
388
499
  // src/components/github/PullRequestsBox.tsx
389
- import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
500
+ import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
390
501
  function PullRequestsBox({
391
502
  prs,
392
503
  selectedPR,
@@ -431,16 +542,16 @@ function PullRequestsBox({
431
542
  const title = "[2] Pull Requests";
432
543
  const subtitle = branch ? ` (${branch})` : "";
433
544
  const borderColor = isFocused ? "yellow" : void 0;
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" }),
545
+ return /* @__PURE__ */ jsx3(TitledBox2, { borderStyle: "round", titles: [`${title}${subtitle}`], borderColor, flexShrink: 0, children: /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", paddingX: 1, overflow: "hidden", children: [
546
+ loading && /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "Loading PRs..." }),
547
+ error && /* @__PURE__ */ jsx3(Text3, { color: "red", children: error }),
548
+ !loading && !error && /* @__PURE__ */ jsxs3(Fragment2, { children: [
549
+ prs.length === 0 && /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "No PRs for this branch" }),
439
550
  prs.map((pr, idx) => {
440
551
  const isHighlighted = isFocused && idx === highlightedIndex;
441
552
  const isSelected = pr.number === (selectedPR == null ? void 0 : selectedPR.number);
442
553
  const prefix = isHighlighted ? "> " : isSelected ? "\u25CF " : " ";
443
- return /* @__PURE__ */ jsxs2(Text2, { color: isSelected ? "green" : void 0, children: [
554
+ return /* @__PURE__ */ jsxs3(Text3, { color: isSelected ? "green" : void 0, children: [
444
555
  prefix,
445
556
  "#",
446
557
  pr.number,
@@ -449,7 +560,7 @@ function PullRequestsBox({
449
560
  pr.title
450
561
  ] }, pr.number);
451
562
  }),
452
- /* @__PURE__ */ jsxs2(Text2, { color: "blue", children: [
563
+ /* @__PURE__ */ jsxs3(Text3, { color: "blue", children: [
453
564
  isFocused && highlightedIndex === prs.length ? "> " : " ",
454
565
  "+ Create new PR"
455
566
  ] })
@@ -460,8 +571,8 @@ function PullRequestsBox({
460
571
  // src/components/github/RemotesBox.tsx
461
572
  import { useEffect as useEffect2, useState as useState2 } from "react";
462
573
  import { TitledBox as TitledBox3 } from "@mishieck/ink-titled-box";
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";
574
+ import { Box as Box4, Text as Text4, useInput as useInput3 } from "ink";
575
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
465
576
  function RemotesBox({ remotes, selectedRemote, onSelect, loading, error, isFocused }) {
466
577
  const [highlightedIndex, setHighlightedIndex] = useState2(0);
467
578
  useEffect2(() => {
@@ -485,15 +596,15 @@ function RemotesBox({ remotes, selectedRemote, onSelect, loading, error, isFocus
485
596
  );
486
597
  const title = "[1] Remotes";
487
598
  const borderColor = isFocused ? "yellow" : void 0;
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" }),
599
+ return /* @__PURE__ */ jsx4(TitledBox3, { borderStyle: "round", titles: [title], borderColor, flexShrink: 0, children: /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingX: 1, overflow: "hidden", children: [
600
+ loading && /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "Loading..." }),
601
+ error && /* @__PURE__ */ jsx4(Text4, { color: "red", children: error }),
602
+ !loading && !error && remotes.length === 0 && /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "No remotes configured" }),
492
603
  !loading && !error && remotes.map((remote, idx) => {
493
604
  const isHighlighted = isFocused && idx === highlightedIndex;
494
605
  const isSelected = remote.name === selectedRemote;
495
606
  const prefix = isHighlighted ? "> " : isSelected ? "\u25CF " : " ";
496
- return /* @__PURE__ */ jsxs3(Text3, { color: isSelected ? "green" : void 0, children: [
607
+ return /* @__PURE__ */ jsxs4(Text4, { color: isSelected ? "green" : void 0, children: [
497
608
  prefix,
498
609
  remote.name,
499
610
  " (",
@@ -505,7 +616,7 @@ function RemotesBox({ remotes, selectedRemote, onSelect, loading, error, isFocus
505
616
  }
506
617
 
507
618
  // src/components/github/GitHubView.tsx
508
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
619
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
509
620
  function GitHubView({ isFocused, onKeybindingsChange }) {
510
621
  const [isRepo, setIsRepo] = useState3(null);
511
622
  const [repoPath, setRepoPath] = useState3(null);
@@ -658,10 +769,10 @@ function GitHubView({ isFocused, onKeybindingsChange }) {
658
769
  { isActive: isFocused }
659
770
  );
660
771
  if (isRepo === false) {
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" }) });
772
+ return /* @__PURE__ */ jsx5(TitledBox4, { borderStyle: "round", titles: ["Error"], flexGrow: 1, children: /* @__PURE__ */ jsx5(Text5, { color: "red", children: "Current directory is not a git repository" }) });
662
773
  }
663
- return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", flexGrow: 1, children: [
664
- /* @__PURE__ */ jsx4(
774
+ return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", flexGrow: 1, children: [
775
+ /* @__PURE__ */ jsx5(
665
776
  RemotesBox,
666
777
  {
667
778
  remotes,
@@ -672,7 +783,7 @@ function GitHubView({ isFocused, onKeybindingsChange }) {
672
783
  isFocused: isFocused && focusedBox === "remotes"
673
784
  }
674
785
  ),
675
- /* @__PURE__ */ jsx4(
786
+ /* @__PURE__ */ jsx5(
676
787
  PullRequestsBox,
677
788
  {
678
789
  prs,
@@ -686,7 +797,7 @@ function GitHubView({ isFocused, onKeybindingsChange }) {
686
797
  isFocused: isFocused && focusedBox === "prs"
687
798
  }
688
799
  ),
689
- /* @__PURE__ */ jsx4(
800
+ /* @__PURE__ */ jsx5(
690
801
  PRDetailsBox,
691
802
  {
692
803
  pr: prDetails,
@@ -702,7 +813,7 @@ function GitHubView({ isFocused, onKeybindingsChange }) {
702
813
  import { useCallback as useCallback2, useEffect as useEffect5, useState as useState7 } from "react";
703
814
  import open2 from "open";
704
815
  import { TitledBox as TitledBox5 } from "@mishieck/ink-titled-box";
705
- import { Box as Box10, Text as Text10, useInput as useInput9 } from "ink";
816
+ import { Box as Box11, Text as Text11, useInput as useInput9 } from "ink";
706
817
 
707
818
  // src/lib/jira/parser.ts
708
819
  var TICKET_KEY_PATTERN = /^[A-Z][A-Z0-9]+-\d+$/;
@@ -929,9 +1040,9 @@ async function applyTransition(auth, ticketKey, transitionId) {
929
1040
 
930
1041
  // src/components/jira/ChangeStatusModal.tsx
931
1042
  import { useEffect as useEffect4, useState as useState4 } from "react";
932
- import { Box as Box5, Text as Text5, useInput as useInput5 } from "ink";
1043
+ import { Box as Box6, Text as Text6, useInput as useInput5 } from "ink";
933
1044
  import SelectInput from "ink-select-input";
934
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1045
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
935
1046
  function ChangeStatusModal({ repoPath, ticketKey, currentStatus, onComplete, onCancel }) {
936
1047
  const [transitions, setTransitions] = useState4([]);
937
1048
  const [loading, setLoading] = useState4(true);
@@ -991,23 +1102,23 @@ function ChangeStatusModal({ repoPath, ticketKey, currentStatus, onComplete, onC
991
1102
  value: t.id
992
1103
  }));
993
1104
  const initialIndex = Math.max(0, transitions.findIndex((t) => t.to.name === currentStatus));
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: [
1105
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, paddingY: 1, children: [
1106
+ /* @__PURE__ */ jsxs6(Text6, { bold: true, color: "yellow", children: [
996
1107
  "Change Status: ",
997
1108
  ticketKey
998
1109
  ] }),
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" }) })
1110
+ loading && /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Loading transitions..." }),
1111
+ error && /* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { color: "red", children: error }) }),
1112
+ !loading && !error && transitions.length === 0 && /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "No available transitions" }),
1113
+ !loading && !error && transitions.length > 0 && !applying && /* @__PURE__ */ jsx6(Box6, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx6(SelectInput, { items, initialIndex, onSelect: handleSelect }) }),
1114
+ applying && /* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { color: "yellow", children: "Updating status..." }) }),
1115
+ /* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Esc to cancel" }) })
1005
1116
  ] });
1006
1117
  }
1007
1118
 
1008
1119
  // src/components/jira/ConfigureJiraSiteModal.tsx
1009
1120
  import { useState as useState5 } from "react";
1010
- import { Box as Box6, Text as Text6, useInput as useInput6 } from "ink";
1121
+ import { Box as Box7, Text as Text7, useInput as useInput6 } from "ink";
1011
1122
 
1012
1123
  // src/lib/editor.ts
1013
1124
  import { spawnSync } from "child_process";
@@ -1038,7 +1149,7 @@ function openInEditor(content, filename) {
1038
1149
  }
1039
1150
 
1040
1151
  // src/components/jira/ConfigureJiraSiteModal.tsx
1041
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1152
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1042
1153
  function ConfigureJiraSiteModal({
1043
1154
  initialSiteUrl,
1044
1155
  initialEmail,
@@ -1102,41 +1213,41 @@ function ConfigureJiraSiteModal({
1102
1213
  const prefix = isSelected ? "> " : " ";
1103
1214
  const color = isSelected ? "yellow" : void 0;
1104
1215
  const displayValue = isSensitive && value ? "*".repeat(Math.min(value.length, 20)) : value;
1105
- return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
1106
- /* @__PURE__ */ jsxs6(Text6, { color, bold: isSelected, children: [
1216
+ return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
1217
+ /* @__PURE__ */ jsxs7(Text7, { color, bold: isSelected, children: [
1107
1218
  prefix,
1108
1219
  label
1109
1220
  ] }),
1110
- value !== void 0 && /* @__PURE__ */ jsx6(Box6, { marginLeft: 4, children: /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: displayValue || "(empty - press Enter to edit)" }) })
1221
+ value !== void 0 && /* @__PURE__ */ jsx7(Box7, { marginLeft: 4, children: /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: displayValue || "(empty - press Enter to edit)" }) })
1111
1222
  ] });
1112
1223
  };
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 }) }),
1224
+ return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, paddingY: 1, children: [
1225
+ /* @__PURE__ */ jsx7(Text7, { bold: true, color: "cyan", children: "Configure Jira Site" }),
1226
+ /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Up/Down to select, Enter to edit, Esc to cancel" }),
1227
+ /* @__PURE__ */ jsx7(Box7, { marginTop: 1 }),
1228
+ error && /* @__PURE__ */ jsx7(Box7, { marginBottom: 1, children: /* @__PURE__ */ jsx7(Text7, { color: "red", children: error }) }),
1118
1229
  renderItem("siteUrl", "Site URL (e.g., https://company.atlassian.net)", siteUrl),
1119
- /* @__PURE__ */ jsx6(Box6, { marginTop: 1 }),
1230
+ /* @__PURE__ */ jsx7(Box7, { marginTop: 1 }),
1120
1231
  renderItem("email", "Email", email),
1121
- /* @__PURE__ */ jsx6(Box6, { marginTop: 1 }),
1232
+ /* @__PURE__ */ jsx7(Box7, { marginTop: 1 }),
1122
1233
  renderItem("apiToken", "API Token", apiToken, true),
1123
- /* @__PURE__ */ jsx6(Box6, { marginTop: 1 }),
1124
- /* @__PURE__ */ jsx6(Box6, { children: /* @__PURE__ */ jsxs6(Text6, { color: selectedItem === "submit" ? "green" : void 0, bold: selectedItem === "submit", children: [
1234
+ /* @__PURE__ */ jsx7(Box7, { marginTop: 1 }),
1235
+ /* @__PURE__ */ jsx7(Box7, { children: /* @__PURE__ */ jsxs7(Text7, { color: selectedItem === "submit" ? "green" : void 0, bold: selectedItem === "submit", children: [
1125
1236
  selectedItem === "submit" ? "> " : " ",
1126
1237
  canSubmit ? "[Save Configuration]" : "[Fill all fields first]"
1127
1238
  ] }) }),
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" }) })
1239
+ loading && /* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text7, { color: "yellow", children: "Validating credentials..." }) }),
1240
+ /* @__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" }) })
1130
1241
  ] });
1131
1242
  }
1132
1243
 
1133
1244
  // src/components/jira/LinkTicketModal.tsx
1134
1245
  import { useState as useState6 } from "react";
1135
- import { Box as Box8, Text as Text8, useInput as useInput8 } from "ink";
1246
+ import { Box as Box9, Text as Text9, useInput as useInput8 } from "ink";
1136
1247
 
1137
1248
  // src/components/ui/TextInput.tsx
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";
1249
+ import { Box as Box8, Text as Text8, useInput as useInput7 } from "ink";
1250
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
1140
1251
  function TextInput({ value, onChange, placeholder, isActive, mask }) {
1141
1252
  useInput7(
1142
1253
  (input, key) => {
@@ -1157,14 +1268,14 @@ function TextInput({ value, onChange, placeholder, isActive, mask }) {
1157
1268
  );
1158
1269
  const displayValue = mask ? "*".repeat(value.length) : value;
1159
1270
  const showPlaceholder = value.length === 0 && placeholder;
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: " " })
1271
+ return /* @__PURE__ */ jsx8(Box8, { children: /* @__PURE__ */ jsxs8(Text8, { children: [
1272
+ showPlaceholder ? /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: placeholder }) : /* @__PURE__ */ jsx8(Text8, { children: displayValue }),
1273
+ isActive && /* @__PURE__ */ jsx8(Text8, { backgroundColor: "yellow", children: " " })
1163
1274
  ] }) });
1164
1275
  }
1165
1276
 
1166
1277
  // src/components/jira/LinkTicketModal.tsx
1167
- import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
1278
+ import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
1168
1279
  function LinkTicketModal({ onSubmit, onCancel, loading, error }) {
1169
1280
  const [ticketInput, setTicketInput] = useState6("");
1170
1281
  const canSubmit = ticketInput.trim().length > 0;
@@ -1181,14 +1292,14 @@ function LinkTicketModal({ onSubmit, onCancel, loading, error }) {
1181
1292
  },
1182
1293
  { isActive: !loading }
1183
1294
  );
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(
1295
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, paddingY: 1, children: [
1296
+ /* @__PURE__ */ jsx9(Text9, { bold: true, color: "yellow", children: "Link Jira Ticket" }),
1297
+ /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "Type ticket ID, Enter to submit, Esc to cancel" }),
1298
+ /* @__PURE__ */ jsx9(Box9, { marginTop: 1 }),
1299
+ error && /* @__PURE__ */ jsx9(Box9, { marginBottom: 1, children: /* @__PURE__ */ jsx9(Text9, { color: "red", children: error }) }),
1300
+ /* @__PURE__ */ jsxs9(Box9, { children: [
1301
+ /* @__PURE__ */ jsx9(Text9, { color: "blue", children: "Ticket: " }),
1302
+ /* @__PURE__ */ jsx9(
1192
1303
  TextInput,
1193
1304
  {
1194
1305
  value: ticketInput,
@@ -1198,23 +1309,23 @@ function LinkTicketModal({ onSubmit, onCancel, loading, error }) {
1198
1309
  }
1199
1310
  )
1200
1311
  ] }),
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" }) })
1312
+ loading && /* @__PURE__ */ jsx9(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text9, { color: "yellow", children: "Fetching ticket..." }) }),
1313
+ /* @__PURE__ */ jsx9(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "Examples: PROJ-123 or https://company.atlassian.net/browse/PROJ-123" }) })
1203
1314
  ] });
1204
1315
  }
1205
1316
 
1206
1317
  // src/components/jira/TicketItem.tsx
1207
- import { Box as Box9, Text as Text9 } from "ink";
1208
- import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
1318
+ import { Box as Box10, Text as Text10 } from "ink";
1319
+ import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
1209
1320
  function TicketItem({ ticketKey, summary, status, isHighlighted, isSelected }) {
1210
1321
  const prefix = isHighlighted ? "> " : isSelected ? "\u25CF " : " ";
1211
1322
  const textColor = isSelected ? "green" : void 0;
1212
- return /* @__PURE__ */ jsx9(Box9, { children: /* @__PURE__ */ jsxs9(Text9, { color: textColor, children: [
1323
+ return /* @__PURE__ */ jsx10(Box10, { children: /* @__PURE__ */ jsxs10(Text10, { color: textColor, children: [
1213
1324
  prefix,
1214
- /* @__PURE__ */ jsx9(Text9, { bold: true, color: "blue", children: ticketKey }),
1325
+ /* @__PURE__ */ jsx10(Text10, { bold: true, color: "blue", children: ticketKey }),
1215
1326
  " ",
1216
1327
  summary,
1217
- status && /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
1328
+ status && /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
1218
1329
  " [",
1219
1330
  status,
1220
1331
  "]"
@@ -1223,7 +1334,7 @@ function TicketItem({ ticketKey, summary, status, isHighlighted, isSelected }) {
1223
1334
  }
1224
1335
 
1225
1336
  // src/components/jira/JiraView.tsx
1226
- import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
1337
+ import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
1227
1338
  function JiraView({ isFocused, onModalChange, onKeybindingsChange }) {
1228
1339
  const [repoPath, setRepoPath] = useState7(null);
1229
1340
  const [currentBranch, setCurrentBranch] = useState7(null);
@@ -1438,12 +1549,12 @@ function JiraView({ isFocused, onModalChange, onKeybindingsChange }) {
1438
1549
  { isActive: isFocused && !showConfigureModal && !showLinkModal && !showStatusModal }
1439
1550
  );
1440
1551
  if (isRepo === false) {
1441
- return /* @__PURE__ */ jsx10(TitledBox5, { borderStyle: "round", titles: ["Jira"], flexShrink: 0, children: /* @__PURE__ */ jsx10(Text10, { color: "red", children: "Not a git repository" }) });
1552
+ return /* @__PURE__ */ jsx11(TitledBox5, { borderStyle: "round", titles: ["Jira"], flexShrink: 0, children: /* @__PURE__ */ jsx11(Text11, { color: "red", children: "Not a git repository" }) });
1442
1553
  }
1443
1554
  if (showConfigureModal) {
1444
1555
  const siteUrl = repoPath ? getJiraSiteUrl(repoPath) : void 0;
1445
1556
  const creds = repoPath ? getJiraCredentials(repoPath) : { email: null, apiToken: null };
1446
- return /* @__PURE__ */ jsx10(Box10, { flexDirection: "column", flexShrink: 0, children: /* @__PURE__ */ jsx10(
1557
+ return /* @__PURE__ */ jsx11(Box11, { flexDirection: "column", flexShrink: 0, children: /* @__PURE__ */ jsx11(
1447
1558
  ConfigureJiraSiteModal,
1448
1559
  {
1449
1560
  initialSiteUrl: siteUrl ?? void 0,
@@ -1459,7 +1570,7 @@ function JiraView({ isFocused, onModalChange, onKeybindingsChange }) {
1459
1570
  ) });
1460
1571
  }
1461
1572
  if (showLinkModal) {
1462
- return /* @__PURE__ */ jsx10(Box10, { flexDirection: "column", flexShrink: 0, children: /* @__PURE__ */ jsx10(
1573
+ return /* @__PURE__ */ jsx11(Box11, { flexDirection: "column", flexShrink: 0, children: /* @__PURE__ */ jsx11(
1463
1574
  LinkTicketModal,
1464
1575
  {
1465
1576
  onSubmit: handleLinkSubmit,
@@ -1474,7 +1585,7 @@ function JiraView({ isFocused, onModalChange, onKeybindingsChange }) {
1474
1585
  }
1475
1586
  if (showStatusModal && repoPath && currentBranch && tickets[highlightedIndex]) {
1476
1587
  const ticket = tickets[highlightedIndex];
1477
- return /* @__PURE__ */ jsx10(Box10, { flexDirection: "column", flexShrink: 0, children: /* @__PURE__ */ jsx10(
1588
+ return /* @__PURE__ */ jsx11(Box11, { flexDirection: "column", flexShrink: 0, children: /* @__PURE__ */ jsx11(
1478
1589
  ChangeStatusModal,
1479
1590
  {
1480
1591
  repoPath,
@@ -1491,10 +1602,10 @@ function JiraView({ isFocused, onModalChange, onKeybindingsChange }) {
1491
1602
  }
1492
1603
  const title = "[4] Jira";
1493
1604
  const borderColor = isFocused ? "yellow" : void 0;
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(
1605
+ return /* @__PURE__ */ jsx11(TitledBox5, { borderStyle: "round", titles: [title], borderColor, flexShrink: 0, children: /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", paddingX: 1, children: [
1606
+ jiraState === "not_configured" && /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "No Jira site configured" }),
1607
+ jiraState === "no_tickets" && /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "No tickets linked to this branch" }),
1608
+ jiraState === "has_tickets" && tickets.map((ticket, idx) => /* @__PURE__ */ jsx11(
1498
1609
  TicketItem,
1499
1610
  {
1500
1611
  ticketKey: ticket.key,
@@ -1508,8 +1619,8 @@ function JiraView({ isFocused, onModalChange, onKeybindingsChange }) {
1508
1619
  }
1509
1620
 
1510
1621
  // src/components/ui/KeybindingsBar.tsx
1511
- import { Box as Box11, Text as Text11 } from "ink";
1512
- import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
1622
+ import { Box as Box12, Text as Text12 } from "ink";
1623
+ import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
1513
1624
  var globalBindings = [
1514
1625
  { key: "1-4", label: "Focus" },
1515
1626
  { key: "j/k", label: "Navigate" },
@@ -1520,14 +1631,14 @@ var modalBindings = [
1520
1631
  ];
1521
1632
  function KeybindingsBar({ contextBindings = [], modalOpen = false }) {
1522
1633
  const allBindings = modalOpen ? [...contextBindings, ...modalBindings] : [...contextBindings, ...globalBindings];
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 })
1634
+ return /* @__PURE__ */ jsx12(Box12, { flexShrink: 0, paddingX: 1, gap: 2, children: allBindings.map((binding) => /* @__PURE__ */ jsxs12(Box12, { gap: 1, children: [
1635
+ /* @__PURE__ */ jsx12(Text12, { bold: true, color: binding.color ?? "yellow", children: binding.key }),
1636
+ /* @__PURE__ */ jsx12(Text12, { dimColor: true, children: binding.label })
1526
1637
  ] }, binding.key)) });
1527
1638
  }
1528
1639
 
1529
1640
  // src/app.tsx
1530
- import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
1641
+ import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
1531
1642
  function App() {
1532
1643
  const { exit } = useApp();
1533
1644
  const [focusedView, setFocusedView] = useState8("github");
@@ -1547,15 +1658,15 @@ function App() {
1547
1658
  },
1548
1659
  { isActive: !modalOpen }
1549
1660
  );
1550
- return /* @__PURE__ */ jsxs12(Box12, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: [
1551
- /* @__PURE__ */ jsx12(
1661
+ return /* @__PURE__ */ jsxs13(Box13, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: [
1662
+ /* @__PURE__ */ jsx13(
1552
1663
  GitHubView,
1553
1664
  {
1554
1665
  isFocused: focusedView === "github",
1555
1666
  onKeybindingsChange: focusedView === "github" ? setContextBindings : void 0
1556
1667
  }
1557
1668
  ),
1558
- /* @__PURE__ */ jsx12(
1669
+ /* @__PURE__ */ jsx13(
1559
1670
  JiraView,
1560
1671
  {
1561
1672
  isFocused: focusedView === "jira",
@@ -1563,7 +1674,7 @@ function App() {
1563
1674
  onKeybindingsChange: focusedView === "jira" ? setContextBindings : void 0
1564
1675
  }
1565
1676
  ),
1566
- /* @__PURE__ */ jsx12(KeybindingsBar, { contextBindings, modalOpen })
1677
+ /* @__PURE__ */ jsx13(KeybindingsBar, { contextBindings, modalOpen })
1567
1678
  ] });
1568
1679
  }
1569
1680
 
@@ -1571,9 +1682,9 @@ function App() {
1571
1682
  import { render as inkRender } from "ink";
1572
1683
 
1573
1684
  // src/lib/Screen.tsx
1574
- import { Box as Box13, useStdout } from "ink";
1685
+ import { Box as Box14, useStdout } from "ink";
1575
1686
  import { useCallback as useCallback3, useEffect as useEffect6, useState as useState9 } from "react";
1576
- import { jsx as jsx13 } from "react/jsx-runtime";
1687
+ import { jsx as jsx14 } from "react/jsx-runtime";
1577
1688
  function Screen({ children }) {
1578
1689
  const { stdout } = useStdout();
1579
1690
  const getSize = useCallback3(
@@ -1588,17 +1699,17 @@ function Screen({ children }) {
1588
1699
  stdout.off("resize", onResize);
1589
1700
  };
1590
1701
  }, [stdout, getSize]);
1591
- return /* @__PURE__ */ jsx13(Box13, { height: size.height, width: size.width, children });
1702
+ return /* @__PURE__ */ jsx14(Box14, { height: size.height, width: size.width, children });
1592
1703
  }
1593
1704
 
1594
1705
  // src/lib/render.tsx
1595
- import { jsx as jsx14 } from "react/jsx-runtime";
1706
+ import { jsx as jsx15 } from "react/jsx-runtime";
1596
1707
  var ENTER_ALT_BUFFER = "\x1B[?1049h";
1597
1708
  var EXIT_ALT_BUFFER = "\x1B[?1049l";
1598
1709
  var CLEAR_SCREEN = "\x1B[2J\x1B[H";
1599
1710
  function render(node, options) {
1600
1711
  process.stdout.write(ENTER_ALT_BUFFER + CLEAR_SCREEN);
1601
- const element = /* @__PURE__ */ jsx14(Screen, { children: node });
1712
+ const element = /* @__PURE__ */ jsx15(Screen, { children: node });
1602
1713
  const instance = inkRender(element, options);
1603
1714
  setImmediate(() => instance.rerender(element));
1604
1715
  const cleanup = () => process.stdout.write(EXIT_ALT_BUFFER);
@@ -1619,7 +1730,7 @@ function render(node, options) {
1619
1730
  }
1620
1731
 
1621
1732
  // src/cli.tsx
1622
- import { jsx as jsx15 } from "react/jsx-runtime";
1733
+ import { jsx as jsx16 } from "react/jsx-runtime";
1623
1734
  meow(
1624
1735
  `
1625
1736
  Usage
@@ -1641,4 +1752,4 @@ meow(
1641
1752
  }
1642
1753
  }
1643
1754
  );
1644
- render(/* @__PURE__ */ jsx15(App, {}));
1755
+ render(/* @__PURE__ */ jsx16(App, {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clairo",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -22,9 +22,12 @@
22
22
  ],
23
23
  "dependencies": {
24
24
  "@mishieck/ink-titled-box": "^0.4.2",
25
+ "cli-table3": "^0.6.5",
25
26
  "ink": "^6.6.0",
27
+ "ink-link": "^5.0.0",
26
28
  "ink-scroll-view": "^0.3.5",
27
29
  "ink-select-input": "^6.2.0",
30
+ "marked": "^17.0.1",
28
31
  "meow": "^11.0.0",
29
32
  "open": "^11.0.0",
30
33
  "react": "^19.2.4"