@dacsar/prview 1.0.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.js +349 -216
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -28341,109 +28341,6 @@ var require_stack_utils = __commonJS({
28341
28341
  }
28342
28342
  });
28343
28343
 
28344
- // node_modules/deepmerge/dist/cjs.js
28345
- var require_cjs = __commonJS({
28346
- "node_modules/deepmerge/dist/cjs.js"(exports, module2) {
28347
- "use strict";
28348
- var isMergeableObject = function isMergeableObject2(value) {
28349
- return isNonNullObject(value) && !isSpecial(value);
28350
- };
28351
- function isNonNullObject(value) {
28352
- return !!value && typeof value === "object";
28353
- }
28354
- function isSpecial(value) {
28355
- var stringValue = Object.prototype.toString.call(value);
28356
- return stringValue === "[object RegExp]" || stringValue === "[object Date]" || isReactElement(value);
28357
- }
28358
- var canUseSymbol = typeof Symbol === "function" && Symbol.for;
28359
- var REACT_ELEMENT_TYPE = canUseSymbol ? /* @__PURE__ */ Symbol.for("react.element") : 60103;
28360
- function isReactElement(value) {
28361
- return value.$$typeof === REACT_ELEMENT_TYPE;
28362
- }
28363
- function emptyTarget(val) {
28364
- return Array.isArray(val) ? [] : {};
28365
- }
28366
- function cloneUnlessOtherwiseSpecified(value, options) {
28367
- return options.clone !== false && options.isMergeableObject(value) ? deepmerge2(emptyTarget(value), value, options) : value;
28368
- }
28369
- function defaultArrayMerge(target, source, options) {
28370
- return target.concat(source).map(function(element) {
28371
- return cloneUnlessOtherwiseSpecified(element, options);
28372
- });
28373
- }
28374
- function getMergeFunction(key, options) {
28375
- if (!options.customMerge) {
28376
- return deepmerge2;
28377
- }
28378
- var customMerge = options.customMerge(key);
28379
- return typeof customMerge === "function" ? customMerge : deepmerge2;
28380
- }
28381
- function getEnumerableOwnPropertySymbols(target) {
28382
- return Object.getOwnPropertySymbols ? Object.getOwnPropertySymbols(target).filter(function(symbol) {
28383
- return Object.propertyIsEnumerable.call(target, symbol);
28384
- }) : [];
28385
- }
28386
- function getKeys(target) {
28387
- return Object.keys(target).concat(getEnumerableOwnPropertySymbols(target));
28388
- }
28389
- function propertyIsOnObject(object, property) {
28390
- try {
28391
- return property in object;
28392
- } catch (_) {
28393
- return false;
28394
- }
28395
- }
28396
- function propertyIsUnsafe(target, key) {
28397
- return propertyIsOnObject(target, key) && !(Object.hasOwnProperty.call(target, key) && Object.propertyIsEnumerable.call(target, key));
28398
- }
28399
- function mergeObject(target, source, options) {
28400
- var destination = {};
28401
- if (options.isMergeableObject(target)) {
28402
- getKeys(target).forEach(function(key) {
28403
- destination[key] = cloneUnlessOtherwiseSpecified(target[key], options);
28404
- });
28405
- }
28406
- getKeys(source).forEach(function(key) {
28407
- if (propertyIsUnsafe(target, key)) {
28408
- return;
28409
- }
28410
- if (propertyIsOnObject(target, key) && options.isMergeableObject(source[key])) {
28411
- destination[key] = getMergeFunction(key, options)(target[key], source[key], options);
28412
- } else {
28413
- destination[key] = cloneUnlessOtherwiseSpecified(source[key], options);
28414
- }
28415
- });
28416
- return destination;
28417
- }
28418
- function deepmerge2(target, source, options) {
28419
- options = options || {};
28420
- options.arrayMerge = options.arrayMerge || defaultArrayMerge;
28421
- options.isMergeableObject = options.isMergeableObject || isMergeableObject;
28422
- options.cloneUnlessOtherwiseSpecified = cloneUnlessOtherwiseSpecified;
28423
- var sourceIsArray = Array.isArray(source);
28424
- var targetIsArray = Array.isArray(target);
28425
- var sourceAndTargetTypesMatch = sourceIsArray === targetIsArray;
28426
- if (!sourceAndTargetTypesMatch) {
28427
- return cloneUnlessOtherwiseSpecified(source, options);
28428
- } else if (sourceIsArray) {
28429
- return options.arrayMerge(target, source, options);
28430
- } else {
28431
- return mergeObject(target, source, options);
28432
- }
28433
- }
28434
- deepmerge2.all = function deepmergeAll(array, options) {
28435
- if (!Array.isArray(array)) {
28436
- throw new Error("first argument should be an array");
28437
- }
28438
- return array.reduce(function(prev, next) {
28439
- return deepmerge2(prev, next, options);
28440
- }, {});
28441
- };
28442
- var deepmerge_1 = deepmerge2;
28443
- module2.exports = deepmerge_1;
28444
- }
28445
- });
28446
-
28447
28344
  // node_modules/react/cjs/react-jsx-runtime.production.js
