clairo 0.5.0 → 1.0.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.
- package/README.md +15 -10
- package/dist/cli.js +144 -98
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,29 +7,34 @@ Terminal dashboard for GitHub PRs and Jira tickets.
|
|
|
7
7
|
- Node.js 18+
|
|
8
8
|
- [GitHub CLI](https://cli.github.com/) (`gh`) installed and authenticated
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Usage
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
|
-
|
|
14
|
-
pnpm build
|
|
13
|
+
npx clairo
|
|
15
14
|
```
|
|
16
15
|
|
|
17
|
-
|
|
16
|
+
### Options
|
|
18
17
|
|
|
19
|
-
```
|
|
20
|
-
|
|
18
|
+
```
|
|
19
|
+
--cwd <path>, -C Run in a different directory
|
|
20
|
+
--version Show version
|
|
21
|
+
--help Show help
|
|
21
22
|
```
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
### Examples
|
|
24
25
|
|
|
25
26
|
```bash
|
|
26
|
-
|
|
27
|
+
# Run in current directory
|
|
28
|
+
npx clairo
|
|
29
|
+
|
|
30
|
+
# Run in a different repo
|
|
31
|
+
npx clairo --cwd ~/projects/other-repo
|
|
27
32
|
```
|
|
28
33
|
|
|
29
34
|
## Keyboard
|
|
30
35
|
|
|
31
|
-
- `1-
|
|
36
|
+
- `1-6` - Switch between boxes
|
|
32
37
|
- `j/k` - Navigate lists
|
|
33
38
|
- `Enter` - Select
|
|
34
|
-
- `
|
|
39
|
+
- `o` - Open in browser
|
|
35
40
|
- `Ctrl+C` - Quit
|
package/dist/cli.js
CHANGED
|
@@ -10,7 +10,7 @@ import { Box as Box16, useApp, useInput as useInput13 } from "ink";
|
|
|
10
10
|
// src/components/github/GitHubView.tsx
|
|
11
11
|
import { exec as exec3 } from "child_process";
|
|
12
12
|
import { useCallback, useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
|
|
13
|
-
import { TitledBox as
|
|
13
|
+
import { TitledBox as TitledBox3 } from "@mishieck/ink-titled-box";
|
|
14
14
|
import { Box as Box5, Text as Text5, useInput as useInput4 } from "ink";
|
|
15
15
|
|
|
16
16
|
// src/lib/config/index.ts
|
|
@@ -573,22 +573,22 @@ ${title}
|
|
|
573
573
|
entry += "\n";
|
|
574
574
|
appendToLog(today, entry);
|
|
575
575
|
}
|
|
576
|
-
function logJiraStatusChanged(ticketKey, oldStatus, newStatus) {
|
|
576
|
+
function logJiraStatusChanged(ticketKey, ticketName, oldStatus, newStatus) {
|
|
577
577
|
const timestamp = formatTimestamp();
|
|
578
578
|
const today = getTodayDate();
|
|
579
579
|
const entry = `## ${timestamp} - Updated Jira ticket
|
|
580
580
|
|
|
581
|
-
${ticketKey}: ${
|
|
581
|
+
${ticketKey}: ${ticketName}
|
|
582
|
+
${oldStatus} \u2192 ${newStatus}
|
|
582
583
|
|
|
583
584
|
`;
|
|
584
585
|
appendToLog(today, entry);
|
|
585
586
|
}
|
|
586
587
|
|
|
587
588
|
// src/components/github/PRDetailsBox.tsx
|
|
588
|
-
import { useRef } from "react";
|
|
589
589
|
import open from "open";
|
|
590
|
-
import {
|
|
591
|
-
import { Box as Box2, Text as Text2, useInput } from "ink";
|
|
590
|
+
import { useRef } from "react";
|
|
591
|
+
import { Box as Box2, Text as Text2, useInput, useStdout } from "ink";
|
|
592
592
|
import { ScrollView } from "ink-scroll-view";
|
|
593
593
|
|
|
594
594
|
// src/components/ui/Markdown.tsx
|
|
@@ -755,67 +755,88 @@ function PRDetailsBox({ pr, loading, error, isFocused }) {
|
|
|
755
755
|
},
|
|
756
756
|
{ isActive: isFocused }
|
|
757
757
|
);
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
/* @__PURE__ */ jsx2(
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
758
|
+
const { stdout } = useStdout();
|
|
759
|
+
const terminalWidth = (stdout == null ? void 0 : stdout.columns) ?? 80;
|
|
760
|
+
const columnWidth = Math.floor(terminalWidth / 2);
|
|
761
|
+
const titlePart = `\u256D\u2500 ${displayTitle} `;
|
|
762
|
+
const dashCount = Math.max(0, columnWidth - titlePart.length - 1);
|
|
763
|
+
const topBorder = `${titlePart}${"\u2500".repeat(dashCount)}\u256E`;
|
|
764
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", flexGrow: 1, children: [
|
|
765
|
+
/* @__PURE__ */ jsx2(Text2, { color: borderColor, children: topBorder }),
|
|
766
|
+
/* @__PURE__ */ jsx2(
|
|
767
|
+
Box2,
|
|
768
|
+
{
|
|
769
|
+
flexDirection: "column",
|
|
770
|
+
flexGrow: 1,
|
|
771
|
+
flexBasis: 0,
|
|
772
|
+
overflow: "hidden",
|
|
773
|
+
borderStyle: "round",
|
|
774
|
+
borderTop: false,
|
|
775
|
+
borderColor,
|
|
776
|
+
children: /* @__PURE__ */ jsx2(ScrollView, { ref: scrollRef, children: /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingX: 1, children: [
|
|
777
|
+
loading && /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Loading details..." }),
|
|
778
|
+
error && /* @__PURE__ */ jsx2(Text2, { color: "red", children: error }),
|
|
779
|
+
!loading && !error && !pr && /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Select a PR to view details" }),
|
|
780
|
+
!loading && !error && pr && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
781
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, children: pr.title }),
|
|
782
|
+
/* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
|
|
783
|
+
"by ",
|
|
784
|
+
((_a = pr.author) == null ? void 0 : _a.login) ?? "unknown",
|
|
785
|
+
" | ",
|
|
786
|
+
((_b = pr.commits) == null ? void 0 : _b.length) ?? 0,
|
|
787
|
+
" commits"
|
|
788
|
+
] }),
|
|
789
|
+
/* @__PURE__ */ jsxs2(Box2, { marginTop: 1, children: [
|
|
790
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Review: " }),
|
|
791
|
+
/* @__PURE__ */ jsx2(Text2, { color: reviewColor, children: reviewStatus }),
|
|
792
|
+
/* @__PURE__ */ jsx2(Text2, { children: " | " }),
|
|
793
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Status: " }),
|
|
794
|
+
/* @__PURE__ */ jsx2(Text2, { color: mergeDisplay.color, children: mergeDisplay.text })
|
|
795
|
+
] }),
|
|
796
|
+
(((_c = pr.assignees) == null ? void 0 : _c.length) ?? 0) > 0 && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, children: [
|
|
797
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Assignees: " }),
|
|
798
|
+
/* @__PURE__ */ jsx2(Text2, { children: pr.assignees.map((a) => a.login).join(", ") })
|
|
799
|
+
] }),
|
|
800
|
+
(((_d = pr.reviews) == null ? void 0 : _d.length) ?? 0) > 0 && /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
|
|
801
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Reviews:" }),
|
|
802
|
+
pr.reviews.map((review, idx) => {
|
|
803
|
+
const color = review.state === "APPROVED" ? "green" : review.state === "CHANGES_REQUESTED" ? "red" : review.state === "COMMENTED" ? "blue" : "yellow";
|
|
804
|
+
const icon = review.state === "APPROVED" ? "\u2713" : review.state === "CHANGES_REQUESTED" ? "\u2717" : review.state === "COMMENTED" ? "\u{1F4AC}" : "\u25CB";
|
|
805
|
+
return /* @__PURE__ */ jsxs2(Text2, { color, children: [
|
|
806
|
+
" ",
|
|
807
|
+
icon,
|
|
808
|
+
" ",
|
|
809
|
+
review.author.login
|
|
810
|
+
] }, idx);
|
|
811
|
+
})
|
|
812
|
+
] }),
|
|
813
|
+
(((_e = pr.reviewRequests) == null ? void 0 : _e.length) ?? 0) > 0 && /* @__PURE__ */ jsxs2(Box2, { children: [
|
|
814
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Pending: " }),
|
|
815
|
+
/* @__PURE__ */ jsx2(Text2, { color: "yellow", children: pr.reviewRequests.map((r) => r.login ?? r.name ?? r.slug ?? "Team").join(", ") })
|
|
816
|
+
] }),
|
|
817
|
+
(((_f = pr.statusCheckRollup) == null ? void 0 : _f.length) ?? 0) > 0 && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, flexDirection: "column", children: [
|
|
818
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Checks:" }),
|
|
819
|
+
(_g = pr.statusCheckRollup) == null ? void 0 : _g.map((check, idx) => /* @__PURE__ */ jsxs2(Text2, { color: getCheckColor(check), children: [
|
|
820
|
+
" ",
|
|
821
|
+
getCheckIcon(check),
|
|
822
|
+
" ",
|
|
823
|
+
check.name ?? check.context
|
|
824
|
+
] }, idx))
|
|
825
|
+
] }),
|
|
826
|
+
pr.body && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, flexDirection: "column", children: [
|
|
827
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Description:" }),
|
|
828
|
+
/* @__PURE__ */ jsx2(Markdown, { children: pr.body })
|
|
829
|
+
] })
|
|
830
|
+
] })
|
|
831
|
+
] }) })
|
|
832
|
+
}
|
|
833
|
+
)
|
|
834
|
+
] });
|
|
814
835
|
}
|
|
815
836
|
|
|
816
837
|
// src/components/github/PullRequestsBox.tsx
|
|
817
838
|
import { useEffect, useState } from "react";
|
|
818
|
-
import { TitledBox
|
|
839
|
+
import { TitledBox } from "@mishieck/ink-titled-box";
|
|
819
840
|
import { Box as Box3, Text as Text3, useInput as useInput2 } from "ink";
|
|
820
841
|
|
|
821
842
|
// src/lib/clipboard.ts
|
|
@@ -885,7 +906,7 @@ function PullRequestsBox({
|
|
|
885
906
|
const title = "[2] Pull Requests";
|
|
886
907
|
const subtitle = branch ? ` (${branch})` : "";
|
|
887
908
|
const borderColor = isFocused ? "yellow" : void 0;
|
|
888
|
-
return /* @__PURE__ */ jsx3(
|
|
909
|
+
return /* @__PURE__ */ jsx3(TitledBox, { borderStyle: "round", titles: [`${title}${subtitle}`], borderColor, flexShrink: 0, children: /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", paddingX: 1, overflow: "hidden", children: [
|
|
889
910
|
loading && /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "Loading PRs..." }),
|
|
890
911
|
error && /* @__PURE__ */ jsx3(Text3, { color: "red", children: error }),
|
|
891
912
|
!loading && !error && /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
@@ -893,14 +914,21 @@ function PullRequestsBox({
|
|
|
893
914
|
prs.map((pr, idx) => {
|
|
894
915
|
const isHighlighted = isFocused && idx === highlightedIndex;
|
|
895
916
|
const isSelected = pr.number === (selectedPR == null ? void 0 : selectedPR.number);
|
|
896
|
-
const
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
"
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
917
|
+
const cursor = isHighlighted ? ">" : " ";
|
|
918
|
+
const indicator = isSelected ? " *" : "";
|
|
919
|
+
return /* @__PURE__ */ jsxs3(Box3, { children: [
|
|
920
|
+
/* @__PURE__ */ jsxs3(Text3, { color: isHighlighted ? "yellow" : void 0, children: [
|
|
921
|
+
cursor,
|
|
922
|
+
" "
|
|
923
|
+
] }),
|
|
924
|
+
/* @__PURE__ */ jsxs3(Text3, { color: isSelected ? "green" : void 0, children: [
|
|
925
|
+
"#",
|
|
926
|
+
pr.number,
|
|
927
|
+
" ",
|
|
928
|
+
pr.isDraft ? "[Draft] " : "",
|
|
929
|
+
pr.title
|
|
930
|
+
] }),
|
|
931
|
+
/* @__PURE__ */ jsx3(Text3, { dimColor: true, children: indicator })
|
|
904
932
|
] }, pr.number);
|
|
905
933
|
}),
|
|
906
934
|
/* @__PURE__ */ jsxs3(Text3, { color: "blue", children: [
|
|
@@ -913,7 +941,7 @@ function PullRequestsBox({
|
|
|
913
941
|
|
|
914
942
|
// src/components/github/RemotesBox.tsx
|
|
915
943
|
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
916
|
-
import { TitledBox as
|
|
944
|
+
import { TitledBox as TitledBox2 } from "@mishieck/ink-titled-box";
|
|
917
945
|
import { Box as Box4, Text as Text4, useInput as useInput3 } from "ink";
|
|
918
946
|
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
919
947
|
function RemotesBox({ remotes, selectedRemote, onSelect, loading, error, isFocused }) {
|
|
@@ -939,20 +967,27 @@ function RemotesBox({ remotes, selectedRemote, onSelect, loading, error, isFocus
|
|
|
939
967
|
);
|
|
940
968
|
const title = "[1] Remotes";
|
|
941
969
|
const borderColor = isFocused ? "yellow" : void 0;
|
|
942
|
-
return /* @__PURE__ */ jsx4(
|
|
970
|
+
return /* @__PURE__ */ jsx4(TitledBox2, { borderStyle: "round", titles: [title], borderColor, flexShrink: 0, children: /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingX: 1, overflow: "hidden", children: [
|
|
943
971
|
loading && /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "Loading..." }),
|
|
944
972
|
error && /* @__PURE__ */ jsx4(Text4, { color: "red", children: error }),
|
|
945
973
|
!loading && !error && remotes.length === 0 && /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "No remotes configured" }),
|
|
946
974
|
!loading && !error && remotes.map((remote, idx) => {
|
|
947
975
|
const isHighlighted = isFocused && idx === highlightedIndex;
|
|
948
976
|
const isSelected = remote.name === selectedRemote;
|
|
949
|
-
const
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
977
|
+
const cursor = isHighlighted ? ">" : " ";
|
|
978
|
+
const indicator = isSelected ? " *" : "";
|
|
979
|
+
return /* @__PURE__ */ jsxs4(Box4, { children: [
|
|
980
|
+
/* @__PURE__ */ jsxs4(Text4, { color: isHighlighted ? "yellow" : void 0, children: [
|
|
981
|
+
cursor,
|
|
982
|
+
" "
|
|
983
|
+
] }),
|
|
984
|
+
/* @__PURE__ */ jsxs4(Text4, { color: isSelected ? "green" : void 0, children: [
|
|
985
|
+
remote.name,
|
|
986
|
+
" (",
|
|
987
|
+
remote.url,
|
|
988
|
+
")"
|
|
989
|
+
] }),
|
|
990
|
+
/* @__PURE__ */ jsx4(Text4, { dimColor: true, children: indicator })
|
|
956
991
|
] }, remote.name);
|
|
957
992
|
})
|
|
958
993
|
] }) });
|
|
@@ -1154,7 +1189,7 @@ function GitHubView({ isFocused, onKeybindingsChange, onLogUpdated }) {
|
|
|
1154
1189
|
{ isActive: isFocused }
|
|
1155
1190
|
);
|
|
1156
1191
|
if (isRepo === false) {
|
|
1157
|
-
return /* @__PURE__ */ jsx5(
|
|
1192
|
+
return /* @__PURE__ */ jsx5(TitledBox3, { borderStyle: "round", titles: ["Error"], flexGrow: 1, children: /* @__PURE__ */ jsx5(Text5, { color: "red", children: "Current directory is not a git repository" }) });
|
|
1158
1193
|
}
|
|
1159
1194
|
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", flexGrow: 1, children: [
|
|
1160
1195
|
/* @__PURE__ */ jsx5(
|
|
@@ -1197,7 +1232,7 @@ function GitHubView({ isFocused, onKeybindingsChange, onLogUpdated }) {
|
|
|
1197
1232
|
// src/components/jira/JiraView.tsx
|
|
1198
1233
|
import { useCallback as useCallback2, useEffect as useEffect5, useState as useState7 } from "react";
|
|
1199
1234
|
import open2 from "open";
|
|
1200
|
-
import { TitledBox as
|
|
1235
|
+
import { TitledBox as TitledBox4 } from "@mishieck/ink-titled-box";
|
|
1201
1236
|
import { Box as Box11, Text as Text11, useInput as useInput9 } from "ink";
|
|
1202
1237
|
|
|
1203
1238
|
// src/components/jira/ChangeStatusModal.tsx
|
|
@@ -1711,7 +1746,7 @@ function JiraView({ isFocused, onModalChange, onKeybindingsChange, onLogUpdated
|
|
|
1711
1746
|
{ isActive: isFocused && !showConfigureModal && !showLinkModal && !showStatusModal }
|
|
1712
1747
|
);
|
|
1713
1748
|
if (isRepo === false) {
|
|
1714
|
-
return /* @__PURE__ */ jsx11(
|
|
1749
|
+
return /* @__PURE__ */ jsx11(TitledBox4, { borderStyle: "round", titles: ["Jira"], flexShrink: 0, children: /* @__PURE__ */ jsx11(Text11, { color: "red", children: "Not a git repository" }) });
|
|
1715
1750
|
}
|
|
1716
1751
|
if (showConfigureModal) {
|
|
1717
1752
|
const siteUrl = repoPath ? getJiraSiteUrl(repoPath) : void 0;
|
|
@@ -1756,7 +1791,7 @@ function JiraView({ isFocused, onModalChange, onKeybindingsChange, onLogUpdated
|
|
|
1756
1791
|
onComplete: (newStatus) => {
|
|
1757
1792
|
const oldStatus = ticket.status;
|
|
1758
1793
|
updateTicketStatus(repoPath, currentBranch, ticket.key, newStatus);
|
|
1759
|
-
logJiraStatusChanged(ticket.key, oldStatus, newStatus);
|
|
1794
|
+
logJiraStatusChanged(ticket.key, ticket.summary, oldStatus, newStatus);
|
|
1760
1795
|
onLogUpdated == null ? void 0 : onLogUpdated();
|
|
1761
1796
|
setShowStatusModal(false);
|
|
1762
1797
|
refreshTickets();
|
|
@@ -1767,7 +1802,7 @@ function JiraView({ isFocused, onModalChange, onKeybindingsChange, onLogUpdated
|
|
|
1767
1802
|
}
|
|
1768
1803
|
const title = "[4] Jira";
|
|
1769
1804
|
const borderColor = isFocused ? "yellow" : void 0;
|
|
1770
|
-
return /* @__PURE__ */ jsx11(
|
|
1805
|
+
return /* @__PURE__ */ jsx11(TitledBox4, { borderStyle: "round", titles: [title], borderColor, flexShrink: 0, children: /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", paddingX: 1, children: [
|
|
1771
1806
|
jiraState === "not_configured" && /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "No Jira site configured" }),
|
|
1772
1807
|
jiraState === "no_tickets" && /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "No tickets linked to this branch" }),
|
|
1773
1808
|
jiraState === "has_tickets" && tickets.map((ticket, idx) => /* @__PURE__ */ jsx11(
|
|
@@ -1788,7 +1823,7 @@ import { useCallback as useCallback3, useEffect as useEffect6, useState as useSt
|
|
|
1788
1823
|
import { Box as Box14, useInput as useInput12 } from "ink";
|
|
1789
1824
|
|
|
1790
1825
|
// src/components/logs/LogsHistoryBox.tsx
|
|
1791
|
-
import { TitledBox as
|
|
1826
|
+
import { TitledBox as TitledBox5 } from "@mishieck/ink-titled-box";
|
|
1792
1827
|
import { Box as Box12, Text as Text12, useInput as useInput10 } from "ink";
|
|
1793
1828
|
import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1794
1829
|
function LogsHistoryBox({
|
|
@@ -1819,7 +1854,7 @@ function LogsHistoryBox({
|
|
|
1819
1854
|
},
|
|
1820
1855
|
{ isActive: isFocused }
|
|
1821
1856
|
);
|
|
1822
|
-
return /* @__PURE__ */ jsx12(
|
|
1857
|
+
return /* @__PURE__ */ jsx12(TitledBox5, { borderStyle: "round", titles: [title], borderColor, flexShrink: 0, children: /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", paddingX: 1, children: [
|
|
1823
1858
|
logFiles.length === 0 && /* @__PURE__ */ jsx12(Text12, { dimColor: true, children: "No logs yet" }),
|
|
1824
1859
|
logFiles.map((file, idx) => {
|
|
1825
1860
|
const isHighlighted = idx === highlightedIndex;
|
|
@@ -1848,7 +1883,7 @@ function LogsHistoryBox({
|
|
|
1848
1883
|
|
|
1849
1884
|
// src/components/logs/LogViewerBox.tsx
|
|
1850
1885
|
import { useRef as useRef3 } from "react";
|
|
1851
|
-
import { TitledBox as
|
|
1886
|
+
import { TitledBox as TitledBox6 } from "@mishieck/ink-titled-box";
|
|
1852
1887
|
import { Box as Box13, Text as Text13, useInput as useInput11 } from "ink";
|
|
1853
1888
|
import { ScrollView as ScrollView2 } from "ink-scroll-view";
|
|
1854
1889
|
import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
@@ -1883,7 +1918,7 @@ function LogViewerBox({ date, content, isFocused, onRefresh, onLogCreated }) {
|
|
|
1883
1918
|
},
|
|
1884
1919
|
{ isActive: isFocused }
|
|
1885
1920
|
);
|
|
1886
|
-
return /* @__PURE__ */ jsx13(
|
|
1921
|
+
return /* @__PURE__ */ jsx13(TitledBox6, { borderStyle: "round", titles: [displayTitle], borderColor, flexGrow: 1, children: /* @__PURE__ */ jsx13(Box13, { flexDirection: "column", flexGrow: 1, children: /* @__PURE__ */ jsx13(ScrollView2, { ref: scrollRef, children: /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", paddingX: 1, children: [
|
|
1887
1922
|
!date && /* @__PURE__ */ jsx13(Text13, { dimColor: true, children: "Select a log file to view" }),
|
|
1888
1923
|
date && content === null && /* @__PURE__ */ jsx13(Text13, { dimColor: true, children: "Log file not found" }),
|
|
1889
1924
|
date && content !== null && content.trim() === "" && /* @__PURE__ */ jsx13(Text13, { dimColor: true, children: "Empty log file" }),
|
|
@@ -2096,11 +2131,11 @@ function App() {
|
|
|
2096
2131
|
import { render as inkRender } from "ink";
|
|
2097
2132
|
|
|
2098
2133
|
// src/lib/Screen.tsx
|
|
2099
|
-
import { Box as Box17, useStdout } from "ink";
|
|
2134
|
+
import { Box as Box17, useStdout as useStdout2 } from "ink";
|
|
2100
2135
|
import { useCallback as useCallback5, useEffect as useEffect7, useState as useState10 } from "react";
|
|
2101
2136
|
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
2102
2137
|
function Screen({ children }) {
|
|
2103
|
-
const { stdout } =
|
|
2138
|
+
const { stdout } = useStdout2();
|
|
2104
2139
|
const getSize = useCallback5(
|
|
2105
2140
|
() => ({ height: stdout.rows, width: stdout.columns }),
|
|
2106
2141
|
[stdout]
|
|
@@ -2145,25 +2180,36 @@ function render(node, options) {
|
|
|
2145
2180
|
|
|
2146
2181
|
// src/cli.tsx
|
|
2147
2182
|
import { jsx as jsx19 } from "react/jsx-runtime";
|
|
2148
|
-
meow(
|
|
2183
|
+
var cli = meow(
|
|
2149
2184
|
`
|
|
2150
2185
|
Usage
|
|
2151
2186
|
$ clairo
|
|
2152
2187
|
|
|
2153
2188
|
Options
|
|
2154
|
-
|
|
2189
|
+
--cwd <path> Run in a different directory
|
|
2190
|
+
--version Show version
|
|
2191
|
+
--help Show this help
|
|
2155
2192
|
|
|
2156
2193
|
Examples
|
|
2157
|
-
$ clairo
|
|
2158
|
-
|
|
2194
|
+
$ clairo
|
|
2195
|
+
$ clairo --cwd ~/projects/other-repo
|
|
2159
2196
|
`,
|
|
2160
2197
|
{
|
|
2161
2198
|
importMeta: import.meta,
|
|
2162
2199
|
flags: {
|
|
2163
|
-
|
|
2164
|
-
type: "string"
|
|
2200
|
+
cwd: {
|
|
2201
|
+
type: "string",
|
|
2202
|
+
shortFlag: "C"
|
|
2165
2203
|
}
|
|
2166
2204
|
}
|
|
2167
2205
|
}
|
|
2168
2206
|
);
|
|
2207
|
+
if (cli.flags.cwd) {
|
|
2208
|
+
try {
|
|
2209
|
+
process.chdir(cli.flags.cwd);
|
|
2210
|
+
} catch {
|
|
2211
|
+
console.error(`Error: Cannot access directory "${cli.flags.cwd}"`);
|
|
2212
|
+
process.exit(1);
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2169
2215
|
render(/* @__PURE__ */ jsx19(App, {}));
|