brew-tui 0.9.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.js CHANGED
@@ -70,6 +70,7 @@ import { useEffect as useEffect23, useState as useState20 } from "react";
70
70
  import { useApp } from "ink";
71
71
 
72
72
  // src/components/layout/app-layout.tsx
73
+ import { useRef } from "react";
73
74
  import { Box as Box3 } from "ink";
74
75
 
75
76
  // src/components/layout/header.tsx
@@ -505,13 +506,89 @@ function Footer() {
505
506
  ] });
506
507
  }
507
508
 
509
+ // src/hooks/use-terminal-size.ts
510
+ import { useEffect as useEffect2, useState as useState2 } from "react";
511
+ import { useStdout as useStdout2 } from "ink";
512
+ function useTerminalSize() {
513
+ const { stdout } = useStdout2();
514
+ const [size, setSize] = useState2(() => ({
515
+ columns: stdout?.columns ?? 80,
516
+ rows: stdout?.rows ?? 24
517
+ }));
518
+ useEffect2(() => {
519
+ if (!stdout) return;
520
+ const onResize = () => {
521
+ setSize({
522
+ columns: stdout.columns ?? 80,
523
+ rows: stdout.rows ?? 24
524
+ });
525
+ };
526
+ stdout.on("resize", onResize);
527
+ return () => {
528
+ stdout.off("resize", onResize);
529
+ };
530
+ }, [stdout]);
531
+ return size;
532
+ }
533
+
534
+ // src/hooks/use-container-size.ts
535
+ import { useEffect as useEffect3, useState as useState3 } from "react";
536
+ import { measureElement } from "ink";
537
+ function useContainerSize(ref) {
538
+ const terminal = useTerminalSize();
539
+ const [size, setSize] = useState3({ width: 0, height: 0 });
540
+ useEffect3(() => {
541
+ if (!ref.current) return;
542
+ const measured = measureElement(ref.current);
543
+ setSize(
544
+ (prev) => prev.width === measured.width && prev.height === measured.height ? prev : measured
545
+ );
546
+ }, [ref, terminal.columns, terminal.rows]);
547
+ return size;
548
+ }
549
+
550
+ // src/components/layout/content-size-context.tsx
551
+ import { createContext, useContext } from "react";
552
+ import { jsx as jsx5 } from "react/jsx-runtime";
553
+ var EMPTY_CONTENT_SIZE = { width: 0, height: 0 };
554
+ var ContentSizeContext = createContext(EMPTY_CONTENT_SIZE);
555
+ function ContentSizeProvider({
556
+ children,
557
+ value
558
+ }) {
559
+ return /* @__PURE__ */ jsx5(ContentSizeContext.Provider, { value, children });
560
+ }
561
+ function useContentSize() {
562
+ return useContext(ContentSizeContext);
563
+ }
564
+
508
565
  // src/components/layout/app-layout.tsx
509
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
566
+ import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
510
567
  function AppLayout({ children }) {
511
- return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", width: "100%", children: [
512
- /* @__PURE__ */ jsx5(Header, {}),
513
- /* @__PURE__ */ jsx5(Box3, { flexDirection: "column", flexGrow: 1, paddingX: SPACING.sm, paddingY: SPACING.xs, children }),
514
- /* @__PURE__ */ jsx5(Footer, {})
568
+ const { rows } = useTerminalSize();
569
+ const contentRef = useRef(null);
570
+ const contentSize = useContainerSize(contentRef);
571
+ const innerContentSize = {
572
+ width: Math.max(0, contentSize.width - SPACING.sm * 2),
573
+ height: Math.max(0, contentSize.height - SPACING.xs * 2)
574
+ };
575
+ return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", width: "100%", height: rows, overflow: "hidden", children: [
576
+ /* @__PURE__ */ jsx6(Box3, { flexShrink: 0, children: /* @__PURE__ */ jsx6(Header, {}) }),
577
+ /* @__PURE__ */ jsx6(
578
+ Box3,
579
+ {
580
+ ref: contentRef,
581
+ flexDirection: "column",
582
+ flexGrow: 1,
583
+ flexShrink: 1,
584
+ minHeight: 0,
585
+ overflow: "hidden",
586
+ paddingX: SPACING.sm,
587
+ paddingY: SPACING.xs,
588
+ children: /* @__PURE__ */ jsx6(ContentSizeProvider, { value: innerContentSize, children })
589
+ }
590
+ ),
591
+ /* @__PURE__ */ jsx6(Box3, { flexShrink: 0, children: /* @__PURE__ */ jsx6(Footer, {}) })
515
592
  ] });
516
593
  }
517
594
 
@@ -737,7 +814,7 @@ async function markOnboardingComplete() {
737
814
  }
738
815
 
739
816
  // src/views/welcome.tsx
740
- import { useEffect as useEffect2 } from "react";
817
+ import { useEffect as useEffect4 } from "react";
741
818
  import { Box as Box4, Text as Text5 } from "ink";
742
819
 
743
820
  // src/hooks/use-view-input.ts
@@ -749,9 +826,9 @@ function useViewInput(handler, opts) {
749
826
  }
750
827
 
751
828
  // src/views/welcome.tsx
752
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
829
+ import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
753
830
  function WelcomeView({ onContinue }) {
754
- useEffect2(() => {
831
+ useEffect4(() => {
755
832
  return () => {
756
833
  };
757
834
  }, []);
@@ -761,64 +838,64 @@ function WelcomeView({ onContinue }) {
761
838
  }
762
839
  });
763
840
  return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingY: SPACING.md, paddingX: SPACING.lg, children: [
764
- /* @__PURE__ */ jsx6(Box4, { children: /* @__PURE__ */ jsx6(GradientText, { colors: GRADIENTS.gold, bold: true, children: t("welcome_title") }) }),
765
- /* @__PURE__ */ jsx6(Box4, { marginTop: SPACING.sm, children: /* @__PURE__ */ jsx6(Text5, { color: COLORS.text, children: t("welcome_intro") }) }),
841
+ /* @__PURE__ */ jsx7(Box4, { children: /* @__PURE__ */ jsx7(GradientText, { colors: GRADIENTS.gold, bold: true, children: t("welcome_title") }) }),
842
+ /* @__PURE__ */ jsx7(Box4, { marginTop: SPACING.sm, children: /* @__PURE__ */ jsx7(Text5, { color: COLORS.text, children: t("welcome_intro") }) }),
766
843
  /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: SPACING.sm, children: [
767
- /* @__PURE__ */ jsx6(Text5, { color: COLORS.muted, children: t("welcome_keysHeader") }),
844
+ /* @__PURE__ */ jsx7(Text5, { color: COLORS.muted, children: t("welcome_keysHeader") }),
768
845
  /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingLeft: SPACING.sm, marginTop: SPACING.xs, children: [
769
846
  /* @__PURE__ */ jsxs4(Text5, { children: [
770
- /* @__PURE__ */ jsx6(Text5, { color: COLORS.gold, bold: true, children: "m" }),
847
+ /* @__PURE__ */ jsx7(Text5, { color: COLORS.gold, bold: true, children: "m" }),
771
848
  " ",
772
849
  t("welcome_keyMenu")
773
850
  ] }),
774
851
  /* @__PURE__ */ jsxs4(Text5, { children: [
775
- /* @__PURE__ */ jsx6(Text5, { color: COLORS.gold, bold: true, children: "\u2191 \u2193" }),
852
+ /* @__PURE__ */ jsx7(Text5, { color: COLORS.gold, bold: true, children: "\u2191 \u2193" }),
776
853
  " ",
777
854
  t("welcome_keyMove")
778
855
  ] }),
779
856
  /* @__PURE__ */ jsxs4(Text5, { children: [
780
- /* @__PURE__ */ jsx6(Text5, { color: COLORS.gold, bold: true, children: "1-9" }),
857
+ /* @__PURE__ */ jsx7(Text5, { color: COLORS.gold, bold: true, children: "1-9" }),
781
858
  " ",
782
859
  t("welcome_keyAction")
783
860
  ] }),
784
861
  /* @__PURE__ */ jsxs4(Text5, { children: [
785
- /* @__PURE__ */ jsx6(Text5, { color: COLORS.gold, bold: true, children: "Enter" }),
862
+ /* @__PURE__ */ jsx7(Text5, { color: COLORS.gold, bold: true, children: "Enter" }),
786
863
  " ",
787
864
  t("welcome_keySelect")
788
865
  ] }),
789
866
  /* @__PURE__ */ jsxs4(Text5, { children: [
790
- /* @__PURE__ */ jsx6(Text5, { color: COLORS.gold, bold: true, children: "S" }),
867
+ /* @__PURE__ */ jsx7(Text5, { color: COLORS.gold, bold: true, children: "S" }),
791
868
  " ",
792
869
  t("welcome_keySearch")
793
870
  ] }),
794
871
  /* @__PURE__ */ jsxs4(Text5, { children: [
795
- /* @__PURE__ */ jsx6(Text5, { color: COLORS.gold, bold: true, children: "Esc" }),
872
+ /* @__PURE__ */ jsx7(Text5, { color: COLORS.gold, bold: true, children: "Esc" }),
796
873
  " ",
797
874
  t("welcome_keyBack")
798
875
  ] }),
799
876
  /* @__PURE__ */ jsxs4(Text5, { children: [
800
- /* @__PURE__ */ jsx6(Text5, { color: COLORS.gold, bold: true, children: "L" }),
877
+ /* @__PURE__ */ jsx7(Text5, { color: COLORS.gold, bold: true, children: "L" }),
801
878
  " ",
802
879
  t("welcome_keyLocale")
803
880
  ] }),
804
881
  /* @__PURE__ */ jsxs4(Text5, { children: [
805
- /* @__PURE__ */ jsx6(Text5, { color: COLORS.gold, bold: true, children: "q" }),
882
+ /* @__PURE__ */ jsx7(Text5, { color: COLORS.gold, bold: true, children: "q" }),
806
883
  " ",
807
884
  t("welcome_keyQuit")
808
885
  ] })
809
886
  ] })
810
887
  ] }),
811
888
  /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: SPACING.sm, children: [
812
- /* @__PURE__ */ jsx6(Text5, { color: COLORS.muted, children: t("welcome_proHeader") }),
813
- /* @__PURE__ */ jsx6(Box4, { paddingLeft: SPACING.sm, children: /* @__PURE__ */ jsx6(Text5, { color: COLORS.textSecondary, children: t("welcome_proIntro") }) })
889
+ /* @__PURE__ */ jsx7(Text5, { color: COLORS.muted, children: t("welcome_proHeader") }),
890
+ /* @__PURE__ */ jsx7(Box4, { paddingLeft: SPACING.sm, children: /* @__PURE__ */ jsx7(Text5, { color: COLORS.textSecondary, children: t("welcome_proIntro") }) })
814
891
  ] }),
815
- /* @__PURE__ */ jsx6(Box4, { marginTop: SPACING.md, children: /* @__PURE__ */ jsx6(Text5, { color: COLORS.success, bold: true, children: t("welcome_continueHint") }) })
892
+ /* @__PURE__ */ jsx7(Box4, { marginTop: SPACING.md, children: /* @__PURE__ */ jsx7(Text5, { color: COLORS.success, bold: true, children: t("welcome_continueHint") }) })
816
893
  ] });
817
894
  }
818
895
 
819
896
  // src/components/common/upgrade-prompt.tsx
820
897
  import { Box as Box5, Text as Text6 } from "ink";
821
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
898
+ import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
822
899
  var FEATURE_KEYS = {
823
900
  profiles: { title: "upgrade_profiles", desc: "upgrade_profilesDesc" },
824
901
  "smart-cleanup": { title: "upgrade_cleanup", desc: "upgrade_cleanupDesc" },
@@ -838,7 +915,7 @@ function UpgradePrompt({ viewId }) {
838
915
  const pricingKey = team ? "upgrade_teamPricing" : "upgrade_pricing";
839
916
  const buyUrlKey = team ? "upgrade_buyUrlTeam" : "upgrade_buyUrl";
840
917
  const labelKey = team ? "upgrade_teamLabel" : "upgrade_proLabel";
841
- return /* @__PURE__ */ jsx7(Box5, { flexDirection: "column", alignItems: "center", paddingY: SPACING.sm, children: /* @__PURE__ */ jsxs5(
918
+ return /* @__PURE__ */ jsx8(Box5, { flexDirection: "column", alignItems: "center", paddingY: SPACING.sm, children: /* @__PURE__ */ jsxs5(
842
919
  Box5,
843
920
  {
844
921
  borderStyle: "double",
@@ -854,25 +931,25 @@ function UpgradePrompt({ viewId }) {
854
931
  " ",
855
932
  t(headerKey, { title })
856
933
  ] }),
857
- /* @__PURE__ */ jsx7(Text6, { children: " " }),
858
- /* @__PURE__ */ jsx7(Text6, { color: COLORS.text, wrap: "wrap", children: t(keys.desc) }),
859
- /* @__PURE__ */ jsx7(Text6, { children: " " }),
934
+ /* @__PURE__ */ jsx8(Text6, { children: " " }),
935
+ /* @__PURE__ */ jsx8(Text6, { color: COLORS.text, wrap: "wrap", children: t(keys.desc) }),
936
+ /* @__PURE__ */ jsx8(Text6, { children: " " }),
860
937
  /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", alignItems: "center", children: [
861
- /* @__PURE__ */ jsx7(Text6, { color: COLORS.info, bold: true, children: t(pricingKey) }),
862
- /* @__PURE__ */ jsx7(Text6, { children: " " }),
863
- /* @__PURE__ */ jsx7(Text6, { color: COLORS.muted, children: t("upgrade_buyAt") }),
938
+ /* @__PURE__ */ jsx8(Text6, { color: COLORS.info, bold: true, children: t(pricingKey) }),
939
+ /* @__PURE__ */ jsx8(Text6, { children: " " }),
940
+ /* @__PURE__ */ jsx8(Text6, { color: COLORS.muted, children: t("upgrade_buyAt") }),
864
941
  /* @__PURE__ */ jsxs5(Text6, { color: COLORS.sky, bold: true, children: [
865
942
  " ",
866
943
  t(buyUrlKey)
867
944
  ] }),
868
- /* @__PURE__ */ jsx7(Text6, { children: " " }),
869
- /* @__PURE__ */ jsx7(Text6, { color: COLORS.muted, children: t("upgrade_activateWith") }),
945
+ /* @__PURE__ */ jsx8(Text6, { children: " " }),
946
+ /* @__PURE__ */ jsx8(Text6, { color: COLORS.muted, children: t("upgrade_activateWith") }),
870
947
  /* @__PURE__ */ jsxs5(Text6, { color: COLORS.success, bold: true, children: [
871
948
  " ",
872
949
  t("upgrade_activateCmd")
873
950
  ] }),
874
- /* @__PURE__ */ jsx7(Text6, { children: " " }),
875
- /* @__PURE__ */ jsx7(Text6, { color: COLORS.brand, children: t(labelKey) })
951
+ /* @__PURE__ */ jsx8(Text6, { children: " " }),
952
+ /* @__PURE__ */ jsx8(Text6, { color: COLORS.brand, children: t(labelKey) })
876
953
  ] })
877
954
  ]
878
955
  }
@@ -880,8 +957,8 @@ function UpgradePrompt({ viewId }) {
880
957
  }
881
958
 
882
959
  // src/views/dashboard.tsx
883
- import { useEffect as useEffect3, useMemo as useMemo2 } from "react";
884
- import { Box as Box9, Text as Text12, useStdout as useStdout3 } from "ink";
960
+ import { useEffect as useEffect5, useMemo as useMemo2 } from "react";
961
+ import { Box as Box9, Text as Text12, useStdout as useStdout4 } from "ink";
885
962
 
886
963
  // src/stores/brew-store.ts
887
964
  import { create as create4 } from "zustand";
@@ -1847,10 +1924,10 @@ var useComplianceStore = create8((set, get) => ({
1847
1924
  }));
1848
1925
 
1849
1926
  // src/components/common/stat-card.tsx
1850
- import { Box as Box6, Text as Text7, useStdout as useStdout2 } from "ink";
1851
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
1927
+ import { Box as Box6, Text as Text7, useStdout as useStdout3 } from "ink";
1928
+ import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
1852
1929
  function StatCard({ label, value, color = COLORS.white }) {
1853
- const { stdout } = useStdout2();
1930
+ const { stdout } = useStdout3();
1854
1931
  const cols = stdout?.columns ?? 80;
1855
1932
  const minW = cols < 60 ? 12 : cols < 100 ? 14 : 16;
1856
1933
  return /* @__PURE__ */ jsxs6(
@@ -1864,8 +1941,8 @@ function StatCard({ label, value, color = COLORS.white }) {
1864
1941
  alignItems: "center",
1865
1942
  minWidth: minW,
1866
1943
  children: [
1867
- /* @__PURE__ */ jsx8(Text7, { bold: true, color, children: value }),
1868
- /* @__PURE__ */ jsx8(Text7, { color: COLORS.muted, children: label })
1944
+ /* @__PURE__ */ jsx9(Text7, { bold: true, color, children: value }),
1945
+ /* @__PURE__ */ jsx9(Text7, { color: COLORS.muted, children: label })
1869
1946
  ]
1870
1947
  }
1871
1948
  );
@@ -1874,10 +1951,10 @@ function StatCard({ label, value, color = COLORS.white }) {
1874
1951
  // src/components/common/loading.tsx
1875
1952
  import { Box as Box7, Text as Text8 } from "ink";
1876
1953
  import { Spinner } from "@inkjs/ui";
1877
- import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
1954
+ import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
1878
1955
  function Loading({ message }) {
1879
1956
  useLocaleStore((s) => s.locale);
1880
- return /* @__PURE__ */ jsx9(Box7, { paddingY: SPACING.xs, children: /* @__PURE__ */ jsx9(Spinner, { label: message ?? t("loading_default") }) });
1957
+ return /* @__PURE__ */ jsx10(Box7, { paddingY: SPACING.xs, children: /* @__PURE__ */ jsx10(Spinner, { label: message ?? t("loading_default") }) });
1881
1958
  }
1882
1959
  function ErrorMessage({ message }) {
1883
1960
  useLocaleStore((s) => s.locale);
@@ -1887,7 +1964,7 @@ function ErrorMessage({ message }) {
1887
1964
  " ",
1888
1965
  t("error_prefix")
1889
1966
  ] }),
1890
- /* @__PURE__ */ jsx9(Text8, { color: COLORS.error, children: message })
1967
+ /* @__PURE__ */ jsx10(Text8, { color: COLORS.error, children: message })
1891
1968
  ] });
1892
1969
  }
1893
1970
 