28448
28345
  var require_react_jsx_runtime_production = __commonJS({
28449
28346
  "node_modules/react/cjs/react-jsx-runtime.production.js"(exports) {
@@ -28743,6 +28640,109 @@ var require_jsx_runtime = __commonJS({
28743
28640
  }
28744
28641
  });
28745
28642
 
28643
+ // node_modules/deepmerge/dist/cjs.js
28644
+ var require_cjs = __commonJS({
28645
+ "node_modules/deepmerge/dist/cjs.js"(exports, module2) {
28646
+ "use strict";
28647
+ var isMergeableObject = function isMergeableObject2(value) {
28648
+ return isNonNullObject(value) && !isSpecial(value);
28649
+ };
28650
+ function isNonNullObject(value) {
28651
+ return !!value && typeof value === "object";
28652
+ }
28653
+ function isSpecial(value) {
28654
+ var stringValue = Object.prototype.toString.call(value);
28655
+ return stringValue === "[object RegExp]" || stringValue === "[object Date]" || isReactElement(value);
28656
+ }
28657
+ var canUseSymbol = typeof Symbol === "function" && Symbol.for;
28658
+ var REACT_ELEMENT_TYPE = canUseSymbol ? /* @__PURE__ */ Symbol.for("react.element") : 60103;
28659
+ function isReactElement(value) {
28660
+ return value.$$typeof === REACT_ELEMENT_TYPE;
28661
+ }
28662
+ function emptyTarget(val) {
28663
+ return Array.isArray(val) ? [] : {};
28664
+ }
28665
+ function cloneUnlessOtherwiseSpecified(value, options) {
28666
+ return options.clone !== false && options.isMergeableObject(value) ? deepmerge2(emptyTarget(value), value, options) : value;
28667
+ }
28668
+ function defaultArrayMerge(target, source, options) {
28669
+ return target.concat(source).map(function(element) {
28670
+ return cloneUnlessOtherwiseSpecified(element, options);
28671
+ });
28672
+ }
28673
+ function getMergeFunction(key, options) {
28674
+ if (!options.customMerge) {
28675
+ return deepmerge2;
28676
+ }
28677
+ var customMerge = options.customMerge(key);
28678
+ return typeof customMerge === "function" ? customMerge : deepmerge2;
28679
+ }
28680
+ function getEnumerableOwnPropertySymbols(target) {
28681
+ return Object.getOwnPropertySymbols ? Object.getOwnPropertySymbols(target).filter(function(symbol) {
28682
+ return Object.propertyIsEnumerable.call(target, symbol);
28683
+ }) : [];
28684
+ }
28685
+ function getKeys(target) {
28686
+ return Object.keys(target).concat(getEnumerableOwnPropertySymbols(target));
28687
+ }
28688
+ function propertyIsOnObject(object, property) {
28689
+ try {
28690
+ return property in object;
28691
+ } catch (_) {
28692
+ return false;
28693
+ }
28694
+ }
28695
+ function propertyIsUnsafe(target, key) {
28696
+ return propertyIsOnObject(target, key) && !(Object.hasOwnProperty.call(target, key) && Object.propertyIsEnumerable.call(target, key));
28697
+ }
28698
+ function mergeObject(target, source, options) {
28699
+ var destination = {};
28700
+ if (options.isMergeableObject(target)) {
28701
+ getKeys(target).forEach(function(key) {
28702
+ destination[key] = cloneUnlessOtherwiseSpecified(target[key], options);
28703
+ });
28704
+ }
28705
+ getKeys(source).forEach(function(key) {
28706
+ if (propertyIsUnsafe(target, key)) {
28707
+ return;
28708
+ }
28709
+ if (propertyIsOnObject(target, key) && options.isMergeableObject(source[key])) {
28710
+ destination[key] = getMergeFunction(key, options)(target[key], source[key], options);
28711
+ } else {
28712
+ destination[key] = cloneUnlessOtherwiseSpecified(source[key], options);
28713
+ }
28714
+ });
28715
+ return destination;
28716
+ }
28717
+ function deepmerge2(target, source, options) {
28718
+ options = options || {};
28719
+ options.arrayMerge = options.arrayMerge || defaultArrayMerge;
28720
+ options.isMergeableObject = options.isMergeableObject || isMergeableObject;
28721
+ options.cloneUnlessOtherwiseSpecified = cloneUnlessOtherwiseSpecified;
28722
+ var sourceIsArray = Array.isArray(source);
28723
+ var targetIsArray = Array.isArray(target);
28724
+ var sourceAndTargetTypesMatch = sourceIsArray === targetIsArray;
28725
+ if (!sourceAndTargetTypesMatch) {
28726
+ return cloneUnlessOtherwiseSpecified(source, options);
28727
+ } else if (sourceIsArray) {
28728
+ return options.arrayMerge(target, source, options);
28729
+ } else {
28730
+ return mergeObject(target, source, options);
28731
+ }
28732
+ }
28733
+ deepmerge2.all = function deepmergeAll(array, options) {
28734
+ if (!Array.isArray(array)) {
28735
+ throw new Error("first argument should be an array");
28736
+ }
28737
+ return array.reduce(function(prev, next) {
28738
+ return deepmerge2(prev, next, options);
28739
+ }, {});
28740
+ };
28741
+ var deepmerge_1 = deepmerge2;
28742
+ module2.exports = deepmerge_1;
28743
+ }
28744
+ });
28745
+
28746
28746
  // node_modules/ink/build/render.js
28747
28747
  import { Stream } from "node:stream";
28748
28748
  import process13 from "node:process";
@@ -46027,6 +46027,95 @@ var meow = (helpText, options = {}) => {
46027
46027
  // src/app.tsx
46028
46028
  var import_react62 = __toESM(require_react(), 1);
46029
46029
 
46030
+ // src/constants.ts
46031
+ var COMMANDS = [
46032
+ { key: "Tab", label: "Switch tab" },
46033
+ { key: "j / k", label: "Move selection (\u2191 / \u2193)" },
46034
+ { key: "Enter", label: "Open PR in browser" },
46035
+ { key: "y", label: "Copy PR URL" },
46036
+ { key: "Y", label: "Copy branch name" },
46037
+ { key: "/", label: "Filter" },
46038
+ { key: "r", label: "Refresh" },
46039
+ { key: "h", label: "Toggle this help" },
46040
+ { key: "q", label: "Quit" }
46041
+ ];
46042
+ var COL = {
46043
+ icon: 4,
46044
+ repo: 18,
46045
+ status: 12,
46046
+ diff: 12,
46047
+ elapsed: 8,
46048
+ reviewee: 12,
46049
+ reviewer: 12
46050
+ };
46051
+ var BASE_WIDTH = 7;
46052
+ var OPTIONAL_WIDTH = {
46053
+ repo: COL.repo + 1,
46054
+ // 18 + separator
46055
+ status: COL.status + 2,
46056
+ // 12 + separator + marginLeft
46057
+ diff: COL.diff + 2,
46058
+ elapsed: COL.elapsed + 2,
46059
+ author: COL.reviewee + 2,
46060
+ reviewer: COL.reviewer + 2
46061
+ };
46062
+ var DROP_ORDER = [
46063
+ "reviewer",
46064
+ "author",
46065
+ "repo",
46066
+ "diff",
46067
+ "elapsed",
46068
+ "status"
46069
+ ];
46070
+ var MIN_TITLE_WIDTH = 20;
46071
+ function computeColumnLayout(columns) {
46072
+ const visible = new Set(
46073
+ Object.keys(OPTIONAL_WIDTH)
46074
+ );
46075
+ const fixed = () => {
46076
+ let width = BASE_WIDTH;
46077
+ for (const col of visible) width += OPTIONAL_WIDTH[col];
46078
+ return width;
46079
+ };
46080
+ for (const col of DROP_ORDER) {
46081
+ if (columns - fixed() >= MIN_TITLE_WIDTH) break;
46082
+ visible.delete(col);
46083
+ }
46084
+ return {
46085
+ showRepo: visible.has("repo"),
46086
+ showStatus: visible.has("status"),
46087
+ showDiff: visible.has("diff"),
46088
+ showElapsed: visible.has("elapsed"),
46089
+ showAuthor: visible.has("author"),
46090
+ showReviewer: visible.has("reviewer"),
46091
+ titleWidth: Math.max(10, columns - fixed())
46092
+ };
46093
+ }
46094
+
46095
+ // src/components/help-dialog.tsx
46096
+ var import_jsx_runtime = __toESM(require_jsx_runtime(), 1);
46097
+ function HelpDialog() {
46098
+ const keyWidth = Math.max(...COMMANDS.map((c) => c.key.length));
46099
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { flexGrow: 1, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
46100
+ Box_default,
46101
+ {
46102
+ flexDirection: "column",
46103
+ borderStyle: "round",
46104
+ borderColor: "cyan",
46105
+ paddingX: 2,
46106
+ paddingY: 1,
46107
+ children: [
46108
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { marginBottom: 1, justifyContent: "center", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { bold: true, color: "cyan", children: "Keybindings" }) }),
46109
+ COMMANDS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { children: [
46110
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { width: keyWidth + 2, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { bold: true, color: "white", children: c.key }) }),
46111
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { dimColor: true, children: c.label })
46112
+ ] }, c.key)),
46113
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { marginTop: 1, justifyContent: "center", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { dimColor: true, children: "Press h or Esc to close" }) })
46114
+ ]
46115
+ }
46116
+ ) });
46117
+ }
46118
+
46030
46119
  // node_modules/@inkjs/ui/build/components/badge/badge.js
