@kteneyck/cesium-timeline-core 0.9.0 → 0.10.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/README.md CHANGED
@@ -17,7 +17,7 @@ A canvas-based timeline component for **React** and **Angular** with Cesium Cloc
17
17
  ### React
18
18
 
19
19
  ```bash
20
- npm install @kteneyck/cesium-timeline-react @kteneyck/cesium-timeline-core
20
+ npm install @kteneyck/cesium-timeline-react
21
21
  ```
22
22
 
23
23
  Peer dependencies: `react` ≥ 19, `cesium` ≥ 1.100
@@ -25,7 +25,7 @@ Peer dependencies: `react` ≥ 19, `cesium` ≥ 1.100
25
25
  ### Angular
26
26
 
27
27
  ```bash
28
- npm install @kteneyck/cesium-timeline-angular @kteneyck/cesium-timeline-core
28
+ npm install @kteneyck/cesium-timeline-angular
29
29
  ```
30
30
 
31
31
  Peer dependencies: `@angular/core` ≥ 17, `cesium` ≥ 1.100
@@ -127,12 +127,13 @@ Angular components use standalone imports — no NgModule required. Selectors: `
127
127
  - **Netflix/Hulu-style controls** — transport buttons (⏮ ◀◀ ▶/⏸ ▶▶ ⏭) always stay centered; speed badge and LIVE button in the left column never cause layout shift.
128
128
  - **Conditional start/end buttons** — ⏮ and ⏭ are only rendered when `startTime` and `endTime` props are explicitly provided.
129
129
  - **Speed cycling** — FF cycles through `ffSpeeds` (default `2×→4×→8×→16×→32×→1×`); RW cycles through `rwSpeeds` (default `−1×→−2×→−4×→−8×→−16×→−32×`). Both arrays are fully configurable.
130
- - **LIVE button** — filled `● LIVE` when within 10 s of wall clock; dim outline `LIVE` otherwise; clicking jumps to `Date.now()` and resets speed to 1×.
130
+ - **LIVE button** — shows a red dot + filled background when within 10 s of wall clock; dim outline otherwise. Clicking jumps to `Date.now()` and resets speed to 1×. Configurable size (`sm`/`md`/`lg`) and position (`left`/`right`). Dot color is themeable via `liveDotColor`.
131
131
  - **Speed badge** — shown in the left column when multiplier ≠ 1×; click to reset to 1×.
132
132
  - **Two-line datetime display** — time displayed large/bold; date displayed smaller in the theme's active color.
133
133
  - **Clickable datetime** — pass `onDateTimeClick` to open your own date picker; pass the result back via `jumpToTime` to pan the canvas and set the time.
134
134
  - **Token-based datetime format** — built-in presets plus custom format strings with 17 supported tokens.
135
135
  - **Max tick limit** — `maxTicks` prop prevents the canvas from becoming overloaded at wide zoom levels by coarsening the tick scale automatically.
136
+ - **Ghost / preview needle** — while hovering over the timeline a semi-transparent (15% opacity) preview needle tracks the cursor so you can see exactly where a click or zoom-to-selection drag would land before committing. The ghost disappears when the cursor leaves the canvas or an interaction begins.
136
137
  - **Zoom to selection** — drag in the tick area (away from the needle) to draw a time-range highlight with a crosshair cursor; on release the visible window zooms to exactly the selected span and fires `onRangeSelect` (React) / `rangeSelect` (Angular) with the resulting start and end times.
137
138
  - **Swim lanes** — display time intervals and instants as horizontal rows inside the canvas. Supports customizable styling, click/hover/double-click event hooks, drag-to-reorder, and vertical scrolling when lanes overflow.
138
139
  - **Fully themeable** — 16 theme properties cover every color, size, and font setting, including swim lane item border defaults.
@@ -145,38 +146,41 @@ Angular components use standalone imports — no NgModule required. Selectors: `
145
146
 
146
147
  ### `TimelineProps`
147
148
 
148
- | Prop | Type | Default | Description |
149
- |------|------|---------|-------------|
150
- | `clock` | `Cesium.Clock` | — | Cesium clock to sync with. Falls back to `setInterval` if omitted. |
151
- | `startTime` | `JulianDate \| Date` | now − 12 h | Left bound of initial visible window. Also shows the ⏮ button when provided. |
152
- | `endTime` | `JulianDate \| Date` | now + 12 h | Right bound of initial visible window. Also shows the ⏭ button when provided. |
153
- | `currentTime` | `JulianDate \| Date` | `startTime` | Initial needle position |
154
- | `height` | `number` | `120` | Canvas height in pixels |
155
- | `showControls` | `boolean` | `true` | Show/hide the control bar |
156
- | `enableDrag` | `boolean` | `true` | Show/hide the canvas (drag/seek area) |
157
- | `showLabels` | `boolean` | — | Show/hide tick labels on the canvas |
158
- | `snapToTicks` | `boolean` | — | Snap needle to nearest tick on drag |
159
- | `tickInterval` | `TickInterval \| number` | auto | Override automatic tick interval |
160
- | `maxTicks` | `number` | unlimited | Maximum number of major ticks on the canvas at once. When exceeded the tick scale is automatically coarsened. |
161
- | `ffSpeeds` | `number[]` | `[2,4,8,16,32,1]` | Speed steps cycled by the ▶▶ button. Last entry wraps back to first. |
162
- | `rwSpeeds` | `number[]` | `[1,2,4,8,16,32]` | Absolute-value speed steps cycled by the ◀◀ button (negated internally). |
163
- | `dateTimeFormat` | `string` | `'MMM DD YYYY HH:mm:ss'` | Token-based format string for the controls datetime display |
149
+ | Prop | Type | Default | Description |
150
+ |------|------|---------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
151
+ | `clock` | `Cesium.Clock` | — | Cesium clock to sync with. Falls back to `setInterval` if omitted. |
152
+ | `startTime` | `JulianDate \| Date` | now − 12 h | Left bound of initial visible window. Also shows the ⏮ button when provided. |
153
+ | `endTime` | `JulianDate \| Date` | now + 12 h | Right bound of initial visible window. Also shows the ⏭ button when provided. |
154
+ | `currentTime` | `JulianDate \| Date` | `startTime` | Initial needle position |
155
+ | `height` | `number` | `120` | Canvas height in pixels |
156
+ | `showControls` | `boolean` | `true` | Show/hide the control bar |
157
+ | `enableDrag` | `boolean` | `true` | Show/hide the canvas (drag/seek area) |
158
+ | `showLabels` | `boolean` | — | Show/hide tick labels on the canvas |
159
+ | `snapToTicks` | `boolean` | — | Snap needle to nearest tick on drag |
160
+ | `tickInterval` | `TickInterval \| number` | auto | Override automatic tick interval |
161
+ | `maxTicks` | `number` | unlimited | Maximum number of major ticks on the canvas at once. When exceeded the tick scale is automatically coarsened. |
162
+ | `ffSpeeds` | `number[]` | `[2,4,8,16,32,1]` | Speed steps cycled by the ▶▶ button. Last entry wraps back to first. |
163
+ | `rwSpeeds` | `number[]` | `[1,2,4,8,16,32]` | Absolute-value speed steps cycled by the ◀◀ button (negated internally). |
164
+ | `dateTimeFormat` | `string` | `'MMM DD YYYY HH:mm:ss'` | Token-based format string for the controls datetime display |
164
165
  | `timezone` | `string` | browser local | IANA timezone name (e.g. `'UTC'`, `'America/New_York'`) or `'local'` for the browser's timezone. Controls both tick labels and the datetime display. When set, a short abbreviation (e.g. `UTC`, `EST`) appears to the right of the date. |
