git-viewer 9.0.0 → 11.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.
Files changed (2) hide show
  1. package/dist/entry.bundled.js +137 -112
  2. package/package.json +1 -1
@@ -86,6 +86,8 @@ function createContainer(target, options) {
86
86
  }
87
87
  };
88
88
  }
89
+ var TypedEventTarget = class extends EventTarget {
90
+ };
89
91
  var interactions = /* @__PURE__ */ new Map();
90
92
  var initializedTargets = /* @__PURE__ */ new WeakMap();
91
93
  function defaultOnError(error) {
@@ -1589,74 +1591,54 @@ function jsx(type, props, key) {
1589
1591
  }
1590
1592
 
1591
1593
  // entry.tsx
1592
- var state = {
1593
- refs: null,
1594
- commits: [],
1595
- maxLane: 0,
1596
- selectedCommit: null,
1597
- diff: null,
1598
- filter: "all",
1599
- search: "",
1600
- loading: true,
1601
- fullscreenDiff: false
1602
- };
1603
- var updateApp;
1604
- async function fetchRefs() {
1605
- let res = await fetch("/api/refs");
1594
+ async function fetchRefs(signal) {
1595
+ let res = await fetch("/api/refs", { signal });
1606
1596
  return res.json();
1607
1597
  }
1608
- async function fetchCommits(ref, search) {
1598
+ async function fetchCommits(ref, search, signal) {
1609
1599
  let params = new URLSearchParams();
1610
1600
  if (ref) params.set("ref", ref);
1611
1601
  if (search) params.set("search", search);
1612
- let res = await fetch(`/api/commits?${params}`);
1602
+ let res = await fetch(`/api/commits?${params}`, { signal });
1613
1603
  let data = await res.json();
1614
1604
  return { commits: data.commits, maxLane: data.maxLane };
1615
1605
  }
1616
- async function fetchDiff(sha) {
1617
- let res = await fetch(`/api/diff/${sha}`);
1606
+ async function fetchDiff(sha, signal) {
1607
+ let res = await fetch(`/api/diff/${sha}`, { signal });
1618
1608
  return res.json();
1619
1609
  }
1620
- async function setFilter(filter) {
1621
- state.filter = filter;
1622
- state.loading = true;
1623
- updateApp();
1624
- let ref = filter === "all" ? "all" : filter === "local" ? state.refs?.currentBranch : filter;
1625
- let result = await fetchCommits(ref, state.search);
1626
- state.commits = result.commits;
1627
- state.maxLane = result.maxLane;
1628
- state.loading = false;
1629
- updateApp();
1630
- }
1631
- async function setSearch(search) {
1632
- state.search = search;
1633
- state.loading = true;
1634
- updateApp();
1635
- let ref = state.filter === "all" ? "all" : state.filter === "local" ? state.refs?.currentBranch : state.filter;
1636
- let result = await fetchCommits(ref, search);
1637
- state.commits = result.commits;
1638
- state.maxLane = result.maxLane;
1639
- state.loading = false;
1640
- updateApp();
1641
- }
1642
- async function selectCommit(commit) {
1643
- state.selectedCommit = commit;
1644
- state.diff = null;
1645
- updateApp();
1646
- state.diff = await fetchDiff(commit.sha);
1647
- updateApp();
1648
- }
1649
- function toggleFullscreenDiff(open) {
1650
- if (!document.startViewTransition) {
1651
- state.fullscreenDiff = open;
1652
- updateApp();
1653
- return;
1610
+ var AppStore = class extends TypedEventTarget {
1611
+ constructor() {
1612
+ super(...arguments);
1613
+ __publicField(this, "refs", null);
1614
+ __publicField(this, "filter", "all");
1615
+ __publicField(this, "search", "");
1616
+ __publicField(this, "selectedCommit", null);
1617
+ __publicField(this, "fullscreenDiff", false);
1618
+ }
1619
+ setRefs(refs) {
1620
+ this.refs = refs;
1621
+ this.dispatchEvent(new Event("refs"));
1622
+ }
1623
+ setFilter(filter) {
1624
+ this.filter = filter;
1625
+ this.dispatchEvent(new Event("filter"));
1626
+ }
1627
+ setSearch(search) {
1628
+ this.search = search;
1629
+ this.dispatchEvent(new Event("filter"));
1630
+ }
1631
+ selectCommit(commit) {
1632
+ this.selectedCommit = commit;
1633
+ this.dispatchEvent(new Event("selectedCommit"));
1634
+ }
1635
+ toggleFullscreenDiff(open) {
1636
+ document.startViewTransition(() => {
1637
+ this.fullscreenDiff = open;
1638
+ this.dispatchEvent(new Event("fullscreenDiff"));
1639
+ });
1654
1640
  }
1655
- document.startViewTransition(() => {
1656
- state.fullscreenDiff = open;
1657
- updateApp();
1658
- });
1659
- }
1641
+ };
1660
1642
  var colors = {
1661
1643
  bg: "#ffffff",
1662
1644
  bgLight: "#f6f8fa",
@@ -1688,17 +1670,11 @@ var graphColors = [
1688
1670
  // dark blue
1689
1671
  ];
1690
1672
  function App(handle) {
1691
- updateApp = () => handle.update();
1692
- handle.queueTask(async () => {
1693
- let [refs, commitsResult] = await Promise.all([
1694
- fetchRefs(),
1695
- fetchCommits("all")
1696
- ]);
1697
- state.refs = refs;
1698
- state.commits = commitsResult.commits;
1699
- state.maxLane = commitsResult.maxLane;
1700
- state.loading = false;
1701
- handle.update();
1673
+ let store = new AppStore();
1674
+ handle.context.set(store);
1675
+ handle.queueTask(async (signal) => {
1676
+ let refs = await fetchRefs(signal);
1677
+ store.setRefs(refs);
1702
1678
  });
1703
1679
  return () => /* @__PURE__ */ jsx(
1704
1680
  "div",
@@ -1718,7 +1694,11 @@ function App(handle) {
1718
1694
  }
1719
1695
  );
1720
1696
  }
1721
- function Sidebar() {
1697
+ function Sidebar(handle) {
1698
+ let store = handle.context.get(App);
1699
+ handle.on(store, {
1700
+ refs: () => handle.update()
1701
+ });
1722
1702
  return () => /* @__PURE__ */ jsx(
1723
1703
  "div",
1724
1704
  {
@@ -1735,17 +1715,17 @@ function Sidebar() {
1735
1715
  css: {
1736
1716
  padding: "12px",
1737
1717
  fontWeight: 600,
1738
- fontSize: "11px",
1739
1718
  textTransform: "uppercase",
1740
1719
  letterSpacing: "0.5px",
1741
- color: colors.textMuted
1720
+ color: colors.textMuted,
1721
+ borderBottom: `1px solid ${colors.border}`
1742
1722
  },
1743
1723
  children: "Git Tree Viewer"
1744
1724
  }
1745
1725
  ),
1746
- /* @__PURE__ */ jsx("div", { css: { flex: 1, overflow: "auto", padding: "8px 0" }, children: state.refs && /* @__PURE__ */ jsx(Fragment, { children: [
1747
- /* @__PURE__ */ jsx(RefSection, { title: "LOCAL", nodes: state.refs.local }),
1748
- Object.entries(state.refs.remotes).map(([remote, nodes]) => /* @__PURE__ */ jsx(
1726
+ /* @__PURE__ */ jsx("div", { css: { flex: 1, overflow: "auto", padding: "8px 0" }, children: store.refs && /* @__PURE__ */ jsx(Fragment, { children: [
1727
+ /* @__PURE__ */ jsx(RefSection, { title: "LOCAL", nodes: store.refs.local }),
1728
+ Object.entries(store.refs.remotes).map(([remote, nodes]) => /* @__PURE__ */ jsx(
1749
1729
  RefSection,
1750
1730
  {
1751
1731
  title: remote.toUpperCase(),
@@ -1791,7 +1771,11 @@ function RefSection(handle) {
1791
1771
  ] });
1792
1772
  }
1793
1773
  function RefNodeItem(handle) {
1774
+ let store = handle.context.get(App);
1794
1775
  let expanded = true;
1776
+ handle.on(store, {
1777
+ filter: () => handle.update()
1778
+ });
1795
1779
  return ({ node, depth }) => {
1796
1780
  let paddingLeft = 12 + depth * 12;
1797
1781
  if (node.type === "folder") {
@@ -1825,7 +1809,7 @@ function RefNodeItem(handle) {
1825
1809
  expanded && node.children.map((child) => /* @__PURE__ */ jsx(RefNodeItem, { node: child, depth: depth + 1 }, child.name))
1826
1810
  ] });
1827
1811
  }
1828
- let isSelected = state.filter === node.fullName;
1812
+ let isSelected = store.filter === node.fullName;
1829
1813
  return /* @__PURE__ */ jsx(
1830
1814
  "div",
1831
1815
  {
@@ -1843,7 +1827,7 @@ function RefNodeItem(handle) {
1843
1827
  background: isSelected ? colors.accentDim : colors.bgLighter
1844
1828
  }
1845
1829
  },
1846
- on: { click: () => setFilter(node.fullName) },
1830
+ on: { click: () => store.setFilter(node.fullName) },
1847
1831
  children: [
1848
1832
  node.current && /* @__PURE__ */ jsx("span", { css: { fontSize: "8px", marginRight: "4px" }, children: "\u25CF" }),
1849
1833
  node.name
@@ -1869,12 +1853,27 @@ function MainPanel() {
1869
1853
  }
1870
1854
  );
1871
1855
  }
1872
- function CommitList() {
1873
- let searchTimeout = null;
1874
- function handleSearch(value) {
1875
- if (searchTimeout) clearTimeout(searchTimeout);
1876
- searchTimeout = setTimeout(() => setSearch(value), 300);
1856
+ function CommitList(handle) {
1857
+ let store = handle.context.get(App);
1858
+ let commits = [];
1859
+ let loading = true;
1860
+ async function loadCommits(signal) {
1861
+ loading = true;
1862
+ handle.update();
1863
+ let ref = store.filter === "all" ? "all" : store.filter === "local" ? store.refs?.currentBranch : store.filter;
1864
+ let result = await fetchCommits(ref, store.search, signal);
1865
+ commits = result.commits;
1866
+ loading = false;
1867
+ handle.update();
1877
1868
  }
1869
+ handle.on(store, {
1870
+ refs(_, signal) {
1871
+ loadCommits(signal);
1872
+ },
1873
+ filter(_, signal) {
1874
+ loadCommits(signal);
1875
+ }
1876
+ });
1878
1877
  return () => /* @__PURE__ */ jsx(
1879
1878
  "div",
1880
1879
  {
@@ -1893,18 +1892,18 @@ function CommitList() {
1893
1892
  display: "flex",
1894
1893
  alignItems: "center",
1895
1894
  gap: "8px",
1896
- padding: "8px 12px",
1895
+ padding: "7.5px 12px",
1897
1896
  borderBottom: `1px solid ${colors.border}`,
1898
1897
  background: colors.bgLight
1899
1898
  },
1900
1899
  children: [
1901
1900
  /* @__PURE__ */ jsx(FilterButton, { label: "All", filter: "all" }),
1902
1901
  /* @__PURE__ */ jsx(FilterButton, { label: "Local", filter: "local" }),
1903
- state.refs && /* @__PURE__ */ jsx(
1902
+ store.refs && /* @__PURE__ */ jsx(
1904
1903
  FilterButton,
1905
1904
  {
1906
- label: state.refs.currentBranch,
1907
- filter: state.refs.currentBranch
1905
+ label: store.refs.currentBranch,
1906
+ filter: store.refs.currentBranch
1908
1907
  }
1909
1908
  ),
1910
1909
  /* @__PURE__ */ jsx("div", { css: { flex: 1 } }),
@@ -1925,14 +1924,14 @@ function CommitList() {
1925
1924
  "&::placeholder": { color: colors.textMuted }
1926
1925
  },
1927
1926
  on: {
1928
- input: (e) => handleSearch(e.target.value)
1927
+ input: (e) => store.setSearch(e.currentTarget.value)
1929
1928
  }
1930
1929
  }
1931
1930
  )
1932
1931
  ]
1933
1932
  }
1934
1933
  ),
1935
- /* @__PURE__ */ jsx("div", { css: { flex: 1, overflow: "auto" }, children: state.loading ? /* @__PURE__ */ jsx(
1934
+ /* @__PURE__ */ jsx("div", { css: { flex: 1, overflow: "auto" }, children: loading && commits.length === 0 ? /* @__PURE__ */ jsx(
1936
1935
  "div",
1937
1936
  {
1938
1937
  css: {
@@ -1976,7 +1975,7 @@ function CommitList() {
1976
1975
  /* @__PURE__ */ jsx("th", { css: { width: "150px" }, children: "Date" }),
1977
1976
  /* @__PURE__ */ jsx("th", { css: { width: "80px" }, children: "SHA" })
1978
1977
  ] }) }),
1979
- /* @__PURE__ */ jsx("tbody", { children: state.commits.map((commit) => /* @__PURE__ */ jsx(CommitRow, { commit }, commit.sha)) })
1978
+ /* @__PURE__ */ jsx("tbody", { children: commits.map((commit) => /* @__PURE__ */ jsx(CommitRow, { commit }, commit.sha)) })
1980
1979
  ]
1981
1980
  }
1982
1981
  ) })
@@ -1984,9 +1983,13 @@ function CommitList() {
1984
1983
  }
1985
1984
  );
1986
1985
  }
1987
- function FilterButton() {
1986
+ function FilterButton(handle) {
1987
+ let store = handle.context.get(App);
1988
+ handle.on(store, {
1989
+ filter: () => handle.update()
1990
+ });
1988
1991
  return ({ label, filter }) => {
1989
- let isActive = state.filter === filter;
1992
+ let isActive = store.filter === filter;
1990
1993
  return /* @__PURE__ */ jsx(
1991
1994
  "button",
1992
1995
  {
@@ -2000,15 +2003,19 @@ function FilterButton() {
2000
2003
  cursor: "pointer",
2001
2004
  "&:hover": { borderColor: colors.accent }
2002
2005
  },
2003
- on: { click: () => setFilter(filter) },
2006
+ on: { click: () => store.setFilter(filter) },
2004
2007
  children: label
2005
2008
  }
2006
2009
  );
2007
2010
  };
2008
2011
  }
2009
- function CommitRow() {
2012
+ function CommitRow(handle) {
2013
+ let store = handle.context.get(App);
2014
+ handle.on(store, {
2015
+ selectedCommit: () => handle.update()
2016
+ });
2010
2017
  return ({ commit }) => {
2011
- let isSelected = state.selectedCommit?.sha === commit.sha;
2018
+ let isSelected = store.selectedCommit?.sha === commit.sha;
2012
2019
  let { graph } = commit;
2013
2020
  let maxUsedLane = graph.lane;
2014
2021
  for (let line of graph.lines) {
@@ -2023,7 +2030,7 @@ function CommitRow() {
2023
2030
  cursor: "pointer",
2024
2031
  background: isSelected ? colors.accentDim : "transparent"
2025
2032
  },
2026
- on: { click: () => selectCommit(commit) },
2033
+ on: { click: () => store.selectCommit(commit) },
2027
2034
  children: [
2028
2035
  /* @__PURE__ */ jsx("td", { css: { display: "flex", alignItems: "center" }, children: [
2029
2036
  /* @__PURE__ */ jsx(
@@ -2132,8 +2139,26 @@ function CommitRow() {
2132
2139
  );
2133
2140
  };
2134
2141
  }
2135
- function DiffPanel() {
2142
+ function DiffPanel(handle) {
2143
+ let store = handle.context.get(App);
2144
+ let diff = null;
2136
2145
  let diffContentRef;
2146
+ handle.on(store, {
2147
+ async selectedCommit(_, signal) {
2148
+ if (!store.selectedCommit) {
2149
+ diff = null;
2150
+ handle.update();
2151
+ return;
2152
+ }
2153
+ diff = null;
2154
+ handle.update();
2155
+ diff = await fetchDiff(store.selectedCommit.sha, signal);
2156
+ handle.update();
2157
+ },
2158
+ fullscreenDiff() {
2159
+ handle.update();
2160
+ }
2161
+ });
2137
2162
  function scrollToFile(path) {
2138
2163
  if (!diffContentRef || !path) return;
2139
2164
  let fileHeaders = diffContentRef.querySelectorAll(".d2h-file-header");
@@ -2146,8 +2171,8 @@ function DiffPanel() {
2146
2171
  }
2147
2172
  }
2148
2173
  return () => {
2149
- let isFullscreen = state.fullscreenDiff;
2150
- if (!state.selectedCommit) {
2174
+ let isFullscreen = store.fullscreenDiff;
2175
+ if (!store.selectedCommit) {
2151
2176
  return /* @__PURE__ */ jsx(
2152
2177
  "div",
2153
2178
  {
@@ -2196,23 +2221,23 @@ function DiffPanel() {
2196
2221
  },
2197
2222
  children: [
2198
2223
  /* @__PURE__ */ jsx("div", { css: { flex: 1, minWidth: 0 }, children: [
2199
- /* @__PURE__ */ jsx("div", { css: { fontWeight: 600, marginBottom: "4px" }, children: state.selectedCommit.subject }),
2224
+ /* @__PURE__ */ jsx("div", { css: { fontWeight: 600, marginBottom: "4px" }, children: store.selectedCommit.subject }),
2200
2225
  /* @__PURE__ */ jsx("div", { css: { fontSize: "12px", color: colors.textMuted }, children: [
2201
- /* @__PURE__ */ jsx("span", { children: state.selectedCommit.author }),
2226
+ /* @__PURE__ */ jsx("span", { children: store.selectedCommit.author }),
2202
2227
  /* @__PURE__ */ jsx("span", { css: { margin: "0 8px" }, children: "\u2022" }),
2203
- /* @__PURE__ */ jsx("span", { children: state.selectedCommit.date }),
2228
+ /* @__PURE__ */ jsx("span", { children: store.selectedCommit.date }),
2204
2229
  /* @__PURE__ */ jsx("span", { css: { margin: "0 8px" }, children: "\u2022" }),
2205
- /* @__PURE__ */ jsx("code", { css: { color: colors.accent }, children: state.selectedCommit.shortSha }),
2206
- state.diff && /* @__PURE__ */ jsx(Fragment, { children: [
2230
+ /* @__PURE__ */ jsx("code", { css: { color: colors.accent }, children: store.selectedCommit.shortSha }),
2231
+ diff && /* @__PURE__ */ jsx(Fragment, { children: [
2207
2232
  /* @__PURE__ */ jsx("span", { css: { margin: "0 8px" }, children: "\u2022" }),
2208
2233
  /* @__PURE__ */ jsx("span", { children: [
2209
- state.diff.files.length,
2234
+ diff.files.length,
2210
2235
  " file",
2211
- state.diff.files.length !== 1 ? "s" : ""
2236
+ diff.files.length !== 1 ? "s" : ""
2212
2237
  ] })
2213
2238
  ] })
2214
2239
  ] }),
2215
- state.selectedCommit.body && /* @__PURE__ */ jsx(
2240
+ store.selectedCommit.body && /* @__PURE__ */ jsx(
2216
2241
  "div",
2217
2242
  {
2218
2243
  css: {
@@ -2221,11 +2246,11 @@ function DiffPanel() {
2221
2246
  fontSize: "12px",
2222
2247
  lineHeight: "1.4"
2223
2248
  },
2224
- children: state.selectedCommit.body
2249
+ children: store.selectedCommit.body
2225
2250
  }
2226
2251
  )
2227
2252
  ] }),
2228
- state.diff && /* @__PURE__ */ jsx(
2253
+ diff && /* @__PURE__ */ jsx(
2229
2254
  "button",
2230
2255
  {
2231
2256
  css: {
@@ -2245,7 +2270,7 @@ function DiffPanel() {
2245
2270
  borderColor: colors.accent
2246
2271
  }
2247
2272
  },
2248
- on: { click: () => toggleFullscreenDiff(!isFullscreen) },
2273
+ on: { click: () => store.toggleFullscreenDiff(!isFullscreen) },
2249
2274
  children: isFullscreen ? /* @__PURE__ */ jsx(Fragment, { children: [
2250
2275
  /* @__PURE__ */ jsx(
2251
2276
  "svg",
@@ -2281,7 +2306,7 @@ function DiffPanel() {
2281
2306
  }
2282
2307
  ),
2283
2308
  /* @__PURE__ */ jsx("div", { css: { flex: 1, display: "flex", overflow: "hidden" }, children: [
2284
- state.diff && state.diff.files.length > 0 && /* @__PURE__ */ jsx(
2309
+ diff && diff.files.length > 0 && /* @__PURE__ */ jsx(
2285
2310
  "div",
2286
2311
  {
2287
2312
  css: {
@@ -2307,7 +2332,7 @@ function DiffPanel() {
2307
2332
  children: "Changed Files"
2308
2333
  }
2309
2334
  ),
2310
- /* @__PURE__ */ jsx("div", { css: { flex: 1, overflow: "auto", padding: "4px 0" }, children: state.diff.files.map((file) => /* @__PURE__ */ jsx(
2335
+ /* @__PURE__ */ jsx("div", { css: { flex: 1, overflow: "auto", padding: "4px 0" }, children: diff.files.map((file) => /* @__PURE__ */ jsx(
2311
2336
  FileListItem,
2312
2337
  {
2313
2338
  file,
@@ -2318,7 +2343,7 @@ function DiffPanel() {
2318
2343
  ]
2319
2344
  }
2320
2345
  ),
2321
- /* @__PURE__ */ jsx("div", { css: { flex: 1, overflow: "auto" }, children: state.diff ? /* @__PURE__ */ jsx(
2346
+ /* @__PURE__ */ jsx("div", { css: { flex: 1, overflow: "auto" }, children: diff ? /* @__PURE__ */ jsx(
2322
2347
  "section",
2323
2348
  {
2324
2349
  connect: (node) => diffContentRef = node,
@@ -2348,7 +2373,7 @@ function DiffPanel() {
2348
2373
  },
2349
2374
  "& .d2h-diff-tbody": { position: "relative" }
2350
2375
  },
2351
- innerHTML: state.diff.diffHtml
2376
+ innerHTML: diff.diffHtml
2352
2377
  }
2353
2378
  ) : /* @__PURE__ */ jsx(
2354
2379
  "div",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "git-viewer",
3
- "version": "9.0.0",
3
+ "version": "11.0.0",
4
4
  "description": "Visual git log viewer with branch graph and diff display",
5
5
  "repository": {
6
6
  "type": "git",