46031
46120
  var import_react30 = __toESM(require_react(), 1);
46032
46121
 
@@ -48709,26 +48798,14 @@ var import_react58 = __toESM(require_react(), 1);
48709
48798
  var cursor3 = source_default.inverse(" ");
48710
48799
 
48711
48800
  // src/components/loading.tsx
48712
- var import_jsx_runtime = __toESM(require_jsx_runtime(), 1);
48801
+ var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
48713
48802
  function Loading({ error }) {
48714
48803
  if (error) {
48715
48804
  return null;
48716
48805
  }
48717
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { paddingX: 2, paddingY: 1, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { label: "Fetching pull requests..." }) });
48806
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box_default, { paddingX: 2, paddingY: 1, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Spinner, { label: "Fetching pull requests..." }) });
48718
48807
  }
48719
48808
 
48720
- // src/constants.ts
48721
- var COL = {
48722
- icon: 4,
48723
- repo: 18,
48724
- status: 12,
48725
- diff: 12,
48726
- elapsed: 8,
48727
- reviewee: 12,
48728
- reviewer: 12
48729
- };
48730
- var FIXED_COLS_WIDTH = 92;
48731
-
48732
48809
  // src/utils/format-time.ts
48733
48810
  function formatElapsedTime(createdAt) {
48734
48811
  const now = Date.now();
@@ -48764,33 +48841,41 @@ function getTimeColor(createdAt) {
48764
48841
  }
48765
48842
 
48766
48843
  // src/components/status-badge.tsx
48767
- var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
48844
+ var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
48768
48845
  function StatusBadge({ decision, isDraft }) {
48769
48846
  if (isDraft) {
48770
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { dimColor: true, children: "\u25CC DRAFT" });
48847
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { dimColor: true, children: "\u25CC DRAFT" });
48771
48848
  }
