@kud/gh-ink 0.60.0 → 0.61.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 +88 -4
- package/dist/index.js +329 -288
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React, { ReactNode } from 'react';
|
|
2
2
|
import { PrComments, PrHealthData, PrCheck, Health } from '@kud/gh';
|
|
3
|
-
import {
|
|
4
|
-
import { AnyItem, Section, CiStatus, GHItem, OriginSplit } from '@kud/gh-workflow';
|
|
3
|
+
import { GHItem, AnyItem, Section, CiStatus, OriginSplit } from '@kud/gh-workflow';
|
|
5
4
|
export { AnyItem, Band, CiStatus, GHDetail, GHItem, InboxConfig, Move, OriginSplit, PIN_MARK, RepoHeader, RepoProfile, Section, ShowLess, ShowMore, Standing, SubgroupHeader, TaskRow, bandOf, checkoutDirs, configureInbox, filterByOrigin, filterByRepos, filterBySearch, impliedLabels, inboxConfig, insertRepoHeaders, labelPriority, layoutGHItems, profileOf, relativeTime, repoPriority, resetInboxConfig, sortByRecency, sortItems, whoseMove } from '@kud/gh-workflow';
|
|
5
|
+
import { StyledLine } from '@kud/ink-ui';
|
|
6
6
|
|
|
7
7
|
type CommentsPanelProps = {
|
|
8
8
|
repo: string;
|
|
@@ -179,6 +179,82 @@ declare const SidePanel: ({ sidebar, liveLabel, width, height, focused, cursor,
|
|
|
179
179
|
cursor?: number;
|
|
180
180
|
}) => React.JSX.Element;
|
|
181
181
|
|
|
182
|
+
/**
|
|
183
|
+
* How this row is moving through the list right now.
|
|
184
|
+
*
|
|
185
|
+
* The row itself never works this out: whoever owns the list owns the
|
|
186
|
+
* choreography — what counts as an arrival, how long a departure is held, which
|
|
187
|
+
* frame of a ramp is on screen — and hands the row the conclusion. So this
|
|
188
|
+
* enumerates what the TITLE has to say, not what happened upstream to cause it.
|
|
189
|
+
*
|
|
190
|
+
* `withdrawn` is `departing` plus the strike: a row struck through is one that
|
|
191
|
+
* has been taken off the list rather than moved along it, and the two read
|
|
192
|
+
* differently on purpose.
|
|
193
|
+
*/
|
|
194
|
+
type RowMotion = "arriving" | "departing" | "withdrawn";
|
|
195
|
+
/**
|
|
196
|
+
* A solid pill at the end of the row, saying what just happened to it.
|
|
197
|
+
*
|
|
198
|
+
* Solid because it is an EVENT — `@kud/ink-ui`'s pill law in one line: the
|
|
199
|
+
* column says where it sits, soft says what it is, solid says something
|
|
200
|
+
* happened. The word and the colour are the caller's vocabulary; what the row
|
|
201
|
+
* owns is that the pill is charged against the width budget whether or not it
|
|
202
|
+
* is drawn.
|
|
203
|
+
*/
|
|
204
|
+
type RowAnnouncement = {
|
|
205
|
+
label: string;
|
|
206
|
+
color: string;
|
|
207
|
+
};
|
|
208
|
+
type PrRowProps = {
|
|
209
|
+
item: GHItem;
|
|
210
|
+
active: boolean;
|
|
211
|
+
login?: string;
|
|
212
|
+
/**
|
|
213
|
+
* Columns available to this row, which is NOT always the frame width: a rail
|
|
214
|
+
* beside the list takes its share, and a budget that does not know the rail is
|
|
215
|
+
* there overflows by exactly the rail.
|
|
216
|
+
*/
|
|
217
|
+
cols: number;
|
|
218
|
+
/** Overrides the health glyph — the inbox passes its transit/merge frame here. */
|
|
219
|
+
icon?: {
|
|
220
|
+
glyph: string;
|
|
221
|
+
color: string;
|
|
222
|
+
};
|
|
223
|
+
/**
|
|
224
|
+
* This row's tree glyphs, already assembled — see `treePrefix`. Empty for a
|
|
225
|
+
* top-level row.
|
|
226
|
+
*
|
|
227
|
+
* A row cannot work this out about itself: it is a fact about the rows BELOW
|
|
228
|
+
* it (is a sibling still to come?) and about its ANCESTORS (does a stem still
|
|
229
|
+
* need to run past this level?), so the list supplies it.
|
|
230
|
+
*/
|
|
231
|
+
prefix?: string;
|
|
232
|
+
/**
|
|
233
|
+
* Labels carried by EVERY label-bearing row in this section, measured once by
|
|
234
|
+
* the list. Suppressed here for the same reason `impliedLabels` suppresses a
|
|
235
|
+
* repo's conventional ones — a label on every row classifies nothing — but on
|
|
236
|
+
* the section axis, which catches uniformity that comes from the query rather
|
|
237
|
+
* than from a repo convention. Defaulted so a host that does not measure it
|
|
238
|
+
* keeps exactly the behaviour it had.
|
|
239
|
+
*/
|
|
240
|
+
uniformLabels?: readonly string[];
|
|
241
|
+
/** How the title reads while the row is coming or going. Still when absent. */
|
|
242
|
+
motion?: RowMotion;
|
|
243
|
+
/** In order, left to right. Charged against the width budget either way. */
|
|
244
|
+
announcements?: readonly RowAnnouncement[];
|
|
245
|
+
};
|
|
246
|
+
/**
|
|
247
|
+
* One pull request or issue, as a single line of a list.
|
|
248
|
+
*
|
|
249
|
+
* The shared renderer: the inbox draws its rows with it, and so does anything
|
|
250
|
+
* else that has a `GHItem` and a width. Everything it knows is in its props —
|
|
251
|
+
* it holds no timers, reads no clock, and has no opinion about whether the list
|
|
252
|
+
* is refreshing. That is deliberate and it is the seam: the choreography of
|
|
253
|
+
* arrival, merge and departure belongs to whoever owns the list, and reaches
|
|
254
|
+
* the row as `icon`, `motion` and `announcements` after the decisions are made.
|
|
255
|
+
*/
|
|
256
|
+
declare const PrRow: ({ item, active, login, cols, icon: iconOverride, prefix, uniformLabels, motion, announcements, }: PrRowProps) => React.JSX.Element;
|
|
257
|
+
|
|
182
258
|
/**
|
|
183
259
|
* One state per thing, from a closed set the strip knows how to draw. The host
|
|
184
260
|
* decides what "warn" means — an error-rate edge, a stale feed, a flaky build —
|
|
@@ -252,6 +328,15 @@ declare const healthGlyph: (h: Health) => string;
|
|
|
252
328
|
declare const healthColor: (h: Health) => string;
|
|
253
329
|
declare const healthLegend: [Health, string][];
|
|
254
330
|
|
|
331
|
+
/**
|
|
332
|
+
* Shorten a string to `max` columns, eliding the MIDDLE rather than the tail.
|
|
333
|
+
*
|
|
334
|
+
* Shared rather than local because both row renderers measure against the same
|
|
335
|
+
* budget arithmetic, and a second copy is a second place for the ellipsis rule
|
|
336
|
+
* to drift.
|
|
337
|
+
*/
|
|
338
|
+
declare const truncate: (str: string, max: number) => string;
|
|
339
|
+
|
|
255
340
|
type ExtensionTarget = {
|
|
256
341
|
item?: AnyItem;
|
|
257
342
|
ciJob?: string;
|
|
@@ -421,7 +506,6 @@ declare const fitCount: (items: AnyItem[], start: number, budget: number) => num
|
|
|
421
506
|
declare const windowCount: (items: AnyItem[], start: number, budget: number) => number;
|
|
422
507
|
declare const maxViewStart: (items: AnyItem[], budget: number) => number;
|
|
423
508
|
declare const withHeaders: (items: AnyItem[], idx: number) => number;
|
|
424
|
-
declare const truncate: (str: string, max: number) => string;
|
|
425
509
|
declare const clipboard: (text: string) => void;
|
|
426
510
|
declare const buildCheckoutCmd: (repoFull: string, branch: string, login: string) => Promise<string>;
|
|
427
511
|
declare const resolveRepoPath: (repoFull: string) => Promise<string | null>;
|
|
@@ -629,4 +713,4 @@ declare const matchesFilter: (repo: string, filter: RepoFilter) => boolean;
|
|
|
629
713
|
*/
|
|
630
714
|
declare const parsePatterns: (value: string) => string[];
|
|
631
715
|
|
|
632
|
-
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 Rails, type RepoFilter, 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 };
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
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, StatusMessage, FooterHints, useListCursor, CommandPalette, Tabs, ProgressBar, pillWidth
|
|
3
|
+
import { colors, ScrollView, TextInput, Pill, useAppKeys, LoadingScreen, StatusMessage, FooterHints, 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
|
+
import { PIN_MARK, sizeOf, sizePartsOf, depthOf, impliedLabels, labelPriority, checkoutDirs, profileOf, inboxConfig, relativeTime, filterBySearch, filterByRepos, filterByOrigin } from '@kud/gh-workflow';
|
|
7
|
+
export { PIN_MARK, bandOf, checkoutDirs, configureInbox, filterByOrigin, filterByRepos, filterBySearch, impliedLabels, inboxConfig, insertRepoHeaders, labelPriority, layoutGHItems, profileOf, relativeTime, repoPriority, resetInboxConfig, sortByRecency, sortItems, whoseMove } from '@kud/gh-workflow';
|
|
6
8
|
import { $ } from 'zx';
|
|
7
9
|
import { spawn } from 'child_process';
|
|
8
10
|
import { readFileSync, mkdirSync, writeFileSync, existsSync, readdirSync, statSync, watch, rmSync } from 'fs';
|
|
9
11
|
import { join, dirname, basename } from 'path';
|
|
10
12
|
import { homedir } from 'os';
|
|
11
|
-
import { PIN_MARK, depthOf, checkoutDirs, profileOf, inboxConfig, relativeTime, filterBySearch, filterByRepos, filterByOrigin, sizeOf, sizePartsOf, impliedLabels, labelPriority } from '@kud/gh-workflow';
|
|
12
|
-
export { PIN_MARK, bandOf, checkoutDirs, configureInbox, filterByOrigin, filterByRepos, filterBySearch, impliedLabels, inboxConfig, insertRepoHeaders, labelPriority, layoutGHItems, profileOf, relativeTime, repoPriority, resetInboxConfig, sortByRecency, sortItems, whoseMove } from '@kud/gh-workflow';
|
|
13
13
|
|
|
14
14
|
// src/components/comments-panel.tsx
|
|
15
15
|
var ENTITIES = {
|
|
@@ -748,6 +748,213 @@ var SidePanel = ({
|
|
|
748
748
|
)
|
|
749
749
|
);
|
|
750
750
|
};
|
|
751
|
+
var healthDisplay = {
|
|
752
|
+
none: { glyph: " ", color: colors.muted },
|
|
753
|
+
draft: { glyph: "~", color: colors.muted },
|
|
754
|
+
"ci-fail": { glyph: "\u2717", color: colors.error },
|
|
755
|
+
conflict: { glyph: "!", color: colors.accent },
|
|
756
|
+
"changes-req": { glyph: "\xB1", color: colors.warning },
|
|
757
|
+
threads: { glyph: "\u25C6", color: colors.accent },
|
|
758
|
+
pending: { glyph: "*", color: colors.warning },
|
|
759
|
+
approved: { glyph: "\u2713", color: colors.success },
|
|
760
|
+
waiting: { glyph: "\xB7", color: colors.muted },
|
|
761
|
+
// The one glyph here that MEANS its state rather than merely differing from
|
|
762
|
+
// the others. `✓` and `✗` you never have to think about; `»` you did — it was
|
|
763
|
+
// chosen to suggest "moved through", which is a stretch nobody reads at a
|
|
764
|
+
// glance. This is Nerd Font's git-merge icon, written as an escape because raw
|
|
765
|
+
// PUA bytes get mangled by editors and diffs.
|
|
766
|
+
//
|
|
767
|
+
// The cost, stated rather than discovered: a terminal without a Nerd Font
|
|
768
|
+
// draws a box here where it used to draw a chevron. That is a trade this
|
|
769
|
+
// package has already made once — the inbox hardcodes the comment glyph at
|
|
770
|
+
// \u{f086} — and one state degrading to tofu is cheaper than ten states none
|
|
771
|
+
// of which say what they mean.
|
|
772
|
+
merged: { glyph: "\uE727", color: colors.muted },
|
|
773
|
+
// Nerd Font's closed-pull-request icon, for the same reason as `merged` above
|
|
774
|
+
// and with the same caveat about a font that lacks it. `×` had a second problem
|
|
775
|
+
// beyond being arbitrary: it is one stroke away from `✗` (ci failing) two rows
|
|
776
|
+
// up in this very map, and the shape-distinctness this file turns on is a
|
|
777
|
+
// silhouette test, not a codepoint one.
|
|
778
|
+
closed: { glyph: "\uEBDA", color: colors.muted }
|
|
779
|
+
};
|
|
780
|
+
var healthGlyph = (h) => healthDisplay[h].glyph;
|
|
781
|
+
var healthColor = (h) => healthDisplay[h].color;
|
|
782
|
+
var healthLegend = [
|
|
783
|
+
["approved", "Approved \xB7 ready to merge"],
|
|
784
|
+
["pending", "Checks running"],
|
|
785
|
+
["ci-fail", "CI failing"],
|
|
786
|
+
["conflict", "Merge conflict"],
|
|
787
|
+
["changes-req", "Changes requested"],
|
|
788
|
+
["threads", "Open threads \xB7 your reply"],
|
|
789
|
+
["waiting", "Awaiting review"],
|
|
790
|
+
["draft", "Draft"],
|
|
791
|
+
["merged", "Merged"],
|
|
792
|
+
["closed", "Closed"]
|
|
793
|
+
];
|
|
794
|
+
var UNREAD_DISPLAY = { glyph: "\u25CB", color: colors.muted };
|
|
795
|
+
var displayFor = (h) => h ? healthDisplay[h] : UNREAD_DISPLAY;
|
|
796
|
+
|
|
797
|
+
// src/lib/truncate.ts
|
|
798
|
+
var truncate = (str, max) => {
|
|
799
|
+
if (str.length <= max) return str;
|
|
800
|
+
const half = Math.floor((max - 1) / 2);
|
|
801
|
+
return `${str.slice(0, half)}\u2026${str.slice(-half)}`;
|
|
802
|
+
};
|
|
803
|
+
var DimContext = createContext(false);
|
|
804
|
+
var BACKDROP_FG = "#5a5a68";
|
|
805
|
+
var BACKDROP_FG_RECESSED = "#3a3a46";
|
|
806
|
+
var backdropStyle = (props) => ({
|
|
807
|
+
color: props.dimColor ? BACKDROP_FG_RECESSED : BACKDROP_FG,
|
|
808
|
+
dimColor: false,
|
|
809
|
+
bold: false,
|
|
810
|
+
italic: false,
|
|
811
|
+
inverse: false,
|
|
812
|
+
backgroundColor: void 0
|
|
813
|
+
});
|
|
814
|
+
var Text3 = ({ children, ...props }) => {
|
|
815
|
+
const dimmed = useContext(DimContext);
|
|
816
|
+
return dimmed ? /* @__PURE__ */ jsx(Text, { ...props, ...backdropStyle(props), children }) : /* @__PURE__ */ jsx(Text, { ...props, children });
|
|
817
|
+
};
|
|
818
|
+
var useBackdropped = () => useContext(DimContext);
|
|
819
|
+
var Backdrop = ({
|
|
820
|
+
dimmed,
|
|
821
|
+
absolute,
|
|
822
|
+
height,
|
|
823
|
+
children
|
|
824
|
+
}) => /* @__PURE__ */ jsx(DimContext.Provider, { value: dimmed, children: absolute ? /* @__PURE__ */ jsx(
|
|
825
|
+
Box,
|
|
826
|
+
{
|
|
827
|
+
position: "absolute",
|
|
828
|
+
flexDirection: "column",
|
|
829
|
+
width: "100%",
|
|
830
|
+
height,
|
|
831
|
+
children
|
|
832
|
+
}
|
|
833
|
+
) : children });
|
|
834
|
+
var PrRow = ({
|
|
835
|
+
item,
|
|
836
|
+
active,
|
|
837
|
+
login,
|
|
838
|
+
cols,
|
|
839
|
+
icon: iconOverride,
|
|
840
|
+
prefix = "",
|
|
841
|
+
uniformLabels = [],
|
|
842
|
+
motion,
|
|
843
|
+
announcements = []
|
|
844
|
+
}) => {
|
|
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
|
+
const numStr = `#${item.number}`.padEnd(7);
|
|
854
|
+
const showAuthor = !!item.author && item.author !== login;
|
|
855
|
+
const sizeLabel = sizeOf(item);
|
|
856
|
+
const sizeParts = sizePartsOf(item);
|
|
857
|
+
const unresolvedLabel = item.unresolved > 0 ? `\uF086 ${item.unresolved}` : "";
|
|
858
|
+
const agePair = item.activityAge && item.activityAge !== item.age ? { activity: item.activityAge, lifetime: item.age } : null;
|
|
859
|
+
const ageLabel2 = agePair ? `${agePair.activity} (${agePair.lifetime})` : item.age;
|
|
860
|
+
const pillCaps = announcements.length * 2;
|
|
861
|
+
const repoLabel = depthOf(item) > 0 ? item.repo : "";
|
|
862
|
+
const implied = [...impliedLabels(item.repo), ...uniformLabels];
|
|
863
|
+
const labelNames = (item.labels ?? []).filter((l) => !implied.includes(l)).sort((a, b) => labelPriority(a) - labelPriority(b) || a.localeCompare(b)).slice(0, 2);
|
|
864
|
+
const givingUp = {
|
|
865
|
+
author: false,
|
|
866
|
+
size: false,
|
|
867
|
+
threads: false,
|
|
868
|
+
age: false,
|
|
869
|
+
repo: false,
|
|
870
|
+
labels: 0
|
|
871
|
+
};
|
|
872
|
+
const LABEL_CELL_MAX = 24;
|
|
873
|
+
const labelCell = () => {
|
|
874
|
+
const shown = labelNames.slice(
|
|
875
|
+
0,
|
|
876
|
+
Math.max(0, labelNames.length - givingUp.labels)
|
|
877
|
+
);
|
|
878
|
+
if (shown.length === 0) return "";
|
|
879
|
+
const fitted = [];
|
|
880
|
+
for (const name of shown) {
|
|
881
|
+
const next = [...fitted, name].join(", ");
|
|
882
|
+
if (next.length <= LABEL_CELL_MAX) fitted.push(name);
|
|
883
|
+
}
|
|
884
|
+
if (fitted.length === 0) {
|
|
885
|
+
return `\uF02B ${truncate(shown[0], LABEL_CELL_MAX)}`;
|
|
886
|
+
}
|
|
887
|
+
return `\uF02B ${fitted.join(", ")}`;
|
|
888
|
+
};
|
|
889
|
+
const widthOf2 = () => {
|
|
890
|
+
const suffix = [
|
|
891
|
+
givingUp.age ? "" : ageLabel2 || "",
|
|
892
|
+
// ASCII only, so no PUA double-width correction — see the label cell.
|
|
893
|
+
givingUp.size ? "" : sizeLabel || "",
|
|
894
|
+
givingUp.threads ? "" : unresolvedLabel,
|
|
895
|
+
showAuthor && !givingUp.author ? `by ${item.author}` : "",
|
|
896
|
+
...announcements.map((a) => a.label)
|
|
897
|
+
].filter(Boolean).join(" ");
|
|
898
|
+
const cell = labelCell();
|
|
899
|
+
return 2 + prefix.length + 2 + 2 + 7 + (cell ? 2 + cell.length + 1 : 0) + (givingUp.repo ? 0 : repoLabel.length) + suffix.length + pillCaps + 6;
|
|
900
|
+
};
|
|
901
|
+
const MIN_TITLE = 24;
|
|
902
|
+
for (const give of [
|
|
903
|
+
() => givingUp.author = true,
|
|
904
|
+
() => givingUp.labels = 1,
|
|
905
|
+
() => givingUp.size = true,
|
|
906
|
+
() => givingUp.threads = true,
|
|
907
|
+
() => givingUp.labels = 2,
|
|
908
|
+
() => givingUp.repo = true,
|
|
909
|
+
() => givingUp.age = true
|
|
910
|
+
]) {
|
|
911
|
+
if (cols - widthOf2() >= MIN_TITLE) break;
|
|
912
|
+
give();
|
|
913
|
+
}
|
|
914
|
+
const labelLabel = labelCell();
|
|
915
|
+
const titleMax = Math.max(1, cols - widthOf2());
|
|
916
|
+
return /* @__PURE__ */ jsxs(Box, { children: [
|
|
917
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.info, children: active ? "\u276F " : " " }),
|
|
918
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: prefix }),
|
|
919
|
+
/* @__PURE__ */ jsx(Text3, { color, bold: true, children: icon + " " }),
|
|
920
|
+
/* @__PURE__ */ jsx(Text3, { color: turnColor, bold: turnIcon === "\u2190", children: turnIcon + " " }),
|
|
921
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.accent, children: numStr }),
|
|
922
|
+
/* @__PURE__ */ jsx(
|
|
923
|
+
Text3,
|
|
924
|
+
{
|
|
925
|
+
bold: active || motion === "arriving",
|
|
926
|
+
dimColor: motion === "departing" || motion === "withdrawn",
|
|
927
|
+
strikethrough: motion === "withdrawn",
|
|
928
|
+
children: truncate(item.title, titleMax) + " "
|
|
929
|
+
}
|
|
930
|
+
),
|
|
931
|
+
labelLabel ? /* @__PURE__ */ jsx(Text3, { color: colors.secondary, children: labelLabel + " " }) : null,
|
|
932
|
+
repoLabel && !givingUp.repo ? /* @__PURE__ */ jsx(Text3, { dimColor: true, children: repoLabel }) : null,
|
|
933
|
+
sizeParts && !givingUp.size ? /* @__PURE__ */ jsxs(Text3, { children: [
|
|
934
|
+
" ",
|
|
935
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.success, children: sizeParts.added }),
|
|
936
|
+
" ",
|
|
937
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.error, children: sizeParts.removed })
|
|
938
|
+
] }) : null,
|
|
939
|
+
unresolvedLabel && !givingUp.threads ? /* @__PURE__ */ jsx(
|
|
940
|
+
Text3,
|
|
941
|
+
{
|
|
942
|
+
bold: !spokeLast,
|
|
943
|
+
color: spokeLast ? colors.secondary : colors.accent,
|
|
944
|
+
children: " " + unresolvedLabel
|
|
945
|
+
}
|
|
946
|
+
) : null,
|
|
947
|
+
showAuthor && !givingUp.author ? /* @__PURE__ */ jsx(Text3, { dimColor: true, italic: true, children: " by " + item.author }) : null,
|
|
948
|
+
ageLabel2 && !givingUp.age ? agePair ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
949
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.secondary, children: " " + agePair.activity }),
|
|
950
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: ` (${agePair.lifetime})` })
|
|
951
|
+
] }) : /* @__PURE__ */ jsx(Text3, { color: colors.secondary, children: " " + ageLabel2 }) : null,
|
|
952
|
+
backdropped ? null : announcements.map((a) => /* @__PURE__ */ jsxs(React2.Fragment, { children: [
|
|
953
|
+
/* @__PURE__ */ jsx(Text3, { children: " " }),
|
|
954
|
+
/* @__PURE__ */ jsx(Pill, { color: a.color, children: a.label })
|
|
955
|
+
] }, a.label))
|
|
956
|
+
] });
|
|
957
|
+
};
|
|
751
958
|
var stripGlyph = (state) => {
|
|
752
959
|
switch (state) {
|
|
753
960
|
case "ok":
|
|
@@ -848,51 +1055,6 @@ var StatusStripLine = ({
|
|
|
848
1055
|
age ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` ${age}` }) : null
|
|
849
1056
|
] });
|
|
850
1057
|
};
|
|
851
|
-
var healthDisplay = {
|
|
852
|
-
none: { glyph: " ", color: colors.muted },
|
|
853
|
-
draft: { glyph: "~", color: colors.muted },
|
|
854
|
-
"ci-fail": { glyph: "\u2717", color: colors.error },
|
|
855
|
-
conflict: { glyph: "!", color: colors.accent },
|
|
856
|
-
"changes-req": { glyph: "\xB1", color: colors.warning },
|
|
857
|
-
threads: { glyph: "\u25C6", color: colors.accent },
|
|
858
|
-
pending: { glyph: "*", color: colors.warning },
|
|
859
|
-
approved: { glyph: "\u2713", color: colors.success },
|
|
860
|
-
waiting: { glyph: "\xB7", color: colors.muted },
|
|
861
|
-
// The one glyph here that MEANS its state rather than merely differing from
|
|
862
|
-
// the others. `✓` and `✗` you never have to think about; `»` you did — it was
|
|
863
|
-
// chosen to suggest "moved through", which is a stretch nobody reads at a
|
|
864
|
-
// glance. This is Nerd Font's git-merge icon, written as an escape because raw
|
|
865
|
-
// PUA bytes get mangled by editors and diffs.
|
|
866
|
-
//
|
|
867
|
-
// The cost, stated rather than discovered: a terminal without a Nerd Font
|
|
868
|
-
// draws a box here where it used to draw a chevron. That is a trade this
|
|
869
|
-
// package has already made once — the inbox hardcodes the comment glyph at
|
|
870
|
-
// \u{f086} — and one state degrading to tofu is cheaper than ten states none
|
|
871
|
-
// of which say what they mean.
|
|
872
|
-
merged: { glyph: "\uE727", color: colors.muted },
|
|
873
|
-
// Nerd Font's closed-pull-request icon, for the same reason as `merged` above
|
|
874
|
-
// and with the same caveat about a font that lacks it. `×` had a second problem
|
|
875
|
-
// beyond being arbitrary: it is one stroke away from `✗` (ci failing) two rows
|
|
876
|
-
// up in this very map, and the shape-distinctness this file turns on is a
|
|
877
|
-
// silhouette test, not a codepoint one.
|
|
878
|
-
closed: { glyph: "\uEBDA", color: colors.muted }
|
|
879
|
-
};
|
|
880
|
-
var healthGlyph = (h) => healthDisplay[h].glyph;
|
|
881
|
-
var healthColor = (h) => healthDisplay[h].color;
|
|
882
|
-
var healthLegend = [
|
|
883
|
-
["approved", "Approved \xB7 ready to merge"],
|
|
884
|
-
["pending", "Checks running"],
|
|
885
|
-
["ci-fail", "CI failing"],
|
|
886
|
-
["conflict", "Merge conflict"],
|
|
887
|
-
["changes-req", "Changes requested"],
|
|
888
|
-
["threads", "Open threads \xB7 your reply"],
|
|
889
|
-
["waiting", "Awaiting review"],
|
|
890
|
-
["draft", "Draft"],
|
|
891
|
-
["merged", "Merged"],
|
|
892
|
-
["closed", "Closed"]
|
|
893
|
-
];
|
|
894
|
-
var UNREAD_DISPLAY = { glyph: "\u25CB", color: colors.muted };
|
|
895
|
-
var displayFor = (h) => h ? healthDisplay[h] : UNREAD_DISPLAY;
|
|
896
1058
|
|
|
897
1059
|
// src/inbox/cache.ts
|
|
898
1060
|
var cacheTtlMs = () => inboxConfig().cacheTtlMs;
|
|
@@ -1385,11 +1547,6 @@ var withHeaders = (items, idx) => {
|
|
|
1385
1547
|
start--;
|
|
1386
1548
|
return start;
|
|
1387
1549
|
};
|
|
1388
|
-
var truncate = (str, max) => {
|
|
1389
|
-
if (str.length <= max) return str;
|
|
1390
|
-
const half = Math.floor((max - 1) / 2);
|
|
1391
|
-
return `${str.slice(0, half)}\u2026${str.slice(-half)}`;
|
|
1392
|
-
};
|
|
1393
1550
|
var clipboard = (text) => {
|
|
1394
1551
|
const p = spawn("pbcopy", [], { stdio: "pipe" });
|
|
1395
1552
|
p.stdin.write(text);
|
|
@@ -1574,37 +1731,6 @@ var FRAME_CHROME_COLS = 2 + FRAME_PAD_X * 2;
|
|
|
1574
1731
|
var COLS = (process.stdout.columns ?? 120) - FRAME_CHROME_COLS;
|
|
1575
1732
|
var MODAL_CHROME_COLS = 2 + 1 * 2;
|
|
1576
1733
|
var OVERLAY_BG = "#22222e";
|
|
1577
|
-
var DimContext = createContext(false);
|
|
1578
|
-
var BACKDROP_FG = "#5a5a68";
|
|
1579
|
-
var BACKDROP_FG_RECESSED = "#3a3a46";
|
|
1580
|
-
var backdropStyle = (props) => ({
|
|
1581
|
-
color: props.dimColor ? BACKDROP_FG_RECESSED : BACKDROP_FG,
|
|
1582
|
-
dimColor: false,
|
|
1583
|
-
bold: false,
|
|
1584
|
-
italic: false,
|
|
1585
|
-
inverse: false,
|
|
1586
|
-
backgroundColor: void 0
|
|
1587
|
-
});
|
|
1588
|
-
var Text4 = ({ children, ...props }) => {
|
|
1589
|
-
const dimmed = useContext(DimContext);
|
|
1590
|
-
return dimmed ? /* @__PURE__ */ jsx(Text, { ...props, ...backdropStyle(props), children }) : /* @__PURE__ */ jsx(Text, { ...props, children });
|
|
1591
|
-
};
|
|
1592
|
-
var useBackdropped = () => useContext(DimContext);
|
|
1593
|
-
var Backdrop = ({
|
|
1594
|
-
dimmed,
|
|
1595
|
-
absolute,
|
|
1596
|
-
height,
|
|
1597
|
-
children
|
|
1598
|
-
}) => /* @__PURE__ */ jsx(DimContext.Provider, { value: dimmed, children: absolute ? /* @__PURE__ */ jsx(
|
|
1599
|
-
Box,
|
|
1600
|
-
{
|
|
1601
|
-
position: "absolute",
|
|
1602
|
-
flexDirection: "column",
|
|
1603
|
-
width: "100%",
|
|
1604
|
-
height,
|
|
1605
|
-
children
|
|
1606
|
-
}
|
|
1607
|
-
) : children });
|
|
1608
1734
|
var workCount = (s) => {
|
|
1609
1735
|
let n = 0;
|
|
1610
1736
|
for (let i = 0; i < s.items.length; i++) {
|
|
@@ -1981,13 +2107,13 @@ var InboxHeader = ({
|
|
|
1981
2107
|
COLS - brand.length - countSeg.length - userSeg.length - workLabel.length - budgetSeg.length - statusSeg.length
|
|
1982
2108
|
);
|
|
1983
2109
|
return /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
1984
|
-
/* @__PURE__ */ jsx(
|
|
1985
|
-
/* @__PURE__ */ jsx(
|
|
1986
|
-
userSeg ? /* @__PURE__ */ jsx(
|
|
1987
|
-
scopeLabel ? /* @__PURE__ */ jsx(
|
|
1988
|
-
budgetLabel ? /* @__PURE__ */ jsx(
|
|
2110
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.accent, bold: true, children: brand }),
|
|
2111
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: countSeg }),
|
|
2112
|
+
userSeg ? /* @__PURE__ */ jsx(Text3, { children: userSeg }) : null,
|
|
2113
|
+
scopeLabel ? /* @__PURE__ */ jsx(Text3, { dimColor: true, children: workLabel }) : null,
|
|
2114
|
+
budgetLabel ? /* @__PURE__ */ jsx(Text3, { bold: true, color: budgetCritical ? "#FF5F5F" : colors.accent, children: budgetSeg }) : null,
|
|
1989
2115
|
statusText ? /* @__PURE__ */ jsx(
|
|
1990
|
-
|
|
2116
|
+
Text3,
|
|
1991
2117
|
{
|
|
1992
2118
|
color: statusColor,
|
|
1993
2119
|
dimColor: !statusColor,
|
|
@@ -1995,7 +2121,7 @@ var InboxHeader = ({
|
|
|
1995
2121
|
children: statusSeg
|
|
1996
2122
|
}
|
|
1997
2123
|
) : null,
|
|
1998
|
-
/* @__PURE__ */ jsx(
|
|
2124
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.info, dimColor: true, children: "\u254C".repeat(fill) })
|
|
1999
2125
|
] });
|
|
2000
2126
|
};
|
|
2001
2127
|
var stripSignature = (strip) => strip === null ? "\u2205" : strip.items.map((i) => `${i.key}=${i.state}${i.alarm ? "\u25B2" : ""}`).join(",");
|
|
@@ -2019,24 +2145,24 @@ var CiStatusLine = ({
|
|
|
2019
2145
|
const name = job ?? "ci";
|
|
2020
2146
|
if (state.kind === "loading")
|
|
2021
2147
|
return /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
2022
|
-
/* @__PURE__ */ jsx(
|
|
2023
|
-
/* @__PURE__ */ jsx(
|
|
2148
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: " \xB7 " }),
|
|
2149
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: `${name} loading\u2026` })
|
|
2024
2150
|
] });
|
|
2025
2151
|
if (state.kind === "error")
|
|
2026
2152
|
return /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
2027
|
-
/* @__PURE__ */ jsx(
|
|
2028
|
-
/* @__PURE__ */ jsx(
|
|
2153
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.error, bold: true, children: " \u2717 " }),
|
|
2154
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: `${name} no build / not configured` })
|
|
2029
2155
|
] });
|
|
2030
2156
|
const { status } = state;
|
|
2031
2157
|
const [, color] = jenkinsResultDisplay(status.result, status.building);
|
|
2032
2158
|
const label = status.building ? "BUILDING" : status.result;
|
|
2033
2159
|
return /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
2034
|
-
/* @__PURE__ */ jsx(
|
|
2035
|
-
/* @__PURE__ */ jsx(
|
|
2036
|
-
/* @__PURE__ */ jsx(
|
|
2037
|
-
/* @__PURE__ */ jsx(
|
|
2038
|
-
/* @__PURE__ */ jsx(
|
|
2039
|
-
status.age ? /* @__PURE__ */ jsx(
|
|
2160
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: " " }),
|
|
2161
|
+
/* @__PURE__ */ jsx(Text3, { color, bold: true, children: "\u25CF " }),
|
|
2162
|
+
/* @__PURE__ */ jsx(Text3, { bold: true, children: status.job }),
|
|
2163
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: " " + label }),
|
|
2164
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.accent, children: " #" + status.buildNumber }),
|
|
2165
|
+
status.age ? /* @__PURE__ */ jsx(Text3, { dimColor: true, children: " " + status.age }) : null
|
|
2040
2166
|
] });
|
|
2041
2167
|
};
|
|
2042
2168
|
var FENCE_COLS = 46;
|
|
@@ -2049,10 +2175,10 @@ var RepoHeaderRow = ({
|
|
|
2049
2175
|
const fill = Math.max(4, FENCE_COLS - label.length);
|
|
2050
2176
|
const rule = "\u2500".repeat(fill);
|
|
2051
2177
|
return /* @__PURE__ */ jsxs(Box, { marginTop: gap ? 1 : 0, children: [
|
|
2052
|
-
/* @__PURE__ */ jsx(
|
|
2053
|
-
/* @__PURE__ */ jsx(
|
|
2178
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.info, children: active ? "\u276F " : " " }),
|
|
2179
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: !active, children: "\u2500\u2500 " }),
|
|
2054
2180
|
/* @__PURE__ */ jsx(
|
|
2055
|
-
|
|
2181
|
+
Text3,
|
|
2056
2182
|
{
|
|
2057
2183
|
dimColor: false,
|
|
2058
2184
|
color: active ? void 0 : colors.secondary,
|
|
@@ -2060,7 +2186,7 @@ var RepoHeaderRow = ({
|
|
|
2060
2186
|
children: repo
|
|
2061
2187
|
}
|
|
2062
2188
|
),
|
|
2063
|
-
/* @__PURE__ */ jsx(
|
|
2189
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: !active, children: " " + rule })
|
|
2064
2190
|
] });
|
|
2065
2191
|
};
|
|
2066
2192
|
var MERGED_HOLD_MS = 3e3;
|
|
@@ -2125,48 +2251,48 @@ var ItemRow = ({
|
|
|
2125
2251
|
return /* @__PURE__ */ jsx(RepoHeaderRow, { repo: item.repo, gap: gap ?? false, active });
|
|
2126
2252
|
if (item.kind === "subgroup-header")
|
|
2127
2253
|
return /* @__PURE__ */ jsxs(Box, { marginTop: gap ? 1 : 0, children: [
|
|
2128
|
-
/* @__PURE__ */ jsx(
|
|
2129
|
-
/* @__PURE__ */ jsx(
|
|
2254
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.accent, bold: true, children: " \xBB " }),
|
|
2255
|
+
/* @__PURE__ */ jsx(Text3, { bold: true, children: item.label })
|
|
2130
2256
|
] });
|
|
2131
2257
|
if (item.kind === "show-more")
|
|
2132
2258
|
return /* @__PURE__ */ jsxs(Box, { children: [
|
|
2133
|
-
/* @__PURE__ */ jsx(
|
|
2134
|
-
/* @__PURE__ */ jsx(
|
|
2135
|
-
/* @__PURE__ */ jsx(
|
|
2136
|
-
/* @__PURE__ */ jsx(
|
|
2259
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.info, children: active ? "\u276F " : " " }),
|
|
2260
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: prefix }),
|
|
2261
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: active ? "\u21B5 " : " " }),
|
|
2262
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: `+${item.hidden.length} more` })
|
|
2137
2263
|
] });
|
|
2138
2264
|
if (item.kind === "show-less")
|
|
2139
2265
|
return /* @__PURE__ */ jsxs(Box, { children: [
|
|
2140
|
-
/* @__PURE__ */ jsx(
|
|
2141
|
-
/* @__PURE__ */ jsx(
|
|
2142
|
-
/* @__PURE__ */ jsx(
|
|
2143
|
-
/* @__PURE__ */ jsx(
|
|
2266
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.info, children: active ? "\u276F " : " " }),
|
|
2267
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: prefix }),
|
|
2268
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: active ? "\u21B5 " : " " }),
|
|
2269
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: "show less" })
|
|
2144
2270
|
] });
|
|
2145
2271
|
if (item.kind === "task") {
|
|
2146
2272
|
const note = item.note ?? "";
|
|
2147
2273
|
const transitIcon = !transient ? " " : isDeparture(transient) ? TRANSIT_OUT_FRAMES[rampAt(TRANSIT_OUT_FRAMES.length)] : isArrival(transient) ? TRANSIT_IN_FRAMES[rampAt(TRANSIT_IN_FRAMES.length)] : "\u25C9";
|
|
2148
|
-
const
|
|
2274
|
+
const titleMax = Math.max(
|
|
2149
2275
|
1,
|
|
2150
2276
|
cols - item.key.length - note.length - (item.pill ? pillWidth(item.pill) + 1 : 0) - (farewellLabel ? pillWidth(farewellLabel) + 2 : 0) - prefix.length - (markerCols > 0 ? markerCols + 1 : 0) - 12
|
|
2151
2277
|
);
|
|
2152
2278
|
return /* @__PURE__ */ jsxs(Box, { marginTop: gap ? 1 : 0, children: [
|
|
2153
|
-
/* @__PURE__ */ jsx(
|
|
2154
|
-
/* @__PURE__ */ jsx(
|
|
2155
|
-
/* @__PURE__ */ jsx(
|
|
2156
|
-
/* @__PURE__ */ jsx(
|
|
2157
|
-
markerCols > 0 ? /* @__PURE__ */ jsx(
|
|
2158
|
-
/* @__PURE__ */ jsx(
|
|
2279
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.info, children: active ? "\u276F " : " " }),
|
|
2280
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: prefix }),
|
|
2281
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: parent ? "\u252C " : " " }),
|
|
2282
|
+
/* @__PURE__ */ jsx(Text3, { bold: true, color: transient ? TRANSIT_COLOUR[transient] : void 0, children: transitIcon + " " }),
|
|
2283
|
+
markerCols > 0 ? /* @__PURE__ */ jsx(Text3, { color: item.markerColor, children: (item.marker ?? "").padEnd(markerCols) + " " }) : null,
|
|
2284
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.accent, bold: active, children: item.key + " " }),
|
|
2159
2285
|
/* @__PURE__ */ jsx(
|
|
2160
|
-
|
|
2286
|
+
Text3,
|
|
2161
2287
|
{
|
|
2162
2288
|
bold: active || !!transient && isArrival(transient),
|
|
2163
2289
|
dimColor: !!transient && isDeparture(transient),
|
|
2164
2290
|
strikethrough: transient === "out",
|
|
2165
|
-
children: truncate(item.summary,
|
|
2291
|
+
children: truncate(item.summary, titleMax)
|
|
2166
2292
|
}
|
|
2167
2293
|
),
|
|
2168
2294
|
item.pill && !backdropped ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2169
|
-
/* @__PURE__ */ jsx(
|
|
2295
|
+
/* @__PURE__ */ jsx(Text3, { children: " " }),
|
|
2170
2296
|
/* @__PURE__ */ jsx(
|
|
2171
2297
|
Pill,
|
|
2172
2298
|
{
|
|
@@ -2177,127 +2303,39 @@ var ItemRow = ({
|
|
|
2177
2303
|
}
|
|
2178
2304
|
)
|
|
2179
2305
|
] }) : null,
|
|
2180
|
-
note ? /* @__PURE__ */ jsx(
|
|
2306
|
+
note ? /* @__PURE__ */ jsx(Text3, { dimColor: true, children: ` ${note}` }) : null,
|
|
2181
2307
|
farewellLabel && !backdropped ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2182
|
-
/* @__PURE__ */ jsx(
|
|
2308
|
+
/* @__PURE__ */ jsx(Text3, { children: " " }),
|
|
2183
2309
|
/* @__PURE__ */ jsx(Pill, { color: TRANSIT_COLOUR.out, children: farewellLabel })
|
|
2184
2310
|
] }) : null
|
|
2185
2311
|
] });
|
|
2186
2312
|
}
|
|
2187
|
-
const
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
const
|
|
2195
|
-
const
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
};
|
|
2212
|
-
const LABEL_CELL_MAX = 24;
|
|
2213
|
-
const labelCell = () => {
|
|
2214
|
-
const shown = labelNames.slice(
|
|
2215
|
-
0,
|
|
2216
|
-
Math.max(0, labelNames.length - givingUp.labels)
|
|
2217
|
-
);
|
|
2218
|
-
if (shown.length === 0) return "";
|
|
2219
|
-
const fitted = [];
|
|
2220
|
-
for (const name of shown) {
|
|
2221
|
-
const next = [...fitted, name].join(", ");
|
|
2222
|
-
if (next.length <= LABEL_CELL_MAX) fitted.push(name);
|
|
2223
|
-
}
|
|
2224
|
-
if (fitted.length === 0) {
|
|
2225
|
-
return `\uF02B ${truncate(shown[0], LABEL_CELL_MAX)}`;
|
|
2313
|
+
const icon = merged ? {
|
|
2314
|
+
glyph: MERGED_FRAMES[sparkFrame % MERGED_FRAMES.length],
|
|
2315
|
+
color: MERGED_COLOUR
|
|
2316
|
+
} : transient ? {
|
|
2317
|
+
glyph: isDeparture(transient) ? TRANSIT_OUT_FRAMES[rampAt(TRANSIT_OUT_FRAMES.length)] : isArrival(transient) ? TRANSIT_IN_FRAMES[rampAt(TRANSIT_IN_FRAMES.length)] : displayFor(item.health).glyph,
|
|
2318
|
+
color: TRANSIT_COLOUR[transient]
|
|
2319
|
+
} : void 0;
|
|
2320
|
+
const motion = transient === "out" ? "withdrawn" : transient && isDeparture(transient) ? "departing" : transient && isArrival(transient) ? "arriving" : void 0;
|
|
2321
|
+
const announcements = [
|
|
2322
|
+
...merged ? [{ label: "merged", color: MERGED_COLOUR }] : [],
|
|
2323
|
+
...farewellLabel ? [{ label: farewellLabel, color: TRANSIT_COLOUR.out }] : []
|
|
2324
|
+
];
|
|
2325
|
+
return /* @__PURE__ */ jsx(
|
|
2326
|
+
PrRow,
|
|
2327
|
+
{
|
|
2328
|
+
item,
|
|
2329
|
+
active,
|
|
2330
|
+
login,
|
|
2331
|
+
cols,
|
|
2332
|
+
prefix,
|
|
2333
|
+
uniformLabels,
|
|
2334
|
+
icon,
|
|
2335
|
+
motion,
|
|
2336
|
+
announcements
|
|
2226
2337
|
}
|
|
2227
|
-
|
|
2228
|
-
};
|
|
2229
|
-
const widthOf2 = () => {
|
|
2230
|
-
const suffix = [
|
|
2231
|
-
givingUp.age ? "" : ageLabel2 || "",
|
|
2232
|
-
// ASCII only, so no PUA double-width correction — see the label cell.
|
|
2233
|
-
givingUp.size ? "" : sizeLabel || "",
|
|
2234
|
-
givingUp.threads ? "" : unresolvedLabel,
|
|
2235
|
-
showAuthor && !givingUp.author ? `by ${item.author}` : "",
|
|
2236
|
-
mergedLabel
|
|
2237
|
-
].filter(Boolean).join(" ");
|
|
2238
|
-
const cell = labelCell();
|
|
2239
|
-
return 2 + prefix.length + 2 + 2 + 7 + (cell ? 2 + cell.length + 1 : 0) + (givingUp.repo ? 0 : repoLabel.length) + suffix.length + pillCaps + 6;
|
|
2240
|
-
};
|
|
2241
|
-
const MIN_TITLE = 24;
|
|
2242
|
-
for (const give of [
|
|
2243
|
-
() => givingUp.author = true,
|
|
2244
|
-
() => givingUp.labels = 1,
|
|
2245
|
-
() => givingUp.size = true,
|
|
2246
|
-
() => givingUp.threads = true,
|
|
2247
|
-
() => givingUp.labels = 2,
|
|
2248
|
-
() => givingUp.repo = true,
|
|
2249
|
-
() => givingUp.age = true
|
|
2250
|
-
]) {
|
|
2251
|
-
if (cols - widthOf2() >= MIN_TITLE) break;
|
|
2252
|
-
give();
|
|
2253
|
-
}
|
|
2254
|
-
const labelLabel = labelCell();
|
|
2255
|
-
const titleMax = Math.max(1, cols - widthOf2());
|
|
2256
|
-
return /* @__PURE__ */ jsxs(Box, { children: [
|
|
2257
|
-
/* @__PURE__ */ jsx(Text4, { color: colors.info, children: active ? "\u276F " : " " }),
|
|
2258
|
-
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: prefix }),
|
|
2259
|
-
/* @__PURE__ */ jsx(Text4, { color, bold: true, children: icon + " " }),
|
|
2260
|
-
/* @__PURE__ */ jsx(Text4, { color: turnColor, bold: turnIcon === "\u2190", children: turnIcon + " " }),
|
|
2261
|
-
/* @__PURE__ */ jsx(Text4, { color: colors.accent, children: numStr }),
|
|
2262
|
-
/* @__PURE__ */ jsx(
|
|
2263
|
-
Text4,
|
|
2264
|
-
{
|
|
2265
|
-
bold: active || !!transient && isArrival(transient),
|
|
2266
|
-
dimColor: !!transient && isDeparture(transient),
|
|
2267
|
-
strikethrough: transient === "out",
|
|
2268
|
-
children: truncate(item.title, titleMax) + " "
|
|
2269
|
-
}
|
|
2270
|
-
),
|
|
2271
|
-
labelLabel ? /* @__PURE__ */ jsx(Text4, { color: colors.secondary, children: labelLabel + " " }) : null,
|
|
2272
|
-
repoLabel && !givingUp.repo ? /* @__PURE__ */ jsx(Text4, { dimColor: true, children: repoLabel }) : null,
|
|
2273
|
-
sizeParts && !givingUp.size ? /* @__PURE__ */ jsxs(Text4, { children: [
|
|
2274
|
-
" ",
|
|
2275
|
-
/* @__PURE__ */ jsx(Text4, { color: colors.success, children: sizeParts.added }),
|
|
2276
|
-
" ",
|
|
2277
|
-
/* @__PURE__ */ jsx(Text4, { color: colors.error, children: sizeParts.removed })
|
|
2278
|
-
] }) : null,
|
|
2279
|
-
unresolvedLabel && !givingUp.threads ? /* @__PURE__ */ jsx(
|
|
2280
|
-
Text4,
|
|
2281
|
-
{
|
|
2282
|
-
bold: !spokeLast,
|
|
2283
|
-
color: spokeLast ? colors.secondary : colors.accent,
|
|
2284
|
-
children: " " + unresolvedLabel
|
|
2285
|
-
}
|
|
2286
|
-
) : null,
|
|
2287
|
-
showAuthor && !givingUp.author ? /* @__PURE__ */ jsx(Text4, { dimColor: true, italic: true, children: " by " + item.author }) : null,
|
|
2288
|
-
ageLabel2 && !givingUp.age ? agePair ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2289
|
-
/* @__PURE__ */ jsx(Text4, { color: colors.secondary, children: " " + agePair.activity }),
|
|
2290
|
-
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: ` (${agePair.lifetime})` })
|
|
2291
|
-
] }) : /* @__PURE__ */ jsx(Text4, { color: colors.secondary, children: " " + ageLabel2 }) : null,
|
|
2292
|
-
mergedLabel && !backdropped ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2293
|
-
/* @__PURE__ */ jsx(Text4, { children: " " }),
|
|
2294
|
-
/* @__PURE__ */ jsx(Pill, { color: MERGED_COLOUR, children: mergedLabel })
|
|
2295
|
-
] }) : null,
|
|
2296
|
-
farewellLabel && !backdropped ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2297
|
-
/* @__PURE__ */ jsx(Text4, { children: " " }),
|
|
2298
|
-
/* @__PURE__ */ jsx(Pill, { color: TRANSIT_COLOUR.out, children: farewellLabel })
|
|
2299
|
-
] }) : null
|
|
2300
|
-
] });
|
|
2338
|
+
);
|
|
2301
2339
|
};
|
|
2302
2340
|
var useActionMenu = () => {
|
|
2303
2341
|
const [actions, setActions] = useState(null);
|
|
@@ -2342,15 +2380,15 @@ var ActionMenu = ({
|
|
|
2342
2380
|
paddingX: 1,
|
|
2343
2381
|
marginTop: 1,
|
|
2344
2382
|
children: [
|
|
2345
|
-
/* @__PURE__ */ jsx(
|
|
2346
|
-
/* @__PURE__ */ jsx(
|
|
2383
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.info, bold: true, children: title }),
|
|
2384
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: "\u2500".repeat(32) }),
|
|
2347
2385
|
actions.map((a, i) => /* @__PURE__ */ jsxs(Box, { children: [
|
|
2348
|
-
/* @__PURE__ */ jsx(
|
|
2349
|
-
/* @__PURE__ */ jsx(
|
|
2350
|
-
/* @__PURE__ */ jsx(
|
|
2386
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.info, children: i === cursor ? "\u276F " : " " }),
|
|
2387
|
+
/* @__PURE__ */ jsx(Text3, { bold: i === cursor, children: a.label }),
|
|
2388
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: " " + a.hint })
|
|
2351
2389
|
] }, a.label)),
|
|
2352
|
-
/* @__PURE__ */ jsx(
|
|
2353
|
-
/* @__PURE__ */ jsx(
|
|
2390
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: "\u2500".repeat(32) }),
|
|
2391
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: "\u2191\u2193 navigate \u21B5 confirm esc cancel" })
|
|
2354
2392
|
]
|
|
2355
2393
|
}
|
|
2356
2394
|
);
|
|
@@ -2398,11 +2436,11 @@ var LegendGroup = ({
|
|
|
2398
2436
|
width,
|
|
2399
2437
|
marginRight
|
|
2400
2438
|
}) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width, marginRight, children: [
|
|
2401
|
-
pinned !== void 0 ? /* @__PURE__ */ jsx(
|
|
2439
|
+
pinned !== void 0 ? /* @__PURE__ */ jsx(Text3, { bold: true, dimColor: true, children: pinned ?? " " }) : null,
|
|
2402
2440
|
lines.map(
|
|
2403
|
-
(line, index) => line.kind === "gap" ? /* @__PURE__ */ jsx(
|
|
2404
|
-
/* @__PURE__ */ jsx(
|
|
2405
|
-
/* @__PURE__ */ jsx(
|
|
2441
|
+
(line, index) => line.kind === "gap" ? /* @__PURE__ */ jsx(Text3, { children: " " }, index) : line.kind === "title" ? /* @__PURE__ */ jsx(Text3, { bold: true, dimColor: true, children: line.text }, index) : /* @__PURE__ */ jsxs(Box, { children: [
|
|
2442
|
+
/* @__PURE__ */ jsx(Text3, { color: line.row.color, bold: line.row.bold, children: line.row.cell.padEnd(line.cellWidth) }),
|
|
2443
|
+
/* @__PURE__ */ jsx(Text3, { wrap: "truncate-end", children: line.row.label })
|
|
2406
2444
|
] }, index)
|
|
2407
2445
|
)
|
|
2408
2446
|
] });
|
|
@@ -2523,8 +2561,8 @@ var HelpModal = ({
|
|
|
2523
2561
|
width: contentWidth + MODAL_CHROME_COLS,
|
|
2524
2562
|
children: [
|
|
2525
2563
|
/* @__PURE__ */ jsxs(Box, { children: [
|
|
2526
|
-
/* @__PURE__ */ jsx(
|
|
2527
|
-
scrollable ? /* @__PURE__ */ jsx(
|
|
2564
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.info, bold: true, children: "Legend" }),
|
|
2565
|
+
scrollable ? /* @__PURE__ */ jsx(Text3, { dimColor: true, children: ` ${offset + 1}\u2013${offset + shown} of ${totalRows}` }) : null
|
|
2528
2566
|
] }),
|
|
2529
2567
|
/* @__PURE__ */ jsx(Box, { marginTop: 1, width: contentWidth, children: groups.map((group, index) => /* @__PURE__ */ jsx(
|
|
2530
2568
|
LegendGroup,
|
|
@@ -2536,8 +2574,8 @@ var HelpModal = ({
|
|
|
2536
2574
|
},
|
|
2537
2575
|
group[0]?.title ?? index
|
|
2538
2576
|
)) }),
|
|
2539
|
-
tabHelp && !scrollable ? /* @__PURE__ */ jsx(
|
|
2540
|
-
/* @__PURE__ */ jsx(
|
|
2577
|
+
tabHelp && !scrollable ? /* @__PURE__ */ jsx(Text3, { dimColor: true, children: LEGEND_FOOTNOTE }) : null,
|
|
2578
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: scrollable ? "\u2191\u2193 scroll \xB7 esc \xB7 ? close" : "esc \xB7 ? close" })
|
|
2541
2579
|
]
|
|
2542
2580
|
}
|
|
2543
2581
|
);
|
|
@@ -2552,13 +2590,13 @@ var ExplainModal = ({ item, login }) => /* @__PURE__ */ jsxs(
|
|
|
2552
2590
|
paddingX: 1,
|
|
2553
2591
|
width: Math.min(COLS, 78),
|
|
2554
2592
|
children: [
|
|
2555
|
-
/* @__PURE__ */ jsx(
|
|
2556
|
-
/* @__PURE__ */ jsx(
|
|
2593
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.accent, bold: true, children: `#${item.number} \xB7 ${item.repo}` }),
|
|
2594
|
+
/* @__PURE__ */ jsx(Text3, { children: item.title }),
|
|
2557
2595
|
explainItem(item, login).map((section) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
2558
|
-
/* @__PURE__ */ jsx(
|
|
2559
|
-
section.lines.map((line, i) => /* @__PURE__ */ jsx(
|
|
2596
|
+
/* @__PURE__ */ jsx(Text3, { bold: true, dimColor: true, children: section.heading }),
|
|
2597
|
+
section.lines.map((line, i) => /* @__PURE__ */ jsx(Text3, { children: " " + line }, i))
|
|
2560
2598
|
] }, section.heading)),
|
|
2561
|
-
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(
|
|
2599
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text3, { dimColor: true, children: "esc \xB7 e close" }) })
|
|
2562
2600
|
]
|
|
2563
2601
|
}
|
|
2564
2602
|
);
|
|
@@ -2584,21 +2622,21 @@ var RepoPicker = ({
|
|
|
2584
2622
|
paddingX: 1,
|
|
2585
2623
|
minWidth: 42,
|
|
2586
2624
|
children: [
|
|
2587
|
-
/* @__PURE__ */ jsx(
|
|
2588
|
-
/* @__PURE__ */ jsx(
|
|
2625
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.info, bold: true, children: `Filter by repo (${selected.size} on)` }),
|
|
2626
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: "\u2500".repeat(36) }),
|
|
2589
2627
|
visible.map((repo, i) => {
|
|
2590
2628
|
const idx = start + i;
|
|
2591
2629
|
const on = selected.has(repo);
|
|
2592
2630
|
const active = idx === cursor;
|
|
2593
2631
|
return /* @__PURE__ */ jsxs(Box, { children: [
|
|
2594
|
-
/* @__PURE__ */ jsx(
|
|
2595
|
-
/* @__PURE__ */ jsx(
|
|
2596
|
-
/* @__PURE__ */ jsx(
|
|
2632
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.info, children: active ? "\u276F " : " " }),
|
|
2633
|
+
/* @__PURE__ */ jsx(Text3, { color: on ? "green" : void 0, children: on ? "\u25C9 " : "\u25CB " }),
|
|
2634
|
+
/* @__PURE__ */ jsx(Text3, { bold: active, children: repo })
|
|
2597
2635
|
] }, repo);
|
|
2598
2636
|
}),
|
|
2599
|
-
repos.length > budget ? /* @__PURE__ */ jsx(
|
|
2600
|
-
/* @__PURE__ */ jsx(
|
|
2601
|
-
/* @__PURE__ */ jsx(
|
|
2637
|
+
repos.length > budget ? /* @__PURE__ */ jsx(Text3, { dimColor: true, children: ` \u2026 ${repos.length} repos total` }) : null,
|
|
2638
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: "\u2500".repeat(36) }),
|
|
2639
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: "space toggle \xB7 a clear all \xB7 \u21B5/esc done" })
|
|
2602
2640
|
]
|
|
2603
2641
|
}
|
|
2604
2642
|
);
|
|
@@ -3302,11 +3340,11 @@ var BrowseScreen = ({
|
|
|
3302
3340
|
const query = palette.trim();
|
|
3303
3341
|
const ticketKey = jiraKeyRe ? query.toUpperCase().match(jiraKeyRe)?.[0] : void 0;
|
|
3304
3342
|
const commands = [];
|
|
3305
|
-
const rich = (key, where) => /* @__PURE__ */ jsxs(
|
|
3343
|
+
const rich = (key, where) => /* @__PURE__ */ jsxs(Text3, { children: [
|
|
3306
3344
|
"Open ",
|
|
3307
|
-
/* @__PURE__ */ jsx(
|
|
3345
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.accent, children: key }),
|
|
3308
3346
|
" ",
|
|
3309
|
-
/* @__PURE__ */ jsx(
|
|
3347
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.info, children: where })
|
|
3310
3348
|
] });
|
|
3311
3349
|
const labels = /* @__PURE__ */ new Map();
|
|
3312
3350
|
if (ticketKey && jiraBase) {
|
|
@@ -3438,8 +3476,8 @@ var BrowseScreen = ({
|
|
|
3438
3476
|
}
|
|
3439
3477
|
) : null,
|
|
3440
3478
|
skippedForBudget ? /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
3441
|
-
/* @__PURE__ */ jsx(
|
|
3442
|
-
/* @__PURE__ */ jsx(
|
|
3479
|
+
/* @__PURE__ */ jsx(Text3, { bold: true, color: colors.accent, children: " \u26A1 auto-refresh paused to save API budget" }),
|
|
3480
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: " r refreshes anyway" })
|
|
3443
3481
|
] }) : null,
|
|
3444
3482
|
/* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(
|
|
3445
3483
|
Tabs,
|
|
@@ -3475,14 +3513,14 @@ var BrowseScreen = ({
|
|
|
3475
3513
|
}
|
|
3476
3514
|
) }),
|
|
3477
3515
|
search != null ? /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
3478
|
-
/* @__PURE__ */ jsx(
|
|
3479
|
-
/* @__PURE__ */ jsx(
|
|
3480
|
-
searchInput ? /* @__PURE__ */ jsx(
|
|
3481
|
-
/* @__PURE__ */ jsx(
|
|
3516
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.info, children: " / " }),
|
|
3517
|
+
/* @__PURE__ */ jsx(Text3, { children: search }),
|
|
3518
|
+
searchInput ? /* @__PURE__ */ jsx(Text3, { color: colors.info, children: "\u258F" }) : null,
|
|
3519
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: ` ${matchCount} match${matchCount !== 1 ? "es" : ""}${searchInput ? " \u21B5 accept \xB7 esc clear" : " esc clear"}` })
|
|
3482
3520
|
] }) : repoFilter.size > 0 ? /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
3483
|
-
/* @__PURE__ */ jsx(
|
|
3484
|
-
/* @__PURE__ */ jsx(
|
|
3485
|
-
/* @__PURE__ */ jsx(
|
|
3521
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.accent, children: " \u25C9 " }),
|
|
3522
|
+
/* @__PURE__ */ jsx(Text3, { children: `${repoFilter.size} repo${repoFilter.size !== 1 ? "s" : ""}` }),
|
|
3523
|
+
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: " f edit \xB7 esc clear" })
|
|
3486
3524
|
] }) : null,
|
|
3487
3525
|
/* @__PURE__ */ jsxs(Box, { children: [
|
|
3488
3526
|
/* @__PURE__ */ jsxs(
|
|
@@ -3520,7 +3558,7 @@ var BrowseScreen = ({
|
|
|
3520
3558
|
},
|
|
3521
3559
|
`${viewStart + i}:${rowKey(item)}`
|
|
3522
3560
|
)) }),
|
|
3523
|
-
hasMore && /* @__PURE__ */ jsxs(
|
|
3561
|
+
hasMore && /* @__PURE__ */ jsxs(Text3, { dimColor: true, children: [
|
|
3524
3562
|
" ",
|
|
3525
3563
|
"\u2193 ",
|
|
3526
3564
|
section.items.length - viewStart - visibleCount,
|
|
@@ -3554,7 +3592,7 @@ var BrowseScreen = ({
|
|
|
3554
3592
|
}
|
|
3555
3593
|
) : null
|
|
3556
3594
|
] }),
|
|
3557
|
-
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: flash ? /* @__PURE__ */ jsx(
|
|
3595
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: flash ? /* @__PURE__ */ jsx(Text3, { color: colors.success, children: flash }) : /* @__PURE__ */ jsx(FooterHints, { hints }) })
|
|
3558
3596
|
]
|
|
3559
3597
|
}
|
|
3560
3598
|
);
|
|
@@ -3569,7 +3607,7 @@ var NoRowsScreen = ({
|
|
|
3569
3607
|
});
|
|
3570
3608
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
3571
3609
|
/* @__PURE__ */ jsx(StatusMessage, { variant: reason === "empty" ? "info" : "error", children: reason === "empty" ? "Nothing open." : `Fetch failed \u2014 ${detail ?? "no reason reported"}` }),
|
|
3572
|
-
reason === "empty" && detail ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(
|
|
3610
|
+
reason === "empty" && detail ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text3, { dimColor: true, children: detail }) }) : null,
|
|
3573
3611
|
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(
|
|
3574
3612
|
FooterHints,
|
|
3575
3613
|
{
|
|
@@ -3737,10 +3775,13 @@ var App = ({
|
|
|
3737
3775
|
const running = [...heldSince].filter(([tab]) => held.has(tab));
|
|
3738
3776
|
if (running.length === 0) return;
|
|
3739
3777
|
const remaining = (at) => at + TRANSIT_HOLD_MS - Date.now();
|
|
3740
|
-
const timer = setTimeout(
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3778
|
+
const timer = setTimeout(
|
|
3779
|
+
() => {
|
|
3780
|
+
for (const [tab, at] of running)
|
|
3781
|
+
if (remaining(at) <= 0) settleTab(tab, transients);
|
|
3782
|
+
},
|
|
3783
|
+
Math.max(0, Math.min(...running.map(([, at]) => remaining(at))))
|
|
3784
|
+
);
|
|
3744
3785
|
return () => clearTimeout(timer);
|
|
3745
3786
|
}, [transients, heldSince, state.phase]);
|
|
3746
3787
|
const pendingSummary = useMemo(
|
|
@@ -4099,4 +4140,4 @@ var matchesFilter = (repo, filter) => {
|
|
|
4099
4140
|
};
|
|
4100
4141
|
var parsePatterns = (value) => value.split(",").map((p) => p.trim()).filter(Boolean);
|
|
4101
4142
|
|
|
4102
|
-
export { ActionMenu, App, COLS, CiStatusLine, CommentsPanel, HealthPanel, MIN_SIDEBAR_COLS, 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 };
|
|
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 };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kud/gh-ink",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.61.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",
|