@kud/gh-ink 0.57.0 → 0.58.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/dist/index.d.ts +12 -2
- package/dist/index.js +110 -12
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -178,6 +178,14 @@ type ExtensionTarget = {
|
|
|
178
178
|
login: string;
|
|
179
179
|
onRemove?: (item: AnyItem) => void;
|
|
180
180
|
showFlash?: (msg: string) => void;
|
|
181
|
+
query?: string;
|
|
182
|
+
ticketKey?: string;
|
|
183
|
+
};
|
|
184
|
+
type Command = {
|
|
185
|
+
id: string;
|
|
186
|
+
title: string;
|
|
187
|
+
group?: string;
|
|
188
|
+
run: () => void | Promise<void>;
|
|
181
189
|
};
|
|
182
190
|
interface InboxExtension {
|
|
183
191
|
id: string;
|
|
@@ -187,6 +195,7 @@ interface InboxExtension {
|
|
|
187
195
|
scope?: "item" | "global";
|
|
188
196
|
drills?: AnyItem["kind"][];
|
|
189
197
|
body: (onExit: () => void, target?: ExtensionTarget) => ReactNode;
|
|
198
|
+
commands?: (target: ExtensionTarget) => Command[];
|
|
190
199
|
}
|
|
191
200
|
|
|
192
201
|
/**
|
|
@@ -437,7 +446,7 @@ declare const ActionMenu: ({ item, actions, cursor, }: {
|
|
|
437
446
|
cursor: number;
|
|
438
447
|
}) => React.JSX.Element;
|
|
439
448
|
declare const signatureOf: (sections: Section[]) => string;
|
|
440
|
-
declare const App: ({ fetcher, cacheKey, title, detailFor, origin, jiraBase, jiraKeyRe, jiraTransitions, hasCiStatus, ciJob, ciFetcher, ciPollMs, watchPath, watchDebounceMs, watchJitterMs, extensions, tabHelp, emptyHint, liveLabel, }: {
|
|
449
|
+
declare const App: ({ fetcher, cacheKey, title, detailFor, origin, jiraBase, jiraKeyRe, jiraSetupHint, jiraTransitions, hasCiStatus, ciJob, ciFetcher, ciPollMs, watchPath, watchDebounceMs, watchJitterMs, extensions, tabHelp, emptyHint, liveLabel, }: {
|
|
441
450
|
fetcher: () => Promise<{
|
|
442
451
|
sections: Section[];
|
|
443
452
|
login: string;
|
|
@@ -475,6 +484,7 @@ declare const App: ({ fetcher, cacheKey, title, detailFor, origin, jiraBase, jir
|
|
|
475
484
|
emptyHint?: string;
|
|
476
485
|
jiraBase?: string;
|
|
477
486
|
jiraKeyRe?: RegExp;
|
|
487
|
+
jiraSetupHint?: string;
|
|
478
488
|
jiraTransitions?: JiraTransition[];
|
|
479
489
|
hasCiStatus?: boolean;
|
|
480
490
|
ciJob?: string;
|
|
@@ -519,4 +529,4 @@ declare const matchesFilter: (repo: string, filter: RepoFilter) => boolean;
|
|
|
519
529
|
*/
|
|
520
530
|
declare const parsePatterns: (value: string) => string[];
|
|
521
531
|
|
|
522
|
-
export { type Action, ActionMenu, App, COLS, CiStatusLine, type CiStatusState, CommentsPanel, type CommentsPanelProps, type DetailContext, type ExplainSection, type ExtensionTarget, HealthPanel, type HealthPanelProps, type InboxBudget, type InboxExtension, type JiraTransition, type LiveLabel, MIN_SIDEBAR_COLS, type RepoFilter, SIDEBAR_COLS, SidePanel, type Sidebar, type SidebarRow, budgetNotice, buildActions, buildCheckoutCmd, clipboard, counts, drillCmd, explainGhAction, explainItem, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, itermRun, jumpToRepo, jumpToRepoPane, matchesFilter, maxViewStart, moveCursor, openInTab, parsePatterns, railCapacity, railWidth, readCache, renderMarkdown, reposInSections, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, signatureOf, toCiStatusState, truncate, useActionMenu, windowCount, withHeaders, withoutItem, workCount, writeCache };
|
|
532
|
+
export { type Action, ActionMenu, App, COLS, CiStatusLine, type CiStatusState, type Command, CommentsPanel, type CommentsPanelProps, type DetailContext, type ExplainSection, type ExtensionTarget, HealthPanel, type HealthPanelProps, type InboxBudget, type InboxExtension, type JiraTransition, type LiveLabel, MIN_SIDEBAR_COLS, type RepoFilter, SIDEBAR_COLS, SidePanel, type Sidebar, type SidebarRow, budgetNotice, buildActions, buildCheckoutCmd, clipboard, counts, drillCmd, explainGhAction, explainItem, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, itermRun, jumpToRepo, jumpToRepoPane, matchesFilter, maxViewStart, moveCursor, openInTab, parsePatterns, railCapacity, railWidth, readCache, renderMarkdown, reposInSections, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, signatureOf, toCiStatusState, truncate, useActionMenu, windowCount, withHeaders, withoutItem, workCount, writeCache };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React2, { createContext, useState, useRef, useEffect, useMemo, useContext } from 'react';
|
|
2
2
|
import { useWindowSize, useInput, Text, Box } from 'ink';
|
|
3
|
-
import { colors, ScrollView, TextInput, useAppKeys, LoadingScreen, ProgressBar, StatusMessage, FooterHints, useListCursor, Tabs, pillWidth, Pill } from '@kud/ink-ui';
|
|
3
|
+
import { colors, ScrollView, TextInput, useAppKeys, LoadingScreen, ProgressBar, StatusMessage, FooterHints, useListCursor, CommandPalette, Tabs, pillWidth, Pill } from '@kud/ink-ui';
|
|
4
4
|
import { isPassCheck, isFailCheck, isInconclusiveCheck, resolveThread, unresolveThread, replyToThread, rerunFailedRun, mergePr, reRequestReviewer } from '@kud/gh';
|
|
5
5
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
6
6
|
import { $ } from 'zx';
|
|
@@ -1521,6 +1521,11 @@ var unsubscribeFrom = async (item) => {
|
|
|
1521
1521
|
if (!id) throw new Error(`no node id for ${item.repo}#${item.number}`);
|
|
1522
1522
|
await quietly`gh api graphql -f query=${UNSUBSCRIBE_MUTATION} -f id=${id}`;
|
|
1523
1523
|
};
|
|
1524
|
+
var openInJira = (jiraBase, key, showFlash) => {
|
|
1525
|
+
quietly`open ${jiraBase}/${key}`.catch(() => {
|
|
1526
|
+
});
|
|
1527
|
+
showFlash(`\u2197 Opened ${key} in Jira`);
|
|
1528
|
+
};
|
|
1524
1529
|
var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions, onRefresh, onRemove, onOpenView, ext) => {
|
|
1525
1530
|
if (item.kind === "repo-header" || item.kind === "subgroup-header" || item.kind === "show-more" || item.kind === "show-less")
|
|
1526
1531
|
return [];
|
|
@@ -1728,11 +1733,7 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
|
|
|
1728
1733
|
actions.push({
|
|
1729
1734
|
label: `Open ${jiraKey} in Jira`,
|
|
1730
1735
|
hint: "t",
|
|
1731
|
-
run: () =>
|
|
1732
|
-
quietly`open ${jiraBase}/${jiraKey}`.catch(() => {
|
|
1733
|
-
});
|
|
1734
|
-
showFlash(`\u2197 Opened ${jiraKey} in Jira`);
|
|
1735
|
-
}
|
|
1736
|
+
run: () => openInJira(jiraBase, jiraKey, showFlash)
|
|
1736
1737
|
});
|
|
1737
1738
|
}
|
|
1738
1739
|
}
|
|
@@ -2289,7 +2290,10 @@ var HelpModal = ({
|
|
|
2289
2290
|
["p", "open repo in new pane"],
|
|
2290
2291
|
["u", "unsubscribe from this item"],
|
|
2291
2292
|
["x", "remove yourself as reviewer"],
|
|
2292
|
-
...hasJira ? [
|
|
2293
|
+
...hasJira ? [
|
|
2294
|
+
["t", "Jira: move / open ticket"],
|
|
2295
|
+
["\u2303K", "launch \xB7 jump to a ticket by key"]
|
|
2296
|
+
] : [],
|
|
2293
2297
|
["/", "search"],
|
|
2294
2298
|
["f", "filter by repo"],
|
|
2295
2299
|
["r", "refresh"],
|
|
@@ -2464,6 +2468,7 @@ var BrowseScreen = ({
|
|
|
2464
2468
|
login,
|
|
2465
2469
|
jiraBase,
|
|
2466
2470
|
jiraKeyRe,
|
|
2471
|
+
jiraSetupHint,
|
|
2467
2472
|
jiraTransitions,
|
|
2468
2473
|
onRefresh,
|
|
2469
2474
|
onActed,
|
|
@@ -2520,6 +2525,7 @@ var BrowseScreen = ({
|
|
|
2520
2525
|
const [helpScroll, setHelpScroll] = useState(0);
|
|
2521
2526
|
const [helpRange, setHelpRange] = useState({ max: 0, page: 1 });
|
|
2522
2527
|
const [explain, setExplain] = useState(false);
|
|
2528
|
+
const [palette, setPalette] = useState(null);
|
|
2523
2529
|
const filterActive = search != null || repoFilter.size > 0;
|
|
2524
2530
|
const reserveCiRow = ciStatusState != null;
|
|
2525
2531
|
const ciStatus = ciStatusState?.kind === "ready" ? ciStatusState.status : null;
|
|
@@ -2628,6 +2634,7 @@ var BrowseScreen = ({
|
|
|
2628
2634
|
const railActive = showRail && railFocus && railRows.length > 0;
|
|
2629
2635
|
const railAt = Math.min(railCursor, Math.max(0, railRows.length - 1));
|
|
2630
2636
|
const peel = () => {
|
|
2637
|
+
if (palette !== null) return setPalette(null), true;
|
|
2631
2638
|
if (help) return setHelp(false), true;
|
|
2632
2639
|
if (explain) return setExplain(false), true;
|
|
2633
2640
|
if (repoPicker) return setRepoPicker(false), true;
|
|
@@ -2645,8 +2652,8 @@ var BrowseScreen = ({
|
|
|
2645
2652
|
};
|
|
2646
2653
|
});
|
|
2647
2654
|
useEffect(() => {
|
|
2648
|
-
onTyping?.(searchInput);
|
|
2649
|
-
}, [searchInput, onTyping]);
|
|
2655
|
+
onTyping?.(searchInput || palette !== null);
|
|
2656
|
+
}, [searchInput, palette, onTyping]);
|
|
2650
2657
|
const railCols = railWidth(COLS);
|
|
2651
2658
|
const listCols = showRail ? COLS - railCols : COLS;
|
|
2652
2659
|
const [sparkFrame, setSparkFrame] = useState(0);
|
|
@@ -2734,7 +2741,12 @@ var BrowseScreen = ({
|
|
|
2734
2741
|
lastKeyAt.current = Date.now();
|
|
2735
2742
|
if (idleFor >= PULSE_IDLE_MS && sparkKey) setPulseArm((n) => n + 1);
|
|
2736
2743
|
if (hidden) return;
|
|
2744
|
+
if (key.ctrl && input === "k") {
|
|
2745
|
+
setPalette((open) => open === null ? "" : null);
|
|
2746
|
+
return;
|
|
2747
|
+
}
|
|
2737
2748
|
if (key.ctrl || key.meta) return;
|
|
2749
|
+
if (palette !== null) return;
|
|
2738
2750
|
if (help) {
|
|
2739
2751
|
if (helpRange.max > 0) {
|
|
2740
2752
|
const step2 = (n) => setHelpScroll((s) => Math.min(helpRange.max, Math.max(0, s + n)));
|
|
@@ -2827,9 +2839,9 @@ var BrowseScreen = ({
|
|
|
2827
2839
|
}))
|
|
2828
2840
|
return;
|
|
2829
2841
|
if (row.url) {
|
|
2830
|
-
quietly`open `.catch(() => {
|
|
2842
|
+
quietly`open ${row.url}`.catch(() => {
|
|
2831
2843
|
});
|
|
2832
|
-
showFlash(`\u2197 Opened `);
|
|
2844
|
+
showFlash(`\u2197 Opened ${row.key}`);
|
|
2833
2845
|
}
|
|
2834
2846
|
return;
|
|
2835
2847
|
}
|
|
@@ -3111,6 +3123,9 @@ var BrowseScreen = ({
|
|
|
3111
3123
|
["\u2190\u2192", "tab"],
|
|
3112
3124
|
["\u21B5/d", "open"],
|
|
3113
3125
|
["m", "actions"],
|
|
3126
|
+
// Only where Jira is configured: without it the launcher can only say
|
|
3127
|
+
// so, and a footer key that opens an apology is a broken feature.
|
|
3128
|
+
...jiraBase ? [["\u2303K", "launch"]] : [],
|
|
3114
3129
|
// Advertised only where it does something, and named for what it
|
|
3115
3130
|
// shows rather than for the furniture: nobody wants "a sidebar".
|
|
3116
3131
|
...showRail ? [["\u21E5", sidebar.title.toLowerCase()]] : sidebar ? [["i", sidebar.title.toLowerCase()]] : [],
|
|
@@ -3120,8 +3135,89 @@ var BrowseScreen = ({
|
|
|
3120
3135
|
const matchCount = section.items.filter(
|
|
3121
3136
|
(i) => i.kind !== "repo-header" && i.kind !== "subgroup-header"
|
|
3122
3137
|
).length;
|
|
3138
|
+
const launcher = useMemo(() => {
|
|
3139
|
+
const run = /* @__PURE__ */ new Map();
|
|
3140
|
+
if (palette === null)
|
|
3141
|
+
return { items: [], run, message: void 0 };
|
|
3142
|
+
const query = palette.trim();
|
|
3143
|
+
const ticketKey = jiraKeyRe ? query.toUpperCase().match(jiraKeyRe)?.[0] : void 0;
|
|
3144
|
+
const commands = [];
|
|
3145
|
+
const rich = (key, where) => /* @__PURE__ */ jsxs(Text3, { children: [
|
|
3146
|
+
"Open ",
|
|
3147
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.accent, children: key }),
|
|
3148
|
+
" ",
|
|
3149
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.info, children: where })
|
|
3150
|
+
] });
|
|
3151
|
+
const labels = /* @__PURE__ */ new Map();
|
|
3152
|
+
if (ticketKey && jiraBase) {
|
|
3153
|
+
const row = {
|
|
3154
|
+
kind: "task",
|
|
3155
|
+
key: ticketKey,
|
|
3156
|
+
ticket: ticketKey,
|
|
3157
|
+
summary: "",
|
|
3158
|
+
url: `${jiraBase}/${ticketKey}`,
|
|
3159
|
+
status: "",
|
|
3160
|
+
age: ""
|
|
3161
|
+
};
|
|
3162
|
+
if (drillExtensionFor(row, extensions)) {
|
|
3163
|
+
commands.push({
|
|
3164
|
+
id: "launcher:here",
|
|
3165
|
+
title: `Open ${ticketKey} here`,
|
|
3166
|
+
run: () => void openDrillView(row)
|
|
3167
|
+
});
|
|
3168
|
+
labels.set("launcher:here", rich(ticketKey, "here"));
|
|
3169
|
+
}
|
|
3170
|
+
commands.push({
|
|
3171
|
+
id: "launcher:jira",
|
|
3172
|
+
title: `Open ${ticketKey} in Jira`,
|
|
3173
|
+
run: () => openInJira(jiraBase, ticketKey, showFlash)
|
|
3174
|
+
});
|
|
3175
|
+
labels.set("launcher:jira", rich(ticketKey, "in Jira"));
|
|
3176
|
+
}
|
|
3177
|
+
const target = {
|
|
3178
|
+
...extensionTargetFor(activeItem),
|
|
3179
|
+
query: palette,
|
|
3180
|
+
ticketKey
|
|
3181
|
+
};
|
|
3182
|
+
for (const ext of extensions ?? []) {
|
|
3183
|
+
for (const command of ext.commands?.(target) ?? []) {
|
|
3184
|
+
commands.push({ ...command, id: `${ext.id}:${command.id}` });
|
|
3185
|
+
}
|
|
3186
|
+
}
|
|
3187
|
+
for (const command of commands) run.set(command.id, command.run);
|
|
3188
|
+
const message = !jiraBase ? `Jira not configured${jiraSetupHint ? ` \xB7 ${jiraSetupHint}` : ""}` : query && !ticketKey ? `no ticket matches "${query}"` : void 0;
|
|
3189
|
+
const items = commands.map((command) => ({
|
|
3190
|
+
id: command.id,
|
|
3191
|
+
title: command.title,
|
|
3192
|
+
group: command.group,
|
|
3193
|
+
label: labels.get(command.id)
|
|
3194
|
+
}));
|
|
3195
|
+
return { items, run, message };
|
|
3196
|
+
}, [palette, activeItem, extensions, jiraBase, jiraKeyRe, jiraSetupHint]);
|
|
3123
3197
|
if (hidden) return null;
|
|
3124
|
-
const overlay =
|
|
3198
|
+
const overlay = palette !== null ? /* @__PURE__ */ jsx(
|
|
3199
|
+
CommandPalette,
|
|
3200
|
+
{
|
|
3201
|
+
items: launcher.items,
|
|
3202
|
+
query: palette,
|
|
3203
|
+
onQueryChange: setPalette,
|
|
3204
|
+
onSelect: (id) => {
|
|
3205
|
+
const run = launcher.run.get(id);
|
|
3206
|
+
setPalette(null);
|
|
3207
|
+
void run?.();
|
|
3208
|
+
},
|
|
3209
|
+
onClose: () => setPalette(null),
|
|
3210
|
+
message: launcher.message,
|
|
3211
|
+
placeholder: "ticket key\u2026",
|
|
3212
|
+
width: Math.min(60, Math.max(30, listCols - 2)),
|
|
3213
|
+
maxRows: Math.max(3, listHeight - 6),
|
|
3214
|
+
hints: [
|
|
3215
|
+
["\u2191\u2193", "move"],
|
|
3216
|
+
["\u23CE", "open"],
|
|
3217
|
+
["esc", "close"]
|
|
3218
|
+
]
|
|
3219
|
+
}
|
|
3220
|
+
) : help ? /* @__PURE__ */ jsx(
|
|
3125
3221
|
HelpModal,
|
|
3126
3222
|
{
|
|
3127
3223
|
extensions,
|
|
@@ -3323,6 +3419,7 @@ var App = ({
|
|
|
3323
3419
|
origin,
|
|
3324
3420
|
jiraBase,
|
|
3325
3421
|
jiraKeyRe,
|
|
3422
|
+
jiraSetupHint,
|
|
3326
3423
|
jiraTransitions,
|
|
3327
3424
|
hasCiStatus,
|
|
3328
3425
|
ciJob,
|
|
@@ -3711,6 +3808,7 @@ var App = ({
|
|
|
3711
3808
|
login: state.login,
|
|
3712
3809
|
jiraBase,
|
|
3713
3810
|
jiraKeyRe,
|
|
3811
|
+
jiraSetupHint,
|
|
3714
3812
|
jiraTransitions,
|
|
3715
3813
|
onRefresh: applyOrRefresh,
|
|
3716
3814
|
onActed,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kud/gh-ink",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.58.0",
|
|
4
4
|
"description": "Ink components for rendering GitHub PR review comments and health — controlled, presentation-only, built on @kud/ink-ui and fed by @kud/gh.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"@kud/gh": "0.17.0",
|
|
52
52
|
"@kud/gh-workflow": "0.12.1",
|
|
53
|
-
"@kud/ink-ui": "0.
|
|
53
|
+
"@kud/ink-ui": "0.30.0",
|
|
54
54
|
"zx": "8.8.5"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|