48772
48849
  switch (decision) {
48773
48850
  case "APPROVED": {
48774
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: "green", children: "\u2713 APPROVED" });
48851
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: "green", children: "\u2713 APPROVED" });
48775
48852
  }
48776
48853
  case "CHANGES_REQUESTED": {
48777
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: "red", children: "\u2715 CHANGES" });
48854
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: "red", children: "\u2715 CHANGES" });
48778
48855
  }
48779
48856
  case "REVIEW_REQUIRED": {
48780
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: "yellow", children: "\u25CF PENDING" });
48857
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: "yellow", children: "\u25CF PENDING" });
48781
48858
  }
48782
48859
  default: {
48783
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: "yellow", children: "\u25CF PENDING" });
48860
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: "yellow", children: "\u25CF PENDING" });
48784
48861
  }
48785
48862
  }
48786
48863
  }
48787
48864
 
48788
48865
  // src/components/pr-row.tsx
48789
- var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
48866
+ var import_jsx_runtime4 = __toESM(require_jsx_runtime(), 1);
48790
48867
  function PrRow({ pr, isSelected }) {
48791
48868
  const { stdout } = use_stdout_default();
48792
48869
  const columns = stdout?.columns ?? 120;
48793
- const titleWidth = Math.max(10, columns - FIXED_COLS_WIDTH);
48870
+ const {
48871
+ showRepo,
48872
+ showStatus,
48873
+ showDiff,
48874
+ showElapsed,
48875
+ showAuthor,
48876
+ showReviewer,
48877
+ titleWidth
48878
+ } = computeColumnLayout(columns);
48794
48879
  const timeColor = getTimeColor(pr.createdAt);
48795
48880
  const elapsed = formatElapsedTime(pr.createdAt);
48796
48881
  const icon = getTimeIcon(pr.createdAt);
@@ -48802,47 +48887,59 @@ function PrRow({ pr, isSelected }) {
48802
48887
  const firstReviewer = filteredReviewers[0];
48803
48888
  const extraCount = filteredReviewers.length - 1;
48804
48889
  const reviewerText = firstReviewer ? `@${firstReviewer.login}${extraCount > 0 ? ` +${extraCount}` : ""}` : "";
48805
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { backgroundColor: isSelected ? "#333333" : void 0, children: [
48806
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: isSelected ? "red" : void 0, children: isSelected ? ">" : " " }),
48807
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { width: COL.icon, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: timeColor, wrap: "truncate", children: ` ${icon} ` }) }),
48808
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { width: COL.repo, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { dimColor: !isSelected, color: selColor, wrap: "truncate", children: [
48809
- repoShort,
48810
- "#",
48811
- pr.number
48812
- ] }) }),
48813
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { dimColor: true, children: "|" }),
48814
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { width: titleWidth, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { bold: isSelected, color: selColor, wrap: "truncate", children: pr.title }) }),
48815
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { dimColor: true, children: "|" }),
48816
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { width: COL.status, marginLeft: 1, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StatusBadge, { decision: pr.reviewDecision, isDraft: pr.isDraft }) }),
48817
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { dimColor: true, children: "|" }),
48818
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { width: COL.diff, marginLeft: 1, justifyContent: "flex-end", children: [
48819
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { color: "green", children: [
48820
- "+",
48821
- pr.additions
48822
- ] }),
48823
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { children: " " }),
48824
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { color: "red", children: [
48825
- "-",
48826
- pr.deletions
48827
- ] })
48890
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { backgroundColor: isSelected ? "#333333" : void 0, children: [
48891
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: isSelected ? "red" : void 0, children: isSelected ? ">" : " " }),
48892
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { width: COL.icon, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: timeColor, wrap: "truncate", children: ` ${icon} ` }) }),
48893
+ showRepo && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
48894
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { width: COL.repo, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { dimColor: !isSelected, color: selColor, wrap: "truncate", children: [
48895
+ repoShort,
48896
+ "#",
48897
+ pr.number
48898
+ ] }) }),
48899
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { dimColor: true, children: "|" })
48828
48900
  ] }),