@@ -1912,14 +1989,14 @@ function StatusBadge({ label, variant }) {
1912
1989
 
1913
1990
  // src/components/common/section-header.tsx
1914
1991
  import { Box as Box8, Text as Text10 } from "ink";
1915
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
1992
+ import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
1916
1993
  function SectionHeader({ emoji, title, color = COLORS.gold, gradient, count }) {
1917
1994
  return /* @__PURE__ */ jsxs9(Box8, { gap: SPACING.xs, children: [
1918
1995
  /* @__PURE__ */ jsxs9(Text10, { children: [
1919
1996
  emoji,
1920
1997
  " "
1921
1998
  ] }),
1922
- gradient ? /* @__PURE__ */ jsx10(GradientText, { colors: gradient, bold: true, children: title }) : /* @__PURE__ */ jsx10(Text10, { bold: true, color, children: title }),
1999
+ gradient ? /* @__PURE__ */ jsx11(GradientText, { colors: gradient, bold: true, children: title }) : /* @__PURE__ */ jsx11(Text10, { bold: true, color, children: title }),
1923
2000
  count !== void 0 && /* @__PURE__ */ jsxs9(Text10, { color: COLORS.textSecondary, children: [
1924
2001
  "(",
1925
2002
  count,
@@ -1930,22 +2007,22 @@ function SectionHeader({ emoji, title, color = COLORS.gold, gradient, count }) {
1930
2007
 
1931
2008
  // src/components/common/version-arrow.tsx
1932
2009
  import { Text as Text11 } from "ink";
1933
- import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
2010
+ import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
1934
2011
  function VersionArrow({ current, latest }) {
1935
2012
  return /* @__PURE__ */ jsxs10(Fragment3, { children: [
1936
2013
  /* @__PURE__ */ jsxs10(Text11, { color: COLORS.muted, children: [
1937
2014
  t("version_installed"),
1938
2015
  " "
1939
2016
  ] }),
1940
- /* @__PURE__ */ jsx11(Text11, { color: COLORS.error, children: current }),
1941
- /* @__PURE__ */ jsx11(Text11, { color: COLORS.warning, children: " \u2500\u2500 " }),
1942
- /* @__PURE__ */ jsx11(Text11, { color: COLORS.gold, children: "\u25B6" }),
2017
+ /* @__PURE__ */ jsx12(Text11, { color: COLORS.error, children: current }),
2018
+ /* @__PURE__ */ jsx12(Text11, { color: COLORS.warning, children: " \u2500\u2500 " }),
2019
+ /* @__PURE__ */ jsx12(Text11, { color: COLORS.gold, children: "\u25B6" }),
1943
2020
  /* @__PURE__ */ jsxs10(Text11, { color: COLORS.muted, children: [
1944
2021
  " ",
1945
2022
  t("version_available"),
1946
2023
  " "
1947
2024
  ] }),
1948
- /* @__PURE__ */ jsx11(Text11, { color: COLORS.teal, children: latest })
2025
+ /* @__PURE__ */ jsx12(Text11, { color: COLORS.teal, children: latest })
1949
2026
  ] });
1950
2027
  }
1951
2028
 
@@ -1977,7 +2054,7 @@ function truncate(str, maxLen) {
1977
2054
  }
1978
2055
 
1979
2056
  // src/views/dashboard.tsx
1980
- import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
2057
+ import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
1981
2058
  function ProStatusPanel() {
1982
2059
  const security = useSecurityStore((s) => s.summary);
1983
2060
  const drift = useBrewfileStore((s) => s.drift);
@@ -1990,28 +2067,28 @@ function ProStatusPanel() {
1990
2067
  const syncAgo = lastSync ? formatRelativeTime(new Date(lastSync).getTime() / 1e3) : null;
1991
2068
  const violationCount = complianceReport ? complianceReport.violations.length : null;
1992
2069
  return /* @__PURE__ */ jsxs11(Box9, { flexDirection: "column", borderStyle: "round", borderColor: COLORS.purple, paddingX: SPACING.sm, paddingY: SPACING.none, marginTop: SPACING.xs, children: [
1993
- /* @__PURE__ */ jsx12(Text12, { bold: true, color: COLORS.purple, children: t("dashboard_pro_status") }),
2070
+ /* @__PURE__ */ jsx13(Text12, { bold: true, color: COLORS.purple, children: t("dashboard_pro_status") }),
1994
2071
  /* @__PURE__ */ jsxs11(Box9, { gap: SPACING.xs, children: [
1995
- /* @__PURE__ */ jsx12(Text12, { color: COLORS.muted, children: t("dashboard_security") }),
1996
- cveCount === null ? /* @__PURE__ */ jsx12(Text12, { color: COLORS.muted, children: "\u2014" }) : cveCount === 0 ? /* @__PURE__ */ jsx12(Text12, { color: COLORS.success, children: t("dashboard_no_cves") }) : /* @__PURE__ */ jsxs11(Text12, { color: COLORS.error, children: [
2072
+ /* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: t("dashboard_security") }),
2073
+ cveCount === null ? /* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: "\u2014" }) : cveCount === 0 ? /* @__PURE__ */ jsx13(Text12, { color: COLORS.success, children: t("dashboard_no_cves") }) : /* @__PURE__ */ jsxs11(Text12, { color: COLORS.error, children: [
1997
2074
  t("dashboard_cves", { count: String(cveCount) }),
1998
2075
  criticalCount && criticalCount > 0 ? ` (${criticalCount} critical)` : ""
1999
2076
  ] })
2000
2077
  ] }),
2001
2078
  /* @__PURE__ */ jsxs11(Box9, { gap: SPACING.xs, children: [
2002
- /* @__PURE__ */ jsx12(Text12, { color: COLORS.muted, children: t("dashboard_brewfile") }),
2003
- driftScore === null ? /* @__PURE__ */ jsx12(Text12, { color: COLORS.muted, children: "\u2014" }) : /* @__PURE__ */ jsxs11(Text12, { color: driftScore >= 80 ? COLORS.success : COLORS.warning, children: [
2079
+ /* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: t("dashboard_brewfile") }),
2080
+ driftScore === null ? /* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: "\u2014" }) : /* @__PURE__ */ jsxs11(Text12, { color: driftScore >= 80 ? COLORS.success : COLORS.warning, children: [
2004
2081
  driftScore,
2005
2082
  "%"
2006
2083
  ] })
2007
2084
  ] }),
2008
2085
  /* @__PURE__ */ jsxs11(Box9, { gap: SPACING.xs, children: [
2009
- /* @__PURE__ */ jsx12(Text12, { color: COLORS.muted, children: t("dashboard_sync") }),
2010
- syncAgo === null ? /* @__PURE__ */ jsx12(Text12, { color: COLORS.muted, children: t("dashboard_sync_never") }) : /* @__PURE__ */ jsx12(Text12, { color: COLORS.info, children: t("dashboard_sync_ago", { time: syncAgo }) })
2086
+ /* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: t("dashboard_sync") }),
2087
+ syncAgo === null ? /* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: t("dashboard_sync_never") }) : /* @__PURE__ */ jsx13(Text12, { color: COLORS.info, children: t("dashboard_sync_ago", { time: syncAgo }) })
2011
2088
  ] }),
2012
2089
  /* @__PURE__ */ jsxs11(Box9, { gap: SPACING.xs, children: [
2013
- /* @__PURE__ */ jsx12(Text12, { color: COLORS.muted, children: t("dashboard_compliance") }),
2014
- violationCount === null ? /* @__PURE__ */ jsx12(Text12, { color: COLORS.muted, children: "\u2014" }) : violationCount === 0 ? /* @__PURE__ */ jsx12(Text12, { color: COLORS.success, children: t("dashboard_compliance_ok") }) : /* @__PURE__ */ jsx12(Text12, { color: COLORS.warning, children: t("dashboard_compliance_violations", { count: String(violationCount) }) })
2090
+ /* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: t("dashboard_compliance") }),
2091
+ violationCount === null ? /* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: "\u2014" }) : violationCount === 0 ? /* @__PURE__ */ jsx13(Text12, { color: COLORS.success, children: t("dashboard_compliance_ok") }) : /* @__PURE__ */ jsx13(Text12, { color: COLORS.warning, children: t("dashboard_compliance_violations", { count: String(violationCount) }) })
2015
2092
  ] })
2016
2093
  ] });
2017
2094
  }
@@ -2026,9 +2103,9 @@ function DashboardView() {
2026
2103
  const lastFetchedAt = useBrewStore((s) => s.lastFetchedAt);
2027
2104
  const fetchAll = useBrewStore((s) => s.fetchAll);
2028
2105
  const isPro = useLicenseStore((s) => s.isPro);
2029
- const { stdout } = useStdout3();
2106
+ const { stdout } = useStdout4();
2030
2107
  const columns = stdout?.columns ?? 80;
2031
- useEffect3(() => {
2108
+ useEffect5(() => {
2032
2109
  fetchAll();
2033
2110
  }, []);
2034
2111
  useViewInput((input) => {
@@ -2053,11 +2130,11 @@ function DashboardView() {
2053
2130
  const outdatedValue = loading.outdated ? "..." : errors.outdated ? t("dashboard_statError") : outdated.formulae.length + outdated.casks.length;
2054
2131
  const servicesValue = loading.services ? "..." : errors.services ? t("dashboard_statError") : `${runningServices}/${services.length}`;
2055
2132
  const lastUpdated = lastFetchedAt.installed ? formatRelativeTime(lastFetchedAt.installed / 1e3) : null;
2056
- if (loading.installed) return /* @__PURE__ */ jsx12(Loading, { message: t("loading_fetchingBrew") });
2133
+ if (loading.installed) return /* @__PURE__ */ jsx13(Loading, { message: t("loading_fetchingBrew") });
2057
2134
  if (errors.installed) {
2058
2135
  return /* @__PURE__ */ jsxs11(Box9, { flexDirection: "column", children: [
2059
- /* @__PURE__ */ jsx12(ErrorMessage, { message: errors.installed }),
2060
- /* @__PURE__ */ jsx12(Box9, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs11(Text12, { color: COLORS.textSecondary, children: [
2136
+ /* @__PURE__ */ jsx13(ErrorMessage, { message: errors.installed }),
2137
+ /* @__PURE__ */ jsx13(Box9, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs11(Text12, { color: COLORS.textSecondary, children: [
2061
2138
  "r:",
2062
2139
  t("hint_refresh")
2063
2140
  ] }) })
@@ -2065,11 +2142,11 @@ function DashboardView() {
2065
2142
  }
2066
2143
  const isNarrow = columns < 60;
2067
2144
  return /* @__PURE__ */ jsxs11(Box9, { flexDirection: "column", gap: SPACING.sm, children: [
2068
- /* @__PURE__ */ jsx12(SectionHeader, { emoji: "\u{1F4CA}", title: t("dashboard_overview"), gradient: GRADIENTS.gold }),
2145
+ /* @__PURE__ */ jsx13(SectionHeader, { emoji: "\u{1F4CA}", title: t("dashboard_overview"), gradient: GRADIENTS.gold }),
2069
2146
  /* @__PURE__ */ jsxs11(Box9, { gap: SPACING.xs, flexWrap: "wrap", flexDirection: isNarrow ? "column" : "row", children: [
2070
- /* @__PURE__ */ jsx12(StatCard, { label: t("dashboard_formulae"), value: formulae.length, color: COLORS.info }),
2071
- /* @__PURE__ */ jsx12(StatCard, { label: t("dashboard_casks"), value: casks.length, color: COLORS.purple }),
2072
- /* @__PURE__ */ jsx12(
2147
+ /* @__PURE__ */ jsx13(StatCard, { label: t("dashboard_formulae"), value: formulae.length, color: COLORS.info }),
2148
+ /* @__PURE__ */ jsx13(StatCard, { label: t("dashboard_casks"), value: casks.length, color: COLORS.purple }),
2149
+ /* @__PURE__ */ jsx13(
2073
2150
  StatCard,
2074
2151
  {
2075
2152
  label: t("dashboard_outdated"),
@@ -2077,7 +2154,7 @@ function DashboardView() {
2077
2154
  color: typeof outdatedValue === "number" && outdatedValue > 0 ? COLORS.warning : errors.outdated ? COLORS.error : COLORS.success
2078
2155
  }
2079
2156
  ),
2080
- /* @__PURE__ */ jsx12(
2157
+ /* @__PURE__ */ jsx13(
2081
2158
  StatCard,
2082
2159
  {
2083
2160
  label: t("dashboard_services"),
@@ -2086,9 +2163,9 @@ function DashboardView() {
2086
2163
  }
2087
2164
  )
2088
2165
  ] }),
2089
- lastUpdated && /* @__PURE__ */ jsx12(Text12, { color: COLORS.muted, children: t("dashboard_lastUpdated", { time: lastUpdated }) }),
2166
+ lastUpdated && /* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: t("dashboard_lastUpdated", { time: lastUpdated }) }),
2090
2167
  partialErrors.length > 0 && /* @__PURE__ */ jsxs11(Box9, { flexDirection: "column", borderStyle: "round", borderColor: COLORS.warning, paddingX: SPACING.sm, paddingY: SPACING.none, children: [
2091
- /* @__PURE__ */ jsx12(Text12, { color: COLORS.warning, bold: true, children: t("dashboard_partialData") }),
2168
+ /* @__PURE__ */ jsx13(Text12, { color: COLORS.warning, bold: true, children: t("dashboard_partialData") }),
2092
2169
  partialErrors.map((item) => /* @__PURE__ */ jsxs11(Text12, { color: COLORS.muted, children: [
2093
2170
  item.label,
2094
2171
  ": ",
@@ -2096,56 +2173,56 @@ function DashboardView() {
2096
2173
  ] }, item.label))
2097
2174
  ] }),
2098
2175
  config && !errors.config && /* @__PURE__ */ jsxs11(Box9, { flexDirection: "column", children: [
2099
- /* @__PURE__ */ jsx12(SectionHeader, { emoji: "\u2139\uFE0F", title: t("dashboard_systemInfo"), gradient: [COLORS.text, COLORS.muted] }),
2176
+ /* @__PURE__ */ jsx13(SectionHeader, { emoji: "\u2139\uFE0F", title: t("dashboard_systemInfo"), gradient: [COLORS.text, COLORS.muted] }),
2100
2177
  /* @__PURE__ */ jsxs11(Box9, { borderStyle: "round", borderColor: COLORS.blue, paddingX: SPACING.sm, paddingY: SPACING.none, flexDirection: "column", marginTop: SPACING.xs, children: [
2101
2178
  /* @__PURE__ */ jsxs11(Text12, { children: [
2102
- /* @__PURE__ */ jsx12(Text12, { color: COLORS.muted, children: t("dashboard_homebrew") }),
2179
+ /* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: t("dashboard_homebrew") }),
2103
2180
  " ",
2104
2181
  config.HOMEBREW_VERSION
2105
2182
  ] }),
2106
2183
  /* @__PURE__ */ jsxs11(Text12, { children: [
2107
- /* @__PURE__ */ jsx12(Text12, { color: COLORS.muted, children: t("dashboard_prefix") }),
2184
+ /* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: t("dashboard_prefix") }),
2108
2185
  " ",
2109
2186
  config.HOMEBREW_PREFIX
2110
2187
  ] }),
2111
2188
  /* @__PURE__ */ jsxs11(Text12, { children: [
2112
- /* @__PURE__ */ jsx12(Text12, { color: COLORS.muted, children: t("dashboard_updated") }),
2189
+ /* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: t("dashboard_updated") }),
2113
2190
  " ",
2114
2191
  config.coreUpdated
2115
2192
  ] })
2116
2193
  ] })
2117
2194
  ] }),
2118
2195
  !errors.outdated && outdated.formulae.length > 0 && /* @__PURE__ */ jsxs11(Box9, { flexDirection: "column", marginTop: SPACING.xs, children: [
2119
- /* @__PURE__ */ jsx12(SectionHeader, { emoji: "\u{1F4E6}", title: t("dashboard_outdatedPackages"), gradient: GRADIENTS.fire }),
2196
+ /* @__PURE__ */ jsx13(SectionHeader, { emoji: "\u{1F4E6}", title: t("dashboard_outdatedPackages"), gradient: GRADIENTS.fire }),
2120
2197
  /* @__PURE__ */ jsxs11(Box9, { paddingLeft: SPACING.sm, flexDirection: "column", children: [
2121
2198
  outdated.formulae.slice(0, 10).map((pkg) => /* @__PURE__ */ jsxs11(Box9, { gap: SPACING.xs, children: [
2122
- /* @__PURE__ */ jsx12(Text12, { color: COLORS.text, children: pkg.name }),
2123
- /* @__PURE__ */ jsx12(VersionArrow, { current: pkg.installed_versions[0] ?? "", latest: pkg.current_version })
2199
+ /* @__PURE__ */ jsx13(Text12, { color: COLORS.text, children: pkg.name }),
2200
+ /* @__PURE__ */ jsx13(VersionArrow, { current: pkg.installed_versions[0] ?? "", latest: pkg.current_version })
2124
2201
  ] }, pkg.name)),
2125
- outdated.formulae.length > 10 && /* @__PURE__ */ jsx12(Text12, { color: COLORS.textSecondary, italic: true, children: t("common_andMore", { count: outdated.formulae.length - 10 }) })
2202
+ outdated.formulae.length > 10 && /* @__PURE__ */ jsx13(Text12, { color: COLORS.textSecondary, italic: true, children: t("common_andMore", { count: outdated.formulae.length - 10 }) })
2126
2203
  ] })
2127
2204
  ] }),
2128
2205
  !errors.services && errorServices > 0 && /* @__PURE__ */ jsxs11(Box9, { flexDirection: "column", marginTop: SPACING.xs, children: [
2129
- /* @__PURE__ */ jsx12(SectionHeader, { emoji: "\u26A0\uFE0F", title: t("dashboard_serviceErrors"), color: COLORS.error }),
2130
- /* @__PURE__ */ jsx12(Box9, { paddingLeft: SPACING.sm, flexDirection: "column", children: errorServiceList.map((s) => /* @__PURE__ */ jsxs11(Box9, { gap: SPACING.xs, children: [
2131
- /* @__PURE__ */ jsx12(StatusBadge, { label: t("badge_error"), variant: "error" }),
2132
- /* @__PURE__ */ jsx12(Text12, { children: s.name }),
2133
- s.exit_code != null && /* @__PURE__ */ jsx12(Text12, { color: COLORS.muted, children: t("common_exit", { code: s.exit_code }) })
2206
+ /* @__PURE__ */ jsx13(SectionHeader, { emoji: "\u26A0\uFE0F", title: t("dashboard_serviceErrors"), color: COLORS.error }),
2207
+ /* @__PURE__ */ jsx13(Box9, { paddingLeft: SPACING.sm, flexDirection: "column", children: errorServiceList.map((s) => /* @__PURE__ */ jsxs11(Box9, { gap: SPACING.xs, children: [
2208
+ /* @__PURE__ */ jsx13(StatusBadge, { label: t("badge_error"), variant: "error" }),
2209
+ /* @__PURE__ */ jsx13(Text12, { children: s.name }),
2210
+ s.exit_code != null && /* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: t("common_exit", { code: s.exit_code }) })
2134
2211
  ] }, s.name)) })
2135
2212
  ] }),
2136
- isPro() && /* @__PURE__ */ jsx12(ProStatusPanel, {})
2213
+ isPro() && /* @__PURE__ */ jsx13(ProStatusPanel, {})
2137
2214
  ] });
2138
2215
  }
2139
2216
 
2140
2217
  // src/views/installed.tsx
2141
- import { useState as useState6, useMemo as useMemo3, useEffect as useEffect9, useRef as useRef2 } from "react";
2218
+ import { useState as useState6, useMemo as useMemo3, useEffect as useEffect9, useRef as useRef3 } from "react";
2142
2219
  import { Box as Box15, Text as Text18 } from "ink";
2143
2220
 
2144
2221
  // src/hooks/use-debounce.ts
2145
- import { useState as useState2, useEffect as useEffect4 } from "react";
2222
+ import { useState as useState4, useEffect as useEffect6 } from "react";
2146
2223
  function useDebounce(value, delayMs) {
2147
- const [debounced, setDebounced] = useState2(value);
2148
- useEffect4(() => {
2224
+ const [debounced, setDebounced] = useState4(value);
2225
+ useEffect6(() => {
2149
2226
  const timer = setTimeout(() => setDebounced(value), delayMs);
2150
2227
  return () => clearTimeout(timer);
2151
2228
  }, [value, delayMs]);
@@ -2153,7 +2230,7 @@ function useDebounce(value, delayMs) {
2153
2230
  }
2154
2231
 
2155
2232
  // src/hooks/use-brew-stream.ts
2156
- import { useState as useState3, useCallback, useRef, useEffect as useEffect5 } from "react";
2233
+ import { useState as useState5, useCallback, useRef as useRef2, useEffect as useEffect7 } from "react";
2157
2234
  var MAX_LINES = 100;
2158
2235
  async function logToHistory(args, success, error) {
2159
2236
  const detected = detectAction(args);
@@ -2166,13 +2243,13 @@ async function logToHistory(args, success, error) {
2166
2243
  }
2167
2244
  }
2168
2245
  function useBrewStream() {
2169
- const [lines, setLines] = useState3([]);
2170
- const [isRunning, setIsRunning] = useState3(false);
2171
- const [error, setError2] = useState3(null);
2172
- const cancelRef = useRef(false);
2173
- const generatorRef = useRef(null);
2174
- const mountedRef = useRef(true);
2175
- useEffect5(() => {
2246
+ const [lines, setLines] = useState5([]);
2247
+ const [isRunning, setIsRunning] = useState5(false);
2248
+ const [error, setError2] = useState5(null);
2249
+ const cancelRef = useRef2(false);
2250
+ const generatorRef = useRef2(null);
2251
+ const mountedRef = useRef2(true);
2252
+ useEffect7(() => {
2176
2253
  mountedRef.current = true;
2177
2254
  return () => {
2178
2255
  mountedRef.current = false;
@@ -2232,7 +2309,7 @@ function useBrewStream() {
2232
2309
  // src/components/common/search-input.tsx
2233
2310
  import { Box as Box10, Text as Text13 } from "ink";
2234
2311
  import { TextInput } from "@inkjs/ui";
2235
- import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
2312
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
2236
2313
  function SearchInput({ defaultValue, onChange, placeholder, isActive = true }) {
2237
2314
  const resolvedPlaceholder = placeholder ?? t("searchInput_placeholder");
2238
2315
  return /* @__PURE__ */ jsxs12(Box10, { children: [
@@ -2240,25 +2317,25 @@ function SearchInput({ defaultValue, onChange, placeholder, isActive = true }) {
2240
2317
  "\u{1F50D}",
2241
2318
  " "
2242
2319
  ] }),
2243
- isActive ? /* @__PURE__ */ jsx13(
2320
+ isActive ? /* @__PURE__ */ jsx14(
2244
2321
  TextInput,
2245
2322
  {
2246
2323
  placeholder: resolvedPlaceholder,
2247
2324
  defaultValue,
2248
2325
  onChange
2249
2326
  }
2250
- ) : /* @__PURE__ */ jsx13(Text13, { color: COLORS.textSecondary, children: defaultValue || placeholder })
2327
+ ) : /* @__PURE__ */ jsx14(Text13, { color: COLORS.textSecondary, children: defaultValue || placeholder })
2251
2328
  ] });
2252
2329
  }
2253
2330
 
2254
2331
  // src/components/common/confirm-dialog.tsx
2255
- import { useEffect as useEffect6 } from "react";
2332
+ import { useEffect as useEffect8 } from "react";
2256
2333
  import { Box as Box11, Text as Text14, useInput as useInput3 } from "ink";
2257
- import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
2334
+ import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
2258
2335
  function ConfirmDialog({ message, onConfirm, onCancel }) {
2259
2336
  const locale = useLocaleStore((s) => s.locale);
2260
2337
  const { openModal, closeModal } = useModalStore();
2261
- useEffect6(() => {
2338
+ useEffect8(() => {
2262
2339
  openModal();
2263
2340
  return () => {
2264
2341
  closeModal();
@@ -2271,11 +2348,11 @@ function ConfirmDialog({ message, onConfirm, onCancel }) {
2271
2348
  else if (key.escape) onCancel();
2272
2349
  });
2273
2350
  return /* @__PURE__ */ jsxs13(Box11, { borderStyle: "double", borderColor: COLORS.purple, paddingX: SPACING.sm, paddingY: SPACING.xs, flexDirection: "column", children: [
2274
- /* @__PURE__ */ jsx14(Text14, { bold: true, color: COLORS.text, children: message }),
2351
+ /* @__PURE__ */ jsx15(Text14, { bold: true, color: COLORS.text, children: message }),
2275
2352
  /* @__PURE__ */ jsxs13(Box11, { marginTop: SPACING.xs, children: [
2276
- /* @__PURE__ */ jsx14(Text14, { color: COLORS.success, children: t("confirm_yes") }),
2277
- /* @__PURE__ */ jsx14(Text14, { children: " / " }),
2278
- /* @__PURE__ */ jsx14(Text14, { color: COLORS.error, children: t("confirm_no") })
2353
+ /* @__PURE__ */ jsx15(Text14, { color: COLORS.success, children: t("confirm_yes") }),
2354
+ /* @__PURE__ */ jsx15(Text14, { children: " / " }),
2355
+ /* @__PURE__ */ jsx15(Text14, { color: COLORS.error, children: t("confirm_no") })
2279
2356
  ] })
2280
2357
  ] });
2281
2358
  }
@@ -2283,13 +2360,13 @@ function ConfirmDialog({ message, onConfirm, onCancel }) {
2283
2360
  // src/components/common/progress-log.tsx
2284
2361
  import { Box as Box12, Text as Text15 } from "ink";
2285
2362
  import { Spinner as Spinner2 } from "@inkjs/ui";
2286
- import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
2363
+ import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
2287
2364
  function ProgressLog({ lines, isRunning, title, maxVisible = 15 }) {
2288
2365
  const start = Math.max(0, lines.length - maxVisible);
2289
2366
  const visible = lines.slice(start);
2290
2367
  return /* @__PURE__ */ jsxs14(Box12, { flexDirection: "column", borderStyle: "round", borderColor: COLORS.sky, paddingX: SPACING.xs, children: [
2291
2368
  title && /* @__PURE__ */ jsxs14(Box12, { marginBottom: SPACING.xs, children: [
2292
- isRunning && /* @__PURE__ */ jsx15(Spinner2, { label: "" }),
2369
+ isRunning && /* @__PURE__ */ jsx16(Spinner2, { label: "" }),
2293
2370
  /* @__PURE__ */ jsxs14(Text15, { bold: true, color: COLORS.sky, children: [
2294
2371
  " ",
2295
2372
  title
@@ -2299,15 +2376,15 @@ function ProgressLog({ lines, isRunning, title, maxVisible = 15 }) {
2299
2376
  // UI-006: keys are absolute indices, so a line that scrolls off-screen
2300
2377
  // does not change the key of remaining lines. Stable identity prevents
2301
2378
  // React from treating the whole list as new on every append.
2302
- /* @__PURE__ */ jsx15(Text15, { color: COLORS.muted, wrap: "wrap", children: line }, `log-${start + i}`)
2379
+ /* @__PURE__ */ jsx16(Text15, { color: COLORS.muted, wrap: "wrap", children: line }, `log-${start + i}`)
2303
2380
  )),
2304
- lines.length === 0 && !isRunning && /* @__PURE__ */ jsx15(Text15, { color: COLORS.textSecondary, italic: true, children: t("progress_noOutput") })
2381
+ lines.length === 0 && !isRunning && /* @__PURE__ */ jsx16(Text15, { color: COLORS.textSecondary, italic: true, children: t("progress_noOutput") })
2305
2382
  ] });
2306
2383
  }
2307
2384
 
2308
2385
  // src/components/common/result-banner.tsx
2309
2386
  import { Box as Box13, Text as Text16 } from "ink";
2310
- import { jsx as jsx16 } from "react/jsx-runtime";
2387
+ import { jsx as jsx17 } from "react/jsx-runtime";
2311
2388
  var STATUS_COLORS = {
2312
2389
  success: COLORS.success,
2313
2390
  error: COLORS.error,
@@ -2315,64 +2392,33 @@ var STATUS_COLORS = {
2315
2392
  info: COLORS.info
2316
2393
  };
2317
2394
  function ResultBanner({ status, message }) {
2318
- return /* @__PURE__ */ jsx16(Box13, { borderStyle: "round", borderColor: STATUS_COLORS[status], paddingX: SPACING.sm, paddingY: SPACING.none, children: /* @__PURE__ */ jsx16(Text16, { color: STATUS_COLORS[status], bold: true, children: message }) });
2395
+ return /* @__PURE__ */ jsx17(Box13, { borderStyle: "round", borderColor: STATUS_COLORS[status], paddingX: SPACING.sm, paddingY: SPACING.none, children: /* @__PURE__ */ jsx17(Text16, { color: STATUS_COLORS[status], bold: true, children: message }) });
2319
2396
  }
2320
2397
 
2321
2398
  // src/components/common/selectable-row.tsx
2322
2399
  import { Box as Box14, Text as Text17 } from "ink";
2323
- import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
2400
+ import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
2324
2401
  function SelectableRow({ isCurrent, children, gap = 1 }) {
2325
2402
  return /* @__PURE__ */ jsxs15(Box14, { gap, children: [
2326
- /* @__PURE__ */ jsx17(Text17, { color: isCurrent ? COLORS.success : COLORS.muted, children: isCurrent ? "\u25B6" : " " }),
2403
+ /* @__PURE__ */ jsx18(Text17, { color: isCurrent ? COLORS.success : COLORS.muted, children: isCurrent ? "\u25B6" : " " }),
2327
2404
  children
2328
2405
  ] });
2329
2406
  }
2330
2407
 
2331
- // src/hooks/use-container-size.ts
2332
- import { useEffect as useEffect8, useState as useState5 } from "react";
2333
- import { measureElement } from "ink";
2334
-
2335
- // src/hooks/use-terminal-size.ts
2336
- import { useEffect as useEffect7, useState as useState4 } from "react";
2337
- import { useStdout as useStdout4 } from "ink";
2338
- function useTerminalSize() {
2339
- const { stdout } = useStdout4();
2340
- const [size, setSize] = useState4(() => ({
2341
- columns: stdout?.columns ?? 80,
2342
- rows: stdout?.rows ?? 24
2343
- }));
2344
- useEffect7(() => {
2345
- if (!stdout) return;
2346
- const onResize = () => {
2347
- setSize({
2348
- columns: stdout.columns ?? 80,
2349
- rows: stdout.rows ?? 24
2350
- });
2351
- };
2352
- stdout.on("resize", onResize);
2353
- return () => {
2354
- stdout.off("resize", onResize);
2355
- };
2356
- }, [stdout]);
2357
- return size;
2358
- }
2359
-
2360
- // src/hooks/use-container-size.ts
2361
- function useContainerSize(ref) {
2362
- const terminal = useTerminalSize();
2363
- const [size, setSize] = useState5({ width: 0, height: 0 });
2364
- useEffect8(() => {
2365
- if (!ref.current) return;
2366
- const measured = measureElement(ref.current);
2367
- setSize(
2368
- (prev) => prev.width === measured.width && prev.height === measured.height ? prev : measured
2369
- );
2370
- }, [ref, terminal.columns, terminal.rows]);
2371
- return size;
2408
+ // src/hooks/use-visible-rows.ts
2409
+ function useVisibleRows({
2410
+ reservedRows,
2411
+ fallbackReservedRows = reservedRows,
2412
+ minRows = 3
2413
+ }) {
2414
+ const { height: contentHeight } = useContentSize();
2415
+ const { rows: terminalRows } = useTerminalSize();
2416
+ const availableRows = contentHeight > 0 ? contentHeight - reservedRows : terminalRows - fallbackReservedRows;
2417
+ return Math.max(minRows, Math.floor(availableRows));
2372
2418
  }
2373
2419
 
2374
2420
  // src/views/installed.tsx
2375
- import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
2421
+ import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
2376
2422
  function InstalledView() {
2377
2423
  const formulae = useBrewStore((s) => s.formulae);
2378
2424
  const casks = useBrewStore((s) => s.casks);
@@ -2382,9 +2428,8 @@ function InstalledView() {
2382
2428
  const navigate = useNavigationStore((s) => s.navigate);
2383
2429
  const selectPackage = useNavigationStore((s) => s.selectPackage);
2384
2430
  const { openModal, closeModal } = useModalStore();
2385
- const containerRef = useRef2(null);
2431
+ const containerRef = useRef3(null);
2386
2432
  const { width: containerWidth } = useContainerSize(containerRef);
2387
- const { rows: terminalRows } = useTerminalSize();
2388
2433
  const columns = containerWidth > 0 ? containerWidth : 80;
2389
2434
  const nameWidth = Math.floor(columns * 0.35);
2390
2435
  const versionWidth = Math.floor(columns * 0.15);
@@ -2395,6 +2440,16 @@ function InstalledView() {
2395
2440
  const [confirmUninstall, setConfirmUninstall] = useState6(null);
2396
2441
  const debouncedFilter = useDebounce(filter, 200);
2397
2442
  const stream = useBrewStream();
2443
+ const listRows = useVisibleRows({
2444
+ reservedRows: isSearching ? 14 : 10,
2445
+ fallbackReservedRows: isSearching ? 18 : 14,
2446
+ minRows: 1
2447
+ });
2448
+ const streamRows = useVisibleRows({
2449
+ reservedRows: 5,
2450
+ fallbackReservedRows: 14,
2451
+ minRows: 1
2452
+ });
2398
2453
  useEffect9(() => {
2399
2454
  fetchInstalled();
2400
2455
  }, []);
@@ -2459,16 +2514,17 @@ function InstalledView() {
2459
2514
  setCursor(0);
2460
2515
  }
2461
2516
  }, { isActive: true });
2462
- if (loading.installed) return /* @__PURE__ */ jsx18(Loading, { message: t("loading_installed") });
2463
- if (errors.installed) return /* @__PURE__ */ jsx18(ErrorMessage, { message: errors.installed });
2517
+ if (loading.installed) return /* @__PURE__ */ jsx19(Loading, { message: t("loading_installed") });
2518
+ if (errors.installed) return /* @__PURE__ */ jsx19(ErrorMessage, { message: errors.installed });
2464
2519
  if (stream.isRunning || stream.lines.length > 0) {
2465
2520
  return /* @__PURE__ */ jsxs16(Box15, { flexDirection: "column", children: [
2466
- /* @__PURE__ */ jsx18(
2521
+ /* @__PURE__ */ jsx19(
2467
2522
  ProgressLog,
2468
2523
  {
2469
2524
  lines: stream.lines,
2470
2525
  isRunning: stream.isRunning,
2471
- title: t("pkgInfo_uninstalling", { name: "..." })
2526
+ title: t("pkgInfo_uninstalling", { name: "..." }),
2527
+ maxVisible: streamRows
2472
2528
  }
2473
2529
  ),
2474
2530
  stream.isRunning && /* @__PURE__ */ jsxs16(Text18, { color: COLORS.textSecondary, children: [
@@ -2476,7 +2532,7 @@ function InstalledView() {
2476
2532
  t("hint_cancel")
2477
2533
  ] }),
2478
2534
  !stream.isRunning && /* @__PURE__ */ jsxs16(Box15, { flexDirection: "column", marginTop: SPACING.xs, children: [
2479
- /* @__PURE__ */ jsx18(
2535
+ /* @__PURE__ */ jsx19(
2480
2536
  ResultBanner,
2481
2537
  {
2482
2538
  status: stream.error ? "error" : "success",
@@ -2490,12 +2546,12 @@ function InstalledView() {
2490
2546
  ] })
2491
2547
  ] });
2492
2548
  }
2493
- const MAX_VISIBLE_ROWS = Math.max(5, terminalRows - 8);
2549
+ const MAX_VISIBLE_ROWS = listRows;
2494
2550
  const start = Math.max(0, cursor - Math.floor(MAX_VISIBLE_ROWS / 2));
2495
2551
  const visible = allItems.slice(start, start + MAX_VISIBLE_ROWS);
2496
2552
  return /* @__PURE__ */ jsxs16(Box15, { flexDirection: "column", ref: containerRef, children: [
2497
2553
  /* @__PURE__ */ jsxs16(Box15, { marginBottom: SPACING.xs, gap: SPACING.xs, children: [
2498
- /* @__PURE__ */ jsx18(
2554
+ /* @__PURE__ */ jsx19(
2499
2555
  Box15,
2500
2556
  {
2501
2557
  borderStyle: "round",
@@ -2508,7 +2564,7 @@ function InstalledView() {
2508
2564
  ] })
2509
2565
  }
2510
2566
  ),
2511
- /* @__PURE__ */ jsx18(
2567
+ /* @__PURE__ */ jsx19(
2512
2568
  Box15,
2513
2569
  {
2514
2570
  borderStyle: "round",
@@ -2522,7 +2578,7 @@ function InstalledView() {
2522
2578
  }
2523
2579
  )
2524
2580
  ] }),
2525
- confirmUninstall && /* @__PURE__ */ jsx18(
2581
+ confirmUninstall && /* @__PURE__ */ jsx19(
2526
2582
  ConfirmDialog,
2527
2583
  {
2528
2584
  message: t("installed_confirmUninstall", { name: confirmUninstall }),
@@ -2536,17 +2592,17 @@ function InstalledView() {
2536
2592
  onCancel: () => setConfirmUninstall(null)
2537
2593
  }
2538
2594
  ),
2539
- isSearching && /* @__PURE__ */ jsx18(Box15, { marginBottom: SPACING.xs, borderStyle: "round", borderColor: COLORS.gold, paddingX: SPACING.xs, children: /* @__PURE__ */ jsx18(SearchInput, { defaultValue: filter, onChange: setFilter, isActive: isSearching }) }),
2595
+ isSearching && /* @__PURE__ */ jsx19(Box15, { marginBottom: SPACING.xs, borderStyle: "round", borderColor: COLORS.gold, paddingX: SPACING.xs, children: /* @__PURE__ */ jsx19(SearchInput, { defaultValue: filter, onChange: setFilter, isActive: isSearching }) }),
2540
2596
  /* @__PURE__ */ jsxs16(Box15, { gap: SPACING.xs, borderStyle: "single", borderBottom: true, borderTop: false, borderLeft: false, borderRight: false, borderColor: COLORS.border, children: [
2541
2597
  /* @__PURE__ */ jsxs16(Text18, { color: COLORS.text, bold: true, children: [
2542
2598
  " ",
2543
2599
  t("installed_col_package").padEnd(nameWidth)
2544
2600
  ] }),
2545
- /* @__PURE__ */ jsx18(Text18, { color: COLORS.text, bold: true, children: t("installed_col_version").padEnd(versionWidth) }),
2546
- /* @__PURE__ */ jsx18(Text18, { color: COLORS.text, bold: true, children: t("installed_col_status") })
2601
+ /* @__PURE__ */ jsx19(Text18, { color: COLORS.text, bold: true, children: t("installed_col_version").padEnd(versionWidth) }),
2602
+ /* @__PURE__ */ jsx19(Text18, { color: COLORS.text, bold: true, children: t("installed_col_status") })
2547
2603
  ] }),
2548
2604
  /* @__PURE__ */ jsxs16(Box15, { flexDirection: "column", children: [
2549
- visible.length === 0 && /* @__PURE__ */ jsx18(Box15, { paddingY: SPACING.xs, justifyContent: "center", children: /* @__PURE__ */ jsx18(Text18, { color: COLORS.textSecondary, italic: true, children: t("installed_noPackages") }) }),
2605
+ visible.length === 0 && /* @__PURE__ */ jsx19(Box15, { paddingY: SPACING.xs, justifyContent: "center", children: /* @__PURE__ */ jsx19(Text18, { color: COLORS.textSecondary, italic: true, children: t("installed_noPackages") }) }),
2550
2606
  start > 0 && /* @__PURE__ */ jsxs16(Text18, { color: COLORS.textSecondary, dimColor: true, children: [
2551
2607
  " ",
2552
2608
  t("scroll_moreAbove", { count: start })
@@ -2555,13 +2611,13 @@ function InstalledView() {
2555
2611
  const idx = start + i;
2556
2612
  const isCurrent = idx === cursor;
2557
2613
  return /* @__PURE__ */ jsxs16(SelectableRow, { isCurrent, children: [
2558
- /* @__PURE__ */ jsx18(Text18, { bold: isCurrent, inverse: isCurrent, color: isCurrent ? COLORS.text : COLORS.muted, children: truncate(item.name, nameWidth).padEnd(nameWidth) }),
2559
- /* @__PURE__ */ jsx18(Text18, { color: COLORS.teal, children: item.version.padEnd(versionWidth) }),
2560
- item.outdated && /* @__PURE__ */ jsx18(StatusBadge, { label: t("badge_outdated"), variant: "warning" }),
2561
- item.pinned && /* @__PURE__ */ jsx18(StatusBadge, { label: t("badge_pinned"), variant: "info" }),
2562
- item.kegOnly && /* @__PURE__ */ jsx18(StatusBadge, { label: t("badge_kegOnly"), variant: "muted" }),
2563
- item.installedAsDependency && /* @__PURE__ */ jsx18(StatusBadge, { label: t("badge_dep"), variant: "muted" }),
2564
- !item.outdated && !item.pinned && !item.kegOnly && !item.installedAsDependency && /* @__PURE__ */ jsx18(Text18, { color: COLORS.textSecondary, dimColor: true, children: truncate(item.desc, 30) })
2614
+ /* @__PURE__ */ jsx19(Text18, { bold: isCurrent, inverse: isCurrent, color: isCurrent ? COLORS.text : COLORS.muted, children: truncate(item.name, nameWidth).padEnd(nameWidth) }),
2615
+ /* @__PURE__ */ jsx19(Text18, { color: COLORS.teal, children: item.version.padEnd(versionWidth) }),
2616
+ item.outdated && /* @__PURE__ */ jsx19(StatusBadge, { label: t("badge_outdated"), variant: "warning" }),
2617
+ item.pinned && /* @__PURE__ */ jsx19(StatusBadge, { label: t("badge_pinned"), variant: "info" }),
2618
+ item.kegOnly && /* @__PURE__ */ jsx19(StatusBadge, { label: t("badge_kegOnly"), variant: "muted" }),
2619
+ item.installedAsDependency && /* @__PURE__ */ jsx19(StatusBadge, { label: t("badge_dep"), variant: "muted" }),
2620
+ !item.outdated && !item.pinned && !item.kegOnly && !item.installedAsDependency && /* @__PURE__ */ jsx19(Text18, { color: COLORS.textSecondary, dimColor: true, children: truncate(item.desc, 30) })
2565
2621
  ] }, item.name);
2566
2622
  }),
2567
2623
  start + MAX_VISIBLE_ROWS < allItems.length && /* @__PURE__ */ jsxs16(Text18, { color: COLORS.textSecondary, dimColor: true, children: [
@@ -2569,15 +2625,15 @@ function InstalledView() {
2569
2625
  t("scroll_moreBelow", { count: allItems.length - start - MAX_VISIBLE_ROWS })
2570
2626
  ] })
2571
2627
  ] }),
2572
- /* @__PURE__ */ jsx18(Box15, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx18(Text18, { color: COLORS.text, bold: true, children: allItems.length > 0 ? `${cursor + 1}/${allItems.length}` : "0/0" }) })
2628
+ /* @__PURE__ */ jsx19(Box15, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx19(Text18, { color: COLORS.text, bold: true, children: allItems.length > 0 ? `${cursor + 1}/${allItems.length}` : "0/0" }) })
2573
2629
  ] });
2574
2630
  }
2575
2631
 
2576
2632
  // src/views/search.tsx
2577
- import { useState as useState7, useCallback as useCallback2, useEffect as useEffect10, useRef as useRef3 } from "react";
2633
+ import { useState as useState7, useCallback as useCallback2, useEffect as useEffect10, useRef as useRef4 } from "react";
2578
2634
  import { Box as Box16, Text as Text19 } from "ink";
2579
2635
  import { TextInput as TextInput2 } from "@inkjs/ui";
2580
- import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
2636
+ import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
2581
2637
  function SearchView() {
2582
2638
  const [query, setQuery] = useState7("");
2583
2639
  const [results, setResults] = useState7(null);
@@ -2590,7 +2646,17 @@ function SearchView() {
2590
2646
  const navigate = useNavigationStore((s) => s.navigate);
2591
2647
  const selectPackage = useNavigationStore((s) => s.selectPackage);
2592
2648
  const fetchInstalled = useBrewStore((s) => s.fetchInstalled);
2593
- const hasRefreshed = useRef3(false);
2649
+ const hasRefreshed = useRef4(false);
2650
+ const resultRows = useVisibleRows({
2651
+ reservedRows: searchError ? 8 : 6,
2652
+ fallbackReservedRows: searchError ? 18 : 16,
2653
+ minRows: 1
2654
+ });
2655
+ const streamRows = useVisibleRows({
2656
+ reservedRows: 5,
2657
+ fallbackReservedRows: 14,
2658
+ minRows: 1
2659
+ });
2594
2660
  useEffect10(() => {
2595
2661
  if (results !== null) {
2596
2662
  openModal();
@@ -2625,10 +2691,18 @@ function SearchView() {
2625
2691
  void fetchInstalled();
2626
2692
  }
2627
2693
  }, [stream.isRunning, stream.error]);
2628
- const MAX_VISIBLE = 20;
2629
- const visibleFormulae = results ? results.formulae.slice(0, MAX_VISIBLE) : [];
2630
- const visibleCasks = results ? results.casks.slice(0, MAX_VISIBLE) : [];
2631
- const allVisible = [...visibleFormulae, ...visibleCasks];
2694
+ const allResults = results ? [
2695
+ ...results.formulae.map((name) => ({ name, type: "formula" })),
2696
+ ...results.casks.map((name) => ({ name, type: "cask" }))
2697
+ ] : [];
2698
+ const start = Math.min(
2699
+ Math.max(0, cursor - Math.floor(resultRows / 2)),
2700
+ Math.max(0, allResults.length - resultRows)
2701
+ );
2702
+ const visibleResults = allResults.slice(start, start + resultRows);
2703
+ useEffect10(() => {
2704
+ setCursor((current) => Math.min(current, Math.max(0, allResults.length - 1)));
2705
+ }, [allResults.length]);
2632
2706
  useViewInput((input, key) => {
2633
2707
  if (stream.isRunning) {
2634
2708
  if (key.escape) stream.cancel();
@@ -2645,17 +2719,18 @@ function SearchView() {
2645
2719
  void doSearch(query);
2646
2720
  return;
2647
2721
  }
2648
- if (key.return && allVisible[cursor]) {
2649
- selectPackage(allVisible[cursor]);
2722
+ if (key.return && allResults[cursor]) {
2723
+ const result = allResults[cursor];
2724
+ selectPackage(result.name, result.type);
2650
2725
  navigate("package-info");
2651
2726
  return;
2652
2727
  }
2653
- if ((input === "i" || input === "1") && allVisible[cursor]) {
2654
- setConfirmInstall(allVisible[cursor]);
2728
+ if ((input === "i" || input === "1") && allResults[cursor]) {
2729
+ setConfirmInstall(allResults[cursor].name);
2655
2730
  return;
2656
2731
  }
2657
2732
  if (input === "j" || key.downArrow) {
2658
- setCursor((c) => Math.min(c + 1, Math.max(0, allVisible.length - 1)));
2733
+ setCursor((c) => Math.min(c + 1, Math.max(0, allResults.length - 1)));
2659
2734
  } else if (input === "k" || key.upArrow) {
2660
2735
  setCursor((c) => Math.max(c - 1, 0));
2661
2736
  } else if (key.escape) {
@@ -2665,12 +2740,13 @@ function SearchView() {
2665
2740
  });
2666
2741
  if (stream.isRunning || stream.lines.length > 0) {
2667
2742
  return /* @__PURE__ */ jsxs17(Box16, { flexDirection: "column", children: [
2668
- /* @__PURE__ */ jsx19(
2743
+ /* @__PURE__ */ jsx20(
2669
2744
  ProgressLog,
2670
2745
  {
2671
2746
  lines: stream.lines,
2672
2747
  isRunning: stream.isRunning,
2673
- title: t("search_installing")
2748
+ title: t("search_installing"),
2749
+ maxVisible: streamRows
2674
2750
  }
2675
2751
  ),
2676
2752
  stream.isRunning && /* @__PURE__ */ jsxs17(Text19, { color: COLORS.textSecondary, children: [
@@ -2678,7 +2754,7 @@ function SearchView() {
2678
2754
  t("hint_cancel")
2679
2755
  ] }),
2680
2756
  !stream.isRunning && /* @__PURE__ */ jsxs17(Box16, { flexDirection: "column", marginTop: SPACING.xs, children: [
2681
- /* @__PURE__ */ jsx19(
2757
+ /* @__PURE__ */ jsx20(
2682
2758
  ResultBanner,
2683
2759
  {
2684
2760
  status: stream.error ? "error" : "success",
@@ -2698,7 +2774,7 @@ function SearchView() {
2698
2774
  "\u{1F50D}",
2699
2775
  " "
2700
2776
  ] }),
2701
- !results ? /* @__PURE__ */ jsx19(
2777
+ !results ? /* @__PURE__ */ jsx20(
2702
2778
  TextInput2,
2703
2779
  {
2704
2780
  placeholder: t("search_placeholder"),
@@ -2709,14 +2785,14 @@ function SearchView() {
2709
2785
  ) : /* @__PURE__ */ jsxs17(Text19, { children: [
2710
2786
  t("search_resultsFor"),
2711
2787
  ' "',
2712
- /* @__PURE__ */ jsx19(Text19, { bold: true, color: COLORS.text, children: query }),
2788
+ /* @__PURE__ */ jsx20(Text19, { bold: true, color: COLORS.text, children: query }),
2713
2789
  '" ',
2714
- /* @__PURE__ */ jsx19(Text19, { color: COLORS.textSecondary, children: t("search_escToClear") })
2790
+ /* @__PURE__ */ jsx20(Text19, { color: COLORS.textSecondary, children: t("search_escToClear") })
2715
2791
  ] })
2716
2792
  ] }),
2717
- searching && /* @__PURE__ */ jsx19(Loading, { message: t("loading_searching") }),
2718
- searchError && /* @__PURE__ */ jsx19(Box16, { marginBottom: SPACING.xs, children: /* @__PURE__ */ jsx19(Text19, { color: COLORS.error, children: searchError }) }),
2719
- confirmInstall && /* @__PURE__ */ jsx19(
2793
+ searching && /* @__PURE__ */ jsx20(Loading, { message: t("loading_searching") }),
2794
+ searchError && /* @__PURE__ */ jsx20(Box16, { marginBottom: SPACING.xs, children: /* @__PURE__ */ jsx20(Text19, { color: COLORS.error, children: searchError }) }),
2795
+ confirmInstall && /* @__PURE__ */ jsx20(
2720
2796
  ConfirmDialog,
2721
2797
  {
2722
2798
  message: t("search_confirmInstall", { name: confirmInstall }),
@@ -2730,39 +2806,45 @@ function SearchView() {
2730
2806
  }
2731
2807
  ),
2732
2808
  results && !searching && !confirmInstall && /* @__PURE__ */ jsxs17(Box16, { flexDirection: "column", children: [
2733
- visibleFormulae.length > 0 && /* @__PURE__ */ jsxs17(Box16, { flexDirection: "column", marginBottom: SPACING.xs, children: [
2734
- /* @__PURE__ */ jsx19(Text19, { bold: true, color: COLORS.info, children: t("search_formulaeHeader", { count: results.formulae.length }) }),
2735
- visibleFormulae.map((name, i) => {
2736
- const isCurrent = i === cursor;
2737
- return /* @__PURE__ */ jsx19(SelectableRow, { isCurrent, children: /* @__PURE__ */ jsx19(Text19, { bold: isCurrent, inverse: isCurrent, children: name }) }, name);
2738
- }),
2739
- results.formulae.length > MAX_VISIBLE && /* @__PURE__ */ jsxs17(Text19, { color: COLORS.textSecondary, dimColor: true, children: [
2740
- " ",
2741
- t("scroll_moreBelow", { count: results.formulae.length - MAX_VISIBLE })
2742
- ] })
2809
+ allResults.length > 0 && /* @__PURE__ */ jsxs17(Text19, { color: COLORS.textSecondary, children: [
2810
+ t("search_formulaeHeader", { count: results.formulae.length }),
2811
+ " ",
2812
+ t("search_casksHeader", { count: results.casks.length })
2743
2813
  ] }),
2744
- visibleCasks.length > 0 && /* @__PURE__ */ jsxs17(Box16, { flexDirection: "column", children: [
2745
- /* @__PURE__ */ jsx19(Text19, { bold: true, color: COLORS.purple, children: t("search_casksHeader", { count: results.casks.length }) }),
2746
- visibleCasks.map((name, i) => {
2747
- const idx = visibleFormulae.length + i;
2814
+ allResults.length > 0 && /* @__PURE__ */ jsxs17(Box16, { flexDirection: "column", children: [
2815
+ start > 0 && /* @__PURE__ */ jsxs17(Text19, { color: COLORS.textSecondary, dimColor: true, children: [
2816
+ " ",
2817
+ t("scroll_moreAbove", { count: start })
2818
+ ] }),
2819
+ visibleResults.map((result, i) => {
2820
+ const idx = start + i;
2748
2821
  const isCurrent = idx === cursor;
2749
- return /* @__PURE__ */ jsx19(SelectableRow, { isCurrent, children: /* @__PURE__ */ jsx19(Text19, { bold: isCurrent, inverse: isCurrent, children: name }) }, name);
2822
+ return /* @__PURE__ */ jsxs17(SelectableRow, { isCurrent, children: [
2823
+ /* @__PURE__ */ jsx20(Text19, { bold: isCurrent, inverse: isCurrent, children: result.name }),
2824
+ /* @__PURE__ */ jsx20(
2825
+ StatusBadge,
2826
+ {
2827
+ label: result.type === "formula" ? "Formula" : "Cask",
2828
+ variant: result.type === "formula" ? "info" : "muted"
2829
+ }
2830
+ )
2831
+ ] }, `${result.type}:${result.name}`);
2750
2832
  }),
2751
- results.casks.length > MAX_VISIBLE && /* @__PURE__ */ jsxs17(Text19, { color: COLORS.textSecondary, dimColor: true, children: [
2833
+ start + resultRows < allResults.length && /* @__PURE__ */ jsxs17(Text19, { color: COLORS.textSecondary, dimColor: true, children: [
2752
2834
  " ",
2753
- t("scroll_moreBelow", { count: results.casks.length - MAX_VISIBLE })
2835
+ t("scroll_moreBelow", { count: allResults.length - start - resultRows })
2754
2836
  ] })
2755
2837
  ] }),
2756
- allVisible.length === 0 && /* @__PURE__ */ jsx19(Box16, { borderStyle: "round", borderColor: COLORS.textSecondary, paddingX: SPACING.sm, children: /* @__PURE__ */ jsx19(Text19, { color: COLORS.textSecondary, italic: true, children: t("search_noResults") }) }),
2757
- /* @__PURE__ */ jsx19(Box16, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx19(Text19, { color: COLORS.text, bold: true, children: allVisible.length > 0 ? `${cursor + 1}/${allVisible.length}` : "" }) })
2838
+ allResults.length === 0 && /* @__PURE__ */ jsx20(Box16, { borderStyle: "round", borderColor: COLORS.textSecondary, paddingX: SPACING.sm, children: /* @__PURE__ */ jsx20(Text19, { color: COLORS.textSecondary, italic: true, children: t("search_noResults") }) }),
2839
+ /* @__PURE__ */ jsx20(Box16, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx20(Text19, { color: COLORS.text, bold: true, children: allResults.length > 0 ? `${cursor + 1}/${allResults.length}` : "" }) })
2758
2840
  ] })
2759
2841
  ] });
2760
2842
  }
2761
2843
 
2762
2844
  // src/views/outdated.tsx
2763
- import { useEffect as useEffect11, useMemo as useMemo4, useRef as useRef4, useState as useState8 } from "react";
2845
+ import { useEffect as useEffect11, useMemo as useMemo4, useRef as useRef5, useState as useState8 } from "react";
2764
2846
  import { Box as Box17, Text as Text20 } from "ink";
2765
- import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
2847
+ import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
2766
2848
  function ImpactPanel({ impact }) {
2767
2849
  const riskColor = impact.risk === "high" ? COLORS.error : impact.risk === "medium" ? COLORS.warning : COLORS.success;
2768
2850
  const riskLabel = impact.risk === "high" ? t("impact_high") : impact.risk === "medium" ? t("impact_medium") : t("impact_low");
@@ -2779,9 +2861,9 @@ function ImpactPanel({ impact }) {
2779
2861
  t("impact_affects", { count: impact.reverseDeps.length })
2780
2862
  ] })
2781
2863
  ] }),
2782
- impact.riskReasons.length > 0 && /* @__PURE__ */ jsx20(Text20, { color: COLORS.textSecondary, children: impact.riskReasons.join(" \xB7 ") }),
2783
- impact.reverseDeps.length > 0 && impact.reverseDeps.length <= 5 && /* @__PURE__ */ jsx20(Text20, { color: COLORS.muted, dimColor: true, children: t("impact_usedBy", { packages: impact.reverseDeps.join(", ") }) }),
2784
- impact.risk === "high" && /* @__PURE__ */ jsx20(Text20, { color: COLORS.info, children: t("impact_brewfile_hint") })
2864
+ impact.riskReasons.length > 0 && /* @__PURE__ */ jsx21(Text20, { color: COLORS.textSecondary, children: impact.riskReasons.join(" \xB7 ") }),
2865
+ impact.reverseDeps.length > 0 && impact.reverseDeps.length <= 5 && /* @__PURE__ */ jsx21(Text20, { color: COLORS.muted, dimColor: true, children: t("impact_usedBy", { packages: impact.reverseDeps.join(", ") }) }),
2866
+ impact.risk === "high" && /* @__PURE__ */ jsx21(Text20, { color: COLORS.info, children: t("impact_brewfile_hint") })
2785
2867
  ] });
2786
2868
  }
2787
2869
  function OutdatedView() {
@@ -2789,10 +2871,20 @@ function OutdatedView() {
2789
2871
  const stream = useBrewStream();
2790
2872
  const [cursor, setCursor] = useState8(0);
2791
2873
  const [confirmAction, setConfirmAction] = useState8(null);
2792
- const hasRefreshed = useRef4(false);
2793
- const pendingUpgradeRef = useRef4(null);
2874
+ const hasRefreshed = useRef5(false);
2875
+ const pendingUpgradeRef = useRef5(null);
2794
2876
  const [impact, setImpact] = useState8(null);
2795
2877
  const [impactLoading, setImpactLoading] = useState8(false);
2878
+ const listRows = useVisibleRows({
2879
+ reservedRows: impact || impactLoading ? 11 : 7,
2880
+ fallbackReservedRows: impact || impactLoading ? 18 : 14,
2881
+ minRows: 1
2882
+ });
2883
+ const streamRows = useVisibleRows({
2884
+ reservedRows: 5,
2885
+ fallbackReservedRows: 14,
2886
+ minRows: 1
2887
+ });
2796
2888
  useEffect11(() => {
2797
2889
  fetchOutdated();
2798
2890
  }, []);
@@ -2880,20 +2972,20 @@ function OutdatedView() {
2880
2972
  void fetchOutdated();
2881
2973
  }
2882
2974
  });
2883
- const { rows: terminalRows } = useTerminalSize();
2884
- const MAX_VISIBLE_ROWS = Math.max(5, terminalRows - 8);
2975
+ const MAX_VISIBLE_ROWS = listRows;
2885
2976
  const start = Math.max(0, cursor - Math.floor(MAX_VISIBLE_ROWS / 2));
2886
2977
  const visible = allOutdated.slice(start, start + MAX_VISIBLE_ROWS);
2887
- if (loading.outdated) return /* @__PURE__ */ jsx20(Loading, { message: t("loading_outdated") });
2888
- if (errors.outdated) return /* @__PURE__ */ jsx20(ErrorMessage, { message: errors.outdated });
2978
+ if (loading.outdated) return /* @__PURE__ */ jsx21(Loading, { message: t("loading_outdated") });
2979
+ if (errors.outdated) return /* @__PURE__ */ jsx21(ErrorMessage, { message: errors.outdated });
2889
2980
  if (stream.isRunning || stream.lines.length > 0) {
2890
2981
  return /* @__PURE__ */ jsxs18(Box17, { flexDirection: "column", children: [
2891
- /* @__PURE__ */ jsx20(
2982
+ /* @__PURE__ */ jsx21(
2892
2983
  ProgressLog,
2893
2984
  {
2894
2985
  lines: stream.lines,
2895
2986
  isRunning: stream.isRunning,
2896
- title: t("outdated_upgrading")
2987
+ title: t("outdated_upgrading"),
2988
+ maxVisible: streamRows
2897
2989
  }
2898
2990
  ),
2899
2991
  stream.isRunning && /* @__PURE__ */ jsxs18(Text20, { color: COLORS.textSecondary, children: [
@@ -2902,7 +2994,7 @@ function OutdatedView() {
2902
2994
  ] }),
2903
2995
  !stream.isRunning && /* @__PURE__ */ jsxs18(Box17, { flexDirection: "column", marginTop: SPACING.xs, children: [
2904
2996
  /* @__PURE__ */ jsxs18(Box17, { borderStyle: "round", borderColor: stream.error ? COLORS.error : COLORS.success, paddingX: SPACING.sm, paddingY: SPACING.none, children: [
2905
- /* @__PURE__ */ jsx20(Text20, { color: stream.error ? COLORS.error : COLORS.success, bold: true, children: stream.error ? `\u2718 ${stream.error}` : `\u2714 ${t("outdated_upgradeComplete")}` }),
2997
+ /* @__PURE__ */ jsx21(Text20, { color: stream.error ? COLORS.error : COLORS.success, bold: true, children: stream.error ? `\u2718 ${stream.error}` : `\u2714 ${t("outdated_upgradeComplete")}` }),
2906
2998
  /* @__PURE__ */ jsxs18(Text20, { color: COLORS.muted, children: [
2907
2999
  " ",
2908
3000
  t("outdated_pressRefresh")
@@ -2920,8 +3012,8 @@ function OutdatedView() {
2920
3012
  const upgradeAllMessage = confirmAction?.type === "all" ? `${t("outdated_confirmAll", { count: allOutdated.length })}
2921
3013
  ${t("outdated_upgradeAllList", { list: allOutdated.map((p) => p.name).join(", ") })}` : "";
2922
3014
  return /* @__PURE__ */ jsxs18(Box17, { flexDirection: "column", children: [
2923
- /* @__PURE__ */ jsx20(SectionHeader, { emoji: "\u{1F4E6}", title: t("outdated_title", { count: allOutdated.length }), gradient: GRADIENTS.fire }),
2924
- confirmAction && /* @__PURE__ */ jsx20(Box17, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx20(
3015
+ /* @__PURE__ */ jsx21(SectionHeader, { emoji: "\u{1F4E6}", title: t("outdated_title", { count: allOutdated.length }), gradient: GRADIENTS.fire }),
3016
+ confirmAction && /* @__PURE__ */ jsx21(Box17, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx21(
2925
3017
  ConfirmDialog,
2926
3018
  {
2927
3019
  message: confirmAction.type === "all" ? upgradeAllMessage : t("outdated_confirmSingle", { name: confirmAction.type === "single" ? confirmAction.name : "" }),
@@ -2939,7 +3031,7 @@ ${t("outdated_upgradeAllList", { list: allOutdated.map((p) => p.name).join(", ")
2939
3031
  onCancel: () => setConfirmAction(null)
2940
3032
  }
2941
3033
  ) }),
2942
- allOutdated.length === 0 && !confirmAction && /* @__PURE__ */ jsx20(Box17, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx20(ResultBanner, { status: "success", message: `\u2714 ${t("outdated_upToDate")}` }) }),
3034
+ allOutdated.length === 0 && !confirmAction && /* @__PURE__ */ jsx21(Box17, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx21(ResultBanner, { status: "success", message: `\u2714 ${t("outdated_upToDate")}` }) }),
2943
3035
  allOutdated.length > 0 && !confirmAction && /* @__PURE__ */ jsxs18(Box17, { flexDirection: "column", marginTop: SPACING.xs, children: [
2944
3036
  start > 0 && /* @__PURE__ */ jsxs18(Text20, { color: COLORS.textSecondary, dimColor: true, children: [
2945
3037
  " ",
@@ -2949,31 +3041,31 @@ ${t("outdated_upgradeAllList", { list: allOutdated.map((p) => p.name).join(", ")
2949
3041
  const idx = start + i;
2950
3042
  const isCurrent = idx === cursor;
2951
3043
  return /* @__PURE__ */ jsxs18(SelectableRow, { isCurrent, children: [
2952
- /* @__PURE__ */ jsx20(Text20, { bold: isCurrent, inverse: isCurrent, color: isCurrent ? COLORS.text : COLORS.muted, children: pkg.name }),
2953
- /* @__PURE__ */ jsx20(VersionArrow, { current: pkg.installed_versions[0] ?? "", latest: pkg.current_version }),
2954
- pkg.pinned && /* @__PURE__ */ jsx20(StatusBadge, { label: t("outdated_pinned"), variant: "info" })
3044
+ /* @__PURE__ */ jsx21(Text20, { bold: isCurrent, inverse: isCurrent, color: isCurrent ? COLORS.text : COLORS.muted, children: pkg.name }),
3045
+ /* @__PURE__ */ jsx21(VersionArrow, { current: pkg.installed_versions[0] ?? "", latest: pkg.current_version }),
3046
+ pkg.pinned && /* @__PURE__ */ jsx21(StatusBadge, { label: t("outdated_pinned"), variant: "info" })
2955
3047
  ] }, pkg.name);
2956
3048
  }),
2957
3049
  start + MAX_VISIBLE_ROWS < allOutdated.length && /* @__PURE__ */ jsxs18(Text20, { color: COLORS.textSecondary, dimColor: true, children: [
2958
3050
  " ",
2959
3051
  t("scroll_moreBelow", { count: allOutdated.length - start - MAX_VISIBLE_ROWS })
2960
3052
  ] }),
2961
- /* @__PURE__ */ jsx20(Box17, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs18(Text20, { color: COLORS.text, bold: true, children: [
3053
+ /* @__PURE__ */ jsx21(Box17, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs18(Text20, { color: COLORS.text, bold: true, children: [
2962
3054
  cursor + 1,
2963
3055
  "/",
2964
3056
  allOutdated.length
2965
3057
  ] }) }),
2966
- impact && !stream.isRunning && !confirmAction && /* @__PURE__ */ jsx20(ImpactPanel, { impact }),
2967
- impactLoading && !stream.isRunning && !confirmAction && /* @__PURE__ */ jsx20(Box17, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx20(Text20, { color: COLORS.textSecondary, children: t("impact_analyzing") }) }),
2968
- /* @__PURE__ */ jsx20(Box17, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx20(Text20, { color: COLORS.textSecondary, children: t("impact_hint") }) })
3058
+ impact && !stream.isRunning && !confirmAction && /* @__PURE__ */ jsx21(ImpactPanel, { impact }),
3059
+ impactLoading && !stream.isRunning && !confirmAction && /* @__PURE__ */ jsx21(Box17, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx21(Text20, { color: COLORS.textSecondary, children: t("impact_analyzing") }) }),
3060
+ /* @__PURE__ */ jsx21(Box17, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx21(Text20, { color: COLORS.textSecondary, children: t("impact_hint") }) })
2969
3061
  ] })
2970
3062
  ] });
2971
3063
  }
2972
3064
 
2973
3065
  // src/views/package-info.tsx
2974
- import { useEffect as useEffect12, useRef as useRef5, useState as useState9 } from "react";
3066
+ import { useEffect as useEffect12, useRef as useRef6, useState as useState9 } from "react";
2975
3067
  import { Box as Box18, Text as Text21 } from "ink";
2976
- import { Fragment as Fragment4, jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
3068
+ import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
2977
3069
  var ACTION_PROGRESS_KEYS = {
2978
3070
  install: "pkgInfo_installing",
2979
3071
  uninstall: "pkgInfo_uninstalling",
@@ -2991,9 +3083,9 @@ function PackageInfoView() {
2991
3083
  const [loading, setLoading2] = useState9(true);
2992
3084
  const [error, setError2] = useState9(null);
2993
3085
  const [confirmAction, setConfirmAction] = useState9(null);
2994
- const activeActionRef = useRef5("install");
2995
- const mountedRef = useRef5(true);
2996
- const hasRefreshed = useRef5(false);
3086
+ const activeActionRef = useRef6("install");
3087
+ const mountedRef = useRef6(true);
3088
+ const hasRefreshed = useRef6(false);
2997
3089
  const stream = useBrewStream();
2998
3090
  useEffect12(() => {
2999
3091
  mountedRef.current = true;
@@ -3069,20 +3161,20 @@ function PackageInfoView() {
3069
3161
  }
3070
3162
  });
3071
3163
  if (!packageName) {
3072
- return /* @__PURE__ */ jsx21(Text21, { color: COLORS.textSecondary, italic: true, children: t("pkgInfo_noPackage") });
3164
+ return /* @__PURE__ */ jsx22(Text21, { color: COLORS.textSecondary, italic: true, children: t("pkgInfo_noPackage") });
3073
3165
  }
3074
- if (loading) return /* @__PURE__ */ jsx21(Loading, { message: t("loading_package", { name: packageName }) });
3075
- if (error) return /* @__PURE__ */ jsx21(ErrorMessage, { message: error });
3076
- if (!formula) return /* @__PURE__ */ jsx21(ErrorMessage, { message: t("pkgInfo_notFound") });
3166
+ if (loading) return /* @__PURE__ */ jsx22(Loading, { message: t("loading_package", { name: packageName }) });
3167
+ if (error) return /* @__PURE__ */ jsx22(ErrorMessage, { message: error });
3168
+ if (!formula) return /* @__PURE__ */ jsx22(ErrorMessage, { message: t("pkgInfo_notFound") });
3077
3169
  if (stream.isRunning || stream.lines.length > 0) {
3078
3170
  return /* @__PURE__ */ jsxs19(Box18, { flexDirection: "column", children: [
3079
- /* @__PURE__ */ jsx21(ProgressLog, { lines: stream.lines, isRunning: stream.isRunning, title: t(ACTION_PROGRESS_KEYS[activeActionRef.current] ?? ACTION_PROGRESS_KEYS["install"], { name: formula.name }) }),
3171
+ /* @__PURE__ */ jsx22(ProgressLog, { lines: stream.lines, isRunning: stream.isRunning, title: t(ACTION_PROGRESS_KEYS[activeActionRef.current] ?? ACTION_PROGRESS_KEYS["install"], { name: formula.name }) }),
3080
3172
  stream.isRunning && /* @__PURE__ */ jsxs19(Text21, { color: COLORS.textSecondary, children: [
3081
3173
  "esc:",
3082
3174
  t("hint_cancel")
3083
3175
  ] }),
3084
3176
  !stream.isRunning && /* @__PURE__ */ jsxs19(Fragment4, { children: [
3085
- /* @__PURE__ */ jsx21(Text21, { color: stream.error ? COLORS.error : COLORS.success, bold: true, children: stream.error ? `\u2718 ${stream.error}` : `\u2714 ${t("pkgInfo_done")}` }),
3177
+ /* @__PURE__ */ jsx22(Text21, { color: stream.error ? COLORS.error : COLORS.success, bold: true, children: stream.error ? `\u2718 ${stream.error}` : `\u2714 ${t("pkgInfo_done")}` }),
3086
3178
  /* @__PURE__ */ jsxs19(Text21, { color: COLORS.textSecondary, children: [
3087
3179
  "esc:",
3088
3180
  t("hint_back")
@@ -3093,7 +3185,7 @@ function PackageInfoView() {
3093
3185
  const installed = formula.installed[0];
3094
3186
  const isInstalled = formula.installed.length > 0;
3095
3187
  return /* @__PURE__ */ jsxs19(Box18, { flexDirection: "column", children: [
3096
- confirmAction && /* @__PURE__ */ jsx21(
3188
+ confirmAction && /* @__PURE__ */ jsx22(
3097
3189
  ConfirmDialog,
3098
3190
  {
3099
3191
  message: t(ACTION_CONFIRM_KEYS[confirmAction], { name: formula.name }),
@@ -3110,42 +3202,42 @@ function PackageInfoView() {
3110
3202
  }
3111
3203
  ),
3112
3204
  /* @__PURE__ */ jsxs19(Box18, { gap: SPACING.sm, marginBottom: SPACING.xs, children: [
3113
- /* @__PURE__ */ jsx21(GradientText, { colors: GRADIENTS.gold, bold: true, children: formula.name }),
3114
- /* @__PURE__ */ jsx21(Text21, { color: COLORS.teal, children: installed?.version ?? formula.versions.stable }),
3115
- isInstalled && /* @__PURE__ */ jsx21(StatusBadge, { label: t("badge_installed"), variant: "success" }),
3116
- formula.outdated && /* @__PURE__ */ jsx21(StatusBadge, { label: t("badge_outdated"), variant: "warning" }),
3117
- formula.pinned && /* @__PURE__ */ jsx21(StatusBadge, { label: t("badge_pinned"), variant: "info" }),
3118
- formula.keg_only && /* @__PURE__ */ jsx21(StatusBadge, { label: t("badge_kegOnly"), variant: "muted" }),
3119
- formula.deprecated && /* @__PURE__ */ jsx21(StatusBadge, { label: t("badge_deprecated"), variant: "error" })
3205
+ /* @__PURE__ */ jsx22(GradientText, { colors: GRADIENTS.gold, bold: true, children: formula.name }),
3206
+ /* @__PURE__ */ jsx22(Text21, { color: COLORS.teal, children: installed?.version ?? formula.versions.stable }),
3207
+ isInstalled && /* @__PURE__ */ jsx22(StatusBadge, { label: t("badge_installed"), variant: "success" }),
3208
+ formula.outdated && /* @__PURE__ */ jsx22(StatusBadge, { label: t("badge_outdated"), variant: "warning" }),
3209
+ formula.pinned && /* @__PURE__ */ jsx22(StatusBadge, { label: t("badge_pinned"), variant: "info" }),
3210
+ formula.keg_only && /* @__PURE__ */ jsx22(StatusBadge, { label: t("badge_kegOnly"), variant: "muted" }),
3211
+ formula.deprecated && /* @__PURE__ */ jsx22(StatusBadge, { label: t("badge_deprecated"), variant: "error" })
3120
3212
  ] }),
3121
3213
  /* @__PURE__ */ jsxs19(Box18, { flexDirection: "column", gap: SPACING.xs, children: [
3122
- /* @__PURE__ */ jsx21(Text21, { children: formula.desc }),
3214
+ /* @__PURE__ */ jsx22(Text21, { children: formula.desc }),
3123
3215
  /* @__PURE__ */ jsxs19(Box18, { flexDirection: "column", children: [
3124
- /* @__PURE__ */ jsx21(SectionHeader, { emoji: "\u{1F4CB}", title: t("pkgInfo_details"), gradient: [COLORS.text, COLORS.muted] }),
3216
+ /* @__PURE__ */ jsx22(SectionHeader, { emoji: "\u{1F4CB}", title: t("pkgInfo_details"), gradient: [COLORS.text, COLORS.muted] }),
3125
3217
  /* @__PURE__ */ jsxs19(Box18, { borderStyle: "round", borderColor: COLORS.border, paddingX: SPACING.sm, flexDirection: "column", children: [
3126
3218
  /* @__PURE__ */ jsxs19(Text21, { children: [
3127
- /* @__PURE__ */ jsx21(Text21, { color: COLORS.muted, children: t("pkgInfo_homepage") }),
3219
+ /* @__PURE__ */ jsx22(Text21, { color: COLORS.muted, children: t("pkgInfo_homepage") }),
3128
3220
  " ",
3129
3221
  formula.homepage
3130
3222
  ] }),
3131
3223
  /* @__PURE__ */ jsxs19(Text21, { children: [
3132
- /* @__PURE__ */ jsx21(Text21, { color: COLORS.muted, children: t("pkgInfo_license") }),
3224
+ /* @__PURE__ */ jsx22(Text21, { color: COLORS.muted, children: t("pkgInfo_license") }),
3133
3225
  " ",
3134
3226
  formula.license
3135
3227
  ] }),
3136
3228
  /* @__PURE__ */ jsxs19(Text21, { children: [
3137
- /* @__PURE__ */ jsx21(Text21, { color: COLORS.muted, children: t("pkgInfo_tap") }),
3229
+ /* @__PURE__ */ jsx22(Text21, { color: COLORS.muted, children: t("pkgInfo_tap") }),
3138
3230
  " ",
3139
3231
  formula.tap
3140
3232
  ] }),
3141
3233
  /* @__PURE__ */ jsxs19(Text21, { children: [
3142
- /* @__PURE__ */ jsx21(Text21, { color: COLORS.muted, children: t("pkgInfo_stable") }),
3234
+ /* @__PURE__ */ jsx22(Text21, { color: COLORS.muted, children: t("pkgInfo_stable") }),
3143
3235
  " ",
3144
3236
  formula.versions.stable
3145
3237
  ] }),
3146
3238
  installed && /* @__PURE__ */ jsxs19(Fragment4, { children: [
3147
3239
  /* @__PURE__ */ jsxs19(Text21, { children: [
3148
- /* @__PURE__ */ jsx21(Text21, { color: COLORS.muted, children: t("pkgInfo_installed") }),
3240
+ /* @__PURE__ */ jsx22(Text21, { color: COLORS.muted, children: t("pkgInfo_installed") }),
3149
3241
  " ",
3150
3242
  installed.version,
3151
3243
  " (",
@@ -3153,12 +3245,12 @@ function PackageInfoView() {
3153
3245
  ")"
3154
3246
  ] }),
3155
3247
  /* @__PURE__ */ jsxs19(Text21, { children: [
3156
- /* @__PURE__ */ jsx21(Text21, { color: COLORS.muted, children: t("pkgInfo_bottle") }),
3248
+ /* @__PURE__ */ jsx22(Text21, { color: COLORS.muted, children: t("pkgInfo_bottle") }),
3157
3249
  " ",
3158
3250
  installed.poured_from_bottle ? t("common_yes") : t("common_no")
3159
3251
  ] }),
3160
3252
  /* @__PURE__ */ jsxs19(Text21, { children: [
3161
- /* @__PURE__ */ jsx21(Text21, { color: COLORS.muted, children: t("pkgInfo_onRequest") }),
3253
+ /* @__PURE__ */ jsx22(Text21, { color: COLORS.muted, children: t("pkgInfo_onRequest") }),
3162
3254
  " ",
3163
3255
  installed.installed_on_request ? t("common_yes") : t("pkgInfo_noDependency")
3164
3256
  ] })
@@ -3166,15 +3258,15 @@ function PackageInfoView() {
3166
3258
  ] })
3167
3259
  ] }),
3168
3260
  formula.dependencies.length > 0 && /* @__PURE__ */ jsxs19(Box18, { flexDirection: "column", children: [
3169
- /* @__PURE__ */ jsx21(SectionHeader, { emoji: "\u{1F517}", title: t("pkgInfo_dependencies", { count: formula.dependencies.length }), gradient: GRADIENTS.ocean }),
3170
- /* @__PURE__ */ jsx21(Box18, { paddingLeft: SPACING.sm, flexWrap: "wrap", columnGap: 2, children: formula.dependencies.map((dep) => /* @__PURE__ */ jsx21(Text21, { color: COLORS.muted, children: dep }, dep)) })
3261
+ /* @__PURE__ */ jsx22(SectionHeader, { emoji: "\u{1F517}", title: t("pkgInfo_dependencies", { count: formula.dependencies.length }), gradient: GRADIENTS.ocean }),
3262
+ /* @__PURE__ */ jsx22(Box18, { paddingLeft: SPACING.sm, flexWrap: "wrap", columnGap: 2, children: formula.dependencies.map((dep) => /* @__PURE__ */ jsx22(Text21, { color: COLORS.muted, children: dep }, dep)) })
3171
3263
  ] }),
3172
3264
  formula.caveats && /* @__PURE__ */ jsxs19(Box18, { flexDirection: "column", children: [
3173
- /* @__PURE__ */ jsx21(SectionHeader, { emoji: "\u26A0\uFE0F", title: t("pkgInfo_caveats"), color: COLORS.warning }),
3174
- /* @__PURE__ */ jsx21(Box18, { borderStyle: "round", borderColor: COLORS.warning, paddingX: SPACING.sm, children: /* @__PURE__ */ jsx21(Text21, { color: COLORS.warning, children: formula.caveats }) })
3265
+ /* @__PURE__ */ jsx22(SectionHeader, { emoji: "\u26A0\uFE0F", title: t("pkgInfo_caveats"), color: COLORS.warning }),
3266
+ /* @__PURE__ */ jsx22(Box18, { borderStyle: "round", borderColor: COLORS.warning, paddingX: SPACING.sm, children: /* @__PURE__ */ jsx22(Text21, { color: COLORS.warning, children: formula.caveats }) })
3175
3267
  ] })
3176
3268
  ] }),
3177
- /* @__PURE__ */ jsx21(Box18, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs19(Text21, { color: COLORS.textSecondary, children: [
3269
+ /* @__PURE__ */ jsx22(Box18, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs19(Text21, { color: COLORS.textSecondary, children: [
3178
3270
  isInstalled ? `u:${t("hint_uninstall")}` : `i:${t("hint_install")}`,
3179
3271
  isInstalled && formula.outdated ? ` U:${t("hint_upgrade")}` : "",
3180
3272
  ` esc:${t("hint_back")}`
@@ -3185,7 +3277,7 @@ function PackageInfoView() {
3185
3277
  // src/views/services.tsx
3186
3278
  import { useEffect as useEffect13, useState as useState10 } from "react";
3187
3279
  import { Box as Box19, Text as Text22, useStdout as useStdout5 } from "ink";
3188
- import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
3280
+ import { jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
3189
3281
  var STATUS_VARIANTS = {
3190
3282
  started: "success",
3191
3283
  stopped: "muted",
@@ -3208,7 +3300,11 @@ function ServicesView() {
3208
3300
  const cols = stdout?.columns ?? 80;
3209
3301
  const svcNameWidth = Math.floor(cols * 0.35);
3210
3302
  const svcStatusWidth = Math.floor(cols * 0.15);
3211
- const MAX_VISIBLE_ROWS = Math.max(5, (stdout?.rows ?? 24) - 10);
3303
+ const MAX_VISIBLE_ROWS = useVisibleRows({
3304
+ reservedRows: lastError || actionInProgress ? 8 : 6,
3305
+ fallbackReservedRows: lastError || actionInProgress ? 16 : 14,
3306
+ minRows: 1
3307
+ });
3212
3308
  useEffect13(() => {
3213
3309
  fetchServices();
3214
3310
  }, []);
@@ -3241,19 +3337,19 @@ function ServicesView() {
3241
3337
  else if (input === "x" || input === "2") setConfirmAction({ type: "stop", name: svc.name });
3242
3338
  else if (input === "R" || input === "3") setConfirmAction({ type: "restart", name: svc.name });
3243
3339
  });
3244
- if (loading.services) return /* @__PURE__ */ jsx22(Loading, { message: t("loading_services") });
3245
- if (errors.services) return /* @__PURE__ */ jsx22(ErrorMessage, { message: errors.services });
3340
+ if (loading.services) return /* @__PURE__ */ jsx23(Loading, { message: t("loading_services") });
3341
+ if (errors.services) return /* @__PURE__ */ jsx23(ErrorMessage, { message: errors.services });
3246
3342
  if (services.length === 0) {
3247
3343
  return /* @__PURE__ */ jsxs20(Box19, { flexDirection: "column", children: [
3248
- /* @__PURE__ */ jsx22(SectionHeader, { emoji: "\u2699\uFE0F", title: t("services_title"), gradient: GRADIENTS.ocean }),
3249
- /* @__PURE__ */ jsx22(Text22, { color: COLORS.textSecondary, italic: true, children: t("services_noServices") })
3344
+ /* @__PURE__ */ jsx23(SectionHeader, { emoji: "\u2699\uFE0F", title: t("services_title"), gradient: GRADIENTS.ocean }),
3345
+ /* @__PURE__ */ jsx23(Text22, { color: COLORS.textSecondary, italic: true, children: t("services_noServices") })
3250
3346
  ] });
3251
3347
  }
3252
3348
  const start = Math.max(0, cursor - Math.floor(MAX_VISIBLE_ROWS / 2));
3253
3349
  const visible = services.slice(start, start + MAX_VISIBLE_ROWS);
3254
3350
  return /* @__PURE__ */ jsxs20(Box19, { flexDirection: "column", children: [
3255
- /* @__PURE__ */ jsx22(SectionHeader, { emoji: "\u2699\uFE0F", title: t("services_titleCount", { count: services.length }), gradient: GRADIENTS.ocean }),
3256
- confirmAction && /* @__PURE__ */ jsx22(Box19, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx22(
3351
+ /* @__PURE__ */ jsx23(SectionHeader, { emoji: "\u2699\uFE0F", title: t("services_titleCount", { count: services.length }), gradient: GRADIENTS.ocean }),
3352
+ confirmAction && /* @__PURE__ */ jsx23(Box19, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx23(
3257
3353
  ConfirmDialog,
3258
3354
  {
3259
3355
  message: confirmAction.type === "stop" ? t("services_confirmStop", { name: confirmAction.name }) : t("services_confirmRestart", { name: confirmAction.name }),
@@ -3278,8 +3374,8 @@ function ServicesView() {
3278
3374
  " ",
3279
3375
  t("services_name").padEnd(svcNameWidth)
3280
3376
  ] }),
3281
- /* @__PURE__ */ jsx22(Text22, { bold: true, color: COLORS.text, children: t("services_status").padEnd(svcStatusWidth) }),
3282
- /* @__PURE__ */ jsx22(Text22, { bold: true, color: COLORS.text, children: t("services_user") })
3377
+ /* @__PURE__ */ jsx23(Text22, { bold: true, color: COLORS.text, children: t("services_status").padEnd(svcStatusWidth) }),
3378
+ /* @__PURE__ */ jsx23(Text22, { bold: true, color: COLORS.text, children: t("services_user") })
3283
3379
  ] }),
3284
3380
  start > 0 && /* @__PURE__ */ jsxs20(Text22, { color: COLORS.textSecondary, dimColor: true, children: [
3285
3381
  " ",
@@ -3289,10 +3385,10 @@ function ServicesView() {
3289
3385
  const idx = start + i;
3290
3386
  const isCurrent = idx === cursor;
3291
3387
  return /* @__PURE__ */ jsxs20(SelectableRow, { isCurrent, children: [
3292
- /* @__PURE__ */ jsx22(Text22, { bold: isCurrent, inverse: isCurrent, color: isCurrent ? COLORS.text : COLORS.muted, children: svc.name.padEnd(svcNameWidth - 2) }),
3293
- /* @__PURE__ */ jsx22(StatusBadge, { label: svc.status, variant: STATUS_VARIANTS[svc.status] }),
3294
- /* @__PURE__ */ jsx22(Text22, { color: COLORS.muted, children: svc.user ?? "-" }),
3295
- svc.exit_code != null && svc.exit_code !== 0 && /* @__PURE__ */ jsx22(Text22, { color: COLORS.error, children: t("common_exit", { code: svc.exit_code }) })
3388
+ /* @__PURE__ */ jsx23(Text22, { bold: isCurrent, inverse: isCurrent, color: isCurrent ? COLORS.text : COLORS.muted, children: svc.name.padEnd(svcNameWidth - 2) }),
3389
+ /* @__PURE__ */ jsx23(StatusBadge, { label: svc.status, variant: STATUS_VARIANTS[svc.status] }),
3390
+ /* @__PURE__ */ jsx23(Text22, { color: COLORS.muted, children: svc.user ?? "-" }),
3391
+ svc.exit_code != null && svc.exit_code !== 0 && /* @__PURE__ */ jsx23(Text22, { color: COLORS.error, children: t("common_exit", { code: svc.exit_code }) })
3296
3392
  ] }, svc.name);
3297
3393
  }),
3298
3394
  start + MAX_VISIBLE_ROWS < services.length && /* @__PURE__ */ jsxs20(Text22, { color: COLORS.textSecondary, dimColor: true, children: [
@@ -3300,9 +3396,9 @@ function ServicesView() {
3300
3396
  t("scroll_moreBelow", { count: services.length - start - MAX_VISIBLE_ROWS })
3301
3397
  ] })
3302
3398
  ] }),
3303
- actionInProgress && /* @__PURE__ */ jsx22(Text22, { color: COLORS.sky, children: t("services_processing") }),
3304
- lastError && /* @__PURE__ */ jsx22(Box19, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx22(Text22, { color: COLORS.error, children: lastError }) }),
3305
- /* @__PURE__ */ jsx22(Box19, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs20(Text22, { color: COLORS.text, bold: true, children: [
3399
+ actionInProgress && /* @__PURE__ */ jsx23(Text22, { color: COLORS.sky, children: t("services_processing") }),
3400
+ lastError && /* @__PURE__ */ jsx23(Box19, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx23(Text22, { color: COLORS.error, children: lastError }) }),
3401
+ /* @__PURE__ */ jsx23(Box19, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs20(Text22, { color: COLORS.text, bold: true, children: [
3306
3402
  cursor + 1,
3307
3403
  "/",
3308
3404
  services.length
@@ -3311,12 +3407,12 @@ function ServicesView() {
3311
3407
  }
3312
3408
 
3313
3409
  // src/views/doctor.tsx
3314
- import { useEffect as useEffect14, useRef as useRef6 } from "react";
3410
+ import { useEffect as useEffect14, useRef as useRef7 } from "react";
3315
3411
  import { Box as Box20, Text as Text23 } from "ink";
3316
- import { jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
3412
+ import { jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
3317
3413
  function DoctorView() {
3318
3414
  const { doctorWarnings, doctorClean, loading, errors, fetchDoctor } = useBrewStore();
3319
- const mountedRef = useRef6(true);
3415
+ const mountedRef = useRef7(true);
3320
3416
  useEffect14(() => {
3321
3417
  mountedRef.current = true;
3322
3418
  return () => {
@@ -3329,24 +3425,24 @@ function DoctorView() {
3329
3425
  useViewInput((input) => {
3330
3426
  if (input === "r" || input === "1") void fetchDoctor();
3331
3427
  });
3332
- if (loading.doctor) return /* @__PURE__ */ jsx23(Loading, { message: t("loading_doctor") });
3333
- if (errors.doctor) return /* @__PURE__ */ jsx23(ErrorMessage, { message: errors.doctor });
3428
+ if (loading.doctor) return /* @__PURE__ */ jsx24(Loading, { message: t("loading_doctor") });
3429
+ if (errors.doctor) return /* @__PURE__ */ jsx24(ErrorMessage, { message: errors.doctor });
3334
3430
  return /* @__PURE__ */ jsxs21(Box20, { flexDirection: "column", children: [
3335
- /* @__PURE__ */ jsx23(SectionHeader, { emoji: "\u{1FA7A}", title: t("doctor_title"), gradient: GRADIENTS.emerald }),
3431
+ /* @__PURE__ */ jsx24(SectionHeader, { emoji: "\u{1FA7A}", title: t("doctor_title"), gradient: GRADIENTS.emerald }),
3336
3432
  /* @__PURE__ */ jsxs21(Box20, { flexDirection: "column", marginTop: SPACING.xs, children: [
3337
- doctorClean && /* @__PURE__ */ jsx23(ResultBanner, { status: "success", message: `\u2714 ${t("doctor_clean")}` }),
3338
- doctorClean === false && doctorWarnings.length === 0 && /* @__PURE__ */ jsx23(Text23, { color: COLORS.warning, children: t("doctor_warningsNotCaptured") }),
3433
+ doctorClean && /* @__PURE__ */ jsx24(ResultBanner, { status: "success", message: `\u2714 ${t("doctor_clean")}` }),
3434
+ doctorClean === false && doctorWarnings.length === 0 && /* @__PURE__ */ jsx24(Text23, { color: COLORS.warning, children: t("doctor_warningsNotCaptured") }),
3339
3435
  doctorWarnings.map((warning, i) => (
3340
3436
  // FE-004: Improved React key
3341
- /* @__PURE__ */ jsx23(Box20, { flexDirection: "column", marginBottom: SPACING.xs, borderStyle: "single", borderColor: COLORS.warning, paddingX: SPACING.xs, children: warning.split("\n").map((line, j) => /* @__PURE__ */ jsx23(Text23, { color: j === 0 ? COLORS.warning : COLORS.muted, children: line }, `warning-${i}-${j}-${line.slice(0, 20)}`)) }, `warning-${i}-${warning.slice(0, 20)}`)
3437
+ /* @__PURE__ */ jsx24(Box20, { flexDirection: "column", marginBottom: SPACING.xs, borderStyle: "single", borderColor: COLORS.warning, paddingX: SPACING.xs, children: warning.split("\n").map((line, j) => /* @__PURE__ */ jsx24(Text23, { color: j === 0 ? COLORS.warning : COLORS.muted, children: line }, `warning-${i}-${j}-${line.slice(0, 20)}`)) }, `warning-${i}-${warning.slice(0, 20)}`)
3342
3438
  ))
3343
3439
  ] }),
3344
- /* @__PURE__ */ jsx23(Box20, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx23(Text23, { color: COLORS.text, bold: true, children: doctorWarnings.length > 0 ? tp("plural_warnings", doctorWarnings.length) : "" }) })
3440
+ /* @__PURE__ */ jsx24(Box20, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx24(Text23, { color: COLORS.text, bold: true, children: doctorWarnings.length > 0 ? tp("plural_warnings", doctorWarnings.length) : "" }) })
3345
3441
  ] });
3346
3442
  }
3347
3443
 
3348
3444
  // src/views/profiles.tsx
3349
- import { useEffect as useEffect15, useRef as useRef7, useState as useState11 } from "react";
3445
+ import { useEffect as useEffect15, useRef as useRef8, useState as useState11 } from "react";
3350
3446
  import { Box as Box25 } from "ink";
3351
3447
 
3352
3448
  // src/stores/profile-store.ts
@@ -3568,12 +3664,12 @@ var useProfileStore = create9((set) => ({
3568
3664
 
3569
3665
  // src/views/profiles/profile-list-mode.tsx
3570
3666
  import { Box as Box21, Text as Text24 } from "ink";
3571
- import { jsx as jsx24, jsxs as jsxs22 } from "react/jsx-runtime";
3667
+ import { jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
3572
3668
  function ProfileListMode({ profileNames, cursor, confirmDelete, loadError, onConfirmDelete, onCancelDelete }) {
3573
3669
  return /* @__PURE__ */ jsxs22(Box21, { flexDirection: "column", children: [
3574
- /* @__PURE__ */ jsx24(SectionHeader, { emoji: "\u{1F4C1}", title: t("profiles_title", { count: profileNames.length }), gradient: GRADIENTS.gold }),
3575
- loadError && /* @__PURE__ */ jsx24(Box21, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx24(Text24, { color: COLORS.error, children: loadError }) }),
3576
- confirmDelete && profileNames[cursor] && /* @__PURE__ */ jsx24(Box21, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx24(
3670
+ /* @__PURE__ */ jsx25(SectionHeader, { emoji: "\u{1F4C1}", title: t("profiles_title", { count: profileNames.length }), gradient: GRADIENTS.gold }),
3671
+ loadError && /* @__PURE__ */ jsx25(Box21, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx25(Text24, { color: COLORS.error, children: loadError }) }),
3672
+ confirmDelete && profileNames[cursor] && /* @__PURE__ */ jsx25(Box21, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx25(
3577
3673
  ConfirmDialog,
3578
3674
  {
3579
3675
  message: t("profiles_confirmDelete", { name: profileNames[cursor] }),
@@ -3581,12 +3677,12 @@ function ProfileListMode({ profileNames, cursor, confirmDelete, loadError, onCon
3581
3677
  onCancel: onCancelDelete
3582
3678
  }
3583
3679
  ) }),
3584
- profileNames.length === 0 && !confirmDelete && /* @__PURE__ */ jsx24(Box21, { marginTop: SPACING.xs, borderStyle: "round", borderColor: COLORS.textSecondary, paddingX: SPACING.sm, paddingY: SPACING.none, children: /* @__PURE__ */ jsxs22(Box21, { flexDirection: "column", children: [
3585
- /* @__PURE__ */ jsx24(Text24, { color: COLORS.textSecondary, italic: true, children: t("profiles_noProfiles") }),
3680
+ profileNames.length === 0 && !confirmDelete && /* @__PURE__ */ jsx25(Box21, { marginTop: SPACING.xs, borderStyle: "round", borderColor: COLORS.textSecondary, paddingX: SPACING.sm, paddingY: SPACING.none, children: /* @__PURE__ */ jsxs22(Box21, { flexDirection: "column", children: [
3681
+ /* @__PURE__ */ jsx25(Text24, { color: COLORS.textSecondary, italic: true, children: t("profiles_noProfiles") }),
3586
3682
  /* @__PURE__ */ jsxs22(Text24, { color: COLORS.muted, children: [
3587
3683
  t("profiles_press"),
3588
3684
  " ",
3589
- /* @__PURE__ */ jsx24(Text24, { color: COLORS.gold, bold: true, children: "n" }),
3685
+ /* @__PURE__ */ jsx25(Text24, { color: COLORS.gold, bold: true, children: "n" }),
3590
3686
  " ",
3591
3687
  t("profiles_exportHint")
3592
3688
  ] })
@@ -3594,9 +3690,9 @@ function ProfileListMode({ profileNames, cursor, confirmDelete, loadError, onCon
3594
3690
  profileNames.length > 0 && !confirmDelete && /* @__PURE__ */ jsxs22(Box21, { flexDirection: "column", marginTop: SPACING.xs, children: [
3595
3691
  profileNames.map((name, i) => {
3596
3692
  const isCurrent = i === cursor;
3597
- return /* @__PURE__ */ jsx24(SelectableRow, { isCurrent, children: /* @__PURE__ */ jsx24(Text24, { bold: isCurrent, inverse: isCurrent, children: name }) }, name);
3693
+ return /* @__PURE__ */ jsx25(SelectableRow, { isCurrent, children: /* @__PURE__ */ jsx25(Text24, { bold: isCurrent, inverse: isCurrent, children: name }) }, name);
3598
3694
  }),
3599
- /* @__PURE__ */ jsx24(Box21, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs22(Text24, { color: COLORS.text, bold: true, children: [
3695
+ /* @__PURE__ */ jsx25(Box21, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs22(Text24, { color: COLORS.text, bold: true, children: [
3600
3696
  cursor + 1,
3601
3697
  "/",
3602
3698
  profileNames.length
@@ -3607,22 +3703,22 @@ function ProfileListMode({ profileNames, cursor, confirmDelete, loadError, onCon
3607
3703
 
3608
3704
  // src/views/profiles/profile-detail-mode.tsx
3609
3705
  import { Box as Box22, Text as Text25 } from "ink";
3610
- import { jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
3706
+ import { jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
3611
3707
  function ProfileDetailMode({ profile }) {
3612
3708
  return /* @__PURE__ */ jsxs23(Box22, { flexDirection: "column", children: [
3613
- /* @__PURE__ */ jsx25(Text25, { bold: true, color: COLORS.gold, children: profile.name }),
3614
- /* @__PURE__ */ jsx25(Text25, { color: COLORS.muted, children: profile.description }),
3615
- /* @__PURE__ */ jsx25(Text25, { color: COLORS.muted, children: t("profiles_created", { date: formatDate(profile.createdAt) }) }),
3709
+ /* @__PURE__ */ jsx26(Text25, { bold: true, color: COLORS.gold, children: profile.name }),
3710
+ /* @__PURE__ */ jsx26(Text25, { color: COLORS.muted, children: profile.description }),
3711
+ /* @__PURE__ */ jsx26(Text25, { color: COLORS.muted, children: t("profiles_created", { date: formatDate(profile.createdAt) }) }),
3616
3712
  /* @__PURE__ */ jsxs23(Box22, { marginTop: SPACING.xs, flexDirection: "column", children: [
3617
- /* @__PURE__ */ jsx25(Text25, { bold: true, children: t("profiles_formulaeCount", { count: profile.formulae.length }) }),
3713
+ /* @__PURE__ */ jsx26(Text25, { bold: true, children: t("profiles_formulaeCount", { count: profile.formulae.length }) }),
3618
3714
  /* @__PURE__ */ jsxs23(Box22, { paddingLeft: SPACING.sm, flexDirection: "column", children: [
3619
- profile.formulae.slice(0, 30).map((f) => /* @__PURE__ */ jsx25(Text25, { color: COLORS.muted, children: f }, f)),
3620
- profile.formulae.length > 30 && /* @__PURE__ */ jsx25(Text25, { color: COLORS.textSecondary, italic: true, children: t("common_andMore", { count: profile.formulae.length - 30 }) })
3715
+ profile.formulae.slice(0, 30).map((f) => /* @__PURE__ */ jsx26(Text25, { color: COLORS.muted, children: f }, f)),
3716
+ profile.formulae.length > 30 && /* @__PURE__ */ jsx26(Text25, { color: COLORS.textSecondary, italic: true, children: t("common_andMore", { count: profile.formulae.length - 30 }) })
3621
3717
  ] }),
3622
- /* @__PURE__ */ jsx25(Text25, { bold: true, children: t("profiles_casksCount", { count: profile.casks.length }) }),
3623
- /* @__PURE__ */ jsx25(Box22, { paddingLeft: SPACING.sm, flexDirection: "column", children: profile.casks.map((c) => /* @__PURE__ */ jsx25(Text25, { color: COLORS.muted, children: c }, c)) })
3718
+ /* @__PURE__ */ jsx26(Text25, { bold: true, children: t("profiles_casksCount", { count: profile.casks.length }) }),
3719
+ /* @__PURE__ */ jsx26(Box22, { paddingLeft: SPACING.sm, flexDirection: "column", children: profile.casks.map((c) => /* @__PURE__ */ jsx26(Text25, { color: COLORS.muted, children: c }, c)) })
3624
3720
  ] }),
3625
- /* @__PURE__ */ jsx25(Box22, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs23(Text25, { color: COLORS.textSecondary, children: [
3721
+ /* @__PURE__ */ jsx26(Box22, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs23(Text25, { color: COLORS.textSecondary, children: [
3626
3722
  "esc:",
3627
3723
  t("hint_back"),
3628
3724
  " e:",
@@ -3636,11 +3732,11 @@ function ProfileDetailMode({ profile }) {
3636
3732
  // src/views/profiles/profile-create-flow.tsx
3637
3733
  import { Box as Box23, Text as Text26 } from "ink";
3638
3734
  import { TextInput as TextInput3 } from "@inkjs/ui";
3639
- import { jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
3735
+ import { jsx as jsx27, jsxs as jsxs24 } from "react/jsx-runtime";
3640
3736
  function ProfileCreateName({ onSubmit }) {
3641
3737
  return /* @__PURE__ */ jsxs24(Box23, { flexDirection: "column", children: [
3642
- /* @__PURE__ */ jsx26(Text26, { bold: true, children: t("profiles_createName") }),
3643
- /* @__PURE__ */ jsx26(
3738
+ /* @__PURE__ */ jsx27(Text26, { bold: true, children: t("profiles_createName") }),
3739
+ /* @__PURE__ */ jsx27(
3644
3740
  TextInput3,
3645
3741
  {
3646
3742
  placeholder: t("profiles_namePlaceholder"),
@@ -3651,12 +3747,12 @@ function ProfileCreateName({ onSubmit }) {
3651
3747
  }
3652
3748
  function ProfileCreateDesc({ name, loadError, onSubmit }) {
3653
3749
  return /* @__PURE__ */ jsxs24(Box23, { flexDirection: "column", children: [
3654
- /* @__PURE__ */ jsx26(Text26, { bold: true, children: t("profiles_createDesc", { name }) }),
3750
+ /* @__PURE__ */ jsx27(Text26, { bold: true, children: t("profiles_createDesc", { name }) }),
3655
3751
  loadError && /* @__PURE__ */ jsxs24(Text26, { color: COLORS.error, children: [
3656
3752
  t("error_prefix"),
3657
3753
  loadError
3658
3754
  ] }),
3659
- /* @__PURE__ */ jsx26(
3755
+ /* @__PURE__ */ jsx27(
3660
3756
  TextInput3,
3661
3757
  {
3662
3758
  placeholder: t("profiles_descPlaceholder"),
@@ -3669,11 +3765,11 @@ function ProfileCreateDesc({ name, loadError, onSubmit }) {
3669
3765
  // src/views/profiles/profile-edit-flow.tsx
3670
3766
  import { Box as Box24, Text as Text27 } from "ink";
3671
3767
  import { TextInput as TextInput4 } from "@inkjs/ui";
3672
- import { jsx as jsx27, jsxs as jsxs25 } from "react/jsx-runtime";
3768
+ import { jsx as jsx28, jsxs as jsxs25 } from "react/jsx-runtime";
3673
3769
  function ProfileEditName({ defaultName, onSubmit }) {
3674
3770
  return /* @__PURE__ */ jsxs25(Box24, { flexDirection: "column", children: [
3675
- /* @__PURE__ */ jsx27(Text27, { bold: true, children: t("profiles_editName") }),
3676
- /* @__PURE__ */ jsx27(
3771
+ /* @__PURE__ */ jsx28(Text27, { bold: true, children: t("profiles_editName") }),
3772
+ /* @__PURE__ */ jsx28(
3677
3773
  TextInput4,
3678
3774
  {
3679
3775
  defaultValue: defaultName,
@@ -3684,12 +3780,12 @@ function ProfileEditName({ defaultName, onSubmit }) {
3684
3780
  }
3685
3781
  function ProfileEditDesc({ name, defaultDesc, loadError, onSubmit }) {
3686
3782
  return /* @__PURE__ */ jsxs25(Box24, { flexDirection: "column", children: [
3687
- /* @__PURE__ */ jsx27(Text27, { bold: true, children: t("profiles_editDesc", { name }) }),
3783
+ /* @__PURE__ */ jsx28(Text27, { bold: true, children: t("profiles_editDesc", { name }) }),
3688
3784
  loadError && /* @__PURE__ */ jsxs25(Text27, { color: COLORS.error, children: [
3689
3785
  t("error_prefix"),
3690
3786
  loadError
3691
3787
  ] }),
3692
- /* @__PURE__ */ jsx27(
3788
+ /* @__PURE__ */ jsx28(
3693
3789
  TextInput4,
3694
3790
  {
3695
3791
  defaultValue: defaultDesc,
@@ -3700,7 +3796,7 @@ function ProfileEditDesc({ name, defaultDesc, loadError, onSubmit }) {
3700
3796
  }
3701
3797
 
3702
3798
  // src/views/profiles.tsx
3703
- import { jsx as jsx28, jsxs as jsxs26 } from "react/jsx-runtime";
3799
+ import { jsx as jsx29, jsxs as jsxs26 } from "react/jsx-runtime";
3704
3800
  function ProfilesView() {
3705
3801
  const { profileNames, selectedProfile, loading, loadError, fetchProfiles, loadProfile: loadProfile2, exportCurrent, deleteProfile: deleteProfile2, updateProfile: updateProfile2 } = useProfileStore();
3706
3802
  const [cursor, setCursor] = useState11(0);
@@ -3714,8 +3810,8 @@ function ProfilesView() {
3714
3810
  const [importHadError, setImportHadError] = useState11(false);
3715
3811
  const [importProfile2, setImportProfile] = useState11(null);
3716
3812
  const { openModal, closeModal } = useModalStore();
3717
- const importGenRef = useRef7(null);
3718
- const mountedRef = useRef7(true);
3813
+ const importGenRef = useRef8(null);
3814
+ const mountedRef = useRef8(true);
3719
3815
  useEffect15(() => {
3720
3816
  fetchProfiles();
3721
3817
  }, []);
@@ -3809,9 +3905,9 @@ function ProfilesView() {
3809
3905
  }
3810
3906
  }
3811
3907
  };
3812
- if (loading) return /* @__PURE__ */ jsx28(Loading, { message: t("loading_profiles") });
3908
+ if (loading) return /* @__PURE__ */ jsx29(Loading, { message: t("loading_profiles") });
3813
3909
  if (mode === "confirm-import" && importProfile2) {
3814
- return /* @__PURE__ */ jsx28(Box25, { flexDirection: "column", children: /* @__PURE__ */ jsx28(
3910
+ return /* @__PURE__ */ jsx29(Box25, { flexDirection: "column", children: /* @__PURE__ */ jsx29(
3815
3911
  ConfirmDialog,
3816
3912
  {
3817
3913
  message: t("profiles_importSummary", {
@@ -3832,18 +3928,18 @@ function ProfilesView() {
3832
3928
  }
3833
3929
  if (mode === "importing") {
3834
3930
  return /* @__PURE__ */ jsxs26(Box25, { flexDirection: "column", children: [
3835
- /* @__PURE__ */ jsx28(ProgressLog, { lines: importLines, isRunning: importRunning, title: t("profiles_importTitle") }),
3836
- !importRunning && /* @__PURE__ */ jsx28(Box25, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx28(ResultBanner, { status: importHadError ? "error" : "success", message: importHadError ? t("profiles_importPartial") : `\u2714 ${t("profiles_importComplete")}` }) })
3931
+ /* @__PURE__ */ jsx29(ProgressLog, { lines: importLines, isRunning: importRunning, title: t("profiles_importTitle") }),
3932
+ !importRunning && /* @__PURE__ */ jsx29(Box25, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx29(ResultBanner, { status: importHadError ? "error" : "success", message: importHadError ? t("profiles_importPartial") : `\u2714 ${t("profiles_importComplete")}` }) })
3837
3933
  ] });
3838
3934
  }
3839
3935
  if (mode === "create-name") {
3840
- return /* @__PURE__ */ jsx28(ProfileCreateName, { onSubmit: (val) => {
3936
+ return /* @__PURE__ */ jsx29(ProfileCreateName, { onSubmit: (val) => {
3841
3937
  setNewName(val);
3842
3938
  setMode("create-desc");
3843
3939
  } });
3844
3940
  }
3845
3941
  if (mode === "create-desc") {
3846
- return /* @__PURE__ */ jsx28(
3942
+ return /* @__PURE__ */ jsx29(
3847
3943
  ProfileCreateDesc,
3848
3944
  {
3849
3945
  name: newName,
@@ -3860,13 +3956,13 @@ function ProfilesView() {
3860
3956
  );
3861
3957
  }
3862
3958
  if (mode === "edit-name") {
3863
- return /* @__PURE__ */ jsx28(ProfileEditName, { defaultName: editName, onSubmit: (val) => {
3959
+ return /* @__PURE__ */ jsx29(ProfileEditName, { defaultName: editName, onSubmit: (val) => {
3864
3960
  setEditName(val);
3865
3961
  setMode("edit-desc");
3866
3962
  } });
3867
3963
  }
3868
3964
  if (mode === "edit-desc") {
3869
- return /* @__PURE__ */ jsx28(
3965
+ return /* @__PURE__ */ jsx29(
3870
3966
  ProfileEditDesc,
3871
3967
  {
3872
3968
  name: editName,
@@ -3884,9 +3980,9 @@ function ProfilesView() {
3884
3980
  );
3885
3981
  }
3886
3982
  if (mode === "detail" && selectedProfile) {
3887
- return /* @__PURE__ */ jsx28(ProfileDetailMode, { profile: selectedProfile });
3983
+ return /* @__PURE__ */ jsx29(ProfileDetailMode, { profile: selectedProfile });
3888
3984
  }
3889
- return /* @__PURE__ */ jsx28(
3985
+ return /* @__PURE__ */ jsx29(
3890
3986
  ProfileListMode,
3891
3987
  {
3892
3988
  profileNames,
@@ -3903,7 +3999,7 @@ function ProfilesView() {
3903
3999
  }
3904
4000
 
3905
4001
  // src/views/smart-cleanup.tsx
3906
- import { useEffect as useEffect16, useRef as useRef8, useState as useState12 } from "react";
4002
+ import { useEffect as useEffect16, useRef as useRef9, useState as useState12 } from "react";
3907
4003
  import { Box as Box26, Text as Text28 } from "ink";
3908
4004
 
3909
4005
  // src/stores/cleanup-store.ts
@@ -4024,7 +4120,7 @@ var useCleanupStore = create10((set, get) => ({
4024
4120
  }));
4025
4121
 
4026
4122
  // src/views/smart-cleanup.tsx
4027
- import { jsx as jsx29, jsxs as jsxs27 } from "react/jsx-runtime";
4123
+ import { jsx as jsx30, jsxs as jsxs27 } from "react/jsx-runtime";
4028
4124
  function SmartCleanupView() {
4029
4125
  const { summary, selected, loading, error, analyze, toggleSelect, selectAll } = useCleanupStore();
4030
4126
  const [cursor, setCursor] = useState12(0);
@@ -4032,7 +4128,7 @@ function SmartCleanupView() {
4032
4128
  const [confirmForce, setConfirmForce] = useState12(false);
4033
4129
  const [failedNames, setFailedNames] = useState12([]);
4034
4130
  const stream = useBrewStream();
4035
- const hasRefreshed = useRef8(false);
4131
+ const hasRefreshed = useRef9(false);
4036
4132
  useEffect16(() => {
4037
4133
  analyze();
4038
4134
  }, []);
@@ -4075,18 +4171,18 @@ function SmartCleanupView() {
4075
4171
  if (input === "j" || key.downArrow) setCursor((c) => Math.min(c + 1, Math.max(0, candidates.length - 1)));
4076
4172
  else if (input === "k" || key.upArrow) setCursor((c) => Math.max(c - 1, 0));
4077
4173
  });
4078
- if (loading) return /* @__PURE__ */ jsx29(Loading, { message: t("loading_cleanup") });
4079
- if (error) return /* @__PURE__ */ jsx29(ErrorMessage, { message: error });
4174
+ if (loading) return /* @__PURE__ */ jsx30(Loading, { message: t("loading_cleanup") });
4175
+ if (error) return /* @__PURE__ */ jsx30(ErrorMessage, { message: error });
4080
4176
  if (stream.isRunning || stream.lines.length > 0) {
4081
4177
  return /* @__PURE__ */ jsxs27(Box26, { flexDirection: "column", children: [
4082
- /* @__PURE__ */ jsx29(ProgressLog, { lines: stream.lines, isRunning: stream.isRunning, title: t("cleanup_cleaning") }),
4178
+ /* @__PURE__ */ jsx30(ProgressLog, { lines: stream.lines, isRunning: stream.isRunning, title: t("cleanup_cleaning") }),
4083
4179
  stream.isRunning && /* @__PURE__ */ jsxs27(Text28, { color: COLORS.muted, children: [
4084
4180
  "esc:",
4085
4181
  t("hint_cancel")
4086
4182
  ] }),
4087
- !stream.isRunning && !stream.error && /* @__PURE__ */ jsx29(ResultBanner, { status: "success", message: `\u2714 ${t("cleanup_complete")}` }),
4183
+ !stream.isRunning && !stream.error && /* @__PURE__ */ jsx30(ResultBanner, { status: "success", message: `\u2714 ${t("cleanup_complete")}` }),
4088
4184
  !stream.isRunning && stream.error && /* @__PURE__ */ jsxs27(Box26, { flexDirection: "column", gap: SPACING.xs, children: [
4089
- /* @__PURE__ */ jsx29(ResultBanner, { status: "error", message: `\u2718 ${t("cleanup_depError")}` }),
4185
+ /* @__PURE__ */ jsx30(ResultBanner, { status: "error", message: `\u2718 ${t("cleanup_depError")}` }),
4090
4186
  isDependencyError && failedNames.length > 0 && /* @__PURE__ */ jsxs27(Text28, { color: COLORS.warning, children: [
4091
4187
  "F:",
4092
4188
  t("hint_force"),
@@ -4094,7 +4190,7 @@ function SmartCleanupView() {
4094
4190
  t("hint_refresh")
4095
4191
  ] })
4096
4192
  ] }),
4097
- confirmForce && /* @__PURE__ */ jsx29(Box26, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx29(
4193
+ confirmForce && /* @__PURE__ */ jsx30(Box26, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx30(
4098
4194
  ConfirmDialog,
4099
4195
  {
4100
4196
  message: t("cleanup_confirmForce", { count: failedNames.length }),
@@ -4110,15 +4206,15 @@ function SmartCleanupView() {
4110
4206
  ] });
4111
4207
  }
4112
4208
  return /* @__PURE__ */ jsxs27(Box26, { flexDirection: "column", children: [
4113
- /* @__PURE__ */ jsx29(SectionHeader, { emoji: "\u{1F9F9}", title: t("cleanup_title"), gradient: GRADIENTS.emerald }),
4209
+ /* @__PURE__ */ jsx30(SectionHeader, { emoji: "\u{1F9F9}", title: t("cleanup_title"), gradient: GRADIENTS.emerald }),
4114
4210
  summary && /* @__PURE__ */ jsxs27(Box26, { gap: SPACING.xs, marginY: SPACING.xs, children: [
4115
- /* @__PURE__ */ jsx29(StatCard, { label: t("cleanup_orphans"), value: candidates.length, color: candidates.length > 0 ? COLORS.warning : COLORS.success }),
4116
- /* @__PURE__ */ jsx29(StatCard, { label: t("cleanup_reclaimable"), value: summary.totalReclaimableFormatted, color: COLORS.sky }),
4117
- /* @__PURE__ */ jsx29(StatCard, { label: t("cleanup_selected"), value: selected.size, color: selected.size > 0 ? COLORS.success : COLORS.muted })
4211
+ /* @__PURE__ */ jsx30(StatCard, { label: t("cleanup_orphans"), value: candidates.length, color: candidates.length > 0 ? COLORS.warning : COLORS.success }),
4212
+ /* @__PURE__ */ jsx30(StatCard, { label: t("cleanup_reclaimable"), value: summary.totalReclaimableFormatted, color: COLORS.sky }),
4213
+ /* @__PURE__ */ jsx30(StatCard, { label: t("cleanup_selected"), value: selected.size, color: selected.size > 0 ? COLORS.success : COLORS.muted })
4118
4214
  ] }),
4119
4215
  confirmClean && /* @__PURE__ */ jsxs27(Box26, { flexDirection: "column", marginY: SPACING.xs, gap: SPACING.xs, children: [
4120
- /* @__PURE__ */ jsx29(Box26, { borderStyle: "round", borderColor: COLORS.warning, paddingX: SPACING.sm, paddingY: SPACING.none, children: /* @__PURE__ */ jsx29(Text28, { color: COLORS.warning, children: t("cleanup_warning_system_tools") }) }),
4121
- /* @__PURE__ */ jsx29(
4216
+ /* @__PURE__ */ jsx30(Box26, { borderStyle: "round", borderColor: COLORS.warning, paddingX: SPACING.sm, paddingY: SPACING.none, children: /* @__PURE__ */ jsx30(Text28, { color: COLORS.warning, children: t("cleanup_warning_system_tools") }) }),
4217
+ /* @__PURE__ */ jsx30(
4122
4218
  ConfirmDialog,
4123
4219
  {
4124
4220
  message: t("cleanup_confirmUninstall", { count: selected.size }),
@@ -4133,15 +4229,15 @@ function SmartCleanupView() {
4133
4229
  }
4134
4230
  )
4135
4231
  ] }),
4136
- candidates.length === 0 && !confirmClean && /* @__PURE__ */ jsx29(ResultBanner, { status: "success", message: `\u2714 ${t("cleanup_systemClean")}` }),
4232
+ candidates.length === 0 && !confirmClean && /* @__PURE__ */ jsx30(ResultBanner, { status: "success", message: `\u2714 ${t("cleanup_systemClean")}` }),
4137
4233
  candidates.length > 0 && !confirmClean && /* @__PURE__ */ jsxs27(Box26, { flexDirection: "column", children: [
4138
4234
  candidates.map((c, i) => {
4139
4235
  const isCurrent = i === cursor;
4140
4236
  const isSelected = selected.has(c.name);
4141
4237
  return /* @__PURE__ */ jsxs27(SelectableRow, { isCurrent, children: [
4142
- /* @__PURE__ */ jsx29(Text28, { color: isSelected ? COLORS.success : COLORS.muted, children: isSelected ? "\u2611" : "\u2610" }),
4143
- /* @__PURE__ */ jsx29(Text28, { bold: isCurrent, inverse: isCurrent, color: isCurrent ? COLORS.text : COLORS.muted, children: c.name }),
4144
- /* @__PURE__ */ jsx29(Text28, { color: COLORS.warning, children: c.diskUsageFormatted }),
4238
+ /* @__PURE__ */ jsx30(Text28, { color: isSelected ? COLORS.success : COLORS.muted, children: isSelected ? "\u2611" : "\u2610" }),
4239
+ /* @__PURE__ */ jsx30(Text28, { bold: isCurrent, inverse: isCurrent, color: isCurrent ? COLORS.text : COLORS.muted, children: c.name }),
4240
+ /* @__PURE__ */ jsx30(Text28, { color: COLORS.warning, children: c.diskUsageFormatted }),
4145
4241
  /* @__PURE__ */ jsxs27(Text28, { color: COLORS.textSecondary, children: [
4146
4242
  "[",
4147
4243
  c.reason,
@@ -4149,7 +4245,7 @@ function SmartCleanupView() {
4149
4245
  ] })
4150
4246
  ] }, c.name);
4151
4247
  }),
4152
- /* @__PURE__ */ jsx29(Box26, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs27(Text28, { color: COLORS.text, bold: true, children: [
4248
+ /* @__PURE__ */ jsx30(Box26, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs27(Text28, { color: COLORS.text, bold: true, children: [
4153
4249
  cursor + 1,
4154
4250
  "/",
4155
4251
  candidates.length
@@ -4160,7 +4256,7 @@ function SmartCleanupView() {
4160
4256
 
4161
4257
  // src/views/history.tsx
4162
4258
  import { useEffect as useEffect17, useState as useState13, useMemo as useMemo5 } from "react";
4163
- import { Box as Box27, Text as Text29, useStdout as useStdout6 } from "ink";
4259
+ import { Box as Box27, Text as Text29 } from "ink";
4164
4260
 
4165
4261
  // src/stores/history-store.ts
4166
4262
  import { create as create11 } from "zustand";
@@ -4196,7 +4292,7 @@ var useHistoryStore = create11((set) => ({
4196
4292
  }));
4197
4293
 
4198
4294
  // src/views/history.tsx
4199
- import { jsx as jsx30, jsxs as jsxs28 } from "react/jsx-runtime";
4295
+ import { jsx as jsx31, jsxs as jsxs28 } from "react/jsx-runtime";
4200
4296
  var ACTION_ICONS = {
4201
4297
  install: { icon: "+", color: COLORS.success },
4202
4298
  uninstall: { icon: "-", color: COLORS.error },
@@ -4221,8 +4317,16 @@ function HistoryView() {
4221
4317
  const stream = useBrewStream();
4222
4318
  const debouncedQuery = useDebounce(searchQuery, 200);
4223
4319
  const { openModal, closeModal } = useModalStore();
4224
- const { stdout } = useStdout6();
4225
- const MAX_VISIBLE_ROWS = Math.max(5, (stdout?.rows ?? 24) - 8);
4320
+ const MAX_VISIBLE_ROWS = useVisibleRows({
4321
+ reservedRows: isSearching || stream.lines.length > 0 || stream.isRunning ? 8 : 5,
4322
+ fallbackReservedRows: isSearching || stream.lines.length > 0 || stream.isRunning ? 16 : 13,
4323
+ minRows: 1
4324
+ });
4325
+ const streamRows = useVisibleRows({
4326
+ reservedRows: 7,
4327
+ fallbackReservedRows: 16,
4328
+ minRows: 1
4329
+ });
4226
4330
  useEffect17(() => {
4227
4331
  fetchHistory();
4228
4332
  }, []);
@@ -4276,17 +4380,17 @@ function HistoryView() {
4276
4380
  if (input === "j" || key.downArrow) setCursor((c) => Math.min(c + 1, Math.max(0, filtered.length - 1)));
4277
4381
  else if (input === "k" || key.upArrow) setCursor((c) => Math.max(c - 1, 0));
4278
4382
  });
4279
- if (loading) return /* @__PURE__ */ jsx30(Loading, { message: t("loading_history") });
4280
- if (error) return /* @__PURE__ */ jsx30(ErrorMessage, { message: error });
4383
+ if (loading) return /* @__PURE__ */ jsx31(Loading, { message: t("loading_history") });
4384
+ if (error) return /* @__PURE__ */ jsx31(ErrorMessage, { message: error });
4281
4385
  const start = Math.max(0, cursor - Math.floor(MAX_VISIBLE_ROWS / 2));
4282
4386
  const visible = filtered.slice(start, start + MAX_VISIBLE_ROWS);
4283
4387
  return /* @__PURE__ */ jsxs28(Box27, { flexDirection: "column", children: [
4284
4388
  /* @__PURE__ */ jsxs28(Box27, { gap: SPACING.sm, marginBottom: SPACING.xs, children: [
4285
- /* @__PURE__ */ jsx30(SectionHeader, { emoji: "\u{1F4DC}", title: t("history_title", { count: filtered.length }), gradient: GRADIENTS.gold }),
4286
- /* @__PURE__ */ jsx30(Text29, { color: filter === "all" ? COLORS.text : COLORS.gold, children: t("history_filterLabel", { filter }) })
4389
+ /* @__PURE__ */ jsx31(SectionHeader, { emoji: "\u{1F4DC}", title: t("history_title", { count: filtered.length }), gradient: GRADIENTS.gold }),
4390
+ /* @__PURE__ */ jsx31(Text29, { color: filter === "all" ? COLORS.text : COLORS.gold, children: t("history_filterLabel", { filter }) })
4287
4391
  ] }),
4288
- isSearching && /* @__PURE__ */ jsx30(Box27, { marginBottom: SPACING.xs, children: /* @__PURE__ */ jsx30(SearchInput, { defaultValue: searchQuery, onChange: setSearchQuery, placeholder: t("history_searchPlaceholder"), isActive: true }) }),
4289
- confirmClear && /* @__PURE__ */ jsx30(
4392
+ isSearching && /* @__PURE__ */ jsx31(Box27, { marginBottom: SPACING.xs, children: /* @__PURE__ */ jsx31(SearchInput, { defaultValue: searchQuery, onChange: setSearchQuery, placeholder: t("history_searchPlaceholder"), isActive: true }) }),
4393
+ confirmClear && /* @__PURE__ */ jsx31(
4290
4394
  ConfirmDialog,
4291
4395
  {
4292
4396
  message: t("history_confirmClear", { count: entries.length }),
@@ -4297,7 +4401,7 @@ function HistoryView() {
4297
4401
  onCancel: () => setConfirmClear(false)
4298
4402
  }
4299
4403
  ),
4300
- confirmReplay && /* @__PURE__ */ jsx30(
4404
+ confirmReplay && /* @__PURE__ */ jsx31(
4301
4405
  ConfirmDialog,
4302
4406
  {
4303
4407
  message: confirmReplay.action === "upgrade-all" ? t("history_replayAll") + "\n" + t("upgrade_all_warning") : t("history_confirmReplay", { action: t(ACTION_LABEL_KEYS[confirmReplay.action]), name: confirmReplay.packageName ?? "" }),
@@ -4325,8 +4429,16 @@ function HistoryView() {
4325
4429
  onCancel: () => setConfirmReplay(null)
4326
4430
  }
4327
4431
  ),
4328
- (stream.isRunning || stream.lines.length > 0) && /* @__PURE__ */ jsx30(Box27, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx30(ProgressLog, { lines: stream.lines, isRunning: stream.isRunning, title: t("hint_replay") }) }),
4329
- filtered.length === 0 && !confirmClear && /* @__PURE__ */ jsx30(Text29, { color: COLORS.textSecondary, italic: true, children: filter !== "all" ? t("history_noEntriesFor", { filter }) : t("history_noEntries") }),
4432
+ (stream.isRunning || stream.lines.length > 0) && /* @__PURE__ */ jsx31(Box27, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx31(
4433
+ ProgressLog,
4434
+ {
4435
+ lines: stream.lines,
4436
+ isRunning: stream.isRunning,
4437
+ title: t("hint_replay"),
4438
+ maxVisible: streamRows
4439
+ }
4440
+ ) }),
4441
+ filtered.length === 0 && !confirmClear && /* @__PURE__ */ jsx31(Text29, { color: COLORS.textSecondary, italic: true, children: filter !== "all" ? t("history_noEntriesFor", { filter }) : t("history_noEntries") }),
4330
4442
  filtered.length > 0 && !confirmClear && /* @__PURE__ */ jsxs28(Box27, { flexDirection: "column", children: [
4331
4443
  start > 0 && /* @__PURE__ */ jsxs28(Text29, { color: COLORS.textSecondary, dimColor: true, children: [
4332
4444
  " ",
@@ -4338,18 +4450,18 @@ function HistoryView() {
4338
4450
  const { icon, color } = ACTION_ICONS[entry.action];
4339
4451
  const ts = new Date(entry.timestamp).getTime() / 1e3;
4340
4452
  return /* @__PURE__ */ jsxs28(SelectableRow, { isCurrent, children: [
4341
- /* @__PURE__ */ jsx30(Text29, { color, bold: true, children: icon }),
4342
- /* @__PURE__ */ jsx30(Text29, { bold: isCurrent, inverse: isCurrent, color: isCurrent ? COLORS.text : COLORS.muted, children: t(ACTION_LABEL_KEYS[entry.action]).padEnd(12) }),
4343
- /* @__PURE__ */ jsx30(Text29, { color: COLORS.text, children: entry.packageName ?? t("history_all") }),
4344
- entry.success ? /* @__PURE__ */ jsx30(StatusBadge, { label: t("badge_ok"), variant: "success" }) : /* @__PURE__ */ jsx30(StatusBadge, { label: t("badge_fail"), variant: "error" }),
4345
- /* @__PURE__ */ jsx30(Text29, { color: COLORS.muted, children: formatRelativeTime(ts) })
4453
+ /* @__PURE__ */ jsx31(Text29, { color, bold: true, children: icon }),
4454
+ /* @__PURE__ */ jsx31(Text29, { bold: isCurrent, inverse: isCurrent, color: isCurrent ? COLORS.text : COLORS.muted, children: t(ACTION_LABEL_KEYS[entry.action]).padEnd(12) }),
4455
+ /* @__PURE__ */ jsx31(Text29, { color: COLORS.text, children: entry.packageName ?? t("history_all") }),
4456
+ entry.success ? /* @__PURE__ */ jsx31(StatusBadge, { label: t("badge_ok"), variant: "success" }) : /* @__PURE__ */ jsx31(StatusBadge, { label: t("badge_fail"), variant: "error" }),
4457
+ /* @__PURE__ */ jsx31(Text29, { color: COLORS.muted, children: formatRelativeTime(ts) })
4346
4458
  ] }, entry.id);
4347
4459
  }),
4348
4460
  start + MAX_VISIBLE_ROWS < filtered.length && /* @__PURE__ */ jsxs28(Text29, { color: COLORS.textSecondary, dimColor: true, children: [
4349
4461
  " ",
4350
4462
  t("scroll_moreBelow", { count: filtered.length - start - MAX_VISIBLE_ROWS })
4351
4463
  ] }),
4352
- /* @__PURE__ */ jsx30(Box27, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs28(Text29, { color: COLORS.text, bold: true, children: [
4464
+ /* @__PURE__ */ jsx31(Box27, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs28(Text29, { color: COLORS.text, bold: true, children: [
4353
4465
  cursor + 1,
4354
4466
  "/",
4355
4467
  filtered.length
@@ -4361,7 +4473,7 @@ function HistoryView() {
4361
4473
  // src/views/security-audit.tsx
4362
4474
  import { useEffect as useEffect18, useState as useState14 } from "react";
4363
4475
  import { Box as Box28, Text as Text30 } from "ink";
4364
- import { jsx as jsx31, jsxs as jsxs29 } from "react/jsx-runtime";
4476
+ import { jsx as jsx32, jsxs as jsxs29 } from "react/jsx-runtime";
4365
4477
  var SEVERITY_COLORS = {
4366
4478
  CRITICAL: COLORS.error,
4367
4479
  HIGH: COLORS.error,
@@ -4410,17 +4522,17 @@ function SecurityAuditView() {
4410
4522
  setExpandedPkg(expandedPkg === results[cursor].packageName ? null : results[cursor].packageName);
4411
4523
  }
4412
4524
  });
4413
- if (loading) return /* @__PURE__ */ jsx31(Loading, { message: t("loading_security") });
4525
+ if (loading) return /* @__PURE__ */ jsx32(Loading, { message: t("loading_security") });
4414
4526
  if (error) {
4415
4527
  const displayError = isNetworkError(error) ? t("security_networkError") : error;
4416
- return /* @__PURE__ */ jsx31(ErrorMessage, { message: displayError });
4528
+ return /* @__PURE__ */ jsx32(ErrorMessage, { message: displayError });
4417
4529
  }
4418
4530
  const cacheAge = cachedAt ? formatRelativeTime(cachedAt / 1e3) : null;
4419
4531
  return /* @__PURE__ */ jsxs29(Box28, { flexDirection: "column", children: [
4420
- /* @__PURE__ */ jsx31(SectionHeader, { emoji: "\u{1F6E1}\uFE0F", title: t("security_title"), gradient: GRADIENTS.ocean }),
4532
+ /* @__PURE__ */ jsx32(SectionHeader, { emoji: "\u{1F6E1}\uFE0F", title: t("security_title"), gradient: GRADIENTS.ocean }),
4421
4533
  summary && /* @__PURE__ */ jsxs29(Box28, { gap: SPACING.xs, marginY: SPACING.xs, children: [
4422
- /* @__PURE__ */ jsx31(StatCard, { label: t("security_scanned"), value: summary.totalPackages, color: COLORS.info }),
4423
- /* @__PURE__ */ jsx31(
4534
+ /* @__PURE__ */ jsx32(StatCard, { label: t("security_scanned"), value: summary.totalPackages, color: COLORS.info }),
4535
+ /* @__PURE__ */ jsx32(
4424
4536
  StatCard,
4425
4537
  {
4426
4538
  label: t("security_vulnerable"),
@@ -4428,14 +4540,14 @@ function SecurityAuditView() {
4428
4540
  color: summary.vulnerablePackages > 0 ? COLORS.error : COLORS.success
4429
4541
  }
4430
4542
  ),
4431
- summary.criticalCount > 0 && /* @__PURE__ */ jsx31(StatCard, { label: t("security_critical"), value: summary.criticalCount, color: COLORS.error }),
4432
- summary.highCount > 0 && /* @__PURE__ */ jsx31(StatCard, { label: t("security_high"), value: summary.highCount, color: COLORS.error }),
4433
- summary.mediumCount > 0 && /* @__PURE__ */ jsx31(StatCard, { label: t("security_medium"), value: summary.mediumCount, color: COLORS.warning })
4543
+ summary.criticalCount > 0 && /* @__PURE__ */ jsx32(StatCard, { label: t("security_critical"), value: summary.criticalCount, color: COLORS.error }),
4544
+ summary.highCount > 0 && /* @__PURE__ */ jsx32(StatCard, { label: t("security_high"), value: summary.highCount, color: COLORS.error }),
4545
+ summary.mediumCount > 0 && /* @__PURE__ */ jsx32(StatCard, { label: t("security_medium"), value: summary.mediumCount, color: COLORS.warning })
4434
4546
  ] }),
4435
- cacheAge && /* @__PURE__ */ jsx31(Text30, { color: COLORS.muted, children: t("security_cachedResults", { time: cacheAge }) }),
4436
- summary && /* @__PURE__ */ jsx31(Box28, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx31(Text30, { color: COLORS.textSecondary, italic: true, children: t("security_coverage_warning") }) }),
4437
- results.length === 0 && summary && /* @__PURE__ */ jsx31(Box28, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx31(ResultBanner, { status: "success", message: `\u2714 ${t("security_noVulns")}` }) }),
4438
- confirmUpgrade && /* @__PURE__ */ jsx31(Box28, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx31(
4547
+ cacheAge && /* @__PURE__ */ jsx32(Text30, { color: COLORS.muted, children: t("security_cachedResults", { time: cacheAge }) }),
4548
+ summary && /* @__PURE__ */ jsx32(Box28, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx32(Text30, { color: COLORS.textSecondary, italic: true, children: t("security_coverage_warning") }) }),
4549
+ results.length === 0 && summary && /* @__PURE__ */ jsx32(Box28, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx32(ResultBanner, { status: "success", message: `\u2714 ${t("security_noVulns")}` }) }),
4550
+ confirmUpgrade && /* @__PURE__ */ jsx32(Box28, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx32(
4439
4551
  ConfirmDialog,
4440
4552
  {
4441
4553
  message: t("security_confirmUpgrade", { name: confirmUpgrade }),
@@ -4448,44 +4560,44 @@ function SecurityAuditView() {
4448
4560
  onCancel: () => setConfirmUpgrade(null)
4449
4561
  }
4450
4562
  ) }),
4451
- (stream.isRunning || stream.lines.length > 0) && /* @__PURE__ */ jsx31(Box28, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx31(ProgressLog, { lines: stream.lines, isRunning: stream.isRunning, title: t("hint_upgrade") }) }),
4563
+ (stream.isRunning || stream.lines.length > 0) && /* @__PURE__ */ jsx32(Box28, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx32(ProgressLog, { lines: stream.lines, isRunning: stream.isRunning, title: t("hint_upgrade") }) }),
4452
4564
  results.length > 0 && /* @__PURE__ */ jsxs29(Box28, { flexDirection: "column", marginTop: SPACING.xs, children: [
4453
4565
  results.map((pkg, i) => {
4454
4566
  const isCurrent = i === cursor;
4455
4567
  const isExpanded = expandedPkg === pkg.packageName;
4456
4568
  return /* @__PURE__ */ jsxs29(Box28, { flexDirection: "column", children: [
4457
4569
  /* @__PURE__ */ jsxs29(SelectableRow, { isCurrent, children: [
4458
- /* @__PURE__ */ jsx31(StatusBadge, { label: pkg.maxSeverity, variant: SEVERITY_BADGE[pkg.maxSeverity] }),
4459
- /* @__PURE__ */ jsx31(Text30, { bold: isCurrent, inverse: isCurrent, color: isCurrent ? COLORS.text : COLORS.muted, children: pkg.packageName }),
4460
- /* @__PURE__ */ jsx31(Text30, { color: COLORS.muted, children: pkg.installedVersion }),
4461
- /* @__PURE__ */ jsx31(Text30, { color: COLORS.muted, children: tp("plural_vulns", pkg.vulnerabilities.length) }),
4570
+ /* @__PURE__ */ jsx32(StatusBadge, { label: pkg.maxSeverity, variant: SEVERITY_BADGE[pkg.maxSeverity] }),
4571
+ /* @__PURE__ */ jsx32(Text30, { bold: isCurrent, inverse: isCurrent, color: isCurrent ? COLORS.text : COLORS.muted, children: pkg.packageName }),
4572
+ /* @__PURE__ */ jsx32(Text30, { color: COLORS.muted, children: pkg.installedVersion }),
4573
+ /* @__PURE__ */ jsx32(Text30, { color: COLORS.muted, children: tp("plural_vulns", pkg.vulnerabilities.length) }),
4462
4574
  pkg.vulnerabilities.some((v) => v.fixedVersion) && /* @__PURE__ */ jsxs29(Text30, { color: COLORS.textSecondary, children: [
4463
4575
  "[R:",
4464
4576
  t("hint_rollback"),
4465
4577
  "]"
4466
4578
  ] }),
4467
- /* @__PURE__ */ jsx31(Text30, { color: COLORS.muted, children: isExpanded ? "\u25BC" : "\u25B6" })
4579
+ /* @__PURE__ */ jsx32(Text30, { color: COLORS.muted, children: isExpanded ? "\u25BC" : "\u25B6" })
4468
4580
  ] }),
4469
- isExpanded && /* @__PURE__ */ jsx31(Box28, { flexDirection: "column", paddingLeft: SPACING.lg, marginBottom: SPACING.xs, children: pkg.vulnerabilities.map((vuln) => /* @__PURE__ */ jsxs29(Box28, { flexDirection: "column", marginBottom: SPACING.xs, children: [
4581
+ isExpanded && /* @__PURE__ */ jsx32(Box28, { flexDirection: "column", paddingLeft: SPACING.lg, marginBottom: SPACING.xs, children: pkg.vulnerabilities.map((vuln) => /* @__PURE__ */ jsxs29(Box28, { flexDirection: "column", marginBottom: SPACING.xs, children: [
4470
4582
  /* @__PURE__ */ jsxs29(Box28, { gap: SPACING.xs, children: [
4471
- /* @__PURE__ */ jsx31(Text30, { color: SEVERITY_COLORS[vuln.severity], bold: true, children: vuln.id }),
4583
+ /* @__PURE__ */ jsx32(Text30, { color: SEVERITY_COLORS[vuln.severity], bold: true, children: vuln.id }),
4472
4584
  /* @__PURE__ */ jsxs29(Text30, { color: COLORS.muted, children: [
4473
4585
  "[",
4474
4586
  vuln.severity,
4475
4587
  "]"
4476
4588
  ] })
4477
4589
  ] }),
4478
- /* @__PURE__ */ jsx31(Text30, { color: COLORS.muted, wrap: "wrap", children: vuln.summary }),
4479
- vuln.fixedVersion && /* @__PURE__ */ jsx31(Text30, { color: COLORS.success, children: t("security_fixedIn", { version: vuln.fixedVersion }) })
4590
+ /* @__PURE__ */ jsx32(Text30, { color: COLORS.muted, wrap: "wrap", children: vuln.summary }),
4591
+ vuln.fixedVersion && /* @__PURE__ */ jsx32(Text30, { color: COLORS.success, children: t("security_fixedIn", { version: vuln.fixedVersion }) })
4480
4592
  ] }, vuln.id)) })
4481
4593
  ] }, pkg.packageName);
4482
4594
  }),
4483
- /* @__PURE__ */ jsx31(Box28, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs29(Text30, { color: COLORS.text, bold: true, children: [
4595
+ /* @__PURE__ */ jsx32(Box28, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs29(Text30, { color: COLORS.text, bold: true, children: [
4484
4596
  cursor + 1,
4485
4597
  "/",
4486
4598
  results.length
4487
4599
  ] }) }),
4488
- /* @__PURE__ */ jsx31(Box28, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx31(Text30, { color: COLORS.textSecondary, children: t("security_rollback_hint") }) })
4600
+ /* @__PURE__ */ jsx32(Box28, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx32(Text30, { color: COLORS.textSecondary, children: t("security_rollback_hint") }) })
4489
4601
  ] })
4490
4602
  ] });
4491
4603
  }
@@ -4570,7 +4682,7 @@ async function redeemPromoCode(code) {
4570
4682
  }
4571
4683
 
4572
4684
  // src/views/account.tsx
4573
- import { Fragment as Fragment5, jsx as jsx32, jsxs as jsxs30 } from "react/jsx-runtime";
4685
+ import { Fragment as Fragment5, jsx as jsx33, jsxs as jsxs30 } from "react/jsx-runtime";
4574
4686
  function AccountView() {
4575
4687
  const { status, license, deactivate: deactivate2, revalidate: revalidate2, degradation } = useLicenseStore();
4576
4688
  const [confirmDeactivate, setConfirmDeactivate] = useState15(false);
@@ -4605,11 +4717,11 @@ function AccountView() {
4605
4717
  return key.slice(0, 4) + "-****-****-" + key.slice(-4);
4606
4718
  };
4607
4719
  if (status === "validating") {
4608
- return /* @__PURE__ */ jsx32(Loading, { message: t("account_loading") });
4720
+ return /* @__PURE__ */ jsx33(Loading, { message: t("account_loading") });
4609
4721
  }
4610
4722
  return /* @__PURE__ */ jsxs30(Box29, { flexDirection: "column", children: [
4611
- /* @__PURE__ */ jsx32(SectionHeader, { emoji: "\u{1F464}", title: t("account_title"), gradient: GRADIENTS.gold }),
4612
- confirmDeactivate && /* @__PURE__ */ jsx32(Box29, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx32(
4723
+ /* @__PURE__ */ jsx33(SectionHeader, { emoji: "\u{1F464}", title: t("account_title"), gradient: GRADIENTS.gold }),
4724
+ confirmDeactivate && /* @__PURE__ */ jsx33(Box29, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx33(
4613
4725
  ConfirmDialog,
4614
4726
  {
4615
4727
  message: t("account_confirmDeactivate"),
@@ -4630,38 +4742,38 @@ function AccountView() {
4630
4742
  ) }),
4631
4743
  /* @__PURE__ */ jsxs30(Box29, { flexDirection: "column", marginTop: SPACING.xs, paddingLeft: SPACING.sm, children: [
4632
4744
  /* @__PURE__ */ jsxs30(Box29, { gap: SPACING.xs, children: [
4633
- /* @__PURE__ */ jsx32(Text31, { color: COLORS.muted, children: t("account_statusLabel") }),
4634
- status === "pro" && /* @__PURE__ */ jsx32(Text31, { color: COLORS.success, bold: true, children: t("account_pro") }),
4635
- status === "free" && /* @__PURE__ */ jsx32(Text31, { color: COLORS.muted, children: t("account_free") }),
4636
- status === "expired" && /* @__PURE__ */ jsx32(Text31, { color: COLORS.error, children: t("account_expired") })
4745
+ /* @__PURE__ */ jsx33(Text31, { color: COLORS.muted, children: t("account_statusLabel") }),
4746
+ status === "pro" && /* @__PURE__ */ jsx33(Text31, { color: COLORS.success, bold: true, children: t("account_pro") }),
4747
+ status === "free" && /* @__PURE__ */ jsx33(Text31, { color: COLORS.muted, children: t("account_free") }),
4748
+ status === "expired" && /* @__PURE__ */ jsx33(Text31, { color: COLORS.error, children: t("account_expired") })
4637
4749
  ] }),
4638
- (degradation === "warning" || degradation === "limited") && license && /* @__PURE__ */ jsx32(Box29, { marginTop: SPACING.xs, borderStyle: "round", borderColor: COLORS.warning, paddingX: SPACING.sm, paddingY: SPACING.none, children: /* @__PURE__ */ jsx32(Text31, { color: COLORS.warning, children: t("license_offlineWarning", {
4750
+ (degradation === "warning" || degradation === "limited") && license && /* @__PURE__ */ jsx33(Box29, { marginTop: SPACING.xs, borderStyle: "round", borderColor: COLORS.warning, paddingX: SPACING.sm, paddingY: SPACING.none, children: /* @__PURE__ */ jsx33(Text31, { color: COLORS.warning, children: t("license_offlineWarning", {
4639
4751
  days: Math.floor((Date.now() - new Date(license.lastValidatedAt).getTime()) / (24 * 60 * 60 * 1e3))
4640
4752
  }) }) }),
4641
4753
  license && /* @__PURE__ */ jsxs30(Fragment5, { children: [
4642
4754
  /* @__PURE__ */ jsxs30(Box29, { gap: SPACING.xs, children: [
4643
- /* @__PURE__ */ jsx32(Text31, { color: COLORS.muted, children: t("account_emailLabel") }),
4644
- /* @__PURE__ */ jsx32(Text31, { children: license.customerEmail })
4755
+ /* @__PURE__ */ jsx33(Text31, { color: COLORS.muted, children: t("account_emailLabel") }),
4756
+ /* @__PURE__ */ jsx33(Text31, { children: license.customerEmail })
4645
4757
  ] }),
4646
4758
  /* @__PURE__ */ jsxs30(Box29, { gap: SPACING.xs, children: [
4647
- /* @__PURE__ */ jsx32(Text31, { color: COLORS.muted, children: t("account_nameLabel") }),
4648
- /* @__PURE__ */ jsx32(Text31, { children: license.customerName })
4759
+ /* @__PURE__ */ jsx33(Text31, { color: COLORS.muted, children: t("account_nameLabel") }),
4760
+ /* @__PURE__ */ jsx33(Text31, { children: license.customerName })
4649
4761
  ] }),
4650
4762
  /* @__PURE__ */ jsxs30(Box29, { gap: SPACING.xs, children: [
4651
- /* @__PURE__ */ jsx32(Text31, { color: COLORS.muted, children: t("account_planLabel") }),
4652
- /* @__PURE__ */ jsx32(Text31, { color: COLORS.success, bold: true, children: "Pro" })
4763
+ /* @__PURE__ */ jsx33(Text31, { color: COLORS.muted, children: t("account_planLabel") }),
4764
+ /* @__PURE__ */ jsx33(Text31, { color: COLORS.success, bold: true, children: "Pro" })
4653
4765
  ] }),
4654
4766
  /* @__PURE__ */ jsxs30(Box29, { gap: SPACING.xs, children: [
4655
- /* @__PURE__ */ jsx32(Text31, { color: COLORS.muted, children: t("account_keyLabel") }),
4656
- /* @__PURE__ */ jsx32(Text31, { children: maskKey(license.key) })
4767
+ /* @__PURE__ */ jsx33(Text31, { color: COLORS.muted, children: t("account_keyLabel") }),
4768
+ /* @__PURE__ */ jsx33(Text31, { children: maskKey(license.key) })
4657
4769
  ] }),
4658
4770
  license.expiresAt && /* @__PURE__ */ jsxs30(Box29, { gap: SPACING.xs, children: [
4659
- /* @__PURE__ */ jsx32(Text31, { color: COLORS.muted, children: t("account_expiresLabel") }),
4660
- /* @__PURE__ */ jsx32(Text31, { children: formatDate(license.expiresAt) })
4771
+ /* @__PURE__ */ jsx33(Text31, { color: COLORS.muted, children: t("account_expiresLabel") }),
4772
+ /* @__PURE__ */ jsx33(Text31, { children: formatDate(license.expiresAt) })
4661
4773
  ] }),
4662
4774
  /* @__PURE__ */ jsxs30(Box29, { gap: SPACING.xs, children: [
4663
- /* @__PURE__ */ jsx32(Text31, { color: COLORS.muted, children: t("account_activatedLabel") }),
4664
- /* @__PURE__ */ jsx32(Text31, { children: formatDate(license.activatedAt) })
4775
+ /* @__PURE__ */ jsx33(Text31, { color: COLORS.muted, children: t("account_activatedLabel") }),
4776
+ /* @__PURE__ */ jsx33(Text31, { children: formatDate(license.activatedAt) })
4665
4777
  ] })
4666
4778
  ] }),
4667
4779
  status === "free" && /* @__PURE__ */ jsxs30(Box29, { flexDirection: "column", marginTop: SPACING.sm, borderStyle: "round", borderColor: COLORS.brand, paddingX: SPACING.sm, paddingY: SPACING.xs, children: [
@@ -4670,30 +4782,30 @@ function AccountView() {
4670
4782
  " ",
4671
4783
  t("account_upgradeTitle")
4672
4784
  ] }),
4673
- /* @__PURE__ */ jsx32(Text31, { children: " " }),
4674
- /* @__PURE__ */ jsx32(Text31, { children: t("account_unlockDesc") }),
4675
- /* @__PURE__ */ jsx32(Text31, { color: COLORS.info, bold: true, children: t("account_pricing") }),
4676
- /* @__PURE__ */ jsx32(Text31, { children: " " }),
4785
+ /* @__PURE__ */ jsx33(Text31, { children: " " }),
4786
+ /* @__PURE__ */ jsx33(Text31, { children: t("account_unlockDesc") }),
4787
+ /* @__PURE__ */ jsx33(Text31, { color: COLORS.info, bold: true, children: t("account_pricing") }),
4788
+ /* @__PURE__ */ jsx33(Text31, { children: " " }),
4677
4789
  /* @__PURE__ */ jsxs30(Text31, { color: COLORS.muted, children: [
4678
4790
  t("upgrade_buyAt"),
4679
4791
  " ",
4680
- /* @__PURE__ */ jsx32(Text31, { color: COLORS.sky, bold: true, children: t("upgrade_buyUrl") })
4792
+ /* @__PURE__ */ jsx33(Text31, { color: COLORS.sky, bold: true, children: t("upgrade_buyUrl") })
4681
4793
  ] }),
4682
4794
  /* @__PURE__ */ jsxs30(Text31, { color: COLORS.muted, children: [
4683
4795
  t("account_runActivate"),
4684
4796
  " ",
4685
- /* @__PURE__ */ jsx32(Text31, { color: COLORS.success, bold: true, children: t("account_activateCmd") })
4797
+ /* @__PURE__ */ jsx33(Text31, { color: COLORS.success, bold: true, children: t("account_activateCmd") })
4686
4798
  ] })
4687
4799
  ] }),
4688
- status === "expired" && /* @__PURE__ */ jsx32(Box29, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx32(Box29, { borderStyle: "round", borderColor: COLORS.error, paddingX: SPACING.sm, paddingY: SPACING.none, children: /* @__PURE__ */ jsx32(Text31, { color: COLORS.error, children: t("account_licenseExpired") }) }) }),
4689
- deactivating && /* @__PURE__ */ jsx32(Text31, { color: COLORS.sky, children: t("account_deactivating") }),
4690
- deactivateError && /* @__PURE__ */ jsx32(Text31, { color: COLORS.error, children: deactivateError })
4800
+ status === "expired" && /* @__PURE__ */ jsx33(Box29, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx33(Box29, { borderStyle: "round", borderColor: COLORS.error, paddingX: SPACING.sm, paddingY: SPACING.none, children: /* @__PURE__ */ jsx33(Text31, { color: COLORS.error, children: t("account_licenseExpired") }) }) }),
4801
+ deactivating && /* @__PURE__ */ jsx33(Text31, { color: COLORS.sky, children: t("account_deactivating") }),
4802
+ deactivateError && /* @__PURE__ */ jsx33(Text31, { color: COLORS.error, children: deactivateError })
4691
4803
  ] }),
4692
- /* @__PURE__ */ jsx32(Box29, { flexDirection: "column", marginTop: SPACING.xs, paddingLeft: SPACING.sm, children: promoMode ? /* @__PURE__ */ jsxs30(Box29, { flexDirection: "column", gap: SPACING.xs, children: [
4693
- /* @__PURE__ */ jsx32(Text31, { bold: true, color: COLORS.gold, children: t("account_promoTitle") }),
4694
- promoLoading ? /* @__PURE__ */ jsx32(Text31, { color: COLORS.sky, children: t("account_promoValidating") }) : /* @__PURE__ */ jsxs30(Box29, { gap: SPACING.xs, children: [
4695
- /* @__PURE__ */ jsx32(Text31, { color: COLORS.muted, children: t("account_promoLabel") }),
4696
- /* @__PURE__ */ jsx32(
4804
+ /* @__PURE__ */ jsx33(Box29, { flexDirection: "column", marginTop: SPACING.xs, paddingLeft: SPACING.sm, children: promoMode ? /* @__PURE__ */ jsxs30(Box29, { flexDirection: "column", gap: SPACING.xs, children: [
4805
+ /* @__PURE__ */ jsx33(Text31, { bold: true, color: COLORS.gold, children: t("account_promoTitle") }),
4806
+ promoLoading ? /* @__PURE__ */ jsx33(Text31, { color: COLORS.sky, children: t("account_promoValidating") }) : /* @__PURE__ */ jsxs30(Box29, { gap: SPACING.xs, children: [
4807
+ /* @__PURE__ */ jsx33(Text31, { color: COLORS.muted, children: t("account_promoLabel") }),
4808
+ /* @__PURE__ */ jsx33(
4697
4809
  TextInput5,
4698
4810
  {
4699
4811
  defaultValue: "",
@@ -4717,21 +4829,21 @@ function AccountView() {
4717
4829
  }
4718
4830
  )
4719
4831
  ] }),
4720
- promoResult && /* @__PURE__ */ jsx32(ResultBanner, { status: promoResult.success ? "success" : "error", message: promoResult.message }),
4721
- /* @__PURE__ */ jsx32(Text31, { color: COLORS.textSecondary, dimColor: true, children: t("account_promoEsc") })
4722
- ] }) : /* @__PURE__ */ jsx32(Text31, { color: COLORS.textSecondary, children: t("account_promoHint") }) }),
4723
- /* @__PURE__ */ jsx32(Box29, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs30(Text31, { color: COLORS.textSecondary, children: [
4832
+ promoResult && /* @__PURE__ */ jsx33(ResultBanner, { status: promoResult.success ? "success" : "error", message: promoResult.message }),
4833
+ /* @__PURE__ */ jsx33(Text31, { color: COLORS.textSecondary, dimColor: true, children: t("account_promoEsc") })
4834
+ ] }) : /* @__PURE__ */ jsx33(Text31, { color: COLORS.textSecondary, children: t("account_promoHint") }) }),
4835
+ /* @__PURE__ */ jsx33(Box29, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs30(Text31, { color: COLORS.textSecondary, children: [
4724
4836
  status === "pro" || status === "team" ? `d ${t("hint_deactivate")} ` : "",
4725
4837
  status === "pro" || status === "team" || status === "expired" ? `v ${t("hint_revalidate")} ` : "",
4726
4838
  revalidating ? t("account_revalidating") : "",
4727
4839
  " ",
4728
- t("app_version", { version: "0.9.2" })
4840
+ t("app_version", { version: "1.0.0" })
4729
4841
  ] }) })
4730
4842
  ] });
4731
4843
  }
4732
4844
 
4733
4845
  // src/views/rollback.tsx
4734
- import { useCallback as useCallback3, useEffect as useEffect19, useRef as useRef9, useState as useState16 } from "react";
4846
+ import { useCallback as useCallback3, useEffect as useEffect19, useRef as useRef10, useState as useState16 } from "react";
4735
4847
  import { Box as Box30, Text as Text32 } from "ink";
4736
4848
 
4737
4849
  // src/stores/rollback-store.ts
@@ -4942,7 +5054,7 @@ var useRollbackStore = create12((set) => ({
4942
5054
  }));
4943
5055
 
4944
5056
  // src/views/rollback.tsx
4945
- import { jsx as jsx33, jsxs as jsxs31 } from "react/jsx-runtime";
5057
+ import { jsx as jsx34, jsxs as jsxs31 } from "react/jsx-runtime";
4946
5058
  function strategyLabel(action) {
4947
5059
  switch (action.strategy) {
4948
5060
  case "versioned-formula":
@@ -4976,15 +5088,15 @@ function PlanView({ plan }) {
4976
5088
  plan.snapshotLabel,
4977
5089
  " "
4978
5090
  ] }),
4979
- /* @__PURE__ */ jsx33(Text32, { color: COLORS.textSecondary, children: plan.snapshotDate })
5091
+ /* @__PURE__ */ jsx34(Text32, { color: COLORS.textSecondary, children: plan.snapshotDate })
4980
5092
  ] }),
4981
- plan.actions.length === 0 && /* @__PURE__ */ jsx33(ResultBanner, { status: "success", message: t("rollback_diff_empty") }),
5093
+ plan.actions.length === 0 && /* @__PURE__ */ jsx34(ResultBanner, { status: "success", message: t("rollback_diff_empty") }),
4982
5094
  plan.actions.map((a) => /* @__PURE__ */ jsxs31(Box30, { children: [
4983
5095
  /* @__PURE__ */ jsxs31(Text32, { color: actionColor(a), children: [
4984
5096
  actionPrefix(a),
4985
5097
  " "
4986
5098
  ] }),
4987
- /* @__PURE__ */ jsx33(Text32, { color: actionColor(a), bold: true, children: a.packageName }),
5099
+ /* @__PURE__ */ jsx34(Text32, { color: actionColor(a), bold: true, children: a.packageName }),
4988
5100
  a.fromVersion !== "" && a.toVersion !== "" && /* @__PURE__ */ jsxs31(Text32, { color: COLORS.textSecondary, children: [
4989
5101
  " ",
4990
5102
  a.fromVersion,
@@ -4995,18 +5107,18 @@ function PlanView({ plan }) {
4995
5107
  " install ",
4996
5108
  a.toVersion
4997
5109
  ] }),
4998
- a.fromVersion !== "" && a.toVersion === "" && /* @__PURE__ */ jsx33(Text32, { color: COLORS.textSecondary, children: " remove" }),
5110
+ a.fromVersion !== "" && a.toVersion === "" && /* @__PURE__ */ jsx34(Text32, { color: COLORS.textSecondary, children: " remove" }),
4999
5111
  /* @__PURE__ */ jsxs31(Text32, { color: COLORS.muted, dimColor: true, children: [
5000
5112
  " [",
5001
5113
  strategyLabel(a),
5002
5114
  "]"
5003
5115
  ] })
5004
5116
  ] }, a.packageName + a.action)),
5005
- plan.warnings.map((w) => /* @__PURE__ */ jsx33(Box30, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs31(Text32, { color: COLORS.warning, children: [
5117
+ plan.warnings.map((w) => /* @__PURE__ */ jsx34(Box30, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs31(Text32, { color: COLORS.warning, children: [
5006
5118
  "\u26A0 ",
5007
5119
  w
5008
5120
  ] }) }, w)),
5009
- /* @__PURE__ */ jsx33(Box30, { marginTop: SPACING.xs, children: plan.canExecute ? /* @__PURE__ */ jsxs31(Text32, { color: COLORS.textSecondary, children: [
5121
+ /* @__PURE__ */ jsx34(Box30, { marginTop: SPACING.xs, children: plan.canExecute ? /* @__PURE__ */ jsxs31(Text32, { color: COLORS.textSecondary, children: [
5010
5122
  "enter:",
5011
5123
  t("rollback_confirm", { count: String(executableCount) }),
5012
5124
  " esc:",
@@ -5026,8 +5138,8 @@ function RollbackView() {
5026
5138
  const [streamLines, setStreamLines] = useState16([]);
5027
5139
  const [streamRunning, setStreamRunning] = useState16(false);
5028
5140
  const [streamError, setStreamError] = useState16(null);
5029
- const generatorRef = useRef9(null);
5030
- const mountedRef = useRef9(true);
5141
+ const generatorRef = useRef10(null);
5142
+ const mountedRef = useRef10(true);
5031
5143
  useEffect19(() => {
5032
5144
  mountedRef.current = true;
5033
5145
  return () => {
@@ -5095,21 +5207,21 @@ function RollbackView() {
5095
5207
  void fetchSnapshots(isPro());
5096
5208
  }
5097
5209
  });
5098
- if (loading) return /* @__PURE__ */ jsx33(Loading, { message: t("rollback_select_snapshot") });
5099
- if (error) return /* @__PURE__ */ jsx33(ErrorMessage, { message: error });
5210
+ if (loading) return /* @__PURE__ */ jsx34(Loading, { message: t("rollback_select_snapshot") });
5211
+ if (error) return /* @__PURE__ */ jsx34(ErrorMessage, { message: error });
5100
5212
  if (phase === "executing") {
5101
- return /* @__PURE__ */ jsx33(Box30, { flexDirection: "column", children: /* @__PURE__ */ jsx33(ProgressLog, { lines: streamLines, isRunning: streamRunning, title: t("rollback_executing") }) });
5213
+ return /* @__PURE__ */ jsx34(Box30, { flexDirection: "column", children: /* @__PURE__ */ jsx34(ProgressLog, { lines: streamLines, isRunning: streamRunning, title: t("rollback_executing") }) });
5102
5214
  }
5103
5215
  if (phase === "result") {
5104
5216
  return /* @__PURE__ */ jsxs31(Box30, { flexDirection: "column", marginTop: SPACING.xs, children: [
5105
- /* @__PURE__ */ jsx33(
5217
+ /* @__PURE__ */ jsx34(
5106
5218
  ResultBanner,
5107
5219
  {
5108
5220
  status: streamError ? "error" : "success",
5109
5221
  message: streamError ? t("rollback_error", { error: streamError }) : t("rollback_success")
5110
5222
  }
5111
5223
  ),
5112
- /* @__PURE__ */ jsx33(Box30, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs31(Text32, { color: COLORS.textSecondary, children: [
5224
+ /* @__PURE__ */ jsx34(Box30, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs31(Text32, { color: COLORS.textSecondary, children: [
5113
5225
  "r:",
5114
5226
  t("hint_refresh"),
5115
5227
  " esc:",
@@ -5118,12 +5230,12 @@ function RollbackView() {
5118
5230
  ] });
5119
5231
  }
5120
5232
  return /* @__PURE__ */ jsxs31(Box30, { flexDirection: "column", children: [
5121
- /* @__PURE__ */ jsx33(SectionHeader, { emoji: "\u23EA", title: t("rollback_title"), gradient: GRADIENTS.gold }),
5122
- snapshots.length === 0 && /* @__PURE__ */ jsx33(Box30, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx33(ResultBanner, { status: "info", message: t("rollback_no_snapshots") }) }),
5233
+ /* @__PURE__ */ jsx34(SectionHeader, { emoji: "\u23EA", title: t("rollback_title"), gradient: GRADIENTS.gold }),
5234
+ snapshots.length === 0 && /* @__PURE__ */ jsx34(Box30, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx34(ResultBanner, { status: "info", message: t("rollback_no_snapshots") }) }),
5123
5235
  phase === "list" && snapshots.length > 0 && /* @__PURE__ */ jsxs31(Box30, { flexDirection: "column", marginTop: SPACING.xs, children: [
5124
- /* @__PURE__ */ jsx33(Text32, { color: COLORS.textSecondary, dimColor: true, children: t("rollback_select_snapshot") }),
5125
- /* @__PURE__ */ jsx33(Box30, { flexDirection: "column", marginTop: SPACING.xs, children: snapshots.map((s, i) => /* @__PURE__ */ jsxs31(SelectableRow, { isCurrent: i === cursor, children: [
5126
- /* @__PURE__ */ jsx33(Text32, { bold: i === cursor, color: i === cursor ? COLORS.text : COLORS.muted, children: s.label ?? t("rollback_snapshot_auto") }),
5236
+ /* @__PURE__ */ jsx34(Text32, { color: COLORS.textSecondary, dimColor: true, children: t("rollback_select_snapshot") }),
5237
+ /* @__PURE__ */ jsx34(Box30, { flexDirection: "column", marginTop: SPACING.xs, children: snapshots.map((s, i) => /* @__PURE__ */ jsxs31(SelectableRow, { isCurrent: i === cursor, children: [
5238
+ /* @__PURE__ */ jsx34(Text32, { bold: i === cursor, color: i === cursor ? COLORS.text : COLORS.muted, children: s.label ?? t("rollback_snapshot_auto") }),
5127
5239
  /* @__PURE__ */ jsxs31(Text32, { color: COLORS.textSecondary, children: [
5128
5240
  " \u2014 ",
5129
5241
  new Date(s.capturedAt).toLocaleString()
@@ -5137,11 +5249,11 @@ function RollbackView() {
5137
5249
  ] }, s.capturedAt)) })
5138
5250
  ] }),
5139
5251
  phase === "plan" && /* @__PURE__ */ jsxs31(Box30, { flexDirection: "column", children: [
5140
- planLoading && /* @__PURE__ */ jsx33(Loading, { message: t("rollback_capturing") }),
5141
- planError && /* @__PURE__ */ jsx33(ErrorMessage, { message: planError }),
5142
- plan && !planLoading && /* @__PURE__ */ jsx33(PlanView, { plan })
5252
+ planLoading && /* @__PURE__ */ jsx34(Loading, { message: t("rollback_capturing") }),
5253
+ planError && /* @__PURE__ */ jsx34(ErrorMessage, { message: planError }),
5254
+ plan && !planLoading && /* @__PURE__ */ jsx34(PlanView, { plan })
5143
5255
  ] }),
5144
- phase === "confirm" && plan && /* @__PURE__ */ jsx33(Box30, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx33(
5256
+ phase === "confirm" && plan && /* @__PURE__ */ jsx34(Box30, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx34(
5145
5257
  ConfirmDialog,
5146
5258
  {
5147
5259
  message: t("rollback_confirm", {
@@ -5155,10 +5267,10 @@ function RollbackView() {
5155
5267
  }
5156
5268
 
5157
5269
  // src/views/brewfile.tsx
5158
- import { useCallback as useCallback4, useEffect as useEffect20, useRef as useRef10, useState as useState17 } from "react";
5270
+ import { useCallback as useCallback4, useEffect as useEffect20, useRef as useRef11, useState as useState17 } from "react";
5159
5271
  import { Box as Box31, Text as Text33 } from "ink";
5160
5272
  import { TextInput as TextInput6 } from "@inkjs/ui";
5161
- import { jsx as jsx34, jsxs as jsxs32 } from "react/jsx-runtime";
5273
+ import { jsx as jsx35, jsxs as jsxs32 } from "react/jsx-runtime";
5162
5274
  function DriftScore({ score }) {
5163
5275
  const color = score >= 80 ? COLORS.success : score >= 50 ? COLORS.warning : COLORS.error;
5164
5276
  const bars = Math.round(score / 10);
@@ -5174,28 +5286,28 @@ function DriftScore({ score }) {
5174
5286
  score,
5175
5287
  "% "
5176
5288
  ] }),
5177
- /* @__PURE__ */ jsx34(Text33, { color: COLORS.textSecondary, children: t("brewfile_compliant") })
5289
+ /* @__PURE__ */ jsx35(Text33, { color: COLORS.textSecondary, children: t("brewfile_compliant") })
5178
5290
  ] });
5179
5291
  }
5180
5292
  function DriftSummary({ drift }) {
5181
5293
  return /* @__PURE__ */ jsxs32(Box31, { flexDirection: "column", marginTop: SPACING.xs, children: [
5182
5294
  drift.missingPackages.length > 0 && /* @__PURE__ */ jsxs32(Box31, { children: [
5183
- /* @__PURE__ */ jsx34(Text33, { color: COLORS.error, children: "\u25CF " }),
5184
- /* @__PURE__ */ jsx34(Text33, { color: COLORS.error, children: t("brewfile_drift_missing", { count: drift.missingPackages.length }) }),
5295
+ /* @__PURE__ */ jsx35(Text33, { color: COLORS.error, children: "\u25CF " }),
5296
+ /* @__PURE__ */ jsx35(Text33, { color: COLORS.error, children: t("brewfile_drift_missing", { count: drift.missingPackages.length }) }),
5185
5297
  /* @__PURE__ */ jsxs32(Text33, { color: COLORS.textSecondary, children: [
5186
5298
  ": " + drift.missingPackages.slice(0, 3).join(", "),
5187
5299
  drift.missingPackages.length > 3 ? "..." : ""
5188
5300
  ] })
5189
5301
  ] }),
5190
5302
  drift.extraPackages.length > 0 && /* @__PURE__ */ jsxs32(Box31, { children: [
5191
- /* @__PURE__ */ jsx34(Text33, { color: COLORS.warning, children: "\u25CF " }),
5192
- /* @__PURE__ */ jsx34(Text33, { color: COLORS.warning, children: t("brewfile_drift_extra", { count: drift.extraPackages.length }) })
5303
+ /* @__PURE__ */ jsx35(Text33, { color: COLORS.warning, children: "\u25CF " }),
5304
+ /* @__PURE__ */ jsx35(Text33, { color: COLORS.warning, children: t("brewfile_drift_extra", { count: drift.extraPackages.length }) })
5193
5305
  ] }),
5194
5306
  drift.wrongVersions.length > 0 && /* @__PURE__ */ jsxs32(Box31, { children: [
5195
- /* @__PURE__ */ jsx34(Text33, { color: COLORS.info, children: "\u25CF " }),
5196
- /* @__PURE__ */ jsx34(Text33, { color: COLORS.info, children: t("brewfile_drift_wrong", { count: drift.wrongVersions.length }) })
5307
+ /* @__PURE__ */ jsx35(Text33, { color: COLORS.info, children: "\u25CF " }),
5308
+ /* @__PURE__ */ jsx35(Text33, { color: COLORS.info, children: t("brewfile_drift_wrong", { count: drift.wrongVersions.length }) })
5197
5309
  ] }),
5198
- drift.missingPackages.length === 0 && drift.extraPackages.length === 0 && drift.wrongVersions.length === 0 && /* @__PURE__ */ jsx34(ResultBanner, { status: "success", message: t("brewfile_in_sync") })
5310
+ drift.missingPackages.length === 0 && drift.extraPackages.length === 0 && drift.wrongVersions.length === 0 && /* @__PURE__ */ jsx35(ResultBanner, { status: "success", message: t("brewfile_in_sync") })
5199
5311
  ] });
5200
5312
  }
5201
5313
  function BrewfileView() {
@@ -5206,8 +5318,8 @@ function BrewfileView() {
5206
5318
  const [streamRunning, setStreamRunning] = useState17(false);
5207
5319
  const [streamError, setStreamError] = useState17(null);
5208
5320
  const [resultMessage, setResultMessage] = useState17("");
5209
- const generatorRef = useRef10(null);
5210
- const mountedRef = useRef10(true);
5321
+ const generatorRef = useRef11(null);
5322
+ const mountedRef = useRef11(true);
5211
5323
  useEffect20(() => {
5212
5324
  mountedRef.current = true;
5213
5325
  void load();
@@ -5275,10 +5387,10 @@ function BrewfileView() {
5275
5387
  if (key.escape) {
5276
5388
  }
5277
5389
  });
5278
- if (loading) return /* @__PURE__ */ jsx34(Loading, { message: t("loading_default") });
5279
- if (error) return /* @__PURE__ */ jsx34(ErrorMessage, { message: error });
5390
+ if (loading) return /* @__PURE__ */ jsx35(Loading, { message: t("loading_default") });
5391
+ if (error) return /* @__PURE__ */ jsx35(ErrorMessage, { message: error });
5280
5392
  if (phase === "confirming-reconcile" && drift) {
5281
- return /* @__PURE__ */ jsx34(
5393
+ return /* @__PURE__ */ jsx35(
5282
5394
  ConfirmDialog,
5283
5395
  {
5284
5396
  message: t("confirm_brewfile_reconcile", {
@@ -5296,13 +5408,13 @@ function BrewfileView() {
5296
5408
  }
5297
5409
  if (phase === "creating") {
5298
5410
  return /* @__PURE__ */ jsxs32(Box31, { flexDirection: "column", marginTop: SPACING.xs, children: [
5299
- /* @__PURE__ */ jsx34(SectionHeader, { emoji: "\u{1F4E6}", title: t("brewfile_title"), gradient: GRADIENTS.ocean }),
5411
+ /* @__PURE__ */ jsx35(SectionHeader, { emoji: "\u{1F4E6}", title: t("brewfile_title"), gradient: GRADIENTS.ocean }),
5300
5412
  /* @__PURE__ */ jsxs32(Box31, { marginTop: SPACING.xs, children: [
5301
5413
  /* @__PURE__ */ jsxs32(Text33, { color: COLORS.textSecondary, children: [
5302
5414
  t("brewfile_create_name"),
5303
5415
  " "
5304
5416
  ] }),
5305
- /* @__PURE__ */ jsx34(
5417
+ /* @__PURE__ */ jsx35(
5306
5418
  TextInput6,
5307
5419
  {
5308
5420
  defaultValue: "My Environment",
@@ -5318,7 +5430,7 @@ function BrewfileView() {
5318
5430
  ] });
5319
5431
  }
5320
5432
  if (phase === "reconciling") {
5321
- return /* @__PURE__ */ jsx34(Box31, { flexDirection: "column", children: /* @__PURE__ */ jsx34(
5433
+ return /* @__PURE__ */ jsx35(Box31, { flexDirection: "column", children: /* @__PURE__ */ jsx35(
5322
5434
  ProgressLog,
5323
5435
  {
5324
5436
  lines: streamLines,
@@ -5329,14 +5441,14 @@ function BrewfileView() {
5329
5441
  }
5330
5442
  if (phase === "result") {
5331
5443
  return /* @__PURE__ */ jsxs32(Box31, { flexDirection: "column", marginTop: SPACING.xs, children: [
5332
- /* @__PURE__ */ jsx34(
5444
+ /* @__PURE__ */ jsx35(
5333
5445
  ResultBanner,
5334
5446
  {
5335
5447
  status: streamError ? "error" : "success",
5336
5448
  message: resultMessage
5337
5449
  }
5338
5450
  ),
5339
- /* @__PURE__ */ jsx34(Box31, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs32(Text33, { color: COLORS.textSecondary, children: [
5451
+ /* @__PURE__ */ jsx35(Box31, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs32(Text33, { color: COLORS.textSecondary, children: [
5340
5452
  "r:",
5341
5453
  t("hint_refresh"),
5342
5454
  " esc:",
@@ -5345,17 +5457,17 @@ function BrewfileView() {
5345
5457
  ] });
5346
5458
  }
5347
5459
  return /* @__PURE__ */ jsxs32(Box31, { flexDirection: "column", children: [
5348
- /* @__PURE__ */ jsx34(SectionHeader, { emoji: "\u{1F4E6}", title: t("brewfile_title"), gradient: GRADIENTS.ocean }),
5460
+ /* @__PURE__ */ jsx35(SectionHeader, { emoji: "\u{1F4E6}", title: t("brewfile_title"), gradient: GRADIENTS.ocean }),
5349
5461
  schema === null ? /* @__PURE__ */ jsxs32(Box31, { marginTop: SPACING.xs, flexDirection: "column", children: [
5350
- /* @__PURE__ */ jsx34(ResultBanner, { status: "info", message: t("brewfile_no_brewfile") }),
5351
- /* @__PURE__ */ jsx34(Box31, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs32(Text33, { color: COLORS.textSecondary, children: [
5462
+ /* @__PURE__ */ jsx35(ResultBanner, { status: "info", message: t("brewfile_no_brewfile") }),
5463
+ /* @__PURE__ */ jsx35(Box31, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs32(Text33, { color: COLORS.textSecondary, children: [
5352
5464
  "n:",
5353
5465
  t("hint_new")
5354
5466
  ] }) })
5355
5467
  ] }) : /* @__PURE__ */ jsxs32(Box31, { flexDirection: "column", marginTop: SPACING.xs, children: [
5356
5468
  /* @__PURE__ */ jsxs32(Box31, { gap: SPACING.sm, children: [
5357
- /* @__PURE__ */ jsx34(Text33, { color: COLORS.text, bold: true, children: schema.meta.name }),
5358
- schema.meta.description && /* @__PURE__ */ jsx34(Text33, { color: COLORS.textSecondary, children: schema.meta.description }),
5469
+ /* @__PURE__ */ jsx35(Text33, { color: COLORS.text, bold: true, children: schema.meta.name }),
5470
+ schema.meta.description && /* @__PURE__ */ jsx35(Text33, { color: COLORS.textSecondary, children: schema.meta.description }),
5359
5471
  schema.strictMode && /* @__PURE__ */ jsxs32(Text33, { color: COLORS.warning, children: [
5360
5472
  "[",
5361
5473
  t("brewfile_strict_mode"),
@@ -5363,15 +5475,15 @@ function BrewfileView() {
5363
5475
  ] })
5364
5476
  ] }),
5365
5477
  /* @__PURE__ */ jsxs32(Box31, { gap: SPACING.md, marginTop: SPACING.xs, children: [
5366
- /* @__PURE__ */ jsx34(Text33, { color: COLORS.sky, children: t("brewfile_formulae_count", { count: schema.formulae.length }) }),
5367
- /* @__PURE__ */ jsx34(Text33, { color: COLORS.teal, children: t("brewfile_casks_count", { count: schema.casks.length }) })
5478
+ /* @__PURE__ */ jsx35(Text33, { color: COLORS.sky, children: t("brewfile_formulae_count", { count: schema.formulae.length }) }),
5479
+ /* @__PURE__ */ jsx35(Text33, { color: COLORS.teal, children: t("brewfile_casks_count", { count: schema.casks.length }) })
5368
5480
  ] }),
5369
- driftLoading && /* @__PURE__ */ jsx34(Box31, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx34(Text33, { color: COLORS.muted, children: t("brewfile_computing_drift") }) }),
5481
+ driftLoading && /* @__PURE__ */ jsx35(Box31, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx35(Text33, { color: COLORS.muted, children: t("brewfile_computing_drift") }) }),
5370
5482
  drift && !driftLoading && /* @__PURE__ */ jsxs32(Box31, { flexDirection: "column", marginTop: SPACING.xs, children: [
5371
- /* @__PURE__ */ jsx34(DriftScore, { score: drift.score }),
5372
- /* @__PURE__ */ jsx34(DriftSummary, { drift })
5483
+ /* @__PURE__ */ jsx35(DriftScore, { score: drift.score }),
5484
+ /* @__PURE__ */ jsx35(DriftSummary, { drift })
5373
5485
  ] }),
5374
- /* @__PURE__ */ jsx34(Box31, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs32(Text33, { color: COLORS.textSecondary, children: [
5486
+ /* @__PURE__ */ jsx35(Box31, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs32(Text33, { color: COLORS.textSecondary, children: [
5375
5487
  "r:",
5376
5488
  t("hint_refresh"),
5377
5489
  drift && (drift.missingPackages.length > 0 || drift.wrongVersions.length > 0) ? ` c:${t("hint_reconcile")}` : "",
@@ -5386,7 +5498,7 @@ function BrewfileView() {
5386
5498
  // src/views/sync.tsx
5387
5499
  import { useCallback as useCallback5, useEffect as useEffect21, useState as useState18 } from "react";
5388
5500
  import { Box as Box32, Text as Text34 } from "ink";
5389
- import { Fragment as Fragment6, jsx as jsx35, jsxs as jsxs33 } from "react/jsx-runtime";
5501
+ import { Fragment as Fragment6, jsx as jsx36, jsxs as jsxs33 } from "react/jsx-runtime";
5390
5502
  function OverviewSection({
5391
5503
  config,
5392
5504
  lastResult,
@@ -5398,17 +5510,17 @@ function OverviewSection({
5398
5510
  const showComplianceHint = !hasConflicts && !!lastResult?.success;
5399
5511
  return /* @__PURE__ */ jsxs33(Box32, { flexDirection: "column", marginTop: SPACING.xs, children: [
5400
5512
  config ? /* @__PURE__ */ jsxs33(Fragment6, { children: [
5401
- /* @__PURE__ */ jsx35(Box32, { marginBottom: SPACING.xs, children: /* @__PURE__ */ jsx35(Text34, { color: COLORS.textSecondary, children: t("sync_machine", { name: config.machineName }) }) }),
5402
- config.lastSync && /* @__PURE__ */ jsx35(Box32, { marginBottom: SPACING.xs, children: /* @__PURE__ */ jsx35(Text34, { color: COLORS.textSecondary, children: t("sync_last_sync", { date: new Date(config.lastSync).toLocaleString() }) }) }),
5403
- hasConflicts ? /* @__PURE__ */ jsx35(
5513
+ /* @__PURE__ */ jsx36(Box32, { marginBottom: SPACING.xs, children: /* @__PURE__ */ jsx36(Text34, { color: COLORS.textSecondary, children: t("sync_machine", { name: config.machineName }) }) }),
5514
+ config.lastSync && /* @__PURE__ */ jsx36(Box32, { marginBottom: SPACING.xs, children: /* @__PURE__ */ jsx36(Text34, { color: COLORS.textSecondary, children: t("sync_last_sync", { date: new Date(config.lastSync).toLocaleString() }) }) }),
5515
+ hasConflicts ? /* @__PURE__ */ jsx36(
5404
5516
  ResultBanner,
5405
5517
  {
5406
5518
  status: "error",
5407
5519
  message: t("sync_status_conflict", { count: String(conflicts.length) })
5408
5520
  }
5409
- ) : lastResult?.success ? /* @__PURE__ */ jsx35(ResultBanner, { status: "success", message: t("sync_status_ok") }) : null
5410
- ] }) : /* @__PURE__ */ jsx35(Box32, { marginBottom: SPACING.xs, children: /* @__PURE__ */ jsx35(Text34, { color: COLORS.textSecondary, children: t("sync_disabled") }) }),
5411
- /* @__PURE__ */ jsx35(Box32, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs33(Text34, { color: COLORS.textSecondary, children: [
5521
+ ) : lastResult?.success ? /* @__PURE__ */ jsx36(ResultBanner, { status: "success", message: t("sync_status_ok") }) : null
5522
+ ] }) : /* @__PURE__ */ jsx36(Box32, { marginBottom: SPACING.xs, children: /* @__PURE__ */ jsx36(Text34, { color: COLORS.textSecondary, children: t("sync_disabled") }) }),
5523
+ /* @__PURE__ */ jsx36(Box32, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs33(Text34, { color: COLORS.textSecondary, children: [
5412
5524
  "s",
5413
5525
  /* @__PURE__ */ jsxs33(Text34, { color: COLORS.gold, children: [
5414
5526
  ":",
@@ -5441,7 +5553,7 @@ function ConflictsList({
5441
5553
  const isActive = i === cursor;
5442
5554
  return /* @__PURE__ */ jsxs33(Box32, { flexDirection: "column", marginBottom: SPACING.xs, children: [
5443
5555
  /* @__PURE__ */ jsxs33(SelectableRow, { isCurrent: isActive, children: [
5444
- /* @__PURE__ */ jsx35(Text34, { bold: true, color: isActive ? COLORS.text : COLORS.textSecondary, children: t("sync_conflict_title", { package: conflict.packageName }) }),
5556
+ /* @__PURE__ */ jsx36(Text34, { bold: true, color: isActive ? COLORS.text : COLORS.textSecondary, children: t("sync_conflict_title", { package: conflict.packageName }) }),
5445
5557
  /* @__PURE__ */ jsxs33(Text34, { color: COLORS.muted, children: [
5446
5558
  " (",
5447
5559
  conflict.packageType,
@@ -5474,7 +5586,7 @@ function ConflictsList({
5474
5586
  ] })
5475
5587
  ] }, `${conflict.packageName}-${conflict.remoteMachine}`);
5476
5588
  }),
5477
- /* @__PURE__ */ jsx35(Box32, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs33(Text34, { color: COLORS.textSecondary, children: [
5589
+ /* @__PURE__ */ jsx36(Box32, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs33(Text34, { color: COLORS.textSecondary, children: [
5478
5590
  "j/k:",
5479
5591
  t("hint_navigate"),
5480
5592
  " l:",
@@ -5591,7 +5703,7 @@ function SyncView() {
5591
5703
  }
5592
5704
  });
5593
5705
  if (phase === "confirming-sync") {
5594
- return /* @__PURE__ */ jsx35(
5706
+ return /* @__PURE__ */ jsx36(
5595
5707
  ConfirmDialog,
5596
5708
  {
5597
5709
  message: t("confirm_sync_now"),
@@ -5605,7 +5717,7 @@ function SyncView() {
5605
5717
  );
5606
5718
  }
5607
5719
  if (phase === "confirming-apply") {
5608
- return /* @__PURE__ */ jsx35(
5720
+ return /* @__PURE__ */ jsx36(
5609
5721
  ConfirmDialog,
5610
5722
  {
5611
5723
  message: t("confirm_sync_apply", { count: String(conflictEntries.length) }),
@@ -5619,20 +5731,20 @@ function SyncView() {
5619
5731
  );
5620
5732
  }
5621
5733
  if (phase === "syncing" || loading) {
5622
- return /* @__PURE__ */ jsx35(Loading, { message: t("sync_syncing") });
5734
+ return /* @__PURE__ */ jsx36(Loading, { message: t("sync_syncing") });
5623
5735
  }
5624
5736
  if (phase === "result") {
5625
5737
  const isError = !!(syncError ?? error);
5626
5738
  return /* @__PURE__ */ jsxs33(Box32, { flexDirection: "column", marginTop: SPACING.xs, children: [
5627
- /* @__PURE__ */ jsx35(SectionHeader, { emoji: "\u{1F504}", title: t("sync_title"), gradient: GRADIENTS.gold }),
5628
- /* @__PURE__ */ jsx35(Box32, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx35(
5739
+ /* @__PURE__ */ jsx36(SectionHeader, { emoji: "\u{1F504}", title: t("sync_title"), gradient: GRADIENTS.gold }),
5740
+ /* @__PURE__ */ jsx36(Box32, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx36(
5629
5741
  ResultBanner,
5630
5742
  {
5631
5743
  status: isError ? "error" : "success",
5632
5744
  message: isError ? t("sync_error", { error: syncError ?? error ?? "" }) : t("sync_success")
5633
5745
  }
5634
5746
  ) }),
5635
- /* @__PURE__ */ jsx35(Box32, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs33(Text34, { color: COLORS.textSecondary, children: [
5747
+ /* @__PURE__ */ jsx36(Box32, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs33(Text34, { color: COLORS.textSecondary, children: [
5636
5748
  "r:",
5637
5749
  t("hint_refresh"),
5638
5750
  " esc:",
@@ -5641,9 +5753,9 @@ function SyncView() {
5641
5753
  ] });
5642
5754
  }
5643
5755
  return /* @__PURE__ */ jsxs33(Box32, { flexDirection: "column", children: [
5644
- /* @__PURE__ */ jsx35(SectionHeader, { emoji: "\u{1F504}", title: t("sync_title"), gradient: GRADIENTS.gold }),
5645
- error && phase === "overview" && /* @__PURE__ */ jsx35(Box32, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx35(ResultBanner, { status: "error", message: t("sync_error", { error }) }) }),
5646
- phase === "overview" && /* @__PURE__ */ jsx35(
5756
+ /* @__PURE__ */ jsx36(SectionHeader, { emoji: "\u{1F504}", title: t("sync_title"), gradient: GRADIENTS.gold }),
5757
+ error && phase === "overview" && /* @__PURE__ */ jsx36(Box32, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx36(ResultBanner, { status: "error", message: t("sync_error", { error }) }) }),
5758
+ phase === "overview" && /* @__PURE__ */ jsx36(
5647
5759
  OverviewSection,
5648
5760
  {
5649
5761
  config,
@@ -5657,14 +5769,14 @@ function SyncView() {
5657
5769
  }
5658
5770
  ),
5659
5771
  phase === "conflicts" && /* @__PURE__ */ jsxs33(Box32, { flexDirection: "column", children: [
5660
- /* @__PURE__ */ jsx35(SectionHeader, { emoji: "\u26A0", title: t("sync_status_conflict", { count: String(conflictEntries.length) }), gradient: GRADIENTS.gold }),
5661
- /* @__PURE__ */ jsx35(ConflictsList, { entries: conflictEntries, cursor })
5772
+ /* @__PURE__ */ jsx36(SectionHeader, { emoji: "\u26A0", title: t("sync_status_conflict", { count: String(conflictEntries.length) }), gradient: GRADIENTS.gold }),
5773
+ /* @__PURE__ */ jsx36(ConflictsList, { entries: conflictEntries, cursor })
5662
5774
  ] })
5663
5775
  ] });
5664
5776
  }
5665
5777
 
5666
5778
  // src/views/compliance.tsx
5667
- import { useCallback as useCallback6, useEffect as useEffect22, useRef as useRef11, useState as useState19 } from "react";
5779
+ import { useCallback as useCallback6, useEffect as useEffect22, useRef as useRef12, useState as useState19 } from "react";
5668
5780
  import { Box as Box33, Text as Text35 } from "ink";
5669
5781
  import { TextInput as TextInput7 } from "@inkjs/ui";
5670
5782
 
@@ -5710,7 +5822,7 @@ async function* remediateViolations(violations, isPro) {
5710
5822
 
5711
5823
  // src/views/compliance.tsx
5712
5824
  import { join as join4 } from "path";
5713
- import { jsx as jsx36, jsxs as jsxs34 } from "react/jsx-runtime";
5825
+ import { jsx as jsx37, jsxs as jsxs34 } from "react/jsx-runtime";
5714
5826
  function ComplianceScore({ report }) {
5715
5827
  const color = report.score >= 80 ? COLORS.success : report.score >= 50 ? COLORS.warning : COLORS.error;
5716
5828
  const bars = Math.round(report.score / 10);
@@ -5745,7 +5857,7 @@ function ViolationItem({ violation }) {
5745
5857
  prefix,
5746
5858
  " "
5747
5859
  ] }),
5748
- /* @__PURE__ */ jsx36(Text35, { color, children: violation.detail })
5860
+ /* @__PURE__ */ jsx37(Text35, { color, children: violation.detail })
5749
5861
  ] });
5750
5862
  }
5751
5863
  function ViolationList({ violations }) {
@@ -5757,14 +5869,14 @@ function ViolationList({ violations }) {
5757
5869
  t("compliance_violations", { count: String(errors.length) }),
5758
5870
  " (errors)"
5759
5871
  ] }),
5760
- errors.map((v) => /* @__PURE__ */ jsx36(ViolationItem, { violation: v }, `${v.type}-${v.packageName}`))
5872
+ errors.map((v) => /* @__PURE__ */ jsx37(ViolationItem, { violation: v }, `${v.type}-${v.packageName}`))
5761
5873
  ] }),
5762
5874
  warnings.length > 0 && /* @__PURE__ */ jsxs34(Box33, { flexDirection: "column", children: [
5763
5875
  /* @__PURE__ */ jsxs34(Text35, { color: COLORS.warning, bold: true, children: [
5764
5876
  t("compliance_violations", { count: String(warnings.length) }),
5765
5877
  " (warnings)"
5766
5878
  ] }),
5767
- warnings.map((v) => /* @__PURE__ */ jsx36(ViolationItem, { violation: v }, `${v.type}-${v.packageName}`))
5879
+ warnings.map((v) => /* @__PURE__ */ jsx37(ViolationItem, { violation: v }, `${v.type}-${v.packageName}`))
5768
5880
  ] })
5769
5881
  ] });
5770
5882
  }
@@ -5775,8 +5887,8 @@ function ComplianceView() {
5775
5887
  const [resultMessage, setResultMessage] = useState19(null);
5776
5888
  const [streamLines, setStreamLines] = useState19([]);
5777
5889
  const [streamRunning, setStreamRunning] = useState19(false);
5778
- const generatorRef = useRef11(null);
5779
- const mountedRef = useRef11(true);
5890
+ const generatorRef = useRef12(null);
5891
+ const mountedRef = useRef12(true);
5780
5892
  useEffect22(() => {
5781
5893
  mountedRef.current = true;
5782
5894
  return () => {
@@ -5889,7 +6001,7 @@ function ComplianceView() {
5889
6001
  const actionable = report.violations.filter(
5890
6002
  (v) => v.type === "missing" || v.type === "wrong-version"
5891
6003
  );
5892
- return /* @__PURE__ */ jsx36(
6004
+ return /* @__PURE__ */ jsx37(
5893
6005
  ConfirmDialog,
5894
6006
  {
5895
6007
  message: t("confirm_compliance_remediate", { count: String(actionable.length) }),
@@ -5905,23 +6017,23 @@ function ComplianceView() {
5905
6017
  if (phase === "remediating" || loading && phase !== "importing") {
5906
6018
  if (phase === "remediating") {
5907
6019
  return /* @__PURE__ */ jsxs34(Box33, { flexDirection: "column", children: [
5908
- /* @__PURE__ */ jsx36(SectionHeader, { emoji: "\u{1F50D}", title: t("compliance_title"), gradient: GRADIENTS.gold }),
5909
- /* @__PURE__ */ jsx36(Box33, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx36(ProgressLog, { lines: streamLines, isRunning: streamRunning, title: t("compliance_remediating") }) })
6020
+ /* @__PURE__ */ jsx37(SectionHeader, { emoji: "\u{1F50D}", title: t("compliance_title"), gradient: GRADIENTS.gold }),
6021
+ /* @__PURE__ */ jsx37(Box33, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx37(ProgressLog, { lines: streamLines, isRunning: streamRunning, title: t("compliance_remediating") }) })
5910
6022
  ] });
5911
6023
  }
5912
- return /* @__PURE__ */ jsx36(Loading, { message: t("compliance_title") });
6024
+ return /* @__PURE__ */ jsx37(Loading, { message: t("compliance_title") });
5913
6025
  }
5914
6026
  if (phase === "result" && resultMessage) {
5915
6027
  return /* @__PURE__ */ jsxs34(Box33, { flexDirection: "column", marginTop: SPACING.xs, children: [
5916
- /* @__PURE__ */ jsx36(SectionHeader, { emoji: "\u{1F50D}", title: t("compliance_title"), gradient: GRADIENTS.gold }),
5917
- /* @__PURE__ */ jsx36(Box33, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx36(
6028
+ /* @__PURE__ */ jsx37(SectionHeader, { emoji: "\u{1F50D}", title: t("compliance_title"), gradient: GRADIENTS.gold }),
6029
+ /* @__PURE__ */ jsx37(Box33, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx37(
5918
6030
  ResultBanner,
5919
6031
  {
5920
6032
  status: resultMessage.ok ? "success" : "error",
5921
6033
  message: resultMessage.text
5922
6034
  }
5923
6035
  ) }),
5924
- /* @__PURE__ */ jsx36(Box33, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs34(Text35, { color: COLORS.textSecondary, children: [
6036
+ /* @__PURE__ */ jsx37(Box33, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs34(Text35, { color: COLORS.textSecondary, children: [
5925
6037
  "r:",
5926
6038
  t("hint_refresh"),
5927
6039
  " esc:",
@@ -5930,11 +6042,11 @@ function ComplianceView() {
5930
6042
  ] });
5931
6043
  }
5932
6044
  return /* @__PURE__ */ jsxs34(Box33, { flexDirection: "column", children: [
5933
- /* @__PURE__ */ jsx36(SectionHeader, { emoji: "\u{1F50D}", title: t("compliance_title"), gradient: GRADIENTS.gold }),
5934
- error && /* @__PURE__ */ jsx36(Box33, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx36(ResultBanner, { status: "error", message: t("compliance_import_error", { error }) }) }),
6045
+ /* @__PURE__ */ jsx37(SectionHeader, { emoji: "\u{1F50D}", title: t("compliance_title"), gradient: GRADIENTS.gold }),
6046
+ error && /* @__PURE__ */ jsx37(Box33, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx37(ResultBanner, { status: "error", message: t("compliance_import_error", { error }) }) }),
5935
6047
  phase === "importing" && /* @__PURE__ */ jsxs34(Box33, { marginTop: SPACING.xs, flexDirection: "column", children: [
5936
- /* @__PURE__ */ jsx36(Text35, { color: COLORS.textSecondary, children: t("compliance_import_prompt") }),
5937
- /* @__PURE__ */ jsx36(Box33, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx36(
6048
+ /* @__PURE__ */ jsx37(Text35, { color: COLORS.textSecondary, children: t("compliance_import_prompt") }),
6049
+ /* @__PURE__ */ jsx37(Box33, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx37(
5938
6050
  TextInput7,
5939
6051
  {
5940
6052
  defaultValue: "",
@@ -5943,20 +6055,20 @@ function ComplianceView() {
5943
6055
  }
5944
6056
  }
5945
6057
  ) }),
5946
- /* @__PURE__ */ jsx36(Box33, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs34(Text35, { color: COLORS.muted, dimColor: true, children: [
6058
+ /* @__PURE__ */ jsx37(Box33, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs34(Text35, { color: COLORS.muted, dimColor: true, children: [
5947
6059
  "esc:",
5948
6060
  t("hint_back")
5949
6061
  ] }) })
5950
6062
  ] }),
5951
6063
  phase === "overview" && /* @__PURE__ */ jsxs34(Box33, { flexDirection: "column", marginTop: SPACING.xs, children: [
5952
- !policy ? /* @__PURE__ */ jsx36(Box33, { flexDirection: "column", children: /* @__PURE__ */ jsx36(Text35, { color: COLORS.textSecondary, children: t("compliance_no_policy") }) }) : /* @__PURE__ */ jsxs34(Box33, { flexDirection: "column", children: [
5953
- /* @__PURE__ */ jsx36(Text35, { color: COLORS.textSecondary, bold: true, children: t("compliance_policy_by", { maintainer: policy.meta.maintainer }) }),
6064
+ !policy ? /* @__PURE__ */ jsx37(Box33, { flexDirection: "column", children: /* @__PURE__ */ jsx37(Text35, { color: COLORS.textSecondary, children: t("compliance_no_policy") }) }) : /* @__PURE__ */ jsxs34(Box33, { flexDirection: "column", children: [
6065
+ /* @__PURE__ */ jsx37(Text35, { color: COLORS.textSecondary, bold: true, children: t("compliance_policy_by", { maintainer: policy.meta.maintainer }) }),
5954
6066
  report ? /* @__PURE__ */ jsxs34(Box33, { flexDirection: "column", marginTop: SPACING.xs, children: [
5955
- /* @__PURE__ */ jsx36(ComplianceScore, { report }),
5956
- report.compliant ? /* @__PURE__ */ jsx36(ResultBanner, { status: "success", message: t("compliance_ok") }) : /* @__PURE__ */ jsx36(ViolationList, { violations: report.violations })
5957
- ] }) : /* @__PURE__ */ jsx36(Box33, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx36(Text35, { color: COLORS.muted, dimColor: true, children: t("compliance_press_r_hint") }) })
6067
+ /* @__PURE__ */ jsx37(ComplianceScore, { report }),
6068
+ report.compliant ? /* @__PURE__ */ jsx37(ResultBanner, { status: "success", message: t("compliance_ok") }) : /* @__PURE__ */ jsx37(ViolationList, { violations: report.violations })
6069
+ ] }) : /* @__PURE__ */ jsx37(Box33, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx37(Text35, { color: COLORS.muted, dimColor: true, children: t("compliance_press_r_hint") }) })
5958
6070
  ] }),
5959
- /* @__PURE__ */ jsx36(Box33, { marginTop: SPACING.sm, flexWrap: "wrap", children: /* @__PURE__ */ jsxs34(Text35, { color: COLORS.textSecondary, children: [
6071
+ /* @__PURE__ */ jsx37(Box33, { marginTop: SPACING.sm, flexWrap: "wrap", children: /* @__PURE__ */ jsxs34(Text35, { color: COLORS.textSecondary, children: [
5960
6072
  "i:",
5961
6073
  t("hint_import"),
5962
6074
  policy && /* @__PURE__ */ jsxs34(Text35, { children: [
@@ -5979,7 +6091,7 @@ function ComplianceView() {
5979
6091
  }
5980
6092
 
5981
6093
  // src/app.tsx
5982
- import { Fragment as Fragment7, jsx as jsx37, jsxs as jsxs35 } from "react/jsx-runtime";
6094
+ import { Fragment as Fragment7, jsx as jsx38, jsxs as jsxs35 } from "react/jsx-runtime";
5983
6095
  function LicenseInitializer() {
5984
6096
  const initLicense = useLicenseStore((s) => s.initialize);
5985
6097
  useEffect23(() => {
@@ -5991,44 +6103,44 @@ function ViewRouter({ currentView }) {
5991
6103
  const isPro = useLicenseStore((s) => s.isPro);
5992
6104
  const isTeam = useLicenseStore((s) => s.isTeam);
5993
6105
  if (isProView(currentView) && !isPro()) {
5994
- return /* @__PURE__ */ jsx37(UpgradePrompt, { viewId: currentView });
6106
+ return /* @__PURE__ */ jsx38(UpgradePrompt, { viewId: currentView });
5995
6107
  }
5996
6108
  if (isTeamView(currentView) && !isTeam()) {
5997
- return /* @__PURE__ */ jsx37(UpgradePrompt, { viewId: currentView });
6109
+ return /* @__PURE__ */ jsx38(UpgradePrompt, { viewId: currentView });
5998
6110
  }
5999
6111
  switch (currentView) {
6000
6112
  case "dashboard":
6001
- return /* @__PURE__ */ jsx37(DashboardView, {});
6113
+ return /* @__PURE__ */ jsx38(DashboardView, {});
6002
6114
  case "installed":
6003
- return /* @__PURE__ */ jsx37(InstalledView, {});
6115
+ return /* @__PURE__ */ jsx38(InstalledView, {});
6004
6116
  case "search":
6005
- return /* @__PURE__ */ jsx37(SearchView, {});
6117
+ return /* @__PURE__ */ jsx38(SearchView, {});
6006
6118
  case "outdated":
6007
- return /* @__PURE__ */ jsx37(OutdatedView, {});
6119
+ return /* @__PURE__ */ jsx38(OutdatedView, {});
6008
6120
  case "package-info":
6009
- return /* @__PURE__ */ jsx37(PackageInfoView, {});
6121
+ return /* @__PURE__ */ jsx38(PackageInfoView, {});
6010
6122
  case "services":
6011
- return /* @__PURE__ */ jsx37(ServicesView, {});
6123
+ return /* @__PURE__ */ jsx38(ServicesView, {});
6012
6124
  case "doctor":
6013
- return /* @__PURE__ */ jsx37(DoctorView, {});
6125
+ return /* @__PURE__ */ jsx38(DoctorView, {});
6014
6126
  case "profiles":
6015
- return /* @__PURE__ */ jsx37(ProfilesView, {});
6127
+ return /* @__PURE__ */ jsx38(ProfilesView, {});
6016
6128
  case "smart-cleanup":
6017
- return /* @__PURE__ */ jsx37(SmartCleanupView, {});
6129
+ return /* @__PURE__ */ jsx38(SmartCleanupView, {});
6018
6130
  case "history":
6019
- return /* @__PURE__ */ jsx37(HistoryView, {});
6131
+ return /* @__PURE__ */ jsx38(HistoryView, {});
6020
6132
  case "rollback":
6021
- return /* @__PURE__ */ jsx37(RollbackView, {});
6133
+ return /* @__PURE__ */ jsx38(RollbackView, {});
6022
6134
  case "brewfile":
6023
- return /* @__PURE__ */ jsx37(BrewfileView, {});
6135
+ return /* @__PURE__ */ jsx38(BrewfileView, {});
6024
6136
  case "sync":
6025
- return /* @__PURE__ */ jsx37(SyncView, {});
6137
+ return /* @__PURE__ */ jsx38(SyncView, {});
6026
6138
  case "security-audit":
6027
- return /* @__PURE__ */ jsx37(SecurityAuditView, {});
6139
+ return /* @__PURE__ */ jsx38(SecurityAuditView, {});
6028
6140
  case "compliance":
6029
- return /* @__PURE__ */ jsx37(ComplianceView, {});
6141
+ return /* @__PURE__ */ jsx38(ComplianceView, {});
6030
6142
  case "account":
6031
- return /* @__PURE__ */ jsx37(AccountView, {});
6143
+ return /* @__PURE__ */ jsx38(AccountView, {});
6032
6144
  }
6033
6145
  }
6034
6146
  function App() {
@@ -6042,14 +6154,14 @@ function App() {
6042
6154
  }, []);
6043
6155
  useGlobalKeyboard({ onQuit: exit });
6044
6156
  if (showWelcome === null) {
6045
- return /* @__PURE__ */ jsx37(AppLayout, { children: /* @__PURE__ */ jsx37(Fragment7, {}) });
6157
+ return /* @__PURE__ */ jsx38(AppLayout, { children: /* @__PURE__ */ jsx38(Fragment7, {}) });
6046
6158
  }
6047
6159
  if (showWelcome) {
6048
- return /* @__PURE__ */ jsx37(AppLayout, { children: /* @__PURE__ */ jsx37(WelcomeView, { onContinue: () => setShowWelcome(false) }) });
6160
+ return /* @__PURE__ */ jsx38(AppLayout, { children: /* @__PURE__ */ jsx38(WelcomeView, { onContinue: () => setShowWelcome(false) }) });
6049
6161
  }
6050
6162
  return /* @__PURE__ */ jsxs35(AppLayout, { children: [
6051
- /* @__PURE__ */ jsx37(LicenseInitializer, {}),
6052
- /* @__PURE__ */ jsx37(ViewRouter, { currentView })
6163
+ /* @__PURE__ */ jsx38(LicenseInitializer, {}),
6164
+ /* @__PURE__ */ jsx38(ViewRouter, { currentView })
6053
6165
  ] });
6054
6166
  }
6055
6167
 
@@ -6133,7 +6245,7 @@ async function reportError(err, context = {}) {
6133
6245
  const config = await resolveConfig();
6134
6246
  if (!config.enabled || !config.endpoint) return;
6135
6247
  const machineId = await getMachineId();
6136
- const version = true ? "0.9.2" : "unknown";
6248
+ const version = true ? "1.0.0" : "unknown";
6137
6249
  await postReport(buildReport("error", err, context, machineId, version), config);
6138
6250
  }
6139
6251
  async function installCrashReporter() {
@@ -6142,7 +6254,7 @@ async function installCrashReporter() {
6142
6254
  if (!config.enabled || !config.endpoint) return;
6143
6255
  _installed = true;
6144
6256
  const machineId = await getMachineId();
6145
- const version = true ? "0.9.2" : "unknown";
6257
+ const version = true ? "1.0.0" : "unknown";
6146
6258
  process.on("uncaughtException", (err) => {
6147
6259
  void postReport(buildReport("fatal", err, { kind: "uncaughtException" }, machineId, version), config);
6148
6260
  });
@@ -6153,11 +6265,11 @@ async function installCrashReporter() {
6153
6265
  }
6154
6266
 
6155
6267
  // src/index.tsx
6156
- import { jsx as jsx38 } from "react/jsx-runtime";
6268
+ import { jsx as jsx39 } from "react/jsx-runtime";
6157
6269
  var [, , command, arg] = process.argv;
6158
6270
  async function runCli() {
6159
6271
  if (command === "--version" || command === "-v" || command === "version") {
6160
- process.stdout.write("0.9.2\n");
6272
+ process.stdout.write("1.0.0\n");
6161
6273
  return;
6162
6274
  }
6163
6275
  await ensureDataDirs();
@@ -6333,14 +6445,14 @@ Snapshots: ${snapshots.length} (latest: ${latest ? formatDate(latest.capturedAt)
6333
6445
  await ensureBrewBarRunning();
6334
6446
  process.env.BREW_TUI_TUI_MODE = "1";
6335
6447
  process.stdout.write("\x1B[2J\x1B[3J\x1B[H");
6336
- render(/* @__PURE__ */ jsx38(App, {}));
6448
+ render(/* @__PURE__ */ jsx39(App, {}));
6337
6449
  }
6338
6450
  async function ensureBrewBarRunning() {
6339
6451
  if (process.platform !== "darwin") return;
6340
6452
  await useLicenseStore.getState().initialize();
6341
6453
  if (!useLicenseStore.getState().isPro()) return;
6342
6454
  const { isBrewBarInstalled, installBrewBar, launchBrewBar } = await import("./brewbar-installer-GWJ76J6G.js");
6343
- const { checkBrewBarVersion } = await import("./version-check-LHQYDFDA.js");
6455
+ const { checkBrewBarVersion } = await import("./version-check-J6PTTQ7M.js");
6344
6456
  try {
6345
6457
  if (!await isBrewBarInstalled()) {
6346
6458
  console.log(t("cli_brewbarInstalling"));