165
- | `onDateTimeClick` | `() => void` | — | Called when the user clicks the datetime display. Use to open your own date picker. |
166
- | `jumpToTime` | `JulianDate \| Date` | — | Set to programmatically jump the timeline to a moment (pans canvas + sets time). |
167
- | `theme` | `Partial<TimelineTheme>` | `defaultTheme` | Theme overrides (merged with defaults) |
168
- | `className` | `string` | — | CSS class applied to the root div |
169
- | `onTimeChange` | `(t: JulianDate) => void` | — | Fires when needle moves (drag, click, or clock tick) |
170
- | `onPlayPause` | `(playing: boolean) => void` | — | Fires on play/pause toggle |
171
- | `onMultiplierChange` | `(m: number) => void` | — | Fires when speed changes |
172
- | `swimLanes` | `SwimLane[]` | — | Array of swim lane definitions to render on the canvas |
173
- | `showSwimLanes` | `boolean` | `true` | Show or hide the swim lanes |
174
- | `onSwimLaneItemClick` | `(info: SwimLaneEventInfo) => void` | — | Fires when a swim lane item is clicked |
175
- | `onSwimLaneItemHover` | `(info: SwimLaneEventInfo \| null) => void` | — | Fires when mouse enters/leaves a swim lane item |
176
- | `onSwimLaneItemDoubleClick` | `(info: SwimLaneEventInfo) => void` | — | Fires when a swim lane item is double-clicked |
177
- | `onSwimLaneReorder` | `(orderedIds: string[]) => void` | — | Fires when swim lanes are reordered via drag. Receives the new lane id order. |
178
- | `onRangeSelect` | `(start: JulianDate, end: JulianDate) => void` | — | Fires when the user completes a click-and-drag in the tick area. The visible window zooms to the selected span; receives the resulting start and end times. |
179
- | `labels` | `Partial<TimelineLabels>` | English defaults | Override any control-bar label or tooltip string. See [Labels & i18n](#labels--i18n). |
166
+ | `onDateTimeClick` | `() => void` | — | Called when the user clicks the datetime display. Use to open your own date picker. |
167
+ | `jumpToTime` | `JulianDate \| Date` | — | Set to programmatically jump the timeline to a moment (pans canvas + sets time). |
168
+ | `theme` | `Partial<TimelineTheme>` | `defaultTheme` | Theme overrides (merged with defaults) |
169
+ | `className` | `string` | — | CSS class applied to the root div |
170
+ | `onTimeChange` | `(t: JulianDate) => void` | — | Fires when needle moves (drag, click, or clock tick) |
171
+ | `onPlayPause` | `(playing: boolean) => void` | — | Fires on play/pause toggle |
172
+ | `onMultiplierChange` | `(m: number) => void` | — | Fires when speed changes |
173
+ | `swimLanes` | `SwimLane[]` | — | Array of swim lane definitions to render on the canvas |
174
+ | `showSwimLanes` | `boolean` | `true` | Show or hide the swim lanes |
175
+ | `onSwimLaneItemClick` | `(info: SwimLaneEventInfo) => void` | — | Fires when a swim lane item is clicked |
176
+ | `onSwimLaneItemHover` | `(info: SwimLaneEventInfo \| null) => void` | — | Fires when mouse enters/leaves a swim lane item |
177
+ | `onSwimLaneItemDoubleClick` | `(info: SwimLaneEventInfo) => void` | — | Fires when a swim lane item is double-clicked |
178
+ | `onSwimLaneReorder` | `(orderedIds: string[]) => void` | — | Fires when swim lanes are reordered via drag. Receives the new lane id order. |
179
+ | `onRangeSelect` | `(start: JulianDate, end: JulianDate) => void` | — | Fires when the user completes a click-and-drag in the tick area. The visible window zooms to the selected span; receives the resulting start and end times. |
180
+ | `labels` | `Partial<TimelineLabels>` | English defaults | Override any control-bar label or tooltip string. See [Labels & i18n](#labels--i18n). |
181
+ | `liveButtonSize` | `'sm' \| 'md' \| 'lg'` | `'md'` | Size of the LIVE button in the control bar. |
182
+ | `liveButtonPosition` | `'left' \| 'right'` | `'left'` | Position of the LIVE button — beside the datetime display (`'left'`) or the opposite side of the control bar (`'right'`). |
183
+ | `invertScrollZoom` | `boolean` | `false` | Reverses the scroll-wheel zoom direction. By default scroll up zooms in and scroll down zooms out. Set to `true` for scroll down zooms in, scroll up zooms out. |
180
184
 
181
185
  ---
182
186
 
@@ -215,6 +219,7 @@ Pass a partial `TimelineTheme` object to the `theme` prop. Any omitted propertie
215
219
  | `buttonActiveColor` | `#d69826` | Active buttons, LIVE, speed badge, and date line colour |
216
220
  | `swimLaneItemBorderColor` | `#666666` | Default border colour for swim lane interval bars. Can be overridden per-lane or per-item. |
217
221
  | `swimLaneItemBorderWidth` | `0` | Default border width (px) for swim lane interval bars. Set to `0` to remove borders globally. Can be overridden per-lane or per-item. |
222
+ | `liveDotColor` | `#e53e3e` | Colour of the dot shown on the LIVE button when playback is live. |
218
223
 
219
224
  > **Note:** Theme colours must be resolved hex/rgb values. CSS variables like `var(--primary-color)` do **not** work in canvas `ctx.fillStyle`. Use `getComputedStyle(document.documentElement).getPropertyValue('--primary-color').trim()` to resolve them first.
220
225
 
@@ -364,13 +369,16 @@ The control bar uses a 3-column CSS grid so the transport buttons are always cen
364
369
 
365
370
  ### LIVE Button
366
371
 
367
- - Shows `● LIVE` (filled background) when the current time is within 10 seconds of `Date.now()`.
368
- - Shows `LIVE` (dim outline) otherwise.
369
- - Clicking jumps to `Date.now()`, centers the visible window ±12 h, and resets speed to 1×.
372
+ - Shows a red dot and filled background when the current time is within 2 seconds of `Date.now()`.
373
+ - Shows `LIVE` (dim outline, no dot) otherwise.
374
+ - Clicking jumps to `Date.now()`, centers the visible window, and resets speed to 1×.
375
+ - **Size** — controlled by the `liveButtonSize` prop: `'sm'` | `'md'` (default) | `'lg'`.
376
+ - **Position** — controlled by the `liveButtonPosition` prop: `'left'` (default, beside the datetime display) | `'right'` (right side of the control bar).
377
+ - **Dot color** — controlled by `theme.liveDotColor` (default `#e53e3e`).
370
378
 
371
379
  ### Speed Badge
372
380
 
373
- - Appears to the right of LIVE when multiplier ≠ 1×.
381
+ - Appears inline beside the LIVE button when multiplier ≠ 1×.
374
382
  - Shows `◀ N×` for reverse, `N× ▶` for fast-forward.
375
383
  - Clicking resets to 1× speed.
376
384
 
@@ -426,7 +434,7 @@ Every label and tooltip in the control bar is overridable via the `labels` prop.
426
434
  |-----|-------------------|-------|
427
435
  | `dateTimeClickTooltip` | `"Click to jump to a date/time"` | Tooltip on the datetime display when `onDateTimeClick` is wired up |
428
436
  | `liveLabel` | `"LIVE"` | LIVE button text when not at live time |
429
- | `liveActiveLabel` | `"LIVE"` | LIVE button text when at live time |
437
+ | `liveActiveLabel` | `"LIVE"` | LIVE button text when at live time (red dot is rendered separately) |
430
438
  | `liveTooltip` | `"Jump to live (now)"` | LIVE button tooltip when not at live time |
431
439
  | `liveActiveTooltip` | `"Currently live"` | LIVE button tooltip when at live time |
432
440
  | `resetSpeedTooltip` | `"Reset to 1× speed"` | Tooltip on the speed-reset badge |
@@ -456,7 +464,7 @@ const frLabels: Partial<TimelineLabels> = {
456
464
  playTooltip: 'Lecture',
457
465
  pauseTooltip: 'Pause',
458
466
  liveLabel: 'EN DIRECT',
459
- liveActiveLabel: 'EN DIRECT',
467
+ liveActiveLabel: 'EN DIRECT',
460
468
  liveTooltip: 'Aller en direct',
461
469
  liveActiveTooltip: 'Vous êtes en direct',
462
470
  rewindTooltip: 'Retour rapide',
@@ -482,7 +490,7 @@ export class AppComponent {
482
490
  playTooltip: 'Lecture',
483
491
  pauseTooltip: 'Pause',
484
492
  liveLabel: 'EN DIRECT',
485
- liveActiveLabel: 'EN DIRECT',
493
+ liveActiveLabel: 'EN DIRECT',
486
494
  liveTooltip: 'Aller en direct',
487
495
  liveActiveTooltip: 'Vous êtes en direct',
488
496
  rewindActiveTooltip: (n) => `Retour ${n}× — cliquer pour accélérer`,
@@ -759,6 +767,36 @@ onRangeSelect(range: { start: Cesium.JulianDate; end: Cesium.JulianDate }) {
759
767
 
760
768
  ---
761
769
 
770
+ ## Ghost / Preview Needle
771
+
772
+ When the user hovers over the timeline canvas a **ghost needle** (a semi-transparent version of the current-time indicator) tracks the cursor position in real time. It renders at **15% opacity** using the same `indicatorColor` and `indicatorLineWidth` as the real needle, giving a clear preview of where a click-to-seek or zoom-to-selection drag would begin — without moving the actual current time.
773
+
774
+ ### Behaviour summary
775
+
776
+ | State | Ghost visible? |
777
+ |---|---|
778
+ | Mouse idle over canvas | ✅ Follows cursor |
779
+ | Dragging (scrub / range-select / slide / zoom) | ❌ Hidden |
780
+ | Mouse leaves canvas | ❌ Hidden |
781
+
782
+ ### Theming the ghost needle
783
+
784
+ The ghost needle inherits `indicatorColor` and `indicatorLineWidth` from your theme — no additional configuration is needed. To change its appearance, update those two theme properties:
785
+
786
+ ```tsx
787
+ <Timeline
788
+ clock={viewer.clock}
789
+ theme={{
790
+ indicatorColor: '#ffd54f',
791
+ indicatorLineWidth: 3,
792
+ }}
793
+ />
794
+ ```
795
+
796
+ The ghost will render as the same colour at 15% opacity, and the real needle will render at full opacity.
797
+
798
+ ---
799
+
762
800
  ## Swim Lanes
763
801
 
764
802
  Swim lanes render time intervals (bars) and instants (markers) as horizontal rows directly on the timeline canvas, aligned with the ticks and needle. They are ideal for visualizing satellite passes, ground contacts, scheduled events, or any temporal data.
@@ -1,11 +1,11 @@
1
1
  import * as A from "cesium";
2
- function Ce(e, t) {
2
+ function Ye(e, t) {
3
3
  return typeof e == "function" ? e(t) : e;
4
4
  }
5
- const Ye = {
5
+ const we = {
6
6
  dateTimeClickTooltip: "Click to jump to a date/time",
7
7
  liveLabel: "LIVE",
8
- liveActiveLabel: "LIVE",
8
+ liveActiveLabel: "LIVE",
9
9
  liveTooltip: "Jump to live (now)",
10
10
  liveActiveTooltip: "Currently live",
11
11
  resetSpeedTooltip: "Reset to 1× speed",
@@ -36,7 +36,7 @@ const Ye = {
36
36
  "Nov",
37
37
  "Dec"
38
38
  ]
39
- }, we = {
39
+ }, Ee = {
40
40
  backgroundColor: "#1a1a1a",
41
41
  tickColor: "#666666",
42
42
  majorTickColor: "#999999",
@@ -52,9 +52,10 @@ const Ye = {
52
52
  buttonHoverColor: "#888888",
53
53
  buttonActiveColor: "#d69826",
54
54
  swimLaneItemBorderColor: "#666666",
55
- swimLaneItemBorderWidth: 0
55
+ swimLaneItemBorderWidth: 0,
56
+ liveDotColor: "#e53e3e"
56
57
  };
57
- var me = /* @__PURE__ */ ((e) => (e[e.FIFTEEN_MIN = 15] = "FIFTEEN_MIN", e[e.THIRTY_MIN = 30] = "THIRTY_MIN", e[e.HOURLY = 60] = "HOURLY", e[e.CUSTOM = -1] = "CUSTOM", e))(me || {});
58
+ var fe = /* @__PURE__ */ ((e) => (e[e.FIFTEEN_MIN = 15] = "FIFTEEN_MIN", e[e.THIRTY_MIN = 30] = "THIRTY_MIN", e[e.HOURLY = 60] = "HOURLY", e[e.CUSTOM = -1] = "CUSTOM", e))(fe || {});
58
59
  const J = {
59
60
  color: "#4da6ff",
60
61
  borderColor: "#2980b9",
@@ -64,23 +65,23 @@ const J = {
64
65
  markerSize: 10,
65
66
  labelColor: "#cccccc",
66
67
  backgroundColor: "transparent"
67
- }, P = 24;
68
- function Ee(e) {
68
+ }, F = 24;
69
+ function $e(e) {
69
70
  return e instanceof A.JulianDate ? A.JulianDate.clone(e) : A.JulianDate.fromDate(e);
70
71
  }
71
- function te(e) {
72
+ function oe(e) {
72
73
  return e instanceof A.JulianDate ? A.JulianDate.toDate(e) : e;
73
74
  }
74
- function F(e) {
75
- return te(e).getTime();
75
+ function N(e) {
76
+ return oe(e).getTime();
76
77
  }
77
- function $e(e) {
78
+ function Ie(e) {
78
79
  return A.JulianDate.fromDate(new Date(e));
79
80
  }
80
- function ge(e, t) {
81
- return F(t) - F(e);
81
+ function Te(e, t) {
82
+ return N(t) - N(e);
82
83
  }
83
- const Te = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], Se = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], fe = {
84
+ const Se = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], be = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], ue = {
84
85
  /** e.g. "Feb 24 2026 14:04:07" — default */
85
86
  DEFAULT: "MMM DD YYYY HH:mm:ss",
86
87
  /** e.g. "Feb 24 2026 02:04:07 PM" */
@@ -95,16 +96,16 @@ const Te = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct"
95
96
  TIME_ONLY: "HH:mm:ss",
96
97
  /** e.g. "02:04:07 PM" */
97
98
  TIME_12: "hh:mm:ss A"
98
- }, Ie = {
99
+ }, Pe = {
99
100
  /** Use the browser's local timezone (default behavior). */
100
101
  LOCAL: "local",
101
102
  /** Coordinated Universal Time. */
102
103
  UTC: "UTC"
103
104
  };
104
- function oe(e, t) {
105
+ function ne(e, t) {
105
106
  if (!t || t === "local") {
106
- const M = e.getFullYear(), h = e.getMonth(), y = e.getDate(), S = e.getHours(), f = S % 12 || 12, u = e.getMinutes(), w = e.getSeconds(), O = e.getMilliseconds();
107
- return { yr: M, mo: h, day: y, hr24: S, hr12: f, min: u, sec: w, ms: O, ampm: S < 12 ? "AM" : "PM" };
107
+ const p = e.getFullYear(), f = e.getMonth(), y = e.getDate(), b = e.getHours(), d = b % 12 || 12, u = e.getMinutes(), T = e.getSeconds(), $ = e.getMilliseconds();
108
+ return { yr: p, mo: f, day: y, hr24: b, hr12: d, min: u, sec: T, ms: $, ampm: b < 12 ? "AM" : "PM" };
108
109
  }
109
110
  const o = new Intl.DateTimeFormat("en-US", {
110
111
  timeZone: t,
@@ -116,49 +117,49 @@ function oe(e, t) {
116
117
  second: "2-digit",
117
118
  hour12: !1
118
119
  }), s = {};
119
- for (const M of o.formatToParts(e))
120
- M.type !== "literal" && (s[M.type] = M.value);
120
+ for (const p of o.formatToParts(e))
121
+ p.type !== "literal" && (s[p.type] = p.value);
121
122
  const n = parseInt(s.year), l = parseInt(s.month) - 1, a = parseInt(s.day);
122
- let r = parseInt(s.hour);
123
- r === 24 && (r = 0);
124
- const c = r % 12 || 12, m = parseInt(s.minute), d = parseInt(s.second), p = e.getMilliseconds();
125
- return { yr: n, mo: l, day: a, hr24: r, hr12: c, min: m, sec: d, ms: p, ampm: r < 12 ? "AM" : "PM" };
123
+ let i = parseInt(s.hour);
124
+ i === 24 && (i = 0);
125
+ const m = i % 12 || 12, c = parseInt(s.minute), M = parseInt(s.second), h = e.getMilliseconds();
126
+ return { yr: n, mo: l, day: a, hr24: i, hr12: m, min: c, sec: M, ms: h, ampm: i < 12 ? "AM" : "PM" };
126
127
  }
127
128
  function Re(e, t) {
128
129
  var n;
129
130
  if (!t || t === "local") return null;
130
- const o = te(e);
131
+ const o = oe(e);
131
132
  return ((n = new Intl.DateTimeFormat("en-US", {
132
133
  timeZone: t,
133
134
  timeZoneName: "short"
134
135
  }).formatToParts(o).find((l) => l.type === "timeZoneName")) == null ? void 0 : n.value) ?? null;
135
136
  }
136
- function ye(e, t = fe.DEFAULT, o) {
137
- const s = te(e), { yr: n, mo: l, day: a, hr24: r, hr12: c, min: m, sec: d, ms: p, ampm: M } = oe(s, o), h = (f) => String(f).padStart(2, "0"), y = (f) => String(f).padStart(3, "0"), S = {
137
+ function ye(e, t = ue.DEFAULT, o) {
138
+ const s = oe(e), { yr: n, mo: l, day: a, hr24: i, hr12: m, min: c, sec: M, ms: h, ampm: p } = ne(s, o), f = (d) => String(d).padStart(2, "0"), y = (d) => String(d).padStart(3, "0"), b = {
138
139
  YYYY: String(n),
139
140
  YY: String(n).slice(-2),
140
- MMMM: Se[l],
141
- MMM: Te[l],
142
- MM: h(l + 1),
141
+ MMMM: be[l],
142
+ MMM: Se[l],
143
+ MM: f(l + 1),
143
144
  M: String(l + 1),
144
- DD: h(a),
145
+ DD: f(a),
145
146
  D: String(a),
146
- HH: h(r),
147
- H: String(r),
148
- hh: h(c),
149
- h: String(c),
150
- mm: h(m),
151
- ss: h(d),
152
- SSS: y(p),
153
- A: M,
154
- a: M.toLowerCase()
147
+ HH: f(i),
148
+ H: String(i),
149
+ hh: f(m),
150
+ h: String(m),
151
+ mm: f(c),
152
+ ss: f(M),
153
+ SSS: y(h),
154
+ A: p,
155
+ a: p.toLowerCase()
155
156
  };
156
157
  return t.replace(
157
158
  /YYYY|YY|MMMM|MMM|MM|M|DD|D|HH|H|hh|h|mm|ss|SSS|A|a/g,
158
- (f) => S[f] ?? f
159
+ (d) => b[d] ?? d
159
160
  );
160
161
  }
161
- function Je(e = fe.DEFAULT) {
162
+ function Je(e = ue.DEFAULT) {
162
163
  const t = ["YYYY", "YY", "MMMM", "MMM", "MM", "M", "DD", "D"], o = ["HH", "H", "hh", "h", "mm", "ss", "SSS", "A", "a"], s = (a) => a.replace(/\s{2,}/g, " ").trim().replace(/^[\s\W]+|[\s\W]+$/g, "").trim();
163
164
  let n = e;
164
165
  for (const a of t) n = n.replace(a, "");
@@ -166,46 +167,46 @@ function Je(e = fe.DEFAULT) {
166
167
  for (const a of o) l = l.replace(a, "");
167
168
  return { timeFormat: s(n), dateFormat: s(l) };
168
169
  }
169
- function Pe(e, t = !1) {
170
+ function Fe(e, t = !1) {
170
171
  return ye(e, t ? "HH:mm:ss" : "HH:mm");
171
172
  }
172
- function be(e, t, o, s) {
173
- const n = F(e), l = F(t), a = F(o);
173
+ function De(e, t, o, s) {
174
+ const n = N(e), l = N(t), a = N(o);
174
175
  if (a === l) return 0;
175
- const r = (n - l) / (a - l);
176
- return Math.max(0, Math.min(1, r)) * s;
177
- }
178
- function Fe(e, t, o, s) {
179
- const n = Math.max(0, Math.min(1, e / s)), l = F(t), a = F(o), r = l + n * (a - l);
180
- return A.JulianDate.fromDate(new Date(r));
176
+ const i = (n - l) / (a - l);
177
+ return Math.max(0, Math.min(1, i)) * s;
181
178
  }
182
179
  function Ne(e, t, o, s) {
183
- const n = [], l = ge(e, t), a = F(e);
184
- let r;
185
- typeof o == "number" && o in me || typeof o == "number" ? r = o * 60 * 1e3 : r = 3600 * 1e3;
186
- const c = r * 4;
187
- let m = a, d = 0;
188
- for (; m <= a + l; ) {
189
- const p = d * r % c === 0, M = be(
190
- new Date(m),
180
+ const n = Math.max(0, Math.min(1, e / s)), l = N(t), a = N(o), i = l + n * (a - l);
181
+ return A.JulianDate.fromDate(new Date(i));
182
+ }
183
+ function _e(e, t, o, s) {
184
+ const n = [], l = Te(e, t), a = N(e);
185
+ let i;
186
+ typeof o == "number" && o in fe || typeof o == "number" ? i = o * 60 * 1e3 : i = 3600 * 1e3;
187
+ const m = i * 4;
188
+ let c = a, M = 0;
189
+ for (; c <= a + l; ) {
190
+ const h = M * i % m === 0, p = De(
191
+ new Date(c),
191
192
  e,
192
193
  t,
193
194
  s
194
195
  );
195
- let h;
196
- if (p) {
197
- const y = new Date(m), S = y.getHours().toString().padStart(2, "0"), f = y.getMinutes().toString().padStart(2, "0");
198
- h = `${S}:${f}`;
196
+ let f;
197
+ if (h) {
198
+ const y = new Date(c), b = y.getHours().toString().padStart(2, "0"), d = y.getMinutes().toString().padStart(2, "0");
199
+ f = `${b}:${d}`;
199
200
  }
200
201
  n.push({
201
- position: M,
202
- isMajor: p,
203
- label: h
204
- }), m += r, d++;
202
+ position: p,
203
+ isMajor: h,
204
+ label: f
205
+ }), c += i, M++;
205
206
  }
206
207
  return n;
207
208
  }
208
- function _e(e, t, o = 10) {
209
+ function We(e, t, o = 10) {
209
210
  let s = t[0], n = Math.abs(s.position - e);
210
211
  for (const l of t) {
211
212
  const a = Math.abs(l.position - e);
@@ -213,7 +214,7 @@ function _e(e, t, o = 10) {
213
214
  }
214
215
  return n <= o ? s.position : e;
215
216
  }
216
- const De = 1e3, Le = 31536e9, L = [
217
+ const ke = 1e3, Le = 31536e9, L = [
217
218
  1e-3,
218
219
  2e-3,
219
220
  5e-3,
@@ -262,56 +263,56 @@ const De = 1e3, Le = 31536e9, L = [
262
263
  126144e5,
263
264
  15768e6,
264
265
  31536e6
265
- ], X = 36, W = 1, ke = 6, x = 6, We = 0.3, He = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
266
+ ], G = 36, O = 1, He = 6, ee = 6, Oe = 0.3, Ae = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
266
267
  function E(e) {
267
268
  return e < 10 ? `0${e}` : `${e}`;
268
269
  }
269
270
  function ce(e, t, o, s, n) {
270
- const l = new Date(e), { yr: a, mo: r, day: c, hr24: m, hr12: d, min: p, sec: M, ms: h, ampm: y } = oe(l, o), S = s ? d : m, f = s ? ` ${y}` : "", u = n ?? He;
271
+ const l = new Date(e), { yr: a, mo: i, day: m, hr24: c, hr12: M, min: h, sec: p, ms: f, ampm: y } = ne(l, o), b = s ? M : c, d = s ? ` ${y}` : "", u = n ?? Ae;
271
272
  if (t > 31536e4) return `${a}`;
272
- if (t > 31536e3) return `${u[r]} ${a}`;
273
- if (t > 604800) return `${u[r]} ${c}`;
274
- if (t > 86400) return `${u[r]} ${c} ${E(S)}:${E(p)}${f}`;
275
- if (t > 3600) return `${E(S)}:${E(p)}${f}`;
276
- if (t > 60) return `${E(S)}:${E(p)}:${E(M)}${f}`;
277
- const w = h > 0 ? `.${String(h).padStart(3, "0")}` : "";
278
- return `${E(S)}:${E(p)}:${E(M)}${w}${f}`;
273
+ if (t > 31536e3) return `${u[i]} ${a}`;
274
+ if (t > 604800) return `${u[i]} ${m}`;
275
+ if (t > 86400) return `${u[i]} ${m} ${E(b)}:${E(h)}${d}`;
276
+ if (t > 3600) return `${E(b)}:${E(h)}${d}`;
277
+ if (t > 60) return `${E(b)}:${E(h)}:${E(p)}${d}`;
278
+ const T = f > 0 ? `.${String(f).padStart(3, "0")}` : "";
279
+ return `${E(b)}:${E(h)}:${E(p)}${T}${d}`;
279
280
  }
280
- function Ae(e, t, o) {
281
+ function Ce(e, t, o) {
281
282
  const s = new Date(e);
282
283
  if (!o || o === "local") {
283
- const c = s.getFullYear(), m = s.getMonth(), d = s.getDate();
284
- return t > 31536e4 ? new Date(Math.floor(c / 100) * 100, 0).getTime() : t > 31536e3 ? new Date(Math.floor(c / 10) * 10, 0).getTime() : t > 86400 ? new Date(c, 0).getTime() : new Date(c, m, d).getTime();
284
+ const m = s.getFullYear(), c = s.getMonth(), M = s.getDate();
285
+ return t > 31536e4 ? new Date(Math.floor(m / 100) * 100, 0).getTime() : t > 31536e3 ? new Date(Math.floor(m / 10) * 10, 0).getTime() : t > 86400 ? new Date(m, 0).getTime() : new Date(m, c, M).getTime();
285
286
  }
286
- const { yr: n, hr24: l, min: a, sec: r } = oe(s, o);
287
- return t > 31536e4 ? Date.UTC(Math.floor(n / 100) * 100, 0, 1) : t > 31536e3 ? Date.UTC(Math.floor(n / 10) * 10, 0, 1) : t > 86400 ? Date.UTC(n, 0, 1) : e - (l * 3600 + a * 60 + r) * 1e3;
287
+ const { yr: n, hr24: l, min: a, sec: i } = ne(s, o);
288
+ return t > 31536e4 ? Date.UTC(Math.floor(n / 100) * 100, 0, 1) : t > 31536e3 ? Date.UTC(Math.floor(n / 10) * 10, 0, 1) : t > 86400 ? Date.UTC(n, 0, 1) : e - (l * 3600 + a * 60 + i) * 1e3;
288
289
  }
289
- function ee(e, t) {
290
+ function te(e, t) {
290
291
  return Math.ceil(e / t + 0.5) * t;
291
292
  }
292
- function ue(e, t, o) {
293
- var s, n, l, a, r, c, m, d, p, M, h, y;
293
+ function he(e, t, o) {
294
+ var s, n, l, a, i, m, c, M, h, p, f, y;
294
295
  return {
295
296
  color: ((s = t.style) == null ? void 0 : s.color) ?? ((n = e.style) == null ? void 0 : n.color) ?? J.color,
296
297
  borderColor: ((l = t.style) == null ? void 0 : l.borderColor) ?? ((a = e.style) == null ? void 0 : a.borderColor) ?? (o == null ? void 0 : o.swimLaneItemBorderColor) ?? J.borderColor,
297
- borderWidth: ((r = t.style) == null ? void 0 : r.borderWidth) ?? ((c = e.style) == null ? void 0 : c.borderWidth) ?? (o == null ? void 0 : o.swimLaneItemBorderWidth) ?? J.borderWidth,
298
- opacity: ((m = t.style) == null ? void 0 : m.opacity) ?? ((d = e.style) == null ? void 0 : d.opacity) ?? J.opacity,
299
- markerShape: ((p = t.style) == null ? void 0 : p.markerShape) ?? ((M = e.style) == null ? void 0 : M.markerShape) ?? J.markerShape,
300
- markerSize: ((h = t.style) == null ? void 0 : h.markerSize) ?? ((y = e.style) == null ? void 0 : y.markerSize) ?? J.markerSize
298
+ borderWidth: ((i = t.style) == null ? void 0 : i.borderWidth) ?? ((m = e.style) == null ? void 0 : m.borderWidth) ?? (o == null ? void 0 : o.swimLaneItemBorderWidth) ?? J.borderWidth,
299
+ opacity: ((c = t.style) == null ? void 0 : c.opacity) ?? ((M = e.style) == null ? void 0 : M.opacity) ?? J.opacity,
300
+ markerShape: ((h = t.style) == null ? void 0 : h.markerShape) ?? ((p = e.style) == null ? void 0 : p.markerShape) ?? J.markerShape,
301
+ markerSize: ((f = t.style) == null ? void 0 : f.markerSize) ?? ((y = e.style) == null ? void 0 : y.markerSize) ?? J.markerSize
301
302
  };
302
303
  }
303
- function he(e) {
304
- return Math.max(De, Math.min(Le, e));
304
+ function pe(e) {
305
+ return Math.max(ke, Math.min(Le, e));
305
306
  }
306
- function Oe(e, t, o) {
307
- const s = t - e, n = (e + t) / 2, l = he(s * o);
307
+ function Ue(e, t, o) {
308
+ const s = t - e, n = (e + t) / 2, l = pe(s * o);
308
309
  return {
309
310
  startMs: n - l / 2,
310
311
  endMs: n + l / 2
311
312
  };
312
313
  }
313
- function Ue(e, t, o, s) {
314
- const n = t - e, l = he(n * o), a = n > 0 ? (s - e) / n : 0.5;
314
+ function ve(e, t, o, s) {
315
+ const n = t - e, l = pe(n * o), a = n > 0 ? (s - e) / n : 0.5;
315
316
  return {
316
317
  startMs: s - a * l,
317
318
  endMs: s + (1 - a) * l
@@ -319,28 +320,28 @@ function Ue(e, t, o, s) {
319
320
  }
320
321
  function Be(e) {
321
322
  let t = 0;
322
- for (const o of e) t += (o.height ?? P) + W;
323
+ for (const o of e) t += (o.height ?? F) + O;
323
324
  return t;
324
325
  }
325
- function ve(e, t, o, s, n) {
326
- const { swimLanes: l, showSwimLanes: a, scrollTop: r, startMs: c, endMs: m, theme: d } = n;
326
+ function ze(e, t, o, s, n) {
327
+ const { swimLanes: l, showSwimLanes: a, scrollTop: i, startMs: m, endMs: c, theme: M } = n;
327
328
  if (!a || l.length === 0) return null;
328
- const p = Math.max(0, s - X);
329
- if (t < 0 || t >= p) return null;
330
- let M = -r;
331
- for (const h of l) {
332
- const y = h.height ?? P, S = M, f = M + y;
333
- if (M += y + W, !(t < S || t >= f)) {
334
- for (const u of h.items) {
329
+ const h = Math.max(0, s - G);
330
+ if (t < 0 || t >= h) return null;
331
+ let p = -i;
332
+ for (const f of l) {
333
+ const y = f.height ?? F, b = p, d = p + y;
334
+ if (p += y + O, !(t < b || t >= d)) {
335
+ for (const u of f.items) {
335
336
  if (u.interval) {
336
- const w = A.JulianDate.toDate(u.interval.start).getTime(), O = A.JulianDate.toDate(u.interval.stop).getTime(), k = (w - c) / (m - c) * o, U = (O - c) / (m - c) * o;
337
- if (e >= Math.max(0, k) && e <= Math.min(o, U))
338
- return { lane: h, item: u };
337
+ const T = A.JulianDate.toDate(u.interval.start).getTime(), $ = A.JulianDate.toDate(u.interval.stop).getTime(), j = (T - m) / (c - m) * o, C = ($ - m) / (c - m) * o;
338
+ if (e >= Math.max(0, j) && e <= Math.min(o, C))
339
+ return { lane: f, item: u };
339
340
  }
340
341
  if (u.instant) {
341
- const O = (A.JulianDate.toDate(u.instant).getTime() - c) / (m - c) * o, k = ue(h, u, d);
342
- if (Math.abs(e - O) <= k.markerSize / 2 + 2)
343
- return { lane: h, item: u };
342
+ const $ = (A.JulianDate.toDate(u.instant).getTime() - m) / (c - m) * o, j = he(f, u, M);
343
+ if (Math.abs(e - $) <= j.markerSize / 2 + 2)
344
+ return { lane: f, item: u };
344
345
  }
345
346
  }
346
347
  return null;
@@ -348,200 +349,205 @@ function ve(e, t, o, s, n) {
348
349
  }
349
350
  return null;
350
351
  }
351
- function ze(e, t, o, s) {
352
+ function je(e, t, o, s) {
352
353
  const { swimLanes: n, showSwimLanes: l, scrollTop: a } = s;
353
354
  if (!l || n.length === 0 || e > 80) return null;
354
- const r = Math.max(0, o - X);
355
- if (t < 0 || t >= r) return null;
356
- let c = -a;
357
- for (const m of n) {
358
- const d = m.height ?? P;
359
- if (t >= c && t < c + d) return m;
360
- c += d + W;
355
+ const i = Math.max(0, o - G);
356
+ if (t < 0 || t >= i) return null;
357
+ let m = -a;
358
+ for (const c of n) {
359
+ const M = c.height ?? F;
360
+ if (t >= m && t < m + M) return c;
361
+ m += M + O;
361
362
  }
362
363
  return null;
363
364
  }
364
- function je(e, t, o) {
365
+ function Xe(e, t, o) {
365
366
  if (!o.showSwimLanes || o.swimLanes.length === 0) return !1;
366
- const s = Math.max(0, t - X);
367
+ const s = Math.max(0, t - G);
367
368
  return e >= 0 && e < s;
368
369
  }
369
- function Xe(e, t, o, s) {
370
+ function Ge(e, t, o, s) {
370
371
  const {
371
372
  startMs: n,
372
373
  endMs: l,
373
374
  currentMs: a,
374
- theme: r,
375
- maxTicks: c,
376
- swimLanes: m,
377
- showSwimLanes: d,
378
- reorderState: p,
379
- timezone: M,
380
- use12h: h,
375
+ theme: i,
376
+ maxTicks: m,
377
+ swimLanes: c,
378
+ showSwimLanes: M,
379
+ reorderState: h,
380
+ timezone: p,
381
+ use12h: f,
381
382
  months: y,
382
- rangeSelection: S
383
+ rangeSelection: b,
384
+ hoverMs: d
383
385
  } = s;
384
- let { scrollTop: f } = s;
385
- const u = (l - n) / 1e3;
386
- if (u <= 0) return f;
387
- e.fillStyle = r.backgroundColor, e.fillRect(0, 0, t, o);
388
- const w = d && m.length > 0, k = w ? Math.max(0, o - X) : 0;
389
- let U = 0;
390
- if (w)
391
- for (const i of m) U += (i.height ?? P) + W;
392
- const G = Math.max(0, U - k);
393
- if (f > G && (f = G), f < 0 && (f = 0), w && k > 0) {
394
- e.save(), e.beginPath(), e.rect(0, 0, t, k), e.clip();
395
- let i = -f;
396
- const b = (D) => (D - n) / (l - n) * t;
397
- for (const D of m) {
398
- const T = D.height ?? P, C = i + T;
399
- if (C > 0 && i < k) {
400
- const g = D.style, B = (g == null ? void 0 : g.backgroundColor) ?? J.backgroundColor;
401
- B && B !== "transparent" && (e.fillStyle = B, e.fillRect(0, i, t, T)), e.strokeStyle = r.tickColor + "44", e.lineWidth = 0.5, e.beginPath(), e.moveTo(0, C), e.lineTo(t, C), e.stroke();
402
- for (const $ of D.items) {
403
- const H = ue(D, $, r);
404
- if ($.interval) {
405
- const V = A.JulianDate.toDate($.interval.start).getTime(), Y = A.JulianDate.toDate($.interval.stop).getTime(), N = b(V), _ = b(Y), q = Math.max(0, N), Q = Math.min(t, _) - q;
406
- if (Q > 0) {
386
+ let { scrollTop: u } = s;
387
+ const T = (l - n) / 1e3;
388
+ if (T <= 0) return u;
389
+ e.fillStyle = i.backgroundColor, e.fillRect(0, 0, t, o);
390
+ const $ = M && c.length > 0, C = $ ? Math.max(0, o - G) : 0;
391
+ let X = 0;
392
+ if ($)
393
+ for (const r of c) X += (r.height ?? F) + O;
394
+ const Z = Math.max(0, X - C);
395
+ if (u > Z && (u = Z), u < 0 && (u = 0), $ && C > 0) {
396
+ e.save(), e.beginPath(), e.rect(0, 0, t, C), e.clip();
397
+ let r = -u;
398
+ const D = (k) => (k - n) / (l - n) * t;
399
+ for (const k of c) {
400
+ const S = k.height ?? F, Y = r + S;
401
+ if (Y > 0 && r < C) {
402
+ const g = k.style, U = (g == null ? void 0 : g.backgroundColor) ?? J.backgroundColor;
403
+ U && U !== "transparent" && (e.fillStyle = U, e.fillRect(0, r, t, S)), e.strokeStyle = i.tickColor + "44", e.lineWidth = 0.5, e.beginPath(), e.moveTo(0, Y), e.lineTo(t, Y), e.stroke();
404
+ for (const I of k.items) {
405
+ const H = he(k, I, i);
406
+ if (I.interval) {
407
+ const q = A.JulianDate.toDate(I.interval.start).getTime(), w = A.JulianDate.toDate(I.interval.stop).getTime(), _ = D(q), W = D(w), Q = Math.max(0, _), x = Math.min(t, W) - Q;
408
+ if (x > 0) {
407
409
  e.globalAlpha = H.opacity, e.fillStyle = H.color;
408
- const se = 3, le = i + se, ae = T - se * 2;
409
- e.fillRect(q, le, Q, ae), H.borderWidth > 0 && (e.strokeStyle = H.borderColor, e.lineWidth = H.borderWidth, e.strokeRect(q, le, Q, ae)), e.globalAlpha = 1;
410
+ const le = 3, ae = r + le, me = S - le * 2;
411
+ e.fillRect(Q, ae, x, me), H.borderWidth > 0 && (e.strokeStyle = H.borderColor, e.lineWidth = H.borderWidth, e.strokeRect(Q, ae, x, me)), e.globalAlpha = 1;
410
412
  }
411
413
  }
412
- if ($.instant) {
413
- const V = A.JulianDate.toDate($.instant).getTime(), Y = b(V);
414
- if (Y >= -H.markerSize && Y <= t + H.markerSize) {
415
- const N = i + T / 2, _ = H.markerSize;
416
- e.globalAlpha = H.opacity, e.fillStyle = H.color, H.markerShape === "diamond" ? (e.beginPath(), e.moveTo(Y, N - _ / 2), e.lineTo(Y + _ / 2, N), e.lineTo(Y, N + _ / 2), e.lineTo(Y - _ / 2, N), e.closePath(), e.fill()) : H.markerShape === "circle" ? (e.beginPath(), e.arc(Y, N, _ / 2, 0, Math.PI * 2), e.fill()) : (e.strokeStyle = H.color, e.lineWidth = 2, e.beginPath(), e.moveTo(Y, i + 2), e.lineTo(Y, i + T - 2), e.stroke()), e.globalAlpha = 1;
414
+ if (I.instant) {
415
+ const q = A.JulianDate.toDate(I.instant).getTime(), w = D(q);
416
+ if (w >= -H.markerSize && w <= t + H.markerSize) {
417
+ const _ = r + S / 2, W = H.markerSize;
418
+ e.globalAlpha = H.opacity, e.fillStyle = H.color, H.markerShape === "diamond" ? (e.beginPath(), e.moveTo(w, _ - W / 2), e.lineTo(w + W / 2, _), e.lineTo(w, _ + W / 2), e.lineTo(w - W / 2, _), e.closePath(), e.fill()) : H.markerShape === "circle" ? (e.beginPath(), e.arc(w, _, W / 2, 0, Math.PI * 2), e.fill()) : (e.strokeStyle = H.color, e.lineWidth = 2, e.beginPath(), e.moveTo(w, r + 2), e.lineTo(w, r + S - 2), e.stroke()), e.globalAlpha = 1;
417
419
  }
418
420
  }
419
421
  }
420
- e.font = `${Math.min(11, T - 4)}px system-ui, sans-serif`, e.textAlign = "left", e.textBaseline = "middle", e.fillStyle = (g == null ? void 0 : g.labelColor) ?? J.labelColor, e.fillText(D.label, ke, i + T / 2);
422
+ e.font = `${Math.min(11, S - 4)}px system-ui, sans-serif`, e.textAlign = "left", e.textBaseline = "middle", e.fillStyle = (g == null ? void 0 : g.labelColor) ?? J.labelColor, e.fillText(k.label, He, r + S / 2);
421
423
  }
422
- if (i += T + W, i >= k) break;
424
+ if (r += S + O, r >= C) break;
423
425
  }
424
- if (p && p.dragging) {
425
- const D = p.currentY - p.dragStartY;
426
- let T = -f;
427
- for (let g = 0; g < m.length && g < p.insertIndex; g++)
428
- T += (m[g].height ?? P) + W;
429
- e.strokeStyle = r.indicatorColor, e.lineWidth = 2, e.beginPath(), e.moveTo(0, T), e.lineTo(t, T), e.stroke();
430
- const C = m.find((g) => g.id === p.dragLaneId);
431
- if (C) {
432
- const g = C.height ?? P;
433
- let B = -f;
434
- for (const $ of m) {
435
- if ($.id === p.dragLaneId) break;
436
- B += ($.height ?? P) + W;
426
+ if (h && h.dragging) {
427
+ const k = h.currentY - h.dragStartY;
428
+ let S = -u;
429
+ for (let g = 0; g < c.length && g < h.insertIndex; g++)
430
+ S += (c[g].height ?? F) + O;
431
+ e.strokeStyle = i.indicatorColor, e.lineWidth = 2, e.beginPath(), e.moveTo(0, S), e.lineTo(t, S), e.stroke();
432
+ const Y = c.find((g) => g.id === h.dragLaneId);
433
+ if (Y) {
434
+ const g = Y.height ?? F;
435
+ let U = -u;
436
+ for (const I of c) {
437
+ if (I.id === h.dragLaneId) break;
438
+ U += (I.height ?? F) + O;
437
439
  }
438
- e.globalAlpha = 0.4, e.fillStyle = r.indicatorColor, e.fillRect(0, B + D, t, g), e.globalAlpha = 1;
440
+ e.globalAlpha = 0.4, e.fillStyle = i.indicatorColor, e.fillRect(0, U + k, t, g), e.globalAlpha = 1;
439
441
  }
440
442
  }
441
- if (U > k) {
442
- const D = t - x - 2, T = k / U, C = Math.max(20, k * T), g = f / G * (k - C);
443
- e.fillStyle = r.tickColor + "22", e.fillRect(D, 0, x, k), e.fillStyle = r.tickColor + "88", e.fillRect(D, g, x, C);
443
+ if (X > C) {
444
+ const k = t - ee - 2, S = C / X, Y = Math.max(20, C * S), g = u / Z * (C - Y);
445
+ e.fillStyle = i.tickColor + "22", e.fillRect(k, 0, ee, C), e.fillStyle = i.tickColor + "88", e.fillRect(k, g, ee, Y);
444
446
  }
445
447
  e.restore();
446
448
  }
447
- e.font = `${r.fontSize}px monospace`;
448
- const pe = ce(n + u * 500, u, M, h, y), Me = e.measureText(pe).width + 24, de = Math.max(Me / t * u, u / 1e3);
449
- let I = L[L.length - 1], v = L.length - 1;
450
- for (let i = 0; i < L.length; i++)
451
- if (L[i] > de) {
452
- I = L[i], v = i;
449
+ e.font = `${i.fontSize}px monospace`;
450
+ const Me = ce(n + T * 500, T, p, f, y), de = e.measureText(Me).width + 24, ge = Math.max(de / t * T, T / 1e3);
451
+ let P = L[L.length - 1], v = L.length - 1;
452
+ for (let r = 0; r < L.length; r++)
453
+ if (L[r] > ge) {
454
+ P = L[r], v = r;
453
455
  break;
454
456
  }
455
- if (c != null && c > 0)
456
- for (; v < L.length - 1 && u / I > c; )
457
- v++, I = L[v];
457
+ if (m != null && m > 0)
458
+ for (; v < L.length - 1 && T / P > m; )
459
+ v++, P = L[v];
458
460
  let R = 0;
459
- for (let i = v - 1; i >= 0; i--)
460
- if (I % L[i] < 1e-4) {
461
- t * (L[i] / u) >= 3 && (R = L[i]);
461
+ for (let r = v - 1; r >= 0; r--)
462
+ if (P % L[r] < 1e-4) {
463
+ t * (L[r] / T) >= 3 && (R = L[r]);
462
464
  break;
463
465
  }
464
- let z = 0;
466
+ let B = 0;
465
467
  if (R > 0) {
466
- for (let i = 0; i < L.length && L[i] < R; i++)
467
- if (R % L[i] < 1e-4 && t * (L[i] / u) >= 3) {
468
- z = L[i];
468
+ for (let r = 0; r < L.length && L[r] < R; r++)
469
+ if (R % L[r] < 1e-4 && t * (L[r] / T) >= 3) {
470
+ B = L[r];
469
471
  break;
470
472
  }
471
473
  }
472
- const ne = Ae(n, u, M), j = (n - ne) / 1e3, Z = j + u, K = (i) => t * ((i - j) / u);
473
- if (z > 0) {
474
- e.strokeStyle = r.tickColor, e.lineWidth = 1;
475
- for (let i = Math.floor(j / z) * z; i <= Z; i = ee(i, z)) {
476
- const b = K(i);
477
- e.beginPath(), e.moveTo(b, o - r.minorTickHeight), e.lineTo(b, o), e.stroke();
474
+ const re = Ce(n, T, p), z = (n - re) / 1e3, K = z + T, V = (r) => t * ((r - z) / T);
475
+ if (B > 0) {
476
+ e.strokeStyle = i.tickColor, e.lineWidth = 1;
477
+ for (let r = Math.floor(z / B) * B; r <= K; r = te(r, B)) {
478
+ const D = V(r);
479
+ e.beginPath(), e.moveTo(D, o - i.minorTickHeight), e.lineTo(D, o), e.stroke();
478
480
  }
479
481
  }
480
482
  if (R > 0) {
481
- e.strokeStyle = r.tickColor, e.lineWidth = 1;
482
- for (let i = Math.floor(j / R) * R; i <= Z; i = ee(i, R)) {
483
- const b = K(i);
484
- e.beginPath(), e.moveTo(b, o - r.minorTickHeight), e.lineTo(b, o), e.stroke();
483
+ e.strokeStyle = i.tickColor, e.lineWidth = 1;
484
+ for (let r = Math.floor(z / R) * R; r <= K; r = te(r, R)) {
485
+ const D = V(r);
486
+ e.beginPath(), e.moveTo(D, o - i.minorTickHeight), e.lineTo(D, o), e.stroke();
485
487
  }
486
488
  }
487
489
  e.textAlign = "center", e.textBaseline = "bottom";
488
- let re = -1 / 0;
489
- for (let i = Math.floor(j / I) * I; i <= Z + I; i = ee(i, I)) {
490
- const b = K(i), D = ne + i * 1e3;
491
- e.strokeStyle = r.majorTickColor, e.lineWidth = 1, e.beginPath(), e.moveTo(b, o - r.majorTickHeight), e.lineTo(b, o), e.stroke();
492
- const T = ce(D, u, M, h, y), C = e.measureText(T).width, g = b - C / 2;
493
- g > re && (e.fillStyle = r.labelColor, e.fillText(T, b, o - r.majorTickHeight - 4), re = g + C + 5);
490
+ let ie = -1 / 0;
491
+ for (let r = Math.floor(z / P) * P; r <= K + P; r = te(r, P)) {
492
+ const D = V(r), k = re + r * 1e3;
493
+ e.strokeStyle = i.majorTickColor, e.lineWidth = 1, e.beginPath(), e.moveTo(D, o - i.majorTickHeight), e.lineTo(D, o), e.stroke();
494
+ const S = ce(k, T, p, f, y), Y = e.measureText(S).width, g = D - Y / 2;
495
+ g > ie && (e.fillStyle = i.labelColor, e.fillText(S, D, o - i.majorTickHeight - 4), ie = g + Y + 5);
496
+ }
497
+ if (b) {
498
+ const r = (b.startMs - n) / (l - n) * t, D = (b.endMs - n) / (l - n) * t, k = Math.min(r, D), S = Math.abs(D - r);
499
+ e.globalAlpha = 0.2, e.fillStyle = i.indicatorColor, e.fillRect(k, 0, S, o), e.globalAlpha = 1;
494
500
  }
495
- if (S) {
496
- const i = (S.startMs - n) / (l - n) * t, b = (S.endMs - n) / (l - n) * t, D = Math.min(i, b), T = Math.abs(b - i);
497
- e.globalAlpha = 0.2, e.fillStyle = r.indicatorColor, e.fillRect(D, 0, T, o), e.globalAlpha = 1;
501
+ const se = (a - n) / (l - n) * t;
502
+ if (e.strokeStyle = i.indicatorColor, e.lineWidth = i.indicatorLineWidth, e.beginPath(), e.moveTo(se, 0), e.lineTo(se, o), e.stroke(), d != null) {
503
+ const r = (d - n) / (l - n) * t;
504
+ e.globalAlpha = 0.15, e.strokeStyle = i.indicatorColor, e.lineWidth = i.indicatorLineWidth, e.beginPath(), e.moveTo(r, 0), e.lineTo(r, o), e.stroke(), e.globalAlpha = 1;
498
505
  }
499
- const ie = (a - n) / (l - n) * t;
500
- return e.strokeStyle = r.indicatorColor, e.lineWidth = r.indicatorLineWidth, e.beginPath(), e.moveTo(ie, 0), e.lineTo(ie, o), e.stroke(), f;
506
+ return u;
501
507
  }
502
508
  export {
503
- Ye as DEFAULT_LABELS,
504
- P as DEFAULT_LANE_HEIGHT,
505
- fe as DateTimeFormats,
506
- ke as LABEL_PAD_LEFT,
507
- W as LANE_GAP,
509
+ we as DEFAULT_LABELS,
510
+ F as DEFAULT_LANE_HEIGHT,
511
+ ue as DateTimeFormats,
512
+ He as LABEL_PAD_LEFT,
513
+ O as LANE_GAP,
508
514
  Le as MAX_SPAN_MS,
509
- De as MIN_SPAN_MS,
510
- He as MONTHS,
511
- x as SCROLLBAR_WIDTH,
512
- We as SWIM_LANE_SCROLL_SPEED,
513
- X as TICK_AREA_HEIGHT,
515
+ ke as MIN_SPAN_MS,
516
+ Ae as MONTHS,
517
+ ee as SCROLLBAR_WIDTH,
518
+ Oe as SWIM_LANE_SCROLL_SPEED,
519
+ G as TICK_AREA_HEIGHT,
514
520
  L as TIC_SCALES,
515
- me as TickInterval,
516
- Ie as Timezones,
517
- Ae as calcEpochMs,
518
- he as clampSpan,
521
+ fe as TickInterval,
522
+ Pe as Timezones,
523
+ Ce as calcEpochMs,
524
+ pe as clampSpan,
519
525
  J as defaultSwimLaneStyle,
520
- we as defaultTheme,
521
- Xe as drawTimeline,
526
+ Ee as defaultTheme,
527
+ Ge as drawTimeline,
522
528
  ye as formatDateTime,
523
- Pe as formatTime,
524
- $e as fromMilliseconds,
525
- Ne as generateTicks,
526
- oe as getDateParts,
527
- ge as getDurationMs,
529
+ Fe as formatTime,
530
+ Ie as fromMilliseconds,
531
+ _e as generateTicks,
532
+ ne as getDateParts,
533
+ Te as getDurationMs,
528
534
  Re as getTimezoneAbbr,
529
- ze as hitTestLaneLabel,
530
- ve as hitTestSwimLane,
531
- je as isInSwimLaneRegion,
535
+ je as hitTestLaneLabel,
536
+ ze as hitTestSwimLane,
537
+ Xe as isInSwimLaneRegion,
532
538
  ce as makeLabel,
533
- ee as nextTic,
534
- Fe as positionToTime,
535
- ue as resolveItemStyle,
536
- Ce as resolveLabel,
537
- _e as snapToTick,
539
+ te as nextTic,
540
+ Ne as positionToTime,
541
+ he as resolveItemStyle,
542
+ Ye as resolveLabel,
543
+ We as snapToTick,
538
544
  Je as splitForDisplay,
539
- be as timeToPosition,
540
- te as toDate,
541
- Ee as toJulianDate,
542
- F as toMilliseconds,
545
+ De as timeToPosition,
546
+ oe as toDate,
547
+ $e as toJulianDate,
548
+ N as toMilliseconds,
543
549
  Be as totalSwimLaneHeight,
544
550
  E as twoD,
545
- Ue as zoomAroundMs,
546
- Oe as zoomRange
551
+ ve as zoomAroundMs,
552
+ Ue as zoomRange
547
553
  };
@@ -1 +1 @@
1
- (function(l,j){typeof exports=="object"&&typeof module<"u"?j(exports,require("cesium")):typeof define=="function"&&define.amd?define(["exports","cesium"],j):(l=typeof globalThis<"u"?globalThis:l||self,j(l.CesiumTimelineCore={},l.Cesium))})(this,(function(l,j){"use strict";function Ae(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const o in e)if(o!=="default"){const i=Object.getOwnPropertyDescriptor(e,o);Object.defineProperty(t,o,i.get?i:{enumerable:!0,get:()=>e[o]})}}return t.default=e,Object.freeze(t)}const k=Ae(j);function He(e,t){return typeof e=="function"?e(t):e}const ke={dateTimeClickTooltip:"Click to jump to a date/time",liveLabel:"LIVE",liveActiveLabel:"● LIVE",liveTooltip:"Jump to live (now)",liveActiveTooltip:"Currently live",resetSpeedTooltip:"Reset to 1× speed",jumpToStartTooltip:"Jump to start",noStartTimeTooltip:"No start time set",jumpToEndTooltip:"Jump to end",noEndTimeTooltip:"No end time set",rewindTooltip:"Rewind",rewindActiveTooltip:e=>`Reverse ${e}× — click to speed up, press play to stop`,playTooltip:"Play",playFromRewindTooltip:"Play (reset to 1×)",pauseTooltip:"Pause",fastForwardTooltip:"Fast forward",fastForwardActiveTooltip:e=>`${e}× speed — click to increase, click again at max to reset`,collapseSwimLanesTooltip:"Collapse swim lanes",expandSwimLanesTooltip:"Expand swim lanes",months:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]},Ce={backgroundColor:"#1a1a1a",tickColor:"#666666",majorTickColor:"#999999",labelColor:"#cccccc",indicatorColor:"#d69826",indicatorLineWidth:5,majorTickHeight:10,minorTickHeight:5,fontSize:12,controlBarBackground:"#242424",controlBarBorder:"#333333",buttonColor:"#666666",buttonHoverColor:"#888888",buttonActiveColor:"#d69826",swimLaneItemBorderColor:"#666666",swimLaneItemBorderWidth:0};var x=(e=>(e[e.FIFTEEN_MIN=15]="FIFTEEN_MIN",e[e.THIRTY_MIN=30]="THIRTY_MIN",e[e.HOURLY=60]="HOURLY",e[e.CUSTOM=-1]="CUSTOM",e))(x||{});const I={color:"#4da6ff",borderColor:"#2980b9",borderWidth:1,opacity:.8,markerShape:"diamond",markerSize:10,labelColor:"#cccccc",backgroundColor:"transparent"},P=24;function Ee(e){return e instanceof k.JulianDate?k.JulianDate.clone(e):k.JulianDate.fromDate(e)}function Z(e){return e instanceof k.JulianDate?k.JulianDate.toDate(e):e}function N(e){return Z(e).getTime()}function _e(e){return k.JulianDate.fromDate(new Date(e))}function me(e,t){return N(t)-N(e)}const we=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],Ye=["January","February","March","April","May","June","July","August","September","October","November","December"],ee={DEFAULT:"MMM DD YYYY HH:mm:ss",TWELVE_HR:"MMM DD YYYY hh:mm:ss A",ISO:"YYYY-MM-DD HH:mm:ss",US:"MM/DD/YYYY HH:mm",EU:"DD/MM/YYYY HH:mm",TIME_ONLY:"HH:mm:ss",TIME_12:"hh:mm:ss A"},Ie={LOCAL:"local",UTC:"UTC"};function V(e,t){if(!t||t==="local"){const d=e.getFullYear(),M=e.getMonth(),D=e.getDate(),b=e.getHours(),u=b%12||12,h=e.getMinutes(),Y=e.getSeconds(),U=e.getMilliseconds();return{yr:d,mo:M,day:D,hr24:b,hr12:u,min:h,sec:Y,ms:U,ampm:b<12?"AM":"PM"}}const o=new Intl.DateTimeFormat("en-US",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1}),i={};for(const d of o.formatToParts(e))d.type!=="literal"&&(i[d.type]=d.value);const n=parseInt(i.year),s=parseInt(i.month)-1,c=parseInt(i.day);let r=parseInt(i.hour);r===24&&(r=0);const m=r%12||12,f=parseInt(i.minute),g=parseInt(i.second),T=e.getMilliseconds();return{yr:n,mo:s,day:c,hr24:r,hr12:m,min:f,sec:g,ms:T,ampm:r<12?"AM":"PM"}}function Pe(e,t){var n;if(!t||t==="local")return null;const o=Z(e);return((n=new Intl.DateTimeFormat("en-US",{timeZone:t,timeZoneName:"short"}).formatToParts(o).find(s=>s.type==="timeZoneName"))==null?void 0:n.value)??null}function fe(e,t=ee.DEFAULT,o){const i=Z(e),{yr:n,mo:s,day:c,hr24:r,hr12:m,min:f,sec:g,ms:T,ampm:d}=V(i,o),M=u=>String(u).padStart(2,"0"),D=u=>String(u).padStart(3,"0"),b={YYYY:String(n),YY:String(n).slice(-2),MMMM:Ye[s],MMM:we[s],MM:M(s+1),M:String(s+1),DD:M(c),D:String(c),HH:M(r),H:String(r),hh:M(m),h:String(m),mm:M(f),ss:M(g),SSS:D(T),A:d,a:d.toLowerCase()};return t.replace(/YYYY|YY|MMMM|MMM|MM|M|DD|D|HH|H|hh|h|mm|ss|SSS|A|a/g,u=>b[u]??u)}function Ne(e=ee.DEFAULT){const t=["YYYY","YY","MMMM","MMM","MM","M","DD","D"],o=["HH","H","hh","h","mm","ss","SSS","A","a"],i=c=>c.replace(/\s{2,}/g," ").trim().replace(/^[\s\W]+|[\s\W]+$/g,"").trim();let n=e;for(const c of t)n=n.replace(c,"");let s=e;for(const c of o)s=s.replace(c,"");return{timeFormat:i(n),dateFormat:i(s)}}function Re(e,t=!1){return fe(e,t?"HH:mm:ss":"HH:mm")}function ue(e,t,o,i){const n=N(e),s=N(t),c=N(o);if(c===s)return 0;const r=(n-s)/(c-s);return Math.max(0,Math.min(1,r))*i}function Fe(e,t,o,i){const n=Math.max(0,Math.min(1,e/i)),s=N(t),c=N(o),r=s+n*(c-s);return k.JulianDate.fromDate(new Date(r))}function $e(e,t,o,i){const n=[],s=me(e,t),c=N(e);let r;typeof o=="number"&&o in x||typeof o=="number"?r=o*60*1e3:r=3600*1e3;const m=r*4;let f=c,g=0;for(;f<=c+s;){const T=g*r%m===0,d=ue(new Date(f),e,t,i);let M;if(T){const D=new Date(f),b=D.getHours().toString().padStart(2,"0"),u=D.getMinutes().toString().padStart(2,"0");M=`${b}:${u}`}n.push({position:d,isMajor:T,label:M}),f+=r,g++}return n}function Oe(e,t,o=10){let i=t[0],n=Math.abs(i.position-e);for(const s of t){const c=Math.abs(s.position-e);c<n&&(n=c,i=s)}return n<=o?i.position:e}const he=1e3,Me=31536e9,y=[.001,.002,.005,.01,.02,.05,.1,.25,.5,1,2,5,10,15,30,60,120,300,600,900,1800,3600,7200,14400,21600,43200,86400,172800,345600,604800,1296e3,2592e3,5184e3,7776e3,15552e3,31536e3,63072e3,126144e3,15768e4,31536e4,63072e4,126144e4,15768e5,31536e5,63072e5,126144e5,15768e6,31536e6],z=36,F=1,Te=6,q=6,Je=.3,de=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function _(e){return e<10?`0${e}`:`${e}`}function te(e,t,o,i,n){const s=new Date(e),{yr:c,mo:r,day:m,hr24:f,hr12:g,min:T,sec:d,ms:M,ampm:D}=V(s,o),b=i?g:f,u=i?` ${D}`:"",h=n??de;if(t>31536e4)return`${c}`;if(t>31536e3)return`${h[r]} ${c}`;if(t>604800)return`${h[r]} ${m}`;if(t>86400)return`${h[r]} ${m} ${_(b)}:${_(T)}${u}`;if(t>3600)return`${_(b)}:${_(T)}${u}`;if(t>60)return`${_(b)}:${_(T)}:${_(d)}${u}`;const Y=M>0?`.${String(M).padStart(3,"0")}`:"";return`${_(b)}:${_(T)}:${_(d)}${Y}${u}`}function ge(e,t,o){const i=new Date(e);if(!o||o==="local"){const m=i.getFullYear(),f=i.getMonth(),g=i.getDate();return t>31536e4?new Date(Math.floor(m/100)*100,0).getTime():t>31536e3?new Date(Math.floor(m/10)*10,0).getTime():t>86400?new Date(m,0).getTime():new Date(m,f,g).getTime()}const{yr:n,hr24:s,min:c,sec:r}=V(i,o);return t>31536e4?Date.UTC(Math.floor(n/100)*100,0,1):t>31536e3?Date.UTC(Math.floor(n/10)*10,0,1):t>86400?Date.UTC(n,0,1):e-(s*3600+c*60+r)*1e3}function Q(e,t){return Math.ceil(e/t+.5)*t}function oe(e,t,o){var i,n,s,c,r,m,f,g,T,d,M,D;return{color:((i=t.style)==null?void 0:i.color)??((n=e.style)==null?void 0:n.color)??I.color,borderColor:((s=t.style)==null?void 0:s.borderColor)??((c=e.style)==null?void 0:c.borderColor)??(o==null?void 0:o.swimLaneItemBorderColor)??I.borderColor,borderWidth:((r=t.style)==null?void 0:r.borderWidth)??((m=e.style)==null?void 0:m.borderWidth)??(o==null?void 0:o.swimLaneItemBorderWidth)??I.borderWidth,opacity:((f=t.style)==null?void 0:f.opacity)??((g=e.style)==null?void 0:g.opacity)??I.opacity,markerShape:((T=t.style)==null?void 0:T.markerShape)??((d=e.style)==null?void 0:d.markerShape)??I.markerShape,markerSize:((M=t.style)==null?void 0:M.markerSize)??((D=e.style)==null?void 0:D.markerSize)??I.markerSize}}function ne(e){return Math.max(he,Math.min(Me,e))}function We(e,t,o){const i=t-e,n=(e+t)/2,s=ne(i*o);return{startMs:n-s/2,endMs:n+s/2}}function Ue(e,t,o,i){const n=t-e,s=ne(n*o),c=n>0?(i-e)/n:.5;return{startMs:i-c*s,endMs:i+(1-c)*s}}function ve(e){let t=0;for(const o of e)t+=(o.height??P)+F;return t}function Be(e,t,o,i,n){const{swimLanes:s,showSwimLanes:c,scrollTop:r,startMs:m,endMs:f,theme:g}=n;if(!c||s.length===0)return null;const T=Math.max(0,i-z);if(t<0||t>=T)return null;let d=-r;for(const M of s){const D=M.height??P,b=d,u=d+D;if(d+=D+F,!(t<b||t>=u)){for(const h of M.items){if(h.interval){const Y=k.JulianDate.toDate(h.interval.start).getTime(),U=k.JulianDate.toDate(h.interval.stop).getTime(),H=(Y-m)/(f-m)*o,v=(U-m)/(f-m)*o;if(e>=Math.max(0,H)&&e<=Math.min(o,v))return{lane:M,item:h}}if(h.instant){const U=(k.JulianDate.toDate(h.instant).getTime()-m)/(f-m)*o,H=oe(M,h,g);if(Math.abs(e-U)<=H.markerSize/2+2)return{lane:M,item:h}}}return null}}return null}function je(e,t,o,i){const{swimLanes:n,showSwimLanes:s,scrollTop:c}=i;if(!s||n.length===0||e>80)return null;const r=Math.max(0,o-z);if(t<0||t>=r)return null;let m=-c;for(const f of n){const g=f.height??P;if(t>=m&&t<m+g)return f;m+=g+F}return null}function ze(e,t,o){if(!o.showSwimLanes||o.swimLanes.length===0)return!1;const i=Math.max(0,t-z);return e>=0&&e<i}function Ge(e,t,o,i){const{startMs:n,endMs:s,currentMs:c,theme:r,maxTicks:m,swimLanes:f,showSwimLanes:g,reorderState:T,timezone:d,use12h:M,months:D,rangeSelection:b}=i;let{scrollTop:u}=i;const h=(s-n)/1e3;if(h<=0)return u;e.fillStyle=r.backgroundColor,e.fillRect(0,0,t,o);const Y=g&&f.length>0,H=Y?Math.max(0,o-z):0;let v=0;if(Y)for(const a of f)v+=(a.height??P)+F;const ie=Math.max(0,v-H);if(u>ie&&(u=ie),u<0&&(u=0),Y&&H>0){e.save(),e.beginPath(),e.rect(0,0,t,H),e.clip();let a=-u;const L=A=>(A-n)/(s-n)*t;for(const A of f){const p=A.height??P,E=a+p;if(E>0&&a<H){const S=A.style,B=(S==null?void 0:S.backgroundColor)??I.backgroundColor;B&&B!=="transparent"&&(e.fillStyle=B,e.fillRect(0,a,t,p)),e.strokeStyle=r.tickColor+"44",e.lineWidth=.5,e.beginPath(),e.moveTo(0,E),e.lineTo(t,E),e.stroke();for(const R of A.items){const C=oe(A,R,r);if(R.interval){const le=k.JulianDate.toDate(R.interval.start).getTime(),w=k.JulianDate.toDate(R.interval.stop).getTime(),J=L(le),W=L(w),se=Math.max(0,J),ce=Math.min(t,W)-se;if(ce>0){e.globalAlpha=C.opacity,e.fillStyle=C.color;const ye=3,De=a+ye,Le=p-ye*2;e.fillRect(se,De,ce,Le),C.borderWidth>0&&(e.strokeStyle=C.borderColor,e.lineWidth=C.borderWidth,e.strokeRect(se,De,ce,Le)),e.globalAlpha=1}}if(R.instant){const le=k.JulianDate.toDate(R.instant).getTime(),w=L(le);if(w>=-C.markerSize&&w<=t+C.markerSize){const J=a+p/2,W=C.markerSize;e.globalAlpha=C.opacity,e.fillStyle=C.color,C.markerShape==="diamond"?(e.beginPath(),e.moveTo(w,J-W/2),e.lineTo(w+W/2,J),e.lineTo(w,J+W/2),e.lineTo(w-W/2,J),e.closePath(),e.fill()):C.markerShape==="circle"?(e.beginPath(),e.arc(w,J,W/2,0,Math.PI*2),e.fill()):(e.strokeStyle=C.color,e.lineWidth=2,e.beginPath(),e.moveTo(w,a+2),e.lineTo(w,a+p-2),e.stroke()),e.globalAlpha=1}}}e.font=`${Math.min(11,p-4)}px system-ui, sans-serif`,e.textAlign="left",e.textBaseline="middle",e.fillStyle=(S==null?void 0:S.labelColor)??I.labelColor,e.fillText(A.label,Te,a+p/2)}if(a+=p+F,a>=H)break}if(T&&T.dragging){const A=T.currentY-T.dragStartY;let p=-u;for(let S=0;S<f.length&&S<T.insertIndex;S++)p+=(f[S].height??P)+F;e.strokeStyle=r.indicatorColor,e.lineWidth=2,e.beginPath(),e.moveTo(0,p),e.lineTo(t,p),e.stroke();const E=f.find(S=>S.id===T.dragLaneId);if(E){const S=E.height??P;let B=-u;for(const R of f){if(R.id===T.dragLaneId)break;B+=(R.height??P)+F}e.globalAlpha=.4,e.fillStyle=r.indicatorColor,e.fillRect(0,B+A,t,S),e.globalAlpha=1}}if(v>H){const A=t-q-2,p=H/v,E=Math.max(20,H*p),S=u/ie*(H-E);e.fillStyle=r.tickColor+"22",e.fillRect(A,0,q,H),e.fillStyle=r.tickColor+"88",e.fillRect(A,S,q,E)}e.restore()}e.font=`${r.fontSize}px monospace`;const Xe=te(n+h*500,h,d,M,D),Ke=e.measureText(Xe).width+24,Ze=Math.max(Ke/t*h,h/1e3);let $=y[y.length-1],G=y.length-1;for(let a=0;a<y.length;a++)if(y[a]>Ze){$=y[a],G=a;break}if(m!=null&&m>0)for(;G<y.length-1&&h/$>m;)G++,$=y[G];let O=0;for(let a=G-1;a>=0;a--)if($%y[a]<1e-4){t*(y[a]/h)>=3&&(O=y[a]);break}let X=0;if(O>0){for(let a=0;a<y.length&&y[a]<O;a++)if(O%y[a]<1e-4&&t*(y[a]/h)>=3){X=y[a];break}}const Se=ge(n,h,d),K=(n-Se)/1e3,re=K+h,ae=a=>t*((a-K)/h);if(X>0){e.strokeStyle=r.tickColor,e.lineWidth=1;for(let a=Math.floor(K/X)*X;a<=re;a=Q(a,X)){const L=ae(a);e.beginPath(),e.moveTo(L,o-r.minorTickHeight),e.lineTo(L,o),e.stroke()}}if(O>0){e.strokeStyle=r.tickColor,e.lineWidth=1;for(let a=Math.floor(K/O)*O;a<=re;a=Q(a,O)){const L=ae(a);e.beginPath(),e.moveTo(L,o-r.minorTickHeight),e.lineTo(L,o),e.stroke()}}e.textAlign="center",e.textBaseline="bottom";let pe=-1/0;for(let a=Math.floor(K/$)*$;a<=re+$;a=Q(a,$)){const L=ae(a),A=Se+a*1e3;e.strokeStyle=r.majorTickColor,e.lineWidth=1,e.beginPath(),e.moveTo(L,o-r.majorTickHeight),e.lineTo(L,o),e.stroke();const p=te(A,h,d,M,D),E=e.measureText(p).width,S=L-E/2;S>pe&&(e.fillStyle=r.labelColor,e.fillText(p,L,o-r.majorTickHeight-4),pe=S+E+5)}if(b){const a=(b.startMs-n)/(s-n)*t,L=(b.endMs-n)/(s-n)*t,A=Math.min(a,L),p=Math.abs(L-a);e.globalAlpha=.2,e.fillStyle=r.indicatorColor,e.fillRect(A,0,p,o),e.globalAlpha=1}const be=(c-n)/(s-n)*t;return e.strokeStyle=r.indicatorColor,e.lineWidth=r.indicatorLineWidth,e.beginPath(),e.moveTo(be,0),e.lineTo(be,o),e.stroke(),u}l.DEFAULT_LABELS=ke,l.DEFAULT_LANE_HEIGHT=P,l.DateTimeFormats=ee,l.LABEL_PAD_LEFT=Te,l.LANE_GAP=F,l.MAX_SPAN_MS=Me,l.MIN_SPAN_MS=he,l.MONTHS=de,l.SCROLLBAR_WIDTH=q,l.SWIM_LANE_SCROLL_SPEED=Je,l.TICK_AREA_HEIGHT=z,l.TIC_SCALES=y,l.TickInterval=x,l.Timezones=Ie,l.calcEpochMs=ge,l.clampSpan=ne,l.defaultSwimLaneStyle=I,l.defaultTheme=Ce,l.drawTimeline=Ge,l.formatDateTime=fe,l.formatTime=Re,l.fromMilliseconds=_e,l.generateTicks=$e,l.getDateParts=V,l.getDurationMs=me,l.getTimezoneAbbr=Pe,l.hitTestLaneLabel=je,l.hitTestSwimLane=Be,l.isInSwimLaneRegion=ze,l.makeLabel=te,l.nextTic=Q,l.positionToTime=Fe,l.resolveItemStyle=oe,l.resolveLabel=He,l.snapToTick=Oe,l.splitForDisplay=Ne,l.timeToPosition=ue,l.toDate=Z,l.toJulianDate=Ee,l.toMilliseconds=N,l.totalSwimLaneHeight=ve,l.twoD=_,l.zoomAroundMs=Ue,l.zoomRange=We,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})}));
1
+ (function(a,B){typeof exports=="object"&&typeof module<"u"?B(exports,require("cesium")):typeof define=="function"&&define.amd?define(["exports","cesium"],B):(a=typeof globalThis<"u"?globalThis:a||self,B(a.CesiumTimelineCore={},a.Cesium))})(this,(function(a,B){"use strict";function ke(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const o in e)if(o!=="default"){const l=Object.getOwnPropertyDescriptor(e,o);Object.defineProperty(t,o,l.get?l:{enumerable:!0,get:()=>e[o]})}}return t.default=e,Object.freeze(t)}const H=ke(B);function He(e,t){return typeof e=="function"?e(t):e}const Ce={dateTimeClickTooltip:"Click to jump to a date/time",liveLabel:"LIVE",liveActiveLabel:"LIVE",liveTooltip:"Jump to live (now)",liveActiveTooltip:"Currently live",resetSpeedTooltip:"Reset to 1× speed",jumpToStartTooltip:"Jump to start",noStartTimeTooltip:"No start time set",jumpToEndTooltip:"Jump to end",noEndTimeTooltip:"No end time set",rewindTooltip:"Rewind",rewindActiveTooltip:e=>`Reverse ${e}× — click to speed up, press play to stop`,playTooltip:"Play",playFromRewindTooltip:"Play (reset to 1×)",pauseTooltip:"Pause",fastForwardTooltip:"Fast forward",fastForwardActiveTooltip:e=>`${e}× speed — click to increase, click again at max to reset`,collapseSwimLanesTooltip:"Collapse swim lanes",expandSwimLanesTooltip:"Expand swim lanes",months:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]},Ee={backgroundColor:"#1a1a1a",tickColor:"#666666",majorTickColor:"#999999",labelColor:"#cccccc",indicatorColor:"#d69826",indicatorLineWidth:5,majorTickHeight:10,minorTickHeight:5,fontSize:12,controlBarBackground:"#242424",controlBarBorder:"#333333",buttonColor:"#666666",buttonHoverColor:"#888888",buttonActiveColor:"#d69826",swimLaneItemBorderColor:"#666666",swimLaneItemBorderWidth:0,liveDotColor:"#e53e3e"};var ee=(e=>(e[e.FIFTEEN_MIN=15]="FIFTEEN_MIN",e[e.THIRTY_MIN=30]="THIRTY_MIN",e[e.HOURLY=60]="HOURLY",e[e.CUSTOM=-1]="CUSTOM",e))(ee||{});const I={color:"#4da6ff",borderColor:"#2980b9",borderWidth:1,opacity:.8,markerShape:"diamond",markerSize:10,labelColor:"#cccccc",backgroundColor:"transparent"},P=24;function _e(e){return e instanceof H.JulianDate?H.JulianDate.clone(e):H.JulianDate.fromDate(e)}function K(e){return e instanceof H.JulianDate?H.JulianDate.toDate(e):e}function N(e){return K(e).getTime()}function we(e){return H.JulianDate.fromDate(new Date(e))}function fe(e,t){return N(t)-N(e)}const Ye=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],Ie=["January","February","March","April","May","June","July","August","September","October","November","December"],te={DEFAULT:"MMM DD YYYY HH:mm:ss",TWELVE_HR:"MMM DD YYYY hh:mm:ss A",ISO:"YYYY-MM-DD HH:mm:ss",US:"MM/DD/YYYY HH:mm",EU:"DD/MM/YYYY HH:mm",TIME_ONLY:"HH:mm:ss",TIME_12:"hh:mm:ss A"},Pe={LOCAL:"local",UTC:"UTC"};function Z(e,t){if(!t||t==="local"){const T=e.getFullYear(),u=e.getMonth(),L=e.getDate(),y=e.getHours(),g=y%12||12,h=e.getMinutes(),p=e.getSeconds(),R=e.getMilliseconds();return{yr:T,mo:u,day:L,hr24:y,hr12:g,min:h,sec:p,ms:R,ampm:y<12?"AM":"PM"}}const o=new Intl.DateTimeFormat("en-US",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1}),l={};for(const T of o.formatToParts(e))T.type!=="literal"&&(l[T.type]=T.value);const n=parseInt(l.year),s=parseInt(l.month)-1,m=parseInt(l.day);let r=parseInt(l.hour);r===24&&(r=0);const c=r%12||12,f=parseInt(l.minute),M=parseInt(l.second),d=e.getMilliseconds();return{yr:n,mo:s,day:m,hr24:r,hr12:c,min:f,sec:M,ms:d,ampm:r<12?"AM":"PM"}}function Ne(e,t){var n;if(!t||t==="local")return null;const o=K(e);return((n=new Intl.DateTimeFormat("en-US",{timeZone:t,timeZoneName:"short"}).formatToParts(o).find(s=>s.type==="timeZoneName"))==null?void 0:n.value)??null}function ue(e,t=te.DEFAULT,o){const l=K(e),{yr:n,mo:s,day:m,hr24:r,hr12:c,min:f,sec:M,ms:d,ampm:T}=Z(l,o),u=g=>String(g).padStart(2,"0"),L=g=>String(g).padStart(3,"0"),y={YYYY:String(n),YY:String(n).slice(-2),MMMM:Ie[s],MMM:Ye[s],MM:u(s+1),M:String(s+1),DD:u(m),D:String(m),HH:u(r),H:String(r),hh:u(c),h:String(c),mm:u(f),ss:u(M),SSS:L(d),A:T,a:T.toLowerCase()};return t.replace(/YYYY|YY|MMMM|MMM|MM|M|DD|D|HH|H|hh|h|mm|ss|SSS|A|a/g,g=>y[g]??g)}function Re(e=te.DEFAULT){const t=["YYYY","YY","MMMM","MMM","MM","M","DD","D"],o=["HH","H","hh","h","mm","ss","SSS","A","a"],l=m=>m.replace(/\s{2,}/g," ").trim().replace(/^[\s\W]+|[\s\W]+$/g,"").trim();let n=e;for(const m of t)n=n.replace(m,"");let s=e;for(const m of o)s=s.replace(m,"");return{timeFormat:l(n),dateFormat:l(s)}}function Fe(e,t=!1){return ue(e,t?"HH:mm:ss":"HH:mm")}function he(e,t,o,l){const n=N(e),s=N(t),m=N(o);if(m===s)return 0;const r=(n-s)/(m-s);return Math.max(0,Math.min(1,r))*l}function $e(e,t,o,l){const n=Math.max(0,Math.min(1,e/l)),s=N(t),m=N(o),r=s+n*(m-s);return H.JulianDate.fromDate(new Date(r))}function Oe(e,t,o,l){const n=[],s=fe(e,t),m=N(e);let r;typeof o=="number"&&o in ee||typeof o=="number"?r=o*60*1e3:r=3600*1e3;const c=r*4;let f=m,M=0;for(;f<=m+s;){const d=M*r%c===0,T=he(new Date(f),e,t,l);let u;if(d){const L=new Date(f),y=L.getHours().toString().padStart(2,"0"),g=L.getMinutes().toString().padStart(2,"0");u=`${y}:${g}`}n.push({position:T,isMajor:d,label:u}),f+=r,M++}return n}function Je(e,t,o=10){let l=t[0],n=Math.abs(l.position-e);for(const s of t){const m=Math.abs(s.position-e);m<n&&(n=m,l=s)}return n<=o?l.position:e}const de=1e3,Te=31536e9,D=[.001,.002,.005,.01,.02,.05,.1,.25,.5,1,2,5,10,15,30,60,120,300,600,900,1800,3600,7200,14400,21600,43200,86400,172800,345600,604800,1296e3,2592e3,5184e3,7776e3,15552e3,31536e3,63072e3,126144e3,15768e4,31536e4,63072e4,126144e4,15768e5,31536e5,63072e5,126144e5,15768e6,31536e6],j=36,$=1,Me=6,V=6,We=.3,ge=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function w(e){return e<10?`0${e}`:`${e}`}function oe(e,t,o,l,n){const s=new Date(e),{yr:m,mo:r,day:c,hr24:f,hr12:M,min:d,sec:T,ms:u,ampm:L}=Z(s,o),y=l?M:f,g=l?` ${L}`:"",h=n??ge;if(t>31536e4)return`${m}`;if(t>31536e3)return`${h[r]} ${m}`;if(t>604800)return`${h[r]} ${c}`;if(t>86400)return`${h[r]} ${c} ${w(y)}:${w(d)}${g}`;if(t>3600)return`${w(y)}:${w(d)}${g}`;if(t>60)return`${w(y)}:${w(d)}:${w(T)}${g}`;const p=u>0?`.${String(u).padStart(3,"0")}`:"";return`${w(y)}:${w(d)}:${w(T)}${p}${g}`}function Se(e,t,o){const l=new Date(e);if(!o||o==="local"){const c=l.getFullYear(),f=l.getMonth(),M=l.getDate();return t>31536e4?new Date(Math.floor(c/100)*100,0).getTime():t>31536e3?new Date(Math.floor(c/10)*10,0).getTime():t>86400?new Date(c,0).getTime():new Date(c,f,M).getTime()}const{yr:n,hr24:s,min:m,sec:r}=Z(l,o);return t>31536e4?Date.UTC(Math.floor(n/100)*100,0,1):t>31536e3?Date.UTC(Math.floor(n/10)*10,0,1):t>86400?Date.UTC(n,0,1):e-(s*3600+m*60+r)*1e3}function q(e,t){return Math.ceil(e/t+.5)*t}function ne(e,t,o){var l,n,s,m,r,c,f,M,d,T,u,L;return{color:((l=t.style)==null?void 0:l.color)??((n=e.style)==null?void 0:n.color)??I.color,borderColor:((s=t.style)==null?void 0:s.borderColor)??((m=e.style)==null?void 0:m.borderColor)??(o==null?void 0:o.swimLaneItemBorderColor)??I.borderColor,borderWidth:((r=t.style)==null?void 0:r.borderWidth)??((c=e.style)==null?void 0:c.borderWidth)??(o==null?void 0:o.swimLaneItemBorderWidth)??I.borderWidth,opacity:((f=t.style)==null?void 0:f.opacity)??((M=e.style)==null?void 0:M.opacity)??I.opacity,markerShape:((d=t.style)==null?void 0:d.markerShape)??((T=e.style)==null?void 0:T.markerShape)??I.markerShape,markerSize:((u=t.style)==null?void 0:u.markerSize)??((L=e.style)==null?void 0:L.markerSize)??I.markerSize}}function ie(e){return Math.max(de,Math.min(Te,e))}function ve(e,t,o){const l=t-e,n=(e+t)/2,s=ie(l*o);return{startMs:n-s/2,endMs:n+s/2}}function Ue(e,t,o,l){const n=t-e,s=ie(n*o),m=n>0?(l-e)/n:.5;return{startMs:l-m*s,endMs:l+(1-m)*s}}function Be(e){let t=0;for(const o of e)t+=(o.height??P)+$;return t}function je(e,t,o,l,n){const{swimLanes:s,showSwimLanes:m,scrollTop:r,startMs:c,endMs:f,theme:M}=n;if(!m||s.length===0)return null;const d=Math.max(0,l-j);if(t<0||t>=d)return null;let T=-r;for(const u of s){const L=u.height??P,y=T,g=T+L;if(T+=L+$,!(t<y||t>=g)){for(const h of u.items){if(h.interval){const p=H.JulianDate.toDate(h.interval.start).getTime(),R=H.JulianDate.toDate(h.interval.stop).getTime(),Q=(p-c)/(f-c)*o,E=(R-c)/(f-c)*o;if(e>=Math.max(0,Q)&&e<=Math.min(o,E))return{lane:u,item:h}}if(h.instant){const R=(H.JulianDate.toDate(h.instant).getTime()-c)/(f-c)*o,Q=ne(u,h,M);if(Math.abs(e-R)<=Q.markerSize/2+2)return{lane:u,item:h}}}return null}}return null}function ze(e,t,o,l){const{swimLanes:n,showSwimLanes:s,scrollTop:m}=l;if(!s||n.length===0||e>80)return null;const r=Math.max(0,o-j);if(t<0||t>=r)return null;let c=-m;for(const f of n){const M=f.height??P;if(t>=c&&t<c+M)return f;c+=M+$}return null}function Xe(e,t,o){if(!o.showSwimLanes||o.swimLanes.length===0)return!1;const l=Math.max(0,t-j);return e>=0&&e<l}function Ge(e,t,o,l){const{startMs:n,endMs:s,currentMs:m,theme:r,maxTicks:c,swimLanes:f,showSwimLanes:M,reorderState:d,timezone:T,use12h:u,months:L,rangeSelection:y,hoverMs:g}=l;let{scrollTop:h}=l;const p=(s-n)/1e3;if(p<=0)return h;e.fillStyle=r.backgroundColor,e.fillRect(0,0,t,o);const R=M&&f.length>0,E=R?Math.max(0,o-j):0;let x=0;if(R)for(const i of f)x+=(i.height??P)+$;const re=Math.max(0,x-E);if(h>re&&(h=re),h<0&&(h=0),R&&E>0){e.save(),e.beginPath(),e.rect(0,0,t,E),e.clip();let i=-h;const A=k=>(k-n)/(s-n)*t;for(const k of f){const b=k.height??P,_=i+b;if(_>0&&i<E){const S=k.style,U=(S==null?void 0:S.backgroundColor)??I.backgroundColor;U&&U!=="transparent"&&(e.fillStyle=U,e.fillRect(0,i,t,b)),e.strokeStyle=r.tickColor+"44",e.lineWidth=.5,e.beginPath(),e.moveTo(0,_),e.lineTo(t,_),e.stroke();for(const F of k.items){const C=ne(k,F,r);if(F.interval){const se=H.JulianDate.toDate(F.interval.start).getTime(),Y=H.JulianDate.toDate(F.interval.stop).getTime(),W=A(se),v=A(Y),me=Math.max(0,W),ce=Math.min(t,v)-me;if(ce>0){e.globalAlpha=C.opacity,e.fillStyle=C.color;const De=3,Le=i+De,Ae=b-De*2;e.fillRect(me,Le,ce,Ae),C.borderWidth>0&&(e.strokeStyle=C.borderColor,e.lineWidth=C.borderWidth,e.strokeRect(me,Le,ce,Ae)),e.globalAlpha=1}}if(F.instant){const se=H.JulianDate.toDate(F.instant).getTime(),Y=A(se);if(Y>=-C.markerSize&&Y<=t+C.markerSize){const W=i+b/2,v=C.markerSize;e.globalAlpha=C.opacity,e.fillStyle=C.color,C.markerShape==="diamond"?(e.beginPath(),e.moveTo(Y,W-v/2),e.lineTo(Y+v/2,W),e.lineTo(Y,W+v/2),e.lineTo(Y-v/2,W),e.closePath(),e.fill()):C.markerShape==="circle"?(e.beginPath(),e.arc(Y,W,v/2,0,Math.PI*2),e.fill()):(e.strokeStyle=C.color,e.lineWidth=2,e.beginPath(),e.moveTo(Y,i+2),e.lineTo(Y,i+b-2),e.stroke()),e.globalAlpha=1}}}e.font=`${Math.min(11,b-4)}px system-ui, sans-serif`,e.textAlign="left",e.textBaseline="middle",e.fillStyle=(S==null?void 0:S.labelColor)??I.labelColor,e.fillText(k.label,Me,i+b/2)}if(i+=b+$,i>=E)break}if(d&&d.dragging){const k=d.currentY-d.dragStartY;let b=-h;for(let S=0;S<f.length&&S<d.insertIndex;S++)b+=(f[S].height??P)+$;e.strokeStyle=r.indicatorColor,e.lineWidth=2,e.beginPath(),e.moveTo(0,b),e.lineTo(t,b),e.stroke();const _=f.find(S=>S.id===d.dragLaneId);if(_){const S=_.height??P;let U=-h;for(const F of f){if(F.id===d.dragLaneId)break;U+=(F.height??P)+$}e.globalAlpha=.4,e.fillStyle=r.indicatorColor,e.fillRect(0,U+k,t,S),e.globalAlpha=1}}if(x>E){const k=t-V-2,b=E/x,_=Math.max(20,E*b),S=h/re*(E-_);e.fillStyle=r.tickColor+"22",e.fillRect(k,0,V,E),e.fillStyle=r.tickColor+"88",e.fillRect(k,S,V,_)}e.restore()}e.font=`${r.fontSize}px monospace`;const Ke=oe(n+p*500,p,T,u,L),Ze=e.measureText(Ke).width+24,Ve=Math.max(Ze/t*p,p/1e3);let O=D[D.length-1],z=D.length-1;for(let i=0;i<D.length;i++)if(D[i]>Ve){O=D[i],z=i;break}if(c!=null&&c>0)for(;z<D.length-1&&p/O>c;)z++,O=D[z];let J=0;for(let i=z-1;i>=0;i--)if(O%D[i]<1e-4){t*(D[i]/p)>=3&&(J=D[i]);break}let X=0;if(J>0){for(let i=0;i<D.length&&D[i]<J;i++)if(J%D[i]<1e-4&&t*(D[i]/p)>=3){X=D[i];break}}const pe=Se(n,p,T),G=(n-pe)/1e3,le=G+p,ae=i=>t*((i-G)/p);if(X>0){e.strokeStyle=r.tickColor,e.lineWidth=1;for(let i=Math.floor(G/X)*X;i<=le;i=q(i,X)){const A=ae(i);e.beginPath(),e.moveTo(A,o-r.minorTickHeight),e.lineTo(A,o),e.stroke()}}if(J>0){e.strokeStyle=r.tickColor,e.lineWidth=1;for(let i=Math.floor(G/J)*J;i<=le;i=q(i,J)){const A=ae(i);e.beginPath(),e.moveTo(A,o-r.minorTickHeight),e.lineTo(A,o),e.stroke()}}e.textAlign="center",e.textBaseline="bottom";let be=-1/0;for(let i=Math.floor(G/O)*O;i<=le+O;i=q(i,O)){const A=ae(i),k=pe+i*1e3;e.strokeStyle=r.majorTickColor,e.lineWidth=1,e.beginPath(),e.moveTo(A,o-r.majorTickHeight),e.lineTo(A,o),e.stroke();const b=oe(k,p,T,u,L),_=e.measureText(b).width,S=A-_/2;S>be&&(e.fillStyle=r.labelColor,e.fillText(b,A,o-r.majorTickHeight-4),be=S+_+5)}if(y){const i=(y.startMs-n)/(s-n)*t,A=(y.endMs-n)/(s-n)*t,k=Math.min(i,A),b=Math.abs(A-i);e.globalAlpha=.2,e.fillStyle=r.indicatorColor,e.fillRect(k,0,b,o),e.globalAlpha=1}const ye=(m-n)/(s-n)*t;if(e.strokeStyle=r.indicatorColor,e.lineWidth=r.indicatorLineWidth,e.beginPath(),e.moveTo(ye,0),e.lineTo(ye,o),e.stroke(),g!=null){const i=(g-n)/(s-n)*t;e.globalAlpha=.15,e.strokeStyle=r.indicatorColor,e.lineWidth=r.indicatorLineWidth,e.beginPath(),e.moveTo(i,0),e.lineTo(i,o),e.stroke(),e.globalAlpha=1}return h}a.DEFAULT_LABELS=Ce,a.DEFAULT_LANE_HEIGHT=P,a.DateTimeFormats=te,a.LABEL_PAD_LEFT=Me,a.LANE_GAP=$,a.MAX_SPAN_MS=Te,a.MIN_SPAN_MS=de,a.MONTHS=ge,a.SCROLLBAR_WIDTH=V,a.SWIM_LANE_SCROLL_SPEED=We,a.TICK_AREA_HEIGHT=j,a.TIC_SCALES=D,a.TickInterval=ee,a.Timezones=Pe,a.calcEpochMs=Se,a.clampSpan=ie,a.defaultSwimLaneStyle=I,a.defaultTheme=Ee,a.drawTimeline=Ge,a.formatDateTime=ue,a.formatTime=Fe,a.fromMilliseconds=we,a.generateTicks=Oe,a.getDateParts=Z,a.getDurationMs=fe,a.getTimezoneAbbr=Ne,a.hitTestLaneLabel=ze,a.hitTestSwimLane=je,a.isInSwimLaneRegion=Xe,a.makeLabel=oe,a.nextTic=q,a.positionToTime=$e,a.resolveItemStyle=ne,a.resolveLabel=He,a.snapToTick=Je,a.splitForDisplay=Re,a.timeToPosition=he,a.toDate=K,a.toJulianDate=_e,a.toMilliseconds=N,a.totalSwimLaneHeight=Be,a.twoD=w,a.zoomAroundMs=Ue,a.zoomRange=ve,Object.defineProperty(a,Symbol.toStringTag,{value:"Module"})}));
package/dist/index.d.ts CHANGED
@@ -36,7 +36,7 @@ export declare interface ControlsBaseProps {
36
36
  onJumpToLive: () => void;
37
37
  /** Reset the playback speed to 1×. */
38
38
  onResetSpeed: () => void;
39
- /** Whether the needle is near the current wall-clock time (within 10 s). */
39
+ /** Whether the needle is near the current wall-clock time (within 2 s). */
40
40
  isLive: boolean;
41
41
  /** Whether to enable the ⏮ jump-to-start button (true when startTime prop was provided). */
42
42
  hasStartTime: boolean;
@@ -57,6 +57,10 @@ export declare interface ControlsBaseProps {
57
57
  * @see TimelineBaseProps.labels
58
58
  */
59
59
  labels?: Partial<TimelineLabels>;
60
+ /** @see TimelineBaseProps.liveButtonSize */
61
+ liveButtonSize?: 'sm' | 'md' | 'lg';
62
+ /** @see TimelineBaseProps.liveButtonPosition */
63
+ liveButtonPosition?: 'left' | 'right';
60
64
  }
61
65
 
62
66
  /** Decomposed date/time fields extracted in a specific timezone. `mo` is 0-indexed. */
@@ -426,6 +430,34 @@ export declare interface TimelineBaseProps {
426
430
  * want to change; everything else falls back to the English defaults.
427
431
  */
428
432
  labels?: Partial<TimelineLabels>;
433
+ /**
434
+ * Size of the LIVE button in the control bar.
435
+ * `'sm'` is compact, `'md'` is the default, `'lg'` is prominent.
436
+ * @default 'md'
437
+ */
438
+ liveButtonSize?: 'sm' | 'md' | 'lg';
439
+ /**
440
+ * Which side of the control bar the LIVE button appears on.
441
+ * `'left'` places it beside the datetime display (default).
442
+ * `'right'` moves it to the right side of the control bar.
443
+ * @default 'left'
444
+ */
445
+ liveButtonPosition?: 'left' | 'right';
446
+ /**
447
+ * When `true`, the timeline is locked to live mode.
448
+ * Needle drag, datetime click, play/pause, rewind, fast-forward,
449
+ * jump-to-start, and jump-to-end are all disabled. The LIVE button
450
+ * becomes a non-interactive status indicator. Canvas zoom and pan
451
+ * remain fully interactive.
452
+ */
453
+ live?: boolean;
454
+ /**
455
+ * When `true`, reverses the scroll-wheel zoom direction so that
456
+ * scrolling down zooms in on time and scrolling up zooms out.
457
+ * By default (false) scrolling up zooms in and scrolling down zooms out.
458
+ * @default false
459
+ */
460
+ invertScrollZoom?: boolean;
429
461
  }
430
462
 
431
463
  /**
@@ -547,6 +579,13 @@ export declare interface TimelineRenderState {
547
579
  startMs: number;
548
580
  endMs: number;
549
581
  } | null;
582
+ /**
583
+ * Canvas-relative X position of the cursor (in CSS pixels) while the user is
584
+ * hovering over the timeline. When non-null a ghost needle is drawn at this
585
+ * position with 15 % opacity so the user can preview where a click / drag
586
+ * would land before committing.
587
+ */
588
+ hoverMs?: number | null;
550
589
  }
551
590
 
552
591
  export declare interface TimelineTheme {
@@ -569,6 +608,8 @@ export declare interface TimelineTheme {
569
608
  swimLaneItemBorderColor: string;
570
609
  /** Default border width for swim lane items (px). Set to 0 to remove borders. */
571
610
  swimLaneItemBorderWidth: number;
611
+ /** Color of the red dot shown on the LIVE button when playback is live. */
612
+ liveDotColor: string;
572
613
  }
573
614
 
574
615
  export declare interface TimePosition {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kteneyck/cesium-timeline-core",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "Framework-agnostic core logic for the Cesium timeline component",
5
5
  "license": "MIT",
6
6
  "author": "kteneyck",