48829
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { dimColor: true, children: "|" }),
48830
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { width: COL.elapsed, marginLeft: 1, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: timeColor, children: elapsed }) }),
48831
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { dimColor: true, children: "|" }),
48832
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { width: COL.reviewee, marginLeft: 1, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { dimColor: true, wrap: "truncate", children: [
48833
- "@",
48834
- pr.author
48835
- ] }) }),
48836
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { dimColor: true, children: "|" }),
48837
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { width: COL.reviewer, marginLeft: 1, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { dimColor: true, wrap: "truncate", children: reviewerText }) })
48901
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { width: titleWidth, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { bold: isSelected, color: selColor, wrap: "truncate", children: pr.title }) }),
48902
+ showStatus && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
48903
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { dimColor: true, children: "|" }),
48904
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { width: COL.status, marginLeft: 1, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(StatusBadge, { decision: pr.reviewDecision, isDraft: pr.isDraft }) })
48905
+ ] }),
48906
+ showDiff && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
48907
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { dimColor: true, children: "|" }),
48908
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { width: COL.diff, marginLeft: 1, justifyContent: "flex-end", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { wrap: "truncate", children: [
48909
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: "green", children: [
48910
+ "+",
48911
+ pr.additions
48912
+ ] }),
48913
+ " ",
48914
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: "red", children: [
48915
+ "-",
48916
+ pr.deletions
48917
+ ] })
48918
+ ] }) })
48919
+ ] }),
48920
+ showElapsed && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
48921
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { dimColor: true, children: "|" }),
48922
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { width: COL.elapsed, marginLeft: 1, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: timeColor, wrap: "truncate", children: elapsed }) })
48923
+ ] }),
48924
+ showAuthor && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
48925
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { dimColor: true, children: "|" }),
48926
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { width: COL.reviewee, marginLeft: 1, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { dimColor: true, wrap: "truncate", children: [
48927
+ "@",
48928
+ pr.author
48929
+ ] }) })
48930
+ ] }),
48931
+ showReviewer && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
48932
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { dimColor: true, children: "|" }),
48933
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { width: COL.reviewer, marginLeft: 1, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { dimColor: true, wrap: "truncate", children: reviewerText }) })
48934
+ ] })
48838
48935
  ] });
