epiq 1.4.3 → 1.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/gui/main.js CHANGED
@@ -24858,7 +24858,8 @@ var GUI_THEME = {
24858
24858
  dim2: "rgb(100 107 133)",
24859
24859
  accent: "#76d4ff",
24860
24860
  green: "#8ce99a",
24861
- red: "#ff8787"
24861
+ red: "#ff8787",
24862
+ transparent: "rgba(0, 0, 0, 0)"
24862
24863
  };
24863
24864
  var EVENT_CATEGORY_COLORS = {
24864
24865
  tickets: GUI_THEME.accent,
@@ -25324,11 +25325,16 @@ var User = ({
25324
25325
  );
25325
25326
 
25326
25327
  // source/version.ts
25327
- var EPIQ_VERSION = "1.4.3";
25328
+ var EPIQ_VERSION = "1.4.5";
25328
25329
 
25329
25330
  // source/gui/client/components/Header.tsx
25330
25331
  var import_jsx_runtime7 = __toESM(require_jsx_runtime(), 1);
25331
- var Header = ({ state, connected, syncStatus }) => {
25332
+ var Header = ({
25333
+ state,
25334
+ connected,
25335
+ scrubbing,
25336
+ syncStatus
25337
+ }) => {
25332
25338
  const syncColor = syncStatus.status === "synced" ? GUI_THEME.green : syncStatus.status === "failed" ? GUI_THEME.red : GUI_THEME.accent;
25333
25339
  const syncLabel = syncStatus.status === "failed" ? "-" : syncStatus.msg.toLowerCase();
25334
25340
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
@@ -25387,6 +25393,10 @@ var Header = ({ state, connected, syncStatus }) => {
25387
25393
  whiteSpace: "nowrap"
25388
25394
  },
25389
25395
  children: [
25396
+ scrubbing && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
25397
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { color: GUI_THEME.accent, fontWeight: 700 }, children: "Read-only" }),
25398
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { color: GUI_THEME.dim }, children: "|" })
25399
+ ] }),
25390
25400
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
25391
25401
  "span",
25392
25402
  {
@@ -25403,7 +25413,6 @@ var Header = ({ state, connected, syncStatus }) => {
25403
25413
  title: syncStatus.status === "failed" ? syncStatus.msg : void 0,
25404
25414
  style: {
25405
25415
  color: GUI_THEME.dim,
25406
- minWidth: 72,
25407
25416
  maxWidth: 220,
25408
25417
  overflow: "hidden",
25409
25418
  textOverflow: "ellipsis",
@@ -27721,11 +27730,11 @@ function addChildren(props, children) {
27721
27730
  }
27722
27731
  }
27723
27732
  }
27724
- function productionCreate(_, jsx35, jsxs23) {
27733
+ function productionCreate(_, jsx37, jsxs25) {
27725
27734
  return create2;
27726
27735
  function create2(_2, type, props, key) {
27727
27736
  const isStaticChildren = Array.isArray(props.children);
27728
- const fn = isStaticChildren ? jsxs23 : jsx35;
27737
+ const fn = isStaticChildren ? jsxs25 : jsx37;
27729
27738
  return key ? fn(type, props, key) : fn(type, props);
27730
27739
  }
27731
27740
  }
@@ -39653,23 +39662,23 @@ var import_react11 = __toESM(require_react(), 1);
39653
39662
 
39654
39663
  // source/gui/client/components/IconComment.tsx
39655
39664
  var import_jsx_runtime22 = __toESM(require_jsx_runtime(), 1);
39656
- var IconComment = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
39665
+ var IconComment = ({ size = 14 }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
39657
39666
  "svg",
39658
39667
  {
39659
39668
  width: size,
39660
39669
  height: size,
39661
- viewBox: "0 0 16 16",
39670
+ viewBox: "0 0 24 24",
39662
39671
  fill: "none",
39672
+ stroke: "currentColor",
39673
+ strokeWidth: "2",
39674
+ strokeLinecap: "round",
39675
+ strokeLinejoin: "round",
39663
39676
  "aria-hidden": "true",
39664
39677
  children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
39665
39678
  "path",
39666
39679
  {
39667
- d: "M3.9 2.6h5.2a2.4 2.4 0 0 1 2.4 2.4v2.5a2.4 2.4 0 0 1-2.4 2.4H6.6l-1.8 2.1.2-2.1H3.9a2.4 2.4 0 0 1-2.4-2.4V5a2.4 2.4 0 0 1 2.4-2.4Z",
39668
39680
  fill: "currentColor",
39669
- stroke: "currentColor",
39670
- strokeWidth: "1.55",
39671
- strokeLinecap: "round",
39672
- strokeLinejoin: "round"
39681
+ d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"
39673
39682
  }
39674
39683
  )
39675
39684
  }
@@ -39864,7 +39873,7 @@ var TicketCard = ({
39864
39873
  color: isSelected ? GUI_THEME.accent : GUI_THEME.secondary,
39865
39874
  background: isSelected ? "rgba(118,228,255,0.10)" : "rgba(255,255,255,0.035)",
39866
39875
  border: `1px solid ${isSelected ? "rgba(118,228,255,0.28)" : GUI_THEME.line}`,
39867
- borderRadius: 999,
39876
+ borderRadius: 6,
39868
39877
  padding: "3px 7px",
39869
39878
  fontSize: 11,
39870
39879
  fontWeight: 600,
@@ -40681,9 +40690,32 @@ var Checkbox = ({
40681
40690
  );
40682
40691
  };
40683
40692
 
40684
- // source/gui/client/components/IconChevronDown.tsx
40693
+ // source/gui/client/components/IconBars.tsx
40685
40694
  var import_jsx_runtime28 = __toESM(require_jsx_runtime(), 1);
40686
- var IconChevronDown = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
40695
+ var IconBars = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
40696
+ "svg",
40697
+ {
40698
+ width: size,
40699
+ height: size,
40700
+ viewBox: "0 0 24 24",
40701
+ fill: "none",
40702
+ stroke: "currentColor",
40703
+ strokeWidth: "2.2",
40704
+ strokeLinecap: "round",
40705
+ "aria-hidden": "true",
40706
+ children: [
40707
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("line", { x1: "3", y1: "8.5", x2: "3", y2: "15.5" }),
40708
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("line", { x1: "7.5", y1: "4.5", x2: "7.5", y2: "19.5" }),
40709
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("line", { x1: "12", y1: "7", x2: "12", y2: "17" }),
40710
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("line", { x1: "16.5", y1: "3", x2: "16.5", y2: "21" }),
40711
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("line", { x1: "21", y1: "9.5", x2: "21", y2: "14.5" })
40712
+ ]
40713
+ }
40714
+ );
40715
+
40716
+ // source/gui/client/components/IconChevronDown.tsx
40717
+ var import_jsx_runtime29 = __toESM(require_jsx_runtime(), 1);
40718
+ var IconChevronDown = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
40687
40719
  "svg",
40688
40720
  {
40689
40721
  width: size,
@@ -40695,13 +40727,13 @@ var IconChevronDown = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime2
40695
40727
  strokeLinecap: "round",
40696
40728
  strokeLinejoin: "round",
40697
40729
  "aria-hidden": "true",
40698
- children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("polyline", { points: "6 9 12 15 18 9" })
40730
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("polyline", { points: "6 9 12 15 18 9" })
40699
40731
  }
40700
40732
  );
40701
40733
 
40702
40734
  // source/gui/client/components/IconChevronRight.tsx
40703
- var import_jsx_runtime29 = __toESM(require_jsx_runtime(), 1);
40704
- var IconChevronRight = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
40735
+ var import_jsx_runtime30 = __toESM(require_jsx_runtime(), 1);
40736
+ var IconChevronRight = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
40705
40737
  "svg",
40706
40738
  {
40707
40739
  width: size,
@@ -40713,12 +40745,33 @@ var IconChevronRight = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime
40713
40745
  strokeLinecap: "round",
40714
40746
  strokeLinejoin: "round",
40715
40747
  "aria-hidden": "true",
40716
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("polyline", { points: "9 18 15 12 9 6" })
40748
+ children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("polyline", { points: "9 18 15 12 9 6" })
40749
+ }
40750
+ );
40751
+
40752
+ // source/gui/client/components/IconScatter.tsx
40753
+ var import_jsx_runtime31 = __toESM(require_jsx_runtime(), 1);
40754
+ var IconScatter = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
40755
+ "svg",
40756
+ {
40757
+ width: size,
40758
+ height: size,
40759
+ viewBox: "0 0 24 24",
40760
+ fill: "currentColor",
40761
+ stroke: "none",
40762
+ "aria-hidden": "true",
40763
+ children: [
40764
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("circle", { cx: "4.5", cy: "8", r: "2.2" }),
40765
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("circle", { cx: "9.5", cy: "17", r: "2.2" }),
40766
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("circle", { cx: "13", cy: "6.5", r: "2.2" }),
40767
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("circle", { cx: "17", cy: "14.5", r: "2.2" }),
40768
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("circle", { cx: "20.5", cy: "8.5", r: "2.2" })
40769
+ ]
40717
40770
  }
40718
40771
  );
