@kud/gh-ink 0.61.2 → 0.62.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 +49 -2
- package/dist/index.js +165 -73
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -242,7 +242,54 @@ type PrRowProps = {
|
|
|
242
242
|
motion?: RowMotion;
|
|
243
243
|
/** In order, left to right. Charged against the width budget either way. */
|
|
244
244
|
announcements?: readonly RowAnnouncement[];
|
|
245
|
+
/**
|
|
246
|
+
* The trailing columns' widths across the section — see `trailingColumnsOf`.
|
|
247
|
+
* Absent, the row measures itself, which aligns nothing but draws the same
|
|
248
|
+
* cells a host that never measured always got.
|
|
249
|
+
*/
|
|
250
|
+
columns?: TrailingColumns;
|
|
251
|
+
/** Trailing columns the section has given up — see `sectionShedOf`. */
|
|
252
|
+
shed?: TrailingShed;
|
|
245
253
|
};
|
|
254
|
+
/**
|
|
255
|
+
* The trailing block, in reading order: how contested, how big, how recent.
|
|
256
|
+
* Threads lead because they are the one cell that makes a claim on you; age
|
|
257
|
+
* ends the row so every row ends on the date.
|
|
258
|
+
*/
|
|
259
|
+
declare const TRAILING: readonly ["threads", "size", "age"];
|
|
260
|
+
/** Width of each trailing column, in terminal cells. Zero draws no column. */
|
|
261
|
+
type TrailingColumns = Record<(typeof TRAILING)[number], number>;
|
|
262
|
+
/** Which trailing columns a whole section has given up. */
|
|
263
|
+
type TrailingShed = Partial<Record<(typeof TRAILING)[number], boolean>>;
|
|
264
|
+
/**
|
|
265
|
+
* The widest value each trailing column holds across these rows, measured once
|
|
266
|
+
* by the list — the same move as `uniformLabels` and `markerCols`. It is what
|
|
267
|
+
* makes the numbers line up: a column as wide as its widest value, right-
|
|
268
|
+
* aligned, so digits sit under digits and the eye can run straight down it.
|
|
269
|
+
* A column no row fills measures zero and is not drawn at all, which is what
|
|
270
|
+
* keeps this from becoming GitHub's grid of `—`.
|
|
271
|
+
*
|
|
272
|
+
* Code points rather than `.length`: every value here is ASCII or a single
|
|
273
|
+
* BMP glyph, so the two agree today, and a surrogate pair is the day they
|
|
274
|
+
* would not.
|
|
275
|
+
*/
|
|
276
|
+
declare const trailingColumnsOf: (items: readonly GHItem[]) => TrailingColumns;
|
|
277
|
+
type LayoutInput = Pick<PrRowProps, "item" | "login" | "cols" | "prefix" | "uniformLabels" | "announcements" | "columns" | "shed">;
|
|
278
|
+
/**
|
|
279
|
+
* Which trailing columns the section has to give up, so that every row gives up
|
|
280
|
+
* the same ones. Each row is laid out alone and the drops are unioned: if any
|
|
281
|
+
* row needs its size cell gone to keep a readable title, the size column goes
|
|
282
|
+
* for all of them.
|
|
283
|
+
*
|
|
284
|
+
* Forcing a drop on a row that did not need it only ever hands that row more
|
|
285
|
+
* room, so it can never push the row further down the ladder than it went on
|
|
286
|
+
* its own — the union is stable in one pass.
|
|
287
|
+
*
|
|
288
|
+
* Announcements are left out on purpose. A MERGED pill lives for three seconds
|
|
289
|
+
* on a row already leaving, and letting it reshape the whole section for those
|
|
290
|
+
* three seconds would move every row under the one you just acted on.
|
|
291
|
+
*/
|
|
292
|
+
declare const sectionShedOf: (rows: readonly Pick<LayoutInput, "item" | "prefix">[], context: Omit<LayoutInput, "item" | "prefix" | "announcements" | "shed">) => TrailingShed;
|
|
246
293
|
/**
|
|
247
294
|
* One pull request or issue, as a single line of a list.
|
|
248
295
|
*
|
|
@@ -253,7 +300,7 @@ type PrRowProps = {
|
|
|
253
300
|
* arrival, merge and departure belongs to whoever owns the list, and reaches
|
|
254
301
|
* the row as `icon`, `motion` and `announcements` after the decisions are made.
|
|
255
302
|
*/
|
|
256
|
-
declare const PrRow: ({ item, active, login, cols, icon: iconOverride, prefix, uniformLabels, motion, announcements, }: PrRowProps) => React.JSX.Element;
|
|
303
|
+
declare const PrRow: ({ item, active, login, cols, icon: iconOverride, prefix, uniformLabels, motion, announcements, columns, shed, }: PrRowProps) => React.JSX.Element;
|
|
257
304
|
|
|
258
305
|
/**
|
|
259
306
|
* One state per thing, from a closed set the strip knows how to draw. The host
|
|
@@ -713,4 +760,4 @@ declare const matchesFilter: (repo: string, filter: RepoFilter) => boolean;
|
|
|
713
760
|
*/
|
|
714
761
|
declare const parsePatterns: (value: string) => string[];
|
|
715
762
|
|
|
716
|
-
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, PrRow, type PrRowProps, type Rails, type RepoFilter, type RowAnnouncement, type RowMotion, SIDEBAR_COLS, SidePanel, type Sidebar, type SidebarRow, type StatusStrip, StatusStripLine, type StripItem, type StripState, type StripStatusState, ageLabel, budgetNotice, buildActions, buildCheckoutCmd, clipboard, counts, drillCmd, explainGhAction, explainItem, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, itermRun, jumpToRepo, jumpToRepoPane, matchesFilter, maxViewStart, moveCursor, openInTab, parsePatterns, railCapacity, railHeights, railRowsOf, railWidth, railsOf, readCache, renderMarkdown, reposInSections, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, signatureOf, stripGlyph, stripLayout, stripSignature, toCiStatusState, truncate, useActionMenu, windowCount, withHeaders, withoutItem, workCount, writeCache };
|
|
763
|
+
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, PrRow, type PrRowProps, type Rails, type RepoFilter, type RowAnnouncement, type RowMotion, SIDEBAR_COLS, SidePanel, type Sidebar, type SidebarRow, type StatusStrip, StatusStripLine, type StripItem, type StripState, type StripStatusState, type TrailingColumns, type TrailingShed, ageLabel, budgetNotice, buildActions, buildCheckoutCmd, clipboard, counts, drillCmd, explainGhAction, explainItem, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, itermRun, jumpToRepo, jumpToRepoPane, matchesFilter, maxViewStart, moveCursor, openInTab, parsePatterns, railCapacity, railHeights, railRowsOf, railWidth, railsOf, readCache, renderMarkdown, reposInSections, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, sectionShedOf, signatureOf, stripGlyph, stripLayout, stripSignature, toCiStatusState, trailingColumnsOf, 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, Pill, useAppKeys, LoadingScreen, StatusMessage, FooterHints, useListCursor, CommandPalette, Tabs, ProgressBar, pillWidth } from '@kud/ink-ui';
|
|
3
|
+
import { colors, ScrollView, TextInput, Pill, useAppKeys, LoadingScreen, StatusMessage, FooterHints, useFilterMode, useListCursor, CommandPalette, Tabs, ProgressBar, pillWidth } 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 { PIN_MARK, sizeOf, sizePartsOf, depthOf, impliedLabels, labelPriority, checkoutDirs, profileOf, inboxConfig, relativeTime, filterBySearch, filterByRepos, filterByOrigin } from '@kud/gh-workflow';
|
|
@@ -475,9 +475,11 @@ var HealthPanel = ({
|
|
|
475
475
|
const safeCursor = Math.min(cursor, Math.max(0, focusCount - 1));
|
|
476
476
|
const selected = safeCursor < checks.length ? checks[safeCursor] : void 0;
|
|
477
477
|
const selectedReviewer = safeCursor >= checks.length ? reviewers[safeCursor - checks.length] : void 0;
|
|
478
|
+
const noteTimer = useRef(null);
|
|
478
479
|
const flash = (msg) => {
|
|
479
480
|
setNote(msg);
|
|
480
|
-
|
|
481
|
+
if (noteTimer.current) clearTimeout(noteTimer.current);
|
|
482
|
+
noteTimer.current = setTimeout(() => setNote(null), 1500);
|
|
481
483
|
};
|
|
482
484
|
const act = async (msg, run, onSuccess) => {
|
|
483
485
|
setBusy(true);
|
|
@@ -831,41 +833,56 @@ var Backdrop = ({
|
|
|
831
833
|
children
|
|
832
834
|
}
|
|
833
835
|
) : children });
|
|
834
|
-
var
|
|
836
|
+
var threadsLabelOf = (item) => item.unresolved > 0 ? `\uF086 ${item.unresolved}` : "";
|
|
837
|
+
var agePairOf = (item) => item.activityAge && item.activityAge !== item.age ? { activity: item.activityAge, lifetime: item.age } : null;
|
|
838
|
+
var ageLabelOf = (item) => {
|
|
839
|
+
const pair = agePairOf(item);
|
|
840
|
+
return pair ? `${pair.activity} (${pair.lifetime})` : item.age;
|
|
841
|
+
};
|
|
842
|
+
var TRAILING = ["threads", "size", "age"];
|
|
843
|
+
var cellsOf = (s) => [...s].length;
|
|
844
|
+
var trailingColumnsOf = (items) => items.reduce(
|
|
845
|
+
(w, item) => ({
|
|
846
|
+
threads: Math.max(w.threads, cellsOf(threadsLabelOf(item))),
|
|
847
|
+
size: Math.max(w.size, cellsOf(sizeOf(item) ?? "")),
|
|
848
|
+
age: Math.max(w.age, cellsOf(ageLabelOf(item) ?? ""))
|
|
849
|
+
}),
|
|
850
|
+
{ threads: 0, size: 0, age: 0 }
|
|
851
|
+
);
|
|
852
|
+
var sectionShedOf = (rows, context) => rows.reduce((shed, row) => {
|
|
853
|
+
const { givingUp } = layoutOf({ ...context, ...row });
|
|
854
|
+
return {
|
|
855
|
+
threads: shed.threads || givingUp.threads,
|
|
856
|
+
size: shed.size || givingUp.size,
|
|
857
|
+
age: shed.age || givingUp.age
|
|
858
|
+
};
|
|
859
|
+
}, {});
|
|
860
|
+
var layoutOf = ({
|
|
835
861
|
item,
|
|
836
|
-
active,
|
|
837
862
|
login,
|
|
838
863
|
cols,
|
|
839
|
-
icon: iconOverride,
|
|
840
864
|
prefix = "",
|
|
841
865
|
uniformLabels = [],
|
|
842
|
-
|
|
843
|
-
|
|
866
|
+
announcements = [],
|
|
867
|
+
columns,
|
|
868
|
+
shed = {}
|
|
844
869
|
}) => {
|
|
845
|
-
const backdropped = useBackdropped();
|
|
846
|
-
const { glyph: healthIcon, color: healthColor2 } = displayFor(item.health);
|
|
847
|
-
const { glyph: icon, color } = iconOverride ?? {
|
|
848
|
-
glyph: healthIcon,
|
|
849
|
-
color: healthColor2
|
|
850
|
-
};
|
|
851
|
-
const spokeLast = !!login && !!item.lastActor && item.lastActor === login;
|
|
852
|
-
const [turnIcon, turnColor] = item.pinned ? [PIN_MARK, colors.accent] : !login || !item.lastActor || spokeLast ? [" ", colors.muted] : ["\u2190", colors.accent];
|
|
853
870
|
const numStr = `#${item.number}`.padEnd(7);
|
|
854
871
|
const showAuthor = !!item.author && item.author !== login;
|
|
855
|
-
const sizeLabel = sizeOf(item);
|
|
856
872
|
const sizeParts = sizePartsOf(item);
|
|
857
|
-
const unresolvedLabel = item
|
|
858
|
-
const agePair = item
|
|
859
|
-
const ageLabel2 =
|
|
873
|
+
const unresolvedLabel = threadsLabelOf(item);
|
|
874
|
+
const agePair = agePairOf(item);
|
|
875
|
+
const ageLabel2 = ageLabelOf(item);
|
|
876
|
+
const own = columns ?? trailingColumnsOf([item]);
|
|
860
877
|
const pillCaps = announcements.length * 2;
|
|
861
878
|
const repoLabel = depthOf(item) > 0 ? item.repo : "";
|
|
862
879
|
const implied = [...impliedLabels(item.repo), ...uniformLabels];
|
|
863
880
|
const labelNames = (item.labels ?? []).filter((l) => !implied.includes(l)).sort((a, b) => labelPriority(a) - labelPriority(b) || a.localeCompare(b)).slice(0, 2);
|
|
864
881
|
const givingUp = {
|
|
865
882
|
author: false,
|
|
866
|
-
size:
|
|
867
|
-
threads:
|
|
868
|
-
age:
|
|
883
|
+
size: !!shed.size,
|
|
884
|
+
threads: !!shed.threads,
|
|
885
|
+
age: !!shed.age,
|
|
869
886
|
repo: false,
|
|
870
887
|
labels: 0
|
|
871
888
|
};
|
|
@@ -887,16 +904,14 @@ var PrRow = ({
|
|
|
887
904
|
return `\uF02B ${fitted.join(", ")}`;
|
|
888
905
|
};
|
|
889
906
|
const widthOf2 = () => {
|
|
890
|
-
const
|
|
891
|
-
givingUp
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
...announcements.map((a) => a.label)
|
|
897
|
-
].filter(Boolean).join(" ");
|
|
907
|
+
const block = TRAILING.reduce(
|
|
908
|
+
(w, k) => givingUp[k] || own[k] === 0 ? w : w + 2 + own[k],
|
|
909
|
+
0
|
|
910
|
+
);
|
|
911
|
+
const author = showAuthor && !givingUp.author ? ` by ${item.author}`.length : 0;
|
|
912
|
+
const pills = announcements.reduce((w, a) => w + 2 + a.label.length, 0);
|
|
898
913
|
const cell = labelCell();
|
|
899
|
-
return 2 + prefix.length + 2 + 2 + 7 + (cell ? 2 + cell.length + 1 : 0) + (givingUp.repo ? 0 : repoLabel.length) +
|
|
914
|
+
return 2 + prefix.length + 2 + 2 + 7 + (cell ? 2 + cell.length + 1 : 0) + (givingUp.repo ? 0 : repoLabel.length) + author + block + pills + pillCaps + 4;
|
|
900
915
|
};
|
|
901
916
|
const MIN_TITLE = 24;
|
|
902
917
|
for (const give of [
|
|
@@ -913,7 +928,64 @@ var PrRow = ({
|
|
|
913
928
|
}
|
|
914
929
|
const labelLabel = labelCell();
|
|
915
930
|
const titleMax = Math.max(1, cols - widthOf2());
|
|
916
|
-
return
|
|
931
|
+
return {
|
|
932
|
+
numStr,
|
|
933
|
+
showAuthor,
|
|
934
|
+
sizeParts,
|
|
935
|
+
unresolvedLabel,
|
|
936
|
+
agePair,
|
|
937
|
+
ageLabel: ageLabel2,
|
|
938
|
+
repoLabel,
|
|
939
|
+
givingUp,
|
|
940
|
+
labelLabel,
|
|
941
|
+
titleMax,
|
|
942
|
+
columns: own
|
|
943
|
+
};
|
|
944
|
+
};
|
|
945
|
+
var PrRow = ({
|
|
946
|
+
item,
|
|
947
|
+
active,
|
|
948
|
+
login,
|
|
949
|
+
cols,
|
|
950
|
+
icon: iconOverride,
|
|
951
|
+
prefix = "",
|
|
952
|
+
uniformLabels = [],
|
|
953
|
+
motion,
|
|
954
|
+
announcements = [],
|
|
955
|
+
columns,
|
|
956
|
+
shed
|
|
957
|
+
}) => {
|
|
958
|
+
const backdropped = useBackdropped();
|
|
959
|
+
const { glyph: healthIcon, color: healthColor2 } = displayFor(item.health);
|
|
960
|
+
const { glyph: icon, color } = iconOverride ?? {
|
|
961
|
+
glyph: healthIcon,
|
|
962
|
+
color: healthColor2
|
|
963
|
+
};
|
|
964
|
+
const spokeLast = !!login && !!item.lastActor && item.lastActor === login;
|
|
965
|
+
const [turnIcon, turnColor] = item.pinned ? [PIN_MARK, colors.accent] : !login || !item.lastActor || spokeLast ? [" ", colors.muted] : ["\u2190", colors.accent];
|
|
966
|
+
const {
|
|
967
|
+
numStr,
|
|
968
|
+
showAuthor,
|
|
969
|
+
sizeParts,
|
|
970
|
+
unresolvedLabel,
|
|
971
|
+
agePair,
|
|
972
|
+
ageLabel: ageLabel2,
|
|
973
|
+
repoLabel,
|
|
974
|
+
givingUp,
|
|
975
|
+
labelLabel,
|
|
976
|
+
titleMax,
|
|
977
|
+
columns: block
|
|
978
|
+
} = layoutOf({
|
|
979
|
+
item,
|
|
980
|
+
login,
|
|
981
|
+
cols,
|
|
982
|
+
prefix,
|
|
983
|
+
uniformLabels,
|
|
984
|
+
announcements,
|
|
985
|
+
columns,
|
|
986
|
+
shed
|
|
987
|
+
});
|
|
988
|
+
return /* @__PURE__ */ jsxs(Box, { width: cols, children: [
|
|
917
989
|
/* @__PURE__ */ jsx(Text3, { color: colors.info, children: active ? "\u276F " : " " }),
|
|
918
990
|
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: prefix }),
|
|
919
991
|
/* @__PURE__ */ jsx(Text3, { color, bold: true, children: icon + " " }),
|
|
@@ -930,25 +1002,43 @@ var PrRow = ({
|
|
|
930
1002
|
),
|
|
931
1003
|
labelLabel ? /* @__PURE__ */ jsx(Text3, { color: colors.secondary, children: labelLabel + " " }) : null,
|
|
932
1004
|
repoLabel && !givingUp.repo ? /* @__PURE__ */ jsx(Text3, { dimColor: true, children: repoLabel }) : null,
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
/* @__PURE__ */ jsx(Text3, { color: colors.error, children: sizeParts.removed })
|
|
938
|
-
] }) : null,
|
|
939
|
-
unresolvedLabel && !givingUp.threads ? /* @__PURE__ */ jsx(
|
|
940
|
-
Text3,
|
|
1005
|
+
showAuthor && !givingUp.author ? /* @__PURE__ */ jsx(Text3, { dimColor: true, italic: true, children: " by " + item.author }) : null,
|
|
1006
|
+
/* @__PURE__ */ jsx(Box, { flexGrow: 1 }),
|
|
1007
|
+
block.threads > 0 && !givingUp.threads ? /* @__PURE__ */ jsx(
|
|
1008
|
+
Box,
|
|
941
1009
|
{
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
1010
|
+
marginLeft: 2,
|
|
1011
|
+
width: block.threads,
|
|
1012
|
+
justifyContent: "flex-end",
|
|
1013
|
+
flexShrink: 0,
|
|
1014
|
+
children: unresolvedLabel ? /* @__PURE__ */ jsx(
|
|
1015
|
+
Text3,
|
|
1016
|
+
{
|
|
1017
|
+
bold: !spokeLast,
|
|
1018
|
+
color: spokeLast ? colors.secondary : colors.accent,
|
|
1019
|
+
children: unresolvedLabel
|
|
1020
|
+
}
|
|
1021
|
+
) : null
|
|
945
1022
|
}
|
|
946
1023
|
) : null,
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
1024
|
+
block.size > 0 && !givingUp.size ? /* @__PURE__ */ jsx(
|
|
1025
|
+
Box,
|
|
1026
|
+
{
|
|
1027
|
+
marginLeft: 2,
|
|
1028
|
+
width: block.size,
|
|
1029
|
+
justifyContent: "flex-end",
|
|
1030
|
+
flexShrink: 0,
|
|
1031
|
+
children: sizeParts ? /* @__PURE__ */ jsxs(Text3, { children: [
|
|
1032
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.success, children: sizeParts.added }),
|
|
1033
|
+
" ",
|
|
1034
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.error, children: sizeParts.removed })
|
|
1035
|
+
] }) : null
|
|
1036
|
+
}
|
|
1037
|
+
) : null,
|
|
1038
|
+
block.age > 0 && !givingUp.age ? /* @__PURE__ */ jsx(Box, { marginLeft: 2, width: block.age, flexShrink: 0, children: agePair ? /* @__PURE__ */ jsxs(Text3, { children: [
|
|
1039
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.secondary, children: agePair.activity }),
|
|
950
1040
|
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: ` (${agePair.lifetime})` })
|
|
951
|
-
] }) : /* @__PURE__ */ jsx(Text3, { color: colors.secondary, children:
|
|
1041
|
+
] }) : ageLabel2 ? /* @__PURE__ */ jsx(Text3, { color: colors.secondary, children: ageLabel2 }) : null }) : null,
|
|
952
1042
|
backdropped ? null : announcements.map((a) => /* @__PURE__ */ jsxs(React2.Fragment, { children: [
|
|
953
1043
|
/* @__PURE__ */ jsx(Text3, { children: " " }),
|
|
954
1044
|
/* @__PURE__ */ jsx(Pill, { color: a.color, children: a.label })
|
|
@@ -2189,7 +2279,7 @@ var RepoHeaderRow = ({
|
|
|
2189
2279
|
/* @__PURE__ */ jsx(Text3, { dimColor: !active, children: " " + rule })
|
|
2190
2280
|
] });
|
|
2191
2281
|
};
|
|
2192
|
-
var MERGED_HOLD_MS =
|
|
2282
|
+
var MERGED_HOLD_MS = 2400;
|
|
2193
2283
|
var MERGED_FRAME_MS = 150;
|
|
2194
2284
|
var MERGED_FRAMES = ["\u2726", "\u2727", "\u2736", "\u2727"];
|
|
2195
2285
|
var MERGED_COLOUR = "#A371F7";
|
|
@@ -2223,7 +2313,7 @@ var TRANSIT_LABEL = {
|
|
|
2223
2313
|
out: "gone"};
|
|
2224
2314
|
var isDeparture = (t) => t === "out" || t === "moved-out";
|
|
2225
2315
|
var isArrival = (t) => t === "in" || t === "moved-in";
|
|
2226
|
-
var LEAVING_HOLD_MS =
|
|
2316
|
+
var LEAVING_HOLD_MS = 1500;
|
|
2227
2317
|
var tabMarker = (marked, id, frame = 0) => marked.has(id) ? `${TAB_PULSE[frame % TAB_PULSE.length]} ` : " ";
|
|
2228
2318
|
var TAB_PULSE = ["\xB7", "\u25CB", "\u25CE", "\u25C9", "\u25CE", "\u25CB"];
|
|
2229
2319
|
var ItemRow = ({
|
|
@@ -2240,7 +2330,9 @@ var ItemRow = ({
|
|
|
2240
2330
|
sparkFrame = 0,
|
|
2241
2331
|
cols = COLS,
|
|
2242
2332
|
markerCols = 0,
|
|
2243
|
-
uniformLabels = []
|
|
2333
|
+
uniformLabels = [],
|
|
2334
|
+
columns,
|
|
2335
|
+
shed
|
|
2244
2336
|
}) => {
|
|
2245
2337
|
const backdropped = useBackdropped();
|
|
2246
2338
|
const transient = leaving ? "out" : refreshMark;
|
|
@@ -2331,6 +2423,8 @@ var ItemRow = ({
|
|
|
2331
2423
|
cols,
|
|
2332
2424
|
prefix,
|
|
2333
2425
|
uniformLabels,
|
|
2426
|
+
columns,
|
|
2427
|
+
shed,
|
|
2334
2428
|
icon,
|
|
2335
2429
|
motion,
|
|
2336
2430
|
announcements
|
|
@@ -2703,8 +2797,6 @@ var BrowseScreen = ({
|
|
|
2703
2797
|
}, [activeId]);
|
|
2704
2798
|
const [flash, setFlash] = useState(null);
|
|
2705
2799
|
const menu = useActionMenu();
|
|
2706
|
-
const [search, setSearch] = useState(null);
|
|
2707
|
-
const [searchInput, setSearchInput] = useState(false);
|
|
2708
2800
|
const [repoFilter, setRepoFilter] = useState(/* @__PURE__ */ new Set());
|
|
2709
2801
|
const [repoPicker, setRepoPicker] = useState(false);
|
|
2710
2802
|
const [help, setHelp] = useState(false);
|
|
@@ -2712,6 +2804,11 @@ var BrowseScreen = ({
|
|
|
2712
2804
|
const [helpRange, setHelpRange] = useState({ max: 0, page: 1 });
|
|
2713
2805
|
const [explain, setExplain] = useState(false);
|
|
2714
2806
|
const [palette, setPalette] = useState(null);
|
|
2807
|
+
const filter = useFilterMode({
|
|
2808
|
+
isActive: !hidden && palette === null && !help && !explain && !repoPicker && menu.actions === null
|
|
2809
|
+
});
|
|
2810
|
+
const search = filter.term;
|
|
2811
|
+
const searchInput = filter.typing;
|
|
2715
2812
|
const filterActive = search != null || repoFilter.size > 0;
|
|
2716
2813
|
const reserveCiRow = ciStatusState != null;
|
|
2717
2814
|
const reserveStripRow = stripState != null;
|
|
@@ -2801,9 +2898,11 @@ var BrowseScreen = ({
|
|
|
2801
2898
|
) : [];
|
|
2802
2899
|
const hasMore = viewStart + visibleCount < section.items.length;
|
|
2803
2900
|
const activeItem = section.items[cursor];
|
|
2901
|
+
const flashTimer = useRef(null);
|
|
2804
2902
|
const showFlash = (msg) => {
|
|
2805
2903
|
setFlash(msg);
|
|
2806
|
-
|
|
2904
|
+
if (flashTimer.current) clearTimeout(flashTimer.current);
|
|
2905
|
+
flashTimer.current = setTimeout(() => setFlash(null), 1500);
|
|
2807
2906
|
};
|
|
2808
2907
|
const markedTabs = useMemo(() => {
|
|
2809
2908
|
const out = /* @__PURE__ */ new Set();
|
|
@@ -2830,7 +2929,7 @@ var BrowseScreen = ({
|
|
|
2830
2929
|
if (repoPicker) return setRepoPicker(false), true;
|
|
2831
2930
|
if (railActive) return setRailFocus(false), true;
|
|
2832
2931
|
if (menu.actions !== null) return menu.close(), true;
|
|
2833
|
-
if (search != null) return
|
|
2932
|
+
if (search != null) return filter.clear(), true;
|
|
2834
2933
|
if (repoFilter.size > 0) return setRepoFilter(/* @__PURE__ */ new Set()), true;
|
|
2835
2934
|
return false;
|
|
2836
2935
|
};
|
|
@@ -2846,6 +2945,13 @@ var BrowseScreen = ({
|
|
|
2846
2945
|
}, [searchInput, palette, onTyping]);
|
|
2847
2946
|
const railCols = railWidth(COLS);
|
|
2848
2947
|
const listCols = showRail ? COLS - railCols : COLS;
|
|
2948
|
+
const trailingColumns = trailingColumnsOf(labelBearing);
|
|
2949
|
+
const trailingShed = sectionShedOf(
|
|
2950
|
+
section.items.flatMap(
|
|
2951
|
+
(item, i) => item.kind === "pr" || item.kind === "issue" ? [{ item, prefix: treePrefix(section.items, i) }] : []
|
|
2952
|
+
),
|
|
2953
|
+
{ login, cols: listCols, uniformLabels, columns: trailingColumns }
|
|
2954
|
+
);
|
|
2849
2955
|
const [sparkFrame, setSparkFrame] = useState(0);
|
|
2850
2956
|
const sparkling = (mergedUrls?.length ?? 0) > 0 || (leavingUrls?.length ?? 0) > 0 || // Any MARKED TAB, not just rows on screen. The scope used to be this tab's
|
|
2851
2957
|
// own items, which was right while the animation lived on the rows and is
|
|
@@ -2972,23 +3078,7 @@ var BrowseScreen = ({
|
|
|
2972
3078
|
}
|
|
2973
3079
|
return;
|
|
2974
3080
|
}
|
|
2975
|
-
if (searchInput && !key.upArrow && !key.downArrow)
|
|
2976
|
-
if (key.return) return setSearchInput(false);
|
|
2977
|
-
if (key.escape) {
|
|
2978
|
-
setSearch(null);
|
|
2979
|
-
return setSearchInput(false);
|
|
2980
|
-
}
|
|
2981
|
-
if (key.backspace || key.delete)
|
|
2982
|
-
return setSearch((s) => (s ?? "").slice(0, -1));
|
|
2983
|
-
if (input && !key.ctrl && !key.meta && !key.tab)
|
|
2984
|
-
return setSearch((s) => (s ?? "") + input);
|
|
2985
|
-
return;
|
|
2986
|
-
}
|
|
2987
|
-
if (input === "/") {
|
|
2988
|
-
setSearch("");
|
|
2989
|
-
setSearchInput(true);
|
|
2990
|
-
return;
|
|
2991
|
-
}
|
|
3081
|
+
if (searchInput && !key.upArrow && !key.downArrow) return;
|
|
2992
3082
|
if (input === "f" && allRepos.length > 0) {
|
|
2993
3083
|
setRepoCursor(0);
|
|
2994
3084
|
setRepoPicker(true);
|
|
@@ -3516,7 +3606,7 @@ var BrowseScreen = ({
|
|
|
3516
3606
|
/* @__PURE__ */ jsx(Text3, { color: colors.info, children: " / " }),
|
|
3517
3607
|
/* @__PURE__ */ jsx(Text3, { children: search }),
|
|
3518
3608
|
searchInput ? /* @__PURE__ */ jsx(Text3, { color: colors.info, children: "\u258F" }) : null,
|
|
3519
|
-
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: ` ${matchCount} match${matchCount !== 1 ? "es" : ""}${
|
|
3609
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: ` ${matchCount} match${matchCount !== 1 ? "es" : ""} ${filter.hints.map(([k, label]) => `${k} ${label}`).join(" \xB7 ")}` })
|
|
3520
3610
|
] }) : repoFilter.size > 0 ? /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
3521
3611
|
/* @__PURE__ */ jsx(Text3, { color: colors.accent, children: " \u25C9 " }),
|
|
3522
3612
|
/* @__PURE__ */ jsx(Text3, { children: `${repoFilter.size} repo${repoFilter.size !== 1 ? "s" : ""}` }),
|
|
@@ -3554,6 +3644,8 @@ var BrowseScreen = ({
|
|
|
3554
3644
|
cols: listCols,
|
|
3555
3645
|
markerCols,
|
|
3556
3646
|
uniformLabels,
|
|
3647
|
+
columns: trailingColumns,
|
|
3648
|
+
shed: trailingShed,
|
|
3557
3649
|
gap: i > 0 && gapsAbove(section.items, viewStart + i)
|
|
3558
3650
|
},
|
|
3559
3651
|
`${viewStart + i}:${rowKey(item)}`
|
|
@@ -4140,4 +4232,4 @@ var matchesFilter = (repo, filter) => {
|
|
|
4140
4232
|
};
|
|
4141
4233
|
var parsePatterns = (value) => value.split(",").map((p) => p.trim()).filter(Boolean);
|
|
4142
4234
|
|
|
4143
|
-
export { ActionMenu, App, COLS, CiStatusLine, CommentsPanel, HealthPanel, MIN_SIDEBAR_COLS, PrRow, SIDEBAR_COLS, SidePanel, StatusStripLine, ageLabel, budgetNotice, buildActions, buildCheckoutCmd, clipboard, counts, drillCmd, explainGhAction, explainItem, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, itermRun, jumpToRepo, jumpToRepoPane, matchesFilter, maxViewStart, moveCursor, openInTab, parsePatterns, railCapacity, railHeights, railRowsOf, railWidth, railsOf, readCache, renderMarkdown, reposInSections, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, signatureOf, stripGlyph, stripLayout, stripSignature, toCiStatusState, truncate, useActionMenu, windowCount, withHeaders, withoutItem, workCount, writeCache };
|
|
4235
|
+
export { ActionMenu, App, COLS, CiStatusLine, CommentsPanel, HealthPanel, MIN_SIDEBAR_COLS, PrRow, SIDEBAR_COLS, SidePanel, StatusStripLine, ageLabel, budgetNotice, buildActions, buildCheckoutCmd, clipboard, counts, drillCmd, explainGhAction, explainItem, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, itermRun, jumpToRepo, jumpToRepoPane, matchesFilter, maxViewStart, moveCursor, openInTab, parsePatterns, railCapacity, railHeights, railRowsOf, railWidth, railsOf, readCache, renderMarkdown, reposInSections, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, sectionShedOf, signatureOf, stripGlyph, stripLayout, stripSignature, toCiStatusState, trailingColumnsOf, truncate, useActionMenu, windowCount, withHeaders, withoutItem, workCount, writeCache };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kud/gh-ink",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.62.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.18.0",
|
|
52
52
|
"@kud/gh-workflow": "0.13.1",
|
|
53
|
-
"@kud/ink-ui": "0.
|
|
53
|
+
"@kud/ink-ui": "0.31.0",
|
|
54
54
|
"zx": "8.8.5"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|