48839
48936
  }
48840
48937
 
48841
48938
  // src/components/pr-table.tsx
48842
- var import_jsx_runtime4 = __toESM(require_jsx_runtime(), 1);
48939
+ var import_jsx_runtime5 = __toESM(require_jsx_runtime(), 1);
48843
48940
  function PrTable({ prs, selectedIndex, maxRows }) {
48844
48941
  if (prs.length === 0) {
48845
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { paddingX: 2, paddingY: 1, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { dimColor: true, children: "No pull requests found." }) });
48942
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { paddingX: 2, paddingY: 1, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: "No pull requests found." }) });
48846
48943
  }
48847
48944
  const visibleCount = Math.max(1, maxRows);
48848
48945
  let scrollOffset = 0;
@@ -48853,7 +48950,7 @@ function PrTable({ prs, selectedIndex, maxRows }) {
48853
48950
  scrollOffset = Math.min(scrollOffset, prs.length - visibleCount);
48854
48951
  }
48855
48952
  const visiblePRs = prs.slice(scrollOffset, scrollOffset + visibleCount);
48856
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { flexDirection: "column", paddingX: 1, children: visiblePRs.map((pr, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
48953
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { flexDirection: "column", paddingX: 1, children: visiblePRs.map((pr, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
48857
48954
  PrRow,
48858
48955
  {
48859
48956
  pr,
@@ -48864,7 +48961,7 @@ function PrTable({ prs, selectedIndex, maxRows }) {
48864
48961
  }
48865
48962
 
48866
48963
  // src/components/status-bar.tsx
48867
- var import_jsx_runtime5 = __toESM(require_jsx_runtime(), 1);
48964
+ var import_jsx_runtime6 = __toESM(require_jsx_runtime(), 1);
48868
48965
  function StatusBar({
48869
48966
  isFilterActive,
48870
48967
  filter,
@@ -48873,11 +48970,12 @@ function StatusBar({
48873
48970
  reviewCount,
48874
48971
  myCount,
48875
48972
  isFilterMode,
48876
- loading
48973
+ loading,
48974
+ copiedMessage
48877
48975
  }) {
48878
48976
  const isReview = activeTab === "review-requested";
48879
48977
  const tabLabel = isReview ? `To Review (${reviewCount})` : `My PRs (${myCount})`;
48880
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
48978
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
48881
48979
  Box_default,
48882
48980
  {
48883
48981
  borderStyle: "single",
@@ -48889,58 +48987,34 @@ function StatusBar({
48889
48987
  paddingX: 1,
48890
48988
  justifyContent: "space-between",
48891
48989
  children: [
48892
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { children: isFilterActive || filter ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
48893
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "yellow", children: "/" }),
48894
- isFilterActive ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
48990
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Box_default, { children: copiedMessage ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Text, { color: "green", children: [
48991
+ "\u2713 ",
48992
+ copiedMessage
48993
+ ] }) : isFilterActive || filter ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
48994
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: "yellow", children: "/" }),
48995
+ isFilterActive ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
48895
48996
  TextInput,
48896
48997
  {
48897
48998
  defaultValue: filter,
48898
48999
  onChange: onFilterChange,
48899
49000
  placeholder: "Filter by title, repo, author, reviewer..."
48900
49001
  }
48901
- ) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { dimColor: true, children: [
49002
+ ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Text, { dimColor: true, children: [
48902
49003
  " ",
48903
49004
  filter
48904
49005
  ] })
48905
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
48906
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { bold: true, color: isReview ? "cyan" : "magenta", children: tabLabel }),
48907
- loading && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: " Refreshing..." })
49006
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
49007
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { bold: true, color: isReview ? "cyan" : "magenta", children: tabLabel }),
49008
+ loading && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { dimColor: true, children: " Refreshing..." })
48908
49009
  ] }) }),
48909
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { gap: 1, children: isFilterMode ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { dimColor: true, children: [
48910
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "gray", children: "Esc" }),
49010
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Box_default, { gap: 1, children: isFilterMode ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Text, { dimColor: true, children: [
49011
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: "gray", children: "Esc" }),
48911
49012
  " ",
48912
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: "cancel" })
48913
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
48914
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
48915
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "white", children: "Tab" }),
48916
- " ",
48917
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: "switch" })
48918
- ] }),
48919
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
48920
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "white", children: "j/k" }),
48921
- " ",
48922
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: "move" })
48923
- ] }),
48924
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
48925
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "white", children: "Enter" }),
48926
- " ",
48927
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: "open" })
48928
- ] }),
48929
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
48930
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "white", children: "/" }),
48931
- " ",
48932
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: "filter" })
48933
- ] }),
48934
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
48935
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "white", children: "r" }),
48936
- " ",
48937
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: "refresh" })
48938
- ] }),
48939
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
48940
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "white", children: "q" }),
48941
- " ",
48942
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: "quit" })
48943
- ] })
49013
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { dimColor: true, children: "cancel" })
49014
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Text, { children: [
49015
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: "white", children: "h" }),
49016
+ " ",
49017
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { dimColor: true, children: "help" })
48944
49018
  ] }) })