40719
40772
 
40720
40773
  // source/gui/client/components/ScrubberParts.tsx
40721
- var import_jsx_runtime30 = __toESM(require_jsx_runtime(), 1);
40774
+ var import_jsx_runtime32 = __toESM(require_jsx_runtime(), 1);
40722
40775
  var toggleButtonStyle = (active) => ({
40723
40776
  background: "transparent",
40724
40777
  border: `1px solid ${active ? GUI_THEME.accent : GUI_THEME.dim}`,
@@ -40728,6 +40781,13 @@ var toggleButtonStyle = (active) => ({
40728
40781
  padding: "2px 8px",
40729
40782
  cursor: "pointer"
40730
40783
  });
40784
+ var iconToggleButtonStyle = (active) => ({
40785
+ ...toggleButtonStyle(active),
40786
+ display: "inline-flex",
40787
+ alignItems: "center",
40788
+ justifyContent: "center",
40789
+ padding: "3px 7px"
40790
+ });
40731
40791
  var CATEGORY_LABELS = {
40732
40792
  tickets: "Tickets",
40733
40793
  comments: "Comments",
@@ -40789,7 +40849,11 @@ var popoverStyle = {
40789
40849
  // Sized for the common case up front, so opening a kind with a list does
40790
40850
  // not visibly widen the panel under the pointer.
40791
40851
  minWidth: 200,
40792
- background: GUI_THEME.panel2,
40852
+ // Slightly sheer over a blur, so the chart it filters stays legible beneath
40853
+ // it rather than being covered outright.
40854
+ background: "rgba(21, 26, 36, 0.88)",
40855
+ backdropFilter: "blur(12px)",
40856
+ WebkitBackdropFilter: "blur(12px)",
40793
40857
  border: `1px solid ${GUI_THEME.line}`,
40794
40858
  borderRadius: 8,
40795
40859
  boxShadow: "0 8px 24px rgba(0, 0, 0, 0.45)",
@@ -40833,7 +40897,7 @@ var Radio = ({
40833
40897
  color: color2,
40834
40898
  disabled,
40835
40899
  onSelect
40836
- }) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
40900
+ }) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
40837
40901
  "button",
40838
40902
  {
40839
40903
  type: "button",
@@ -40855,7 +40919,7 @@ var Radio = ({
40855
40919
  opacity: disabled ? 0.4 : 1
40856
40920
  },
40857
40921
  children: [
40858
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
40922
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
40859
40923
  "span",
40860
40924
  {
40861
40925
  style: {
@@ -40868,7 +40932,7 @@ var Radio = ({
40868
40932
  justifyContent: "center",
40869
40933
  flexShrink: 0
40870
40934
  },
40871
- children: selected && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
40935
+ children: selected && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
40872
40936
  "span",
40873
40937
  {
40874
40938
  style: {
@@ -40905,14 +40969,14 @@ var BoardSeriesGroup = ({
40905
40969
  const label = sole ? `${VIEW_LABELS[view]}: ${sole.name}` : partial ? `${VIEW_LABELS[view]} (multi)` : VIEW_LABELS[view];
40906
40970
  const color2 = sole?.color ?? (partial ? GUI_THEME.dim2 : boardViewColor(view));
40907
40971
  const ref = useDismissOnOutsideClick(expanded, onToggleExpanded);
40908
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
40972
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
40909
40973
  "div",
40910
40974
  {
40911
40975
  ref,
40912
40976
  style: { position: "relative", display: "flex", flexDirection: "column" },
40913
40977
  children: [
40914
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
40915
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
40978
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
40979
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
40916
40980
  Checkbox,
40917
40981
  {
40918
40982
  label: null,
@@ -40922,7 +40986,7 @@ var BoardSeriesGroup = ({
40922
40986
  onChange: onChangeShowIssues
40923
40987
  }
40924
40988
  ),
40925
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
40989
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
40926
40990
  "button",
40927
40991
  {
40928
40992
  type: "button",
@@ -40933,7 +40997,7 @@ var BoardSeriesGroup = ({
40933
40997
  "aria-expanded": expanded,
40934
40998
  style: selectTriggerStyle(color2, !showIssues),
40935
40999
  children: [
40936
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41000
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
40937
41001
  "span",
40938
41002
  {
40939
41003
  style: {
@@ -40944,22 +41008,22 @@ var BoardSeriesGroup = ({
40944
41008
  children: label
40945
41009
  }
40946
41010
  ),
40947
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { style: { display: "inline-flex", flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(IconChevronDown, { size: 12 }) })
41011
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { style: { display: "inline-flex", flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(IconChevronDown, { size: 12 }) })
40948
41012
  ]
40949
41013
  }
40950
41014
  )
40951
41015
  ] }),
40952
- expanded && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { role: "radiogroup", style: popoverStyle, children: BOARD_VIEWS.map((option) => {
41016
+ expanded && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { role: "radiogroup", style: popoverStyle, children: BOARD_VIEWS.map((option) => {
40953
41017
  const selected = view === option;
40954
41018
  const hasList = identityAxisFor(option) !== null;
40955
41019
  const open = selected && identitiesExpanded;
40956
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
41020
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
40957
41021
  "div",
40958
41022
  {
40959
41023
  style: { display: "flex", flexDirection: "column", gap: 7 },
40960
41024
  children: [
40961
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 3 }, children: [
40962
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41025
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 3 }, children: [
41026
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
40963
41027
  Radio,
40964
41028
  {
40965
41029
  label: VIEW_LABELS[option],
@@ -40969,7 +41033,7 @@ var BoardSeriesGroup = ({
40969
41033
  onSelect: () => onChangeView(option)
40970
41034
  }
40971
41035
  ),
40972
- hasList && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41036
+ hasList && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
40973
41037
  "button",
40974
41038
  {
40975
41039
  type: "button",
@@ -40981,11 +41045,11 @@ var BoardSeriesGroup = ({
40981
41045
  title: open ? "Hide the list" : "Pick which to show",
40982
41046
  "aria-expanded": open,
40983
41047
  style: disclosureStyle,
40984
- children: open ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(IconChevronDown, { size: 12 }) : /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(IconChevronRight, { size: 12 })
41048
+ children: open ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(IconChevronDown, { size: 12 }) : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(IconChevronRight, { size: 12 })
40985
41049
  }
40986
41050
  )
40987
41051
  ] }),
40988
- open && identities.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41052
+ open && identities.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
40989
41053
  "div",
40990
41054
  {
40991
41055
  style: {
@@ -40995,7 +41059,7 @@ var BoardSeriesGroup = ({
40995
41059
  maxHeight: 132,
40996
41060
  overflowY: "auto"
40997
41061
  },
40998
- children: identities.map((identity) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
41062
+ children: identities.map((identity) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
40999
41063
  "div",
41000
41064
  {
41001
41065
  style: {
@@ -41005,7 +41069,7 @@ var BoardSeriesGroup = ({
41005
41069
  gap: 10
41006
41070
  },
41007
41071
  children: [
41008
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41072
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
41009
41073
  Checkbox,
41010
41074
  {
41011
41075
  label: identity.name,
@@ -41015,7 +41079,7 @@ var BoardSeriesGroup = ({
41015
41079
  onChange: (next) => onToggleIdentity(identity.id, next)
41016
41080
  }
41017
41081
  ),
41018
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41082
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
41019
41083
  "button",
41020
41084
  {
41021
41085
  type: "button",
@@ -41066,7 +41130,7 @@ var ScrubberControls = ({
41066
41130
  identitiesExpanded,
41067
41131
  categoriesFiltered,
41068
41132
  isScrubbing,
41069
- nowLabel,
41133
+ onReturnToLive,
41070
41134
  onChangeScope,
41071
41135
  onChangeOffset,
41072
41136
  onChangeLayoutMode,
@@ -41077,160 +41141,155 @@ var ScrubberControls = ({
41077
41141
  onToggleIdentity,
41078
41142
  onOnlyIdentity,
41079
41143
  onToggleCategoriesExpanded,
41080
- onSetIdentitiesExpanded,
41081
- onReturnToLive
41082
- }) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [
41083
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
41084
- scope !== "all" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 2 }, children: [
41085
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41086
- "button",
41087
- {
41088
- title: "Earlier",
41089
- onClick: () => onChangeOffset(offset + 1),
41090
- style: navButtonStyle,
41091
- children: "\u25C0"
41092
- }
41093
- ),
41094
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41095
- "span",
41096
- {
41097
- style: {
41098
- fontSize: 10,
41099
- color: GUI_THEME.dim,
41100
- whiteSpace: "nowrap",
41101
- overflow: "hidden",
41102
- // Fixed, not min, so the changing label never shifts the
41103
- // buttons around it.
41104
- width: 88,
41105
- flexShrink: 0,
41106
- textAlign: "center"
41107
- },
41108
- children: formatPeriodLabel(scope, offset, periodRange)
41109
- }
41110
- ),
41111
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41112
- "button",
41113
- {
41114
- title: "Later",
41115
- disabled: offset === 0,
41116
- onClick: () => onChangeOffset(Math.max(0, offset - 1)),
41117
- style: {
41118
- ...navButtonStyle,
41119
- opacity: offset === 0 ? 0.35 : 1,
41120
- cursor: offset === 0 ? "default" : "pointer"
41144
+ onSetIdentitiesExpanded
41145
+ }) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
41146
+ "div",
41147
+ {
41148
+ style: {
41149
+ display: "flex",
41150
+ alignItems: "center",
41151
+ justifyContent: "flex-end",
41152
+ gap: 12
41153
+ },
41154
+ children: [
41155
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
41156
+ scope !== "all" && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 2 }, children: [
41157
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
41158
+ "button",
41159
+ {
41160
+ title: "Earlier",
41161
+ onClick: () => onChangeOffset(offset + 1),
41162
+ style: navButtonStyle,
41163
+ children: "\u25C0"
41164
+ }
41165
+ ),
41166
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
41167
+ "span",
41168
+ {
41169
+ style: {
41170
+ fontSize: 10,
41171
+ color: GUI_THEME.dim,
41172
+ whiteSpace: "nowrap",
41173
+ overflow: "hidden",
41174
+ // Fixed, not min, so the changing label never shifts the
41175
+ // buttons around it.
41176
+ width: 88,
41177
+ flexShrink: 0,
41178
+ textAlign: "center"
41179
+ },
41180
+ children: formatPeriodLabel(scope, offset, periodRange)
41181
+ }
41182
+ ),
41183
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
41184
+ "button",
41185
+ {
41186
+ title: "Later",
41187
+ disabled: offset === 0,
41188
+ onClick: () => onChangeOffset(Math.max(0, offset - 1)),
41189
+ style: {
41190
+ ...navButtonStyle,
41191
+ opacity: offset === 0 ? 0.35 : 1,
41192
+ cursor: offset === 0 ? "default" : "pointer"
41193
+ },
41194
+ children: "\u25B6"
41195
+ }
41196
+ )
41197
+ ] }),
41198
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { style: { display: "flex", gap: 2 }, children: SCOPES.map((option) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
41199
+ "button",
41200
+ {
41201
+ onClick: () => onChangeScope(option),
41202
+ style: toggleButtonStyle(scope === option),
41203
+ children: scopeButtonLabel(option)
41121
41204
  },
41122
- children: "\u25B6"
41123
- }
41124
- )
41125
- ] }),
41126
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { style: { display: "flex", gap: 2 }, children: SCOPES.map((option) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41127
- "button",
41128
- {
41129
- onClick: () => onChangeScope(option),
41130
- style: toggleButtonStyle(scope === option),
41131
- children: scopeButtonLabel(option)
41132
- },
41133
- option
41134
- )) })
41135
- ] }),
41136
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { style: { display: "flex", gap: 2 }, children: [
41137
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41138
- "button",
41139
- {
41140
- title: "How much happened, per equal-width period \u2014 no empty gaps for quiet stretches",
41141
- onClick: () => onChangeLayoutMode("even"),
41142
- style: toggleButtonStyle(layoutMode === "even"),
41143
- children: "Volume"
41144
- }
41145
- ),
41146
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41147
- "button",
41148
- {
41149
- title: "Individual events by exact moment \u2014 x is elapsed time, y is time of day",
41150
- onClick: () => onChangeLayoutMode("real"),
41151
- style: toggleButtonStyle(layoutMode === "real"),
41152
- children: "Events"
41153
- }
41154
- )
41155
- ] }),
41156
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { style: { display: "flex", gap: 12, alignItems: "center" }, children: [
41157
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41158
- Checkbox,
41159
- {
41160
- label: "Code",
41161
- checked: showCommits,
41162
- activeColor: GUI_THEME.green,
41163
- onChange: onChangeShowCommits
41164
- }
41165
- ),
41166
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41167
- BoardSeriesGroup,
41168
- {
41169
- showIssues,
41170
- view: boardView,
41171
- identities,
41172
- hiddenIds: hiddenIdentityIds,
41173
- expanded: categoriesExpanded,
41174
- identitiesExpanded,
41175
- filtered: categoriesFiltered,
41176
- onChangeShowIssues,
41177
- onChangeView: onChangeBoardView,
41178
- onToggleIdentity,
41179
- onOnlyIdentity,
41180
- onToggleExpanded: onToggleCategoriesExpanded,
41181
- onSetIdentitiesExpanded
41182
- }
41183
- )
41184
- ] }),
41185
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41186
- "div",
41187
- {
41188
- style: {
41189
- display: "flex",
41190
- justifyContent: "flex-end",
41191
- alignItems: "center",
41192
- // Fixed, not min, so swapping between "Now" and "Return to live"
41193
- // never resizes the controls row.
41194
- width: 100,
41195
- flexShrink: 0
41196
- },
41197
- children: isScrubbing ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41205
+ option
41206
+ )) })
41207
+ ] }),
41208
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { style: { display: "flex", gap: 2 }, children: [
41209
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
41210
+ "button",
41211
+ {
41212
+ title: "Volume \u2014 how much happened, per equal-width period, with no empty gaps for quiet stretches",
41213
+ "aria-label": "Volume",
41214
+ "aria-pressed": layoutMode === "even",
41215
+ onClick: () => onChangeLayoutMode("even"),
41216
+ style: iconToggleButtonStyle(layoutMode === "even"),
41217
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(IconBars, { size: 13 })
41218
+ }
41219
+ ),
41220
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
41221
+ "button",
41222
+ {
41223
+ title: "Events \u2014 individual events by exact moment, x is elapsed time and y is time of day",
41224
+ "aria-label": "Events",
41225
+ "aria-pressed": layoutMode === "real",
41226
+ onClick: () => onChangeLayoutMode("real"),
41227
+ style: iconToggleButtonStyle(layoutMode === "real"),
41228
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(IconScatter, { size: 13 })
41229
+ }
41230
+ )
41231
+ ] }),
41232
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { style: { display: "flex", gap: 12, alignItems: "center" }, children: [
41233
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
41234
+ Checkbox,
41235
+ {
41236
+ label: "Code",
41237
+ checked: showCommits,
41238
+ activeColor: GUI_THEME.green,
41239
+ onChange: onChangeShowCommits
41240
+ }
41241
+ ),
41242
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
41243
+ BoardSeriesGroup,
41244
+ {
41245
+ showIssues,
41246
+ view: boardView,
41247
+ identities,
41248
+ hiddenIds: hiddenIdentityIds,
41249
+ expanded: categoriesExpanded,
41250
+ identitiesExpanded,
41251
+ filtered: categoriesFiltered,
41252
+ onChangeShowIssues,
41253
+ onChangeView: onChangeBoardView,
41254
+ onToggleIdentity,
41255
+ onOnlyIdentity,
41256
+ onToggleExpanded: onToggleCategoriesExpanded,
41257
+ onSetIdentitiesExpanded
41258
+ }
41259
+ )
41260
+ ] }),
41261
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
41198
41262
  "button",
41199
41263
  {
41200
41264
  onClick: onReturnToLive,
41265
+ disabled: !isScrubbing,
41266
+ title: isScrubbing ? "Leave history and follow the board again" : void 0,
41201
41267
  style: {
41202
41268
  background: "transparent",
41203
- border: `1px solid ${GUI_THEME.accent}`,
41204
- color: GUI_THEME.accent,
41269
+ border: `1px solid ${isScrubbing ? GUI_THEME.accent : GUI_THEME.transparent}`,
41270
+ color: isScrubbing ? GUI_THEME.accent : GUI_THEME.dim,
41205
41271
  borderRadius: 6,
41206
- fontSize: 11,
41272
+ fontFamily: "inherit",
41273
+ width: 60,
41274
+ display: "inline-flex",
41275
+ alignItems: "center",
41276
+ justifyContent: isScrubbing ? "center" : "flex-end",
41277
+ fontSize: 10,
41207
41278
  padding: "2px 8px",
41208
- cursor: "pointer",
41209
- whiteSpace: "nowrap"
41210
- },
41211
- children: "Return to live"
41212
- }
41213
- ) : /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41214
- "span",
41215
- {
41216
- style: {
41217
- fontSize: 11,
41218
- color: GUI_THEME.dim,
41219
- overflow: "hidden",
41220
- textAlign: "right",
41221
- whiteSpace: "nowrap"
41279
+ cursor: isScrubbing ? "pointer" : "default",
41280
+ whiteSpace: "nowrap",
41281
+ flexShrink: 0
41222
41282
  },
41223
- children: nowLabel
41283
+ children: isScrubbing ? "Resume" : "Now"
41224
41284
  }
41225
41285
  )
41226
- }
41227
- )
41228
- ] });
41286
+ ]
41287
+ }
41288
+ );
41229
41289
  var ScrubberHeader = ({
41230
41290
  collapsed,
41231
- onToggleCollapsed,
41232
- scrubbingAsOf
41233
- }) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
41291
+ onToggleCollapsed
41292
+ }) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
41234
41293
  "div",
41235
41294
  {
41236
41295
  style: {
@@ -41240,34 +41299,26 @@ var ScrubberHeader = ({
41240
41299
  fontSize: 11,
41241
41300
  whiteSpace: "nowrap"
41242
41301
  },
41243
- children: [
41244
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
41245
- "button",
41246
- {
41247
- onClick: onToggleCollapsed,
41248
- title: collapsed ? "Show time travel" : "Hide time travel",
41249
- style: {
41250
- background: "transparent",
41251
- border: "none",
41252
- color: GUI_THEME.dim,
41253
- fontSize: 11,
41254
- padding: 0,
41255
- cursor: "pointer",
41256
- display: "flex",
41257
- alignItems: "center",
41258
- gap: 4
41259
- },
41260
- children: [
41261
- "Time travel",
41262
- collapsed ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(IconChevronRight, { size: 12 }) : /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(IconChevronDown, { size: 12 })
41263
- ]
41264
- }
41265
- ),
41266
- scrubbingAsOf !== null && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
41267
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { style: { color: GUI_THEME.accent, fontWeight: 700 }, children: "Read-only" }),
41268
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { style: { color: GUI_THEME.primary }, children: scrubbingAsOf })
41269
- ] })
41270
- ]
41302
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
41303
+ "button",
41304
+ {
41305
+ onClick: onToggleCollapsed,
41306
+ title: collapsed ? "Show time travel" : "Hide time travel",
41307
+ "aria-label": collapsed ? "Show time travel" : "Hide time travel",
41308
+ "aria-expanded": !collapsed,
41309
+ style: {
41310
+ background: GUI_THEME.panel2,
41311
+ border: `1px solid ${GUI_THEME.line}`,
41312
+ borderRadius: 6,
41313
+ color: GUI_THEME.secondary,
41314
+ padding: "3px 7px",
41315
+ cursor: "pointer",
41316
+ display: "inline-flex",
41317
+ alignItems: "center"
41318
+ },
41319
+ children: collapsed ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(IconChevronRight, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(IconChevronDown, { size: 14 })
41320
+ }
41321
+ )
41271
41322
  }