48945
49019
  ]
48946
49020
  }
@@ -49130,15 +49204,23 @@ function usePullRequests() {
49130
49204
  return { reviewRequested, myPRs, loading, error, refresh: load };
49131
49205
  }
49132
49206
 
49133
- // src/utils/open-url.ts
49207
+ // src/utils/copy-to-clipboard.ts
49134
49208
  import { execFile as execFile2 } from "node:child_process";
49209
+ function copyToClipboard(text) {
49210
+ const child = execFile2("pbcopy", () => {
49211
+ });
49212
+ child.stdin?.end(text);
49213
+ }
49214
+
49215
+ // src/utils/open-url.ts
49216
+ import { execFile as execFile3 } from "node:child_process";
49135
49217
  function openUrl(url2) {
49136
- execFile2("open", [url2], () => {
49218
+ execFile3("open", [url2], () => {
49137
49219
  });
49138
49220
  }
49139
49221
 
49140
49222
  // src/app.tsx
49141
- var import_jsx_runtime6 = __toESM(require_jsx_runtime(), 1);
49223
+ var import_jsx_runtime7 = __toESM(require_jsx_runtime(), 1);
49142
49224
  function App2() {
49143
49225
  const { exit } = use_app_default();
49144
49226
  const { stdout } = use_stdout_default();
@@ -49148,8 +49230,30 @@ function App2() {
49148
49230
  const [selectedIndex, setSelectedIndex] = (0, import_react62.useState)(0);
49149
49231
  const [filter, setFilter] = (0, import_react62.useState)("");
49150
49232
  const [isFilterMode, setIsFilterMode] = (0, import_react62.useState)(false);
49233
+ const [showHelp, setShowHelp] = (0, import_react62.useState)(false);
49234
+ const [copiedMessage, setCopiedMessage] = (0, import_react62.useState)("");
49235
+ const copiedTimer = (0, import_react62.useRef)(null);
49236
+ const notifyCopied = (0, import_react62.useCallback)((label) => {
49237
+ setCopiedMessage(`Copied ${label} to clipboard`);
49238
+ if (copiedTimer.current) {
49239
+ clearTimeout(copiedTimer.current);
49240
+ }
49241
+ copiedTimer.current = setTimeout(() => setCopiedMessage(""), 2e3);
49242
+ }, []);
49151
49243
  const currentPRs = activeTab === "review-requested" ? reviewRequested : myPRs;
49152
49244
  const filteredPRs = useFilterSort(currentPRs, filter);
49245
+ const [, setResizeTick] = (0, import_react62.useState)(0);
49246
+ (0, import_react62.useEffect)(() => {
49247
+ if (!stdout) return;
49248
+ const onResize = () => {
49249
+ stdout.write("\x1B[2J\x1B[H");
49250
+ setResizeTick((n) => n + 1);
49251
+ };
49252
+ stdout.on("resize", onResize);
49253
+ return () => {
49254
+ stdout.off("resize", onResize);
49255
+ };
49256
+ }, [stdout]);
49153
49257
  const clampIndex = (0, import_react62.useCallback)(
49154
49258
  (index) => Math.max(0, Math.min(index, filteredPRs.length - 1)),
49155
49259
  [filteredPRs.length]
@@ -49163,12 +49267,24 @@ function App2() {
49163
49267
  },
49164
49268
  { isActive: isFilterMode }
49165
49269
  );
49270
+ use_input_default(
49271
+ (input, key) => {
49272
+ if (input === "h" || key.escape || input === "q") {
49273
+ setShowHelp(false);
49274
+ }
49275
+ },
49276
+ { isActive: showHelp }
49277
+ );
49166
49278
  use_input_default(
49167
49279
  (input, key) => {
49168
49280
  if (input === "q") {
49169
49281
  exit();
49170
49282
  return;
49171
49283
  }
49284
+ if (input === "h") {
49285
+ setShowHelp(true);
49286
+ return;
49287
+ }
49172
49288
  if (key.tab) {
49173
49289
  setActiveTab(
49174
49290
  (prev) => prev === "review-requested" ? "my-prs" : "review-requested"
@@ -49191,6 +49307,22 @@ function App2() {
49191
49307
  }
49192
49308
  return;
49193
49309
  }
49310
+ if (input === "y") {
49311
+ const pr = filteredPRs[selectedIndex];
49312
+ if (pr) {
49313
+ copyToClipboard(pr.url);
49314
+ notifyCopied("URL");
49315
+ }
49316
+ return;
49317
+ }
49318
+ if (input === "Y") {
49319
+ const pr = filteredPRs[selectedIndex];
49320
+ if (pr) {
49321
+ copyToClipboard(pr.branch);
49322
+ notifyCopied("branch");
49323
+ }
49324
+ return;
49325
+ }
49194
49326
  if (input === "/") {
49195
49327
  setIsFilterMode(true);
49196
49328
  return;
@@ -49205,23 +49337,23 @@ function App2() {
49205
49337
  return;
49206
49338
  }
49207
49339
  },
49208
- { isActive: !isFilterMode }
49340
+ { isActive: !isFilterMode && !showHelp }
49209
49341
  );
49210
49342
  const reservedRows = 2 + (error ? 1 : 0);
49211
49343
  const maxRows = rows - reservedRows;
49212
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { flexDirection: "column", height: rows, justifyContent: "flex-end", children: [
49213
- error && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Box_default, { paddingX: 2, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Text, { color: "red", children: [
49344
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Box_default, { flexDirection: "column", height: rows, justifyContent: "flex-end", children: [
49345
+ error && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Box_default, { paddingX: 2, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Text, { color: "red", children: [
49214
49346
  "Error: ",
49215
49347
  error
49216
49348
  ] }) }),
49217
- loading && filteredPRs.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Loading, { error }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
49349
+ showHelp ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HelpDialog, {}) : loading && filteredPRs.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Loading, { error }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
49218
49350
  Box_default,
49219
49351
  {
49220
49352
  flexGrow: 1,
49221
49353
  overflow: "hidden",
49222
49354
  flexDirection: "column",
49223
49355
  justifyContent: "flex-end",
49224
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
49356
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
49225
49357
  PrTable,
49226
49358
  {
49227
49359
  prs: filteredPRs,
@@ -49231,7 +49363,7 @@ function App2() {
49231
49363
  )
49232
49364
  }
49233
49365
  ),
49234
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
49366
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
49235
49367
  StatusBar,
49236
49368
  {
49237
49369
  isFilterActive: isFilterMode,
@@ -49241,14 +49373,15 @@ function App2() {
49241
49373
  reviewCount: reviewRequested.length,
49242
49374
  myCount: myPRs.length,
49243
49375
  isFilterMode,
49244
- loading
49376
+ loading,
49377
+ copiedMessage
49245
49378
  }
49246
49379
  )
49247
49380
  ] });
49248
49381
  }
49249
49382
 
49250
49383
  // src/cli.tsx
49251
- var import_jsx_runtime7 = __toESM(require_jsx_runtime(), 1);
49384
+ var import_jsx_runtime8 = __toESM(require_jsx_runtime(), 1);
49252
49385
  meow(
49253
49386
  `
49254
49387
  Usage
@@ -49271,7 +49404,7 @@ meow(
49271
49404
  }
49272
49405
  );
49273
49406
  process.stdout.write("\x1B[?1049h");
49274
- var instance = render_default(/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(App2, {}));
49407
+ var instance = render_default(/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(App2, {}));
49275
49408
  instance.waitUntilExit().then(() => {
49276
49409
  process.stdout.write("\x1B[?1049l");
49277
49410
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dacsar/prview",
3
- "version": "1.0.1",
3
+ "version": "1.2.0",
4
4
  "description": "TUI tool to check PRs across repositories",
5
5
  "repository": {
6
6
  "type": "git",