41272
41323
  );
41273
41324
  var SegmentHighlight = ({
@@ -41275,7 +41326,7 @@ var SegmentHighlight = ({
41275
41326
  fractionForTime
41276
41327
  }) => {
41277
41328
  const left = fractionForTime(segment.start);
41278
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41329
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
41279
41330
  "div",
41280
41331
  {
41281
41332
  style: {
@@ -41307,7 +41358,7 @@ var SegmentHighlight = ({
41307
41358
  var TrackBaseline = ({
41308
41359
  color: color2,
41309
41360
  anchor
41310
- }) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41361
+ }) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
41311
41362
  "div",
41312
41363
  {
41313
41364
  style: {
@@ -41323,11 +41374,11 @@ var TrackBaseline = ({
41323
41374
  }
41324
41375
  }
41325
41376
  );
41326
- var HourAxisLabels = () => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_jsx_runtime30.Fragment, { children: [
41377
+ var HourAxisLabels = () => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_jsx_runtime32.Fragment, { children: [
41327
41378
  ["00:00", { top: EVENTS_MODE_VERTICAL_PADDING }],
41328
41379
  ["12:00", { top: "50%", transform: "translateY(-50%)" }],
41329
41380
  ["24:00", { bottom: EVENTS_MODE_VERTICAL_PADDING }]
41330
- ].map(([label, position3]) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41381
+ ].map(([label, position3]) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
41331
41382
  "span",
41332
41383
  {
41333
41384
  style: {
@@ -41345,7 +41396,7 @@ var HourAxisLabels = () => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_
41345
41396
  var SeriesLayer = ({
41346
41397
  animate,
41347
41398
  children
41348
- }) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41399
+ }) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
41349
41400
  "div",
41350
41401
  {
41351
41402
  style: {
@@ -41379,8 +41430,8 @@ var VolumeBars = ({
41379
41430
  const timeout = setTimeout(() => setFresh(false), BAR_ENTRANCE_TOTAL_MS);
41380
41431
  return () => clearTimeout(timeout);
41381
41432
  }, []);
41382
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
41383
- highlightedIndex !== null && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41433
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
41434
+ highlightedIndex !== null && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
41384
41435
  "div",
41385
41436
  {
41386
41437
  style: {
@@ -41396,7 +41447,7 @@ var VolumeBars = ({
41396
41447
  }
41397
41448
  }
41398
41449
  ),
41399
- bars.map(({ index: index2, intensity }) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41450
+ bars.map(({ index: index2, intensity }) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
41400
41451
  "div",
41401
41452
  {
41402
41453
  style: {
@@ -41423,8 +41474,8 @@ var ScrubberNeedle = ({ fraction }) => {
41423
41474
  onMouseEnter: () => setHovered(true),
41424
41475
  onMouseLeave: () => setHovered(false)
41425
41476
  };
41426
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
41427
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41477
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
41478
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
41428
41479
  "div",
41429
41480
  {
41430
41481
  ...hover,
@@ -41444,7 +41495,7 @@ var ScrubberNeedle = ({ fraction }) => {
41444
41495
  }
41445
41496
  }
41446
41497
  ),
41447
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41498
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
41448
41499
  "div",
41449
41500
  {
41450
41501
  ...hover,
@@ -41474,7 +41525,7 @@ var ScrubberHoverHint = ({
41474
41525
  fraction,
41475
41526
  trackWidthPx,
41476
41527
  empty: empty3 = false
41477
- }) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
41528
+ }) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
41478
41529
  "div",
41479
41530
  {
41480
41531
  style: {
@@ -41506,8 +41557,8 @@ var ScrubberHoverHint = ({
41506
41557
  zIndex: 5
41507
41558
  },
41508
41559
  children: [
41509
- segmentLabel && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { style: { fontSize: 10, color: GUI_THEME.dim }, children: segmentLabel }),
41510
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41560
+ segmentLabel && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { style: { fontSize: 10, color: GUI_THEME.dim }, children: segmentLabel }),
41561
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
41511
41562
  "div",
41512
41563
  {
41513
41564
  style: {
@@ -41520,7 +41571,7 @@ var ScrubberHoverHint = ({
41520
41571
  children: label
41521
41572
  }
41522
41573
  ),
41523
- rows.map((row, index2) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41574
+ rows.map((row, index2) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
41524
41575
  "div",
41525
41576
  {
41526
41577
  style: {
@@ -41675,7 +41726,7 @@ var ScatterCanvas = ({
41675
41726
  rect.width
41676
41727
  );
41677
41728
  };
41678
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
41729
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
41679
41730
  "canvas",
41680
41731
  {
41681
41732
  ref: canvasRef,
@@ -41704,16 +41755,15 @@ var ScatterCanvas = ({
41704
41755
  };
41705
41756
 
41706
41757
  // source/gui/client/components/ScrubberLayout.tsx
41707
- var import_jsx_runtime31 = __toESM(require_jsx_runtime(), 1);
41758
+ var import_jsx_runtime33 = __toESM(require_jsx_runtime(), 1);
41708
41759
  var ScrubberLayout = ({
41709
41760
  collapsed,
41710
41761
  onToggleCollapsed,
41711
- scrubbingAsOf,
41712
41762
  controls,
41713
41763
  chart
41714
41764
  }) => {
41715
41765
  const { axis, layoutMode, animate, windowKey, on } = chart;
41716
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
41766
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
41717
41767
  Panel,
41718
41768
  {
41719
41769
  as: "div",
@@ -41730,8 +41780,8 @@ var ScrubberLayout = ({
41730
41780
  overflow: "visible"
41731
41781
  },
41732
41782
  children: [
41733
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("style", { children: SCRUBBER_KEYFRAMES }),
41734
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
41783
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("style", { children: SCRUBBER_KEYFRAMES }),
41784
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
41735
41785
  "div",
41736
41786
  {
41737
41787
  style: {
@@ -41740,27 +41790,26 @@ var ScrubberLayout = ({
41740
41790
  gap: collapsed ? 0 : 8
41741
41791
  },
41742
41792
  children: [
41743
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
41793
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
41744
41794
  "div",
41745
41795
  {
41746
41796
  style: {
41747
41797
  display: "flex",
41748
41798
  alignItems: "center",
41749
41799
  justifyContent: "space-between",
41750
- // Fixed whether or not the banner renders, so the track below
41751
- // never shifts vertically.
41800
+ // Holds the row's height when collapsing takes the controls out
41801
+ // of it.
41752
41802
  minHeight: 22
41753
41803
  },
41754
41804
  children: [
41755
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
41805
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
41756
41806
  ScrubberHeader,
41757
41807
  {
41758
41808
  collapsed,
41759
- onToggleCollapsed,
41760
- scrubbingAsOf
41809
+ onToggleCollapsed
41761
41810
  }
41762
41811
  ),
41763
- !collapsed && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(ScrubberControls, { ...controls })
41812
+ !collapsed && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ScrubberControls, { ...controls })
41764
41813
  ]
41765
41814
  }
41766
41815
  ),
@@ -41768,7 +41817,7 @@ var ScrubberLayout = ({
41768
41817
  // spanning them and the gap between. Pointer handlers belong here
41769
41818
  // rather than on either chart, so a drag or hover anywhere across
41770
41819
  // the pair — the gap included — counts as one timeline.
41771
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
41820
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
41772
41821
  "div",
41773
41822
  {
41774
41823
  onPointerDown: on.onPointerDown,
@@ -41785,14 +41834,14 @@ var ScrubberLayout = ({
41785
41834
  cursor: "pointer"
41786
41835
  },
41787
41836
  children: [
41788
- chart.hoveredSegment && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
41837
+ chart.hoveredSegment && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
41789
41838
  SegmentHighlight,
41790
41839
  {
41791
41840
  segment: chart.hoveredSegment,
41792
41841
  fractionForTime: axis.fractionForTime
41793
41842
  }
41794
41843
  ),
41795
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
41844
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
41796
41845
  "div",
41797
41846
  {
41798
41847
  ref: chart.trackRef,
@@ -41807,15 +41856,15 @@ var ScrubberLayout = ({
41807
41856
  alignItems: "center"
41808
41857
  },
41809
41858
  children: [
41810
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
41859
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
41811
41860
  TrackBaseline,
41812
41861
  {
41813
41862
  color: chart.issueSeriesColor,
41814
41863
  anchor: layoutMode === "even" ? "bottom" : "centre"
41815
41864
  }
41816
41865
  ),
41817
- layoutMode === "real" && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(HourAxisLabels, {}),
41818
- chart.showIssues && layoutMode === "even" && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(SeriesLayer, { animate, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
41866
+ layoutMode === "real" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(HourAxisLabels, {}),
41867
+ chart.showIssues && layoutMode === "even" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(SeriesLayer, { animate, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
41819
41868
  VolumeBars,
41820
41869
  {
41821
41870
  bars: chart.issueBars,
@@ -41828,7 +41877,7 @@ var ScrubberLayout = ({
41828
41877
  animate
41829
41878
  }
41830
41879
  ) }, `issues-${windowKey}`),
41831
- layoutMode === "real" && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
41880
+ layoutMode === "real" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
41832
41881
  ScatterCanvas,
41833
41882
  {
41834
41883
  layers: chart.scatterLayers,
@@ -41841,7 +41890,7 @@ var ScrubberLayout = ({
41841
41890
  ]
41842
41891
  }
41843
41892
  ),
41844
- chart.showCommits && layoutMode === "even" && chart.commits.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
41893
+ chart.showCommits && layoutMode === "even" && chart.commits.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
41845
41894
  "div",
41846
41895
  {
41847
41896
  onMouseEnter: on.onCommitTrackMouseEnter,
@@ -41854,8 +41903,8 @@ var ScrubberLayout = ({
41854
41903
  animation: animate ? FADE_IN_ANIMATION : void 0
41855
41904
  },
41856
41905
  children: [
41857
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(TrackBaseline, { color: GUI_THEME.green, anchor: "top" }),
41858
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
41906
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TrackBaseline, { color: GUI_THEME.green, anchor: "top" }),
41907
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
41859
41908
  VolumeBars,
41860
41909
  {
41861
41910
  bars: chart.commitBars,
@@ -41872,8 +41921,8 @@ var ScrubberLayout = ({
41872
41921
  },
41873
41922
  `commits-${windowKey}`
41874
41923
  ),
41875
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(ScrubberNeedle, { fraction: chart.thumbFraction }),
41876
- chart.boardHint && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
41924
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ScrubberNeedle, { fraction: chart.thumbFraction }),
41925
+ chart.boardHint && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
41877
41926
  ScrubberHoverHint,
41878
41927
  {
41879
41928
  ...chart.boardHint,
@@ -41882,7 +41931,7 @@ var ScrubberLayout = ({
41882
41931
  trackWidthPx: chart.trackWidthPx
41883
41932
  }
41884
41933
  ),
41885
- chart.commitHint && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
41934
+ chart.commitHint && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
41886
41935
  ScrubberHoverHint,
41887
41936
  {
41888
41937
  ...chart.commitHint,
@@ -41903,7 +41952,7 @@ var ScrubberLayout = ({
41903
41952
  };
41904
41953
 
41905
41954
  // source/gui/client/components/TimeScrubber.tsx
41906
- var import_jsx_runtime32 = __toESM(require_jsx_runtime(), 1);
41955
+ var import_jsx_runtime34 = __toESM(require_jsx_runtime(), 1);
41907
41956
  var SCRUB_THROTTLE_MS = 120;
41908
41957
  var boardEventRow = (count) => `${count} board event${count === 1 ? "" : "s"}`;
41909
41958
  var COLLAPSED_STORAGE_KEY = "epiq.timeScrubber.collapsed";
@@ -42048,6 +42097,12 @@ var TimeScrubber = ({
42048
42097
  () => JSON.stringify([boardView, [...hiddenIdentityIds].sort()]),
42049
42098
  [boardView, hiddenIdentityIds]
42050
42099
  );
42100
+ const entrance = (0, import_react15.useRef)(0);
42101
+ const armed = (0, import_react15.useRef)(true);
42102
+ const seenHistoryId = (0, import_react15.useRef)(historyId);
42103
+ const armEntrance = () => {
42104
+ armed.current = true;
42105
+ };
42051
42106
  const shownRef = (0, import_react15.useRef)({ timeline, commits });
42052
42107
  const heldKey = (0, import_react15.useRef)(null);
42053
42108
  const heldHistoryId = (0, import_react15.useRef)(null);
@@ -42061,6 +42116,13 @@ var TimeScrubber = ({
42061
42116
  shownRef.current = { timeline, commits };
42062
42117
  awaiting.current = false;
42063
42118
  }
42119
+ if (seenHistoryId.current !== historyId) {
42120
+ seenHistoryId.current = historyId;
42121
+ if (armed.current) {
42122
+ armed.current = false;
42123
+ entrance.current += 1;
42124
+ }
42125
+ }
42064
42126
  const shown = shownRef.current;
42065
42127
  const axis = (0, import_react15.useMemo)(() => buildAxis(shown.timeline, shown.commits), [shown]);
42066
42128
  const categoriesFiltered = (timeline?.events.length ?? 0) > 0;
@@ -42132,26 +42194,13 @@ var TimeScrubber = ({
42132
42194
  index: index2,
42133
42195
  intensity: stats.count / maxCommitCount
42134
42196
  }));
42135
- const [entrance, setEntrance] = (0, import_react15.useState)(0);
42136
- const armed = (0, import_react15.useRef)(true);
42137
- const seenHistoryId = (0, import_react15.useRef)(historyId);
42138
- const armEntrance = () => {
42139
- armed.current = true;
42140
- };
42141
42197
  const armedBoardId = (0, import_react15.useRef)(boardId);
42142
42198
  (0, import_react15.useEffect)(() => {
42143
42199
  if (boardId === null || boardId === armedBoardId.current) return;
42144
42200
  armedBoardId.current = boardId;
42145
42201
  armEntrance();
42146
42202
  }, [boardId]);
42147
- (0, import_react15.useEffect)(() => {
42148
- if (seenHistoryId.current === historyId) return;
42149
- seenHistoryId.current = historyId;
42150
- if (!armed.current) return;
42151
- armed.current = false;
42152
- setEntrance((generation) => generation + 1);
42153
- }, [historyId]);
42154
- const windowKey = `${layoutMode}-${entrance}-${filterKey}`;
42203
+ const windowKey = `${layoutMode}-${entrance.current}-${filterKey}`;
42155
42204
  const scatterLayers = (0, import_react15.useMemo)(
42156
42205
  () => [
42157
42206
  ...commitScatter.mounted ? [
@@ -42267,12 +42316,11 @@ var TimeScrubber = ({
42267
42316
  hoveredEvent?.t ?? hoveredCommit?.commit.time ?? (pointerFraction !== null ? axis.fractionToTime(pointerFraction) : void 0)
42268
42317
  )) ?? null;
42269
42318
  const segmentUnit = chooseSegmentUnit(axis.span);
42270
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
42319
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
42271
42320
  ScrubberLayout,
42272
42321
  {
42273
42322
  collapsed,
42274
42323
  onToggleCollapsed: () => setCollapsed(!collapsed),
42275
- scrubbingAsOf: timeTravel.mode === "scrub" ? timeTravel.asOfTime ? formatDateTime(new Date(timeTravel.asOfTime)) : "" : null,
42276
42324
  controls: {
42277
42325
  scope,
42278
42326
  offset,
@@ -42281,8 +42329,6 @@ var TimeScrubber = ({
42281
42329
  showIssues,
42282
42330
  showCommits,
42283
42331
  allBoards,
42284
- isScrubbing: timeTravel.mode === "scrub",
42285
- nowLabel: scope === "all" || offset === 0 ? "Now" : formatDateTime(new Date(axis.latest)),
42286
42332
  onChangeScope: changeScope,
42287
42333
  onChangeOffset: changeOffset,
42288
42334
  onChangeLayoutMode: setLayoutMode,
@@ -42295,12 +42341,13 @@ var TimeScrubber = ({
42295
42341
  categoriesExpanded,
42296
42342
  identitiesExpanded,
42297
42343
  categoriesFiltered,
42344
+ isScrubbing: timeTravel.mode === "scrub",
42345
+ onReturnToLive,
42298
42346
  onChangeBoardView: changeBoardView,
42299
42347
  onToggleIdentity: toggleIdentity,
42300
42348
  onOnlyIdentity: isolateIdentity,
42301
42349
  onToggleCategoriesExpanded: () => setCategoriesExpanded(!categoriesExpanded),
42302
- onSetIdentitiesExpanded: setIdentitiesExpanded,
42303
- onReturnToLive
42350
+ onSetIdentitiesExpanded: setIdentitiesExpanded
42304
42351
  },
42305
42352
  chart: {
42306
42353
  trackRef,
@@ -42646,9 +42693,9 @@ var blobToBase64 = (blob) => new Promise((resolve, reject) => {
42646
42693
  });
42647
42694
 
42648
42695
  // source/gui/client/App.tsx
42649
- var import_jsx_runtime33 = __toESM(require_jsx_runtime(), 1);
42696
+ var import_jsx_runtime35 = __toESM(require_jsx_runtime(), 1);
42650
42697
  var EMPTY_COMMENTS = {};
42651
- var DropIndicator = () => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
42698
+ var DropIndicator = () => /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
42652
42699
  "div",
42653
42700
  {
42654
42701
  style: {
@@ -43192,7 +43239,7 @@ var App = () => {
43192
43239
  });
43193
43240
  send("issue:comment:delete", { commentId });
43194
43241
  };
43195
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
43242
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
43196
43243
  "div",
43197
43244
  {
43198
43245
  style: {
@@ -43204,30 +43251,38 @@ var App = () => {
43204
43251
  flexDirection: "column"
43205
43252
  },
43206
43253
  children: [
43207
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(GlobalScrollbarStyles, {}),
43208
- commitInspectError && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
43254
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(GlobalScrollbarStyles, {}),
43255
+ commitInspectError && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
43209
43256
  ErrorToast,
43210
43257
  {
43211
43258
  message: `Couldn't open commit diff: ${commitInspectError}`,
43212
43259
  onDismiss: () => setCommitInspectError(null)
43213
43260
  }
43214
43261
  ),
43215
- removeError && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
43262
+ removeError && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
43216
43263
  ErrorToast,
43217
43264
  {
43218
43265
  message: removeError,
43219
43266
  onDismiss: () => setRemoveError(null)
43220
43267
  }
43221
43268
  ),
43222
- actionError && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
43269
+ actionError && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
43223
43270
  ErrorToast,
43224
43271
  {
43225
43272
  message: actionError,
43226
43273
  onDismiss: () => setActionError(null)
43227
43274
  }
43228
43275
  ),
43229
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Header, { state, connected, syncStatus }),
43230
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
43276
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
43277
+ Header,
43278
+ {
43279
+ state,
43280
+ connected,
43281
+ scrubbing: state?.timeTravel?.mode === "scrub",
43282
+ syncStatus
43283
+ }
43284
+ ),
43285
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
43231
43286
  TimeScrubber,
43232
43287
  {
43233
43288
  timeline: history.timeline,
@@ -43243,7 +43298,7 @@ var App = () => {
43243
43298
  onBoardFilterChange: setBoardFilter
43244
43299
  }
43245
43300
  ),
43246
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
43301
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
43247
43302
  "div",
43248
43303
  {
43249
43304
  style: {
@@ -43252,7 +43307,7 @@ var App = () => {
43252
43307
  overflow: "hidden"
43253
43308
  },
43254
43309
  children: [
43255
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
43310
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
43256
43311
  "main",
43257
43312
  {
43258
43313
  onClick: clearPicked,
@@ -43267,7 +43322,7 @@ var App = () => {
43267
43322
  overflow: "hidden"
43268
43323
  },
43269
43324
  children: [
43270
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
43325
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
43271
43326
  "div",
43272
43327
  {
43273
43328
  style: {
@@ -43276,7 +43331,7 @@ var App = () => {
43276
43331
  alignItems: "center",
43277
43332
  gap: 10
43278
43333
  },
43279
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
43334
+ children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
43280
43335
  Dropdown,
43281
43336
  {
43282
43337
  testId: "board-switcher",
@@ -43295,7 +43350,7 @@ var App = () => {
43295
43350
  )
43296
43351
  }
43297
43352
  ),
43298
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
43353
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
43299
43354
  "div",
43300
43355
  {
43301
43356
  style: {
@@ -43307,7 +43362,7 @@ var App = () => {
43307
43362
  overflowY: "hidden"
43308
43363
  },
43309
43364
  children: [
43310
- visibleSwimlanes.map((swimlane) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
43365
+ visibleSwimlanes.map((swimlane) => /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
43311
43366
  SwimlaneColumn,
43312
43367
  {
43313
43368
  swimlane,
@@ -43335,14 +43390,14 @@ var App = () => {
43335
43390
  },
43336
43391
  swimlane.id
43337
43392
  )),
43338
- !(selectedIssue && state?.user) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { style: { width: ASIDE_WIDTH, flexShrink: 0 } })
43393
+ !(selectedIssue && state?.user) && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { style: { width: ASIDE_WIDTH, flexShrink: 0 } })
43339
43394
  ]
43340
43395
  }
43341
43396
  )
43342
43397
  ]
43343
43398
  }
43344
43399
  ),
43345
- pickedIssues.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
43400
+ pickedIssues.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
43346
43401
  BulkDetails,
43347
43402
  {
43348
43403
  issues: pickedIssues,
@@ -43370,7 +43425,7 @@ var App = () => {
43370
43425
  onClear: clearPicked
43371
43426
  }
43372
43427
  ),
43373
- pickedIssues.length <= 1 && selectedIssue && state?.user && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
43428
+ pickedIssues.length <= 1 && selectedIssue && state?.user && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
43374
43429
  IssueDetails,
43375
43430
  {
43376
43431
  whoAmI: state.user,
@@ -43403,7 +43458,7 @@ var App = () => {
43403
43458
  ]
43404
43459
  }
43405
43460
  ),
43406
- createIssueModal && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
43461
+ createIssueModal && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
43407
43462
  CreateIssueModal,
43408
43463
  {
43409
43464
  title: createIssueModal.title,
@@ -43418,12 +43473,12 @@ var App = () => {
43418
43473
  };
43419
43474
 
43420
43475
  // source/gui/client/main.tsx
43421
- var import_jsx_runtime34 = __toESM(require_jsx_runtime(), 1);
43476
+ var import_jsx_runtime36 = __toESM(require_jsx_runtime(), 1);
43422
43477
  (0, import_client.createRoot)(document.getElementById("root")).render(
43423
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(BrowserRouter, { children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(Routes, { children: [
43424
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Route, { path: "/", element: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(App, {}) }),
43425
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Route, { path: "/board/:boardId/*", element: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(App, {}) }),
43426
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Route, { path: "*", element: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Navigate, { to: "/", replace: true }) })
43478
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(BrowserRouter, { children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(Routes, { children: [
43479
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Route, { path: "/", element: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(App, {}) }),
43480
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Route, { path: "/board/:boardId/*", element: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(App, {}) }),
43481
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Route, { path: "*", element: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Navigate, { to: "/", replace: true }) })
43427
43482
  ] }) })
43428
43483
  );
43429
43484
  /*! Bundled license information: