@fxi/zartigl 0.6.0 → 0.7.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.
@@ -1,38 +1,38 @@
1
- const I = { label: "Thermal", tags: ["sequential", "temperature"], colors: ["#042333", "#2c3395", "#744796", "#b15f82", "#eb7958", "#fbb43d", "#e8fa5b"] }, N = { label: "Haline", tags: ["sequential", "salinity"], colors: ["#2a186c", "#17568b", "#1a7e8f", "#22a785", "#55c666", "#aadc32", "#fde333"] }, L = { label: "Solar", tags: ["sequential", "irradiance"], colors: ["#330f0b", "#6b2313", "#a83c12", "#d6621a", "#f3951e", "#f7c741", "#f9f871"] }, V = { label: "Ice", tags: ["sequential"], colors: ["#040d1a", "#123365", "#1c5f9e", "#2b8ece", "#62bde3", "#aaddf2", "#f2faff"] }, B = { label: "Deep", tags: ["sequential", "depth"], colors: ["#fdfecc", "#c8e59b", "#74c8a3", "#3194b0", "#2a5b8e", "#281a5e", "#0c0820"] }, k = { label: "RdYlBu", tags: ["diverging"], colors: ["#3288bd", "#66c2a5", "#abdda4", "#e6f598", "#fee08b", "#fdae61", "#f46d43", "#d53e4f"] }, X = { label: "Dense", tags: ["sequential"], colors: ["#e6f1f1", "#92c4ca", "#44929a", "#20627a", "#1a3c6a", "#211a50", "#0d0621"] }, C = { label: "Algae", tags: ["sequential", "biology", "log"], colors: ["#d7f9d0", "#a2d595", "#64b463", "#129450", "#126e45", "#1a482f", "#122414"] }, O = { label: "Oxygen", tags: ["sequential", "biology", "hypoxia"], colors: ["#09060f", "#5b1028", "#d43d2f", "#f39b3d", "#f3e7b3", "#79cbd1", "#176b9c"] }, q = { label: "Matter", tags: ["sequential", "biology"], colors: ["#fdfecc", "#f2c98a", "#e07c4e", "#bc3754", "#8d1a6d", "#51156b", "#1c0c3f"] }, g = { label: "Viridis", tags: ["sequential", "perceptual"], colors: ["#440154", "#443983", "#31688e", "#21918c", "#35b779", "#90d743", "#fde725"] }, W = { label: "Plasma", tags: ["sequential", "perceptual"], colors: ["#0d0887", "#5e01a6", "#9c179e", "#cc4778", "#ed7953", "#fdb42f", "#f0f921"] }, $ = { label: "Cyclic", tags: ["cyclic", "direction"], colors: ["#2e22ea", "#b541fb", "#fc93c0", "#f1ee35", "#77c80d", "#458776", "#2c24e9"] }, H = { label: "Tempo", tags: ["sequential"], colors: ["#fff6f4", "#c2d1b9", "#7db390", "#2a937f", "#156d73", "#1c455b", "#151d44"] }, j = { label: "Turbid", tags: ["sequential", "biology", "log"], colors: ["#e9f5a0", "#c8c86e", "#a09845", "#786031", "#533324", "#341423", "#150d17"] }, Y = { label: "Speed", tags: ["sequential", "velocity"], colors: ["#fcfea4", "#d5e429", "#94c63e", "#52a657", "#2d8169", "#1d5b6d", "#0d3361"] }, z = { label: "Amp", tags: ["sequential"], colors: ["#f2f2f2", "#c0b8db", "#9180b6", "#6c4e9e", "#4e2e83", "#32185d", "#110a35"] }, K = { label: "Balance", tags: ["diverging"], colors: ["#181c43", "#3066af", "#9bbcdd", "#f2f2f2", "#e07d53", "#b13626", "#2c0b0e"] }, J = { label: "Delta", tags: ["diverging"], colors: ["#0e3f31", "#20877b", "#99d4c1", "#f2f2f2", "#a1b0d4", "#3c5b9e", "#0d1938"] }, Q = { label: "Curl", tags: ["diverging"], colors: ["#152237", "#2471b3", "#8dbac4", "#f2f2f2", "#c79f84", "#a63827", "#270b17"] }, Z = { label: "Gray", tags: ["sequential"], colors: ["#000000", "#252525", "#4d4d4d", "#7a7a7a", "#a8a8a8", "#d4d4d4", "#ffffff"] }, G = {
2
- thermal: I,
1
+ const $ = { label: "Thermal", tags: ["sequential", "temperature"], colors: ["#042333", "#2c3395", "#744796", "#b15f82", "#eb7958", "#fbb43d", "#e8fa5b"] }, W = { label: "Haline", tags: ["sequential", "salinity"], colors: ["#2a186c", "#17568b", "#1a7e8f", "#22a785", "#55c666", "#aadc32", "#fde333"] }, H = { label: "Solar", tags: ["sequential", "irradiance"], colors: ["#330f0b", "#6b2313", "#a83c12", "#d6621a", "#f3951e", "#f7c741", "#f9f871"] }, Y = { label: "Ice", tags: ["sequential"], colors: ["#040d1a", "#123365", "#1c5f9e", "#2b8ece", "#62bde3", "#aaddf2", "#f2faff"] }, z = { label: "Deep", tags: ["sequential", "depth"], colors: ["#fdfecc", "#c8e59b", "#74c8a3", "#3194b0", "#2a5b8e", "#281a5e", "#0c0820"] }, j = { label: "RdYlBu", tags: ["diverging"], colors: ["#3288bd", "#66c2a5", "#abdda4", "#e6f598", "#fee08b", "#fdae61", "#f46d43", "#d53e4f"] }, K = { label: "Dense", tags: ["sequential"], colors: ["#e6f1f1", "#92c4ca", "#44929a", "#20627a", "#1a3c6a", "#211a50", "#0d0621"] }, J = { label: "Algae", tags: ["sequential", "biology", "log"], colors: ["#d7f9d0", "#a2d595", "#64b463", "#129450", "#126e45", "#1a482f", "#122414"] }, Q = { label: "Oxygen", tags: ["sequential", "biology", "hypoxia"], colors: ["#09060f", "#5b1028", "#d43d2f", "#f39b3d", "#f3e7b3", "#79cbd1", "#176b9c"] }, Z = { label: "Matter", tags: ["sequential", "biology"], colors: ["#fdfecc", "#f2c98a", "#e07c4e", "#bc3754", "#8d1a6d", "#51156b", "#1c0c3f"] }, ee = { label: "Viridis", tags: ["sequential", "perceptual"], colors: ["#440154", "#443983", "#31688e", "#21918c", "#35b779", "#90d743", "#fde725"] }, te = { label: "Plasma", tags: ["sequential", "perceptual"], colors: ["#0d0887", "#5e01a6", "#9c179e", "#cc4778", "#ed7953", "#fdb42f", "#f0f921"] }, re = { label: "Cyclic", tags: ["cyclic", "direction"], colors: ["#2e22ea", "#b541fb", "#fc93c0", "#f1ee35", "#77c80d", "#458776", "#2c24e9"] }, ne = { label: "Tempo", tags: ["sequential"], colors: ["#fff6f4", "#c2d1b9", "#7db390", "#2a937f", "#156d73", "#1c455b", "#151d44"] }, ae = { label: "Turbid", tags: ["sequential", "biology", "log"], colors: ["#e9f5a0", "#c8c86e", "#a09845", "#786031", "#533324", "#341423", "#150d17"] }, ie = { label: "Speed", tags: ["sequential", "velocity"], colors: ["#fcfea4", "#d5e429", "#94c63e", "#52a657", "#2d8169", "#1d5b6d", "#0d3361"] }, oe = { label: "Amp", tags: ["sequential"], colors: ["#f2f2f2", "#c0b8db", "#9180b6", "#6c4e9e", "#4e2e83", "#32185d", "#110a35"] }, se = { label: "Balance", tags: ["diverging"], colors: ["#181c43", "#3066af", "#9bbcdd", "#f2f2f2", "#e07d53", "#b13626", "#2c0b0e"] }, ce = { label: "Delta", tags: ["diverging"], colors: ["#0e3f31", "#20877b", "#99d4c1", "#f2f2f2", "#a1b0d4", "#3c5b9e", "#0d1938"] }, de = { label: "Curl", tags: ["diverging"], colors: ["#152237", "#2471b3", "#8dbac4", "#f2f2f2", "#c79f84", "#a63827", "#270b17"] }, ue = { label: "Gray", tags: ["sequential"], colors: ["#000000", "#252525", "#4d4d4d", "#7a7a7a", "#a8a8a8", "#d4d4d4", "#ffffff"] }, g = {
2
+ thermal: $,
3
3
  "thermal-alt": { label: "Thermal Alt", tags: ["sequential", "temperature"], colors: ["#176b9c", "#79cbd1", "#f3e7b3", "#f39b3d", "#d43d2f", "#5b1028", "#09060f"] },
4
- haline: N,
5
- solar: L,
6
- ice: V,
7
- deep: B,
8
- rdylbu: k,
9
- dense: X,
10
- algae: C,
11
- oxygen: O,
12
- matter: q,
13
- viridis: g,
14
- plasma: W,
15
- cyclic: $,
16
- tempo: H,
17
- turbid: j,
18
- speed: Y,
19
- amp: z,
20
- balance: K,
21
- delta: J,
22
- curl: Q,
4
+ haline: W,
5
+ solar: H,
6
+ ice: Y,
7
+ deep: z,
8
+ rdylbu: j,
9
+ dense: K,
10
+ algae: J,
11
+ oxygen: Q,
12
+ matter: Z,
13
+ viridis: ee,
14
+ plasma: te,
15
+ cyclic: re,
16
+ tempo: ne,
17
+ turbid: ae,
18
+ speed: ie,
19
+ amp: oe,
20
+ balance: se,
21
+ delta: ce,
22
+ curl: de,
23
23
  "mono-black": { label: "Black", tags: ["monochrome", "particles"], colors: ["#000000", "#000000"] },
24
24
  "mono-white": { label: "White", tags: ["monochrome", "particles"], colors: ["#ffffff", "#ffffff"] },
25
25
  "mono-pink": { label: "Pink", tags: ["monochrome", "particles"], colors: ["#ff2aa1", "#ff2aa1"] },
26
- gray: Z
26
+ gray: ue
27
27
  };
28
- function A(e) {
28
+ function I(e) {
29
29
  const t = {}, r = e.length - 1;
30
30
  return e.forEach((n, a) => {
31
31
  t[r === 0 ? 0 : a / r] = n;
32
32
  }), t;
33
33
  }
34
- function ee(e, t) {
35
- const r = G;
34
+ function fe(e, t) {
35
+ const r = g;
36
36
  if (typeof e == "string") {
37
37
  const n = r[e];
38
38
  if (!n)
@@ -42,18 +42,18 @@ function ee(e, t) {
42
42
  ).join(", ")}`
43
43
  );
44
44
  const a = t?.reverse ? [...n.colors].reverse() : n.colors;
45
- return A(a);
45
+ return I(a);
46
46
  }
47
47
  if (Array.isArray(e)) {
48
48
  const n = t?.reverse ? [...e].reverse() : e;
49
- return A(n);
49
+ return I(n);
50
50
  }
51
51
  return e;
52
52
  }
53
- function we() {
54
- return Object.entries(G).map(([t, r]) => ({ id: t, ...r }));
53
+ function Ye() {
54
+ return Object.entries(g).map(([t, r]) => ({ id: t, ...r }));
55
55
  }
56
- function x(e, t, r) {
56
+ function N(e, t, r) {
57
57
  const n = e.createShader(t);
58
58
  if (!n)
59
59
  throw new Error("Failed to create shader");
@@ -63,18 +63,18 @@ function x(e, t, r) {
63
63
  }
64
64
  return n;
65
65
  }
66
- function Fe(e, t, r) {
66
+ function ze(e, t, r) {
67
67
  const n = e.createProgram();
68
68
  if (!n)
69
69
  throw new Error("Failed to create program");
70
- const a = x(e, e.VERTEX_SHADER, t), i = x(e, e.FRAGMENT_SHADER, r);
70
+ const a = N(e, e.VERTEX_SHADER, t), i = N(e, e.FRAGMENT_SHADER, r);
71
71
  if (e.attachShader(n, a), e.attachShader(n, i), e.linkProgram(n), !e.getProgramParameter(n, e.LINK_STATUS)) {
72
72
  const s = e.getProgramInfoLog(n);
73
73
  throw e.deleteProgram(n), new Error(`Program link error: ${s}`);
74
74
  }
75
75
  return e.deleteShader(a), e.deleteShader(i), n;
76
76
  }
77
- function Ae(e, t, r, n, a) {
77
+ function je(e, t, r, n, a) {
78
78
  const i = e.createTexture();
79
79
  if (!i)
80
80
  throw new Error("Failed to create texture");
@@ -90,7 +90,7 @@ function Ae(e, t, r, n, a) {
90
90
  r
91
91
  ), e.bindTexture(e.TEXTURE_2D, null), i;
92
92
  }
93
- function te(e, t, r) {
93
+ function le(e, t, r) {
94
94
  const n = e.getParameter(
95
95
  e.TEXTURE_BINDING_2D
96
96
  ), a = e.getParameter(
@@ -122,19 +122,19 @@ function te(e, t, r) {
122
122
  }
123
123
  return o;
124
124
  }
125
- function re(e) {
125
+ function he(e) {
126
126
  return {
127
127
  kind: "rgba8-packed",
128
128
  internalFormat: e.RGBA,
129
129
  type: e.UNSIGNED_BYTE
130
130
  };
131
131
  }
132
- function xe(e) {
132
+ function Ke(e) {
133
133
  if (typeof WebGL2RenderingContext > "u" || !(e instanceof WebGL2RenderingContext))
134
134
  throw new Error("zartigl requires WebGL2");
135
135
  return e;
136
136
  }
137
- function De(e) {
137
+ function Je(e) {
138
138
  const t = [];
139
139
  e.getExtension("EXT_color_buffer_float") ? t.push(
140
140
  { kind: "float32", internalFormat: e.RGBA32F, type: e.FLOAT },
@@ -145,15 +145,15 @@ function De(e) {
145
145
  type: e.HALF_FLOAT
146
146
  });
147
147
  for (const r of t)
148
- if (te(
148
+ if (le(
149
149
  e,
150
150
  r.internalFormat,
151
151
  r.type
152
152
  ))
153
153
  return r;
154
- return re(e);
154
+ return he(e);
155
155
  }
156
- function Ue(e, t, r, n, a, i, s) {
156
+ function Qe(e, t, r, n, a, i, s) {
157
157
  const o = e.createTexture();
158
158
  if (!o)
159
159
  throw new Error("Failed to create texture");
@@ -169,10 +169,10 @@ function Ue(e, t, r, n, a, i, s) {
169
169
  r
170
170
  ), e.bindTexture(e.TEXTURE_2D, null), o;
171
171
  }
172
- function ve(e, t, r) {
172
+ function Ze(e, t, r) {
173
173
  e.activeTexture(e.TEXTURE0 + r), e.bindTexture(e.TEXTURE_2D, t);
174
174
  }
175
- function Me(e, t) {
175
+ function et(e, t) {
176
176
  const r = e.createFramebuffer();
177
177
  if (!r)
178
178
  throw new Error("Failed to create framebuffer");
@@ -184,7 +184,7 @@ function Me(e, t) {
184
184
  0
185
185
  ), e.bindFramebuffer(e.FRAMEBUFFER, null), r;
186
186
  }
187
- function ye(e) {
187
+ function tt(e) {
188
188
  const t = e.createBuffer();
189
189
  if (!t)
190
190
  throw new Error("Failed to create buffer");
@@ -194,7 +194,7 @@ function ye(e) {
194
194
  e.STATIC_DRAW
195
195
  ), t;
196
196
  }
197
- const ae = {
197
+ const me = {
198
198
  0: "#3288bd",
199
199
  0.1: "#66c2a5",
200
200
  0.2: "#abdda4",
@@ -204,19 +204,19 @@ const ae = {
204
204
  0.6: "#f46d43",
205
205
  1: "#d53e4f"
206
206
  };
207
- function Ge(e, t) {
208
- const r = t != null ? ee(t) : ae, n = document.createElement("canvas");
207
+ function rt(e, t) {
208
+ const r = t != null ? fe(t) : me, n = document.createElement("canvas");
209
209
  n.width = 256, n.height = 1;
210
210
  const a = n.getContext("2d"), i = a.createLinearGradient(0, 0, 256, 0);
211
- for (const [o, d] of Object.entries(r))
212
- i.addColorStop(Number(o), d);
211
+ for (const [o, c] of Object.entries(r))
212
+ i.addColorStop(Number(o), c);
213
213
  a.fillStyle = i, a.fillRect(0, 0, 256, 1);
214
214
  const s = e.createTexture();
215
215
  if (!s)
216
216
  throw new Error("Failed to create color ramp texture");
217
217
  return e.bindTexture(e.TEXTURE_2D, s), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.LINEAR), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.LINEAR), e.texImage2D(e.TEXTURE_2D, 0, e.RGBA, e.RGBA, e.UNSIGNED_BYTE, n), e.bindTexture(e.TEXTURE_2D, null), s;
218
218
  }
219
- function Se(e) {
219
+ function nt(e) {
220
220
  const t = e.getExtension("WEBGL_debug_renderer_info");
221
221
  return {
222
222
  vendor: String(e.getParameter(e.VENDOR) ?? ""),
@@ -226,7 +226,7 @@ function Se(e) {
226
226
  version: String(e.getParameter(e.VERSION) ?? "")
227
227
  };
228
228
  }
229
- function Pe(e) {
229
+ function at(e) {
230
230
  return {
231
231
  program: e.getParameter(e.CURRENT_PROGRAM),
232
232
  activeTexture: e.getParameter(e.ACTIVE_TEXTURE),
@@ -243,19 +243,19 @@ function Pe(e) {
243
243
  ]
244
244
  };
245
245
  }
246
- function Ie(e, t) {
246
+ function it(e, t) {
247
247
  e.useProgram(t.program), e.activeTexture(t.activeTexture), e.bindBuffer(e.ARRAY_BUFFER, t.arrayBuffer), e.bindBuffer(e.ELEMENT_ARRAY_BUFFER, t.elementBuffer), e.bindFramebuffer(e.FRAMEBUFFER, t.framebuffer), t.blend ? e.enable(e.BLEND) : e.disable(e.BLEND), t.depthTest ? e.enable(e.DEPTH_TEST) : e.disable(e.DEPTH_TEST), t.stencilTest ? e.enable(e.STENCIL_TEST) : e.disable(e.STENCIL_TEST), e.viewport(t.viewport[0], t.viewport[1], t.viewport[2], t.viewport[3]), e.blendFunc(t.blendFunc[0], t.blendFunc[1]);
248
248
  }
249
- const D = 20, ne = 600;
250
- function ie(e) {
249
+ const L = 20, Ee = 600;
250
+ function Te(e) {
251
251
  const t = Math.max(0, Math.min(1, e));
252
- return D * Math.pow(ne / D, t);
252
+ return L * Math.pow(Ee / L, t);
253
253
  }
254
- function Ne(e) {
255
- return Math.exp(-1 / ie(e));
254
+ function ot(e) {
255
+ return Math.exp(-1 / Te(e));
256
256
  }
257
- const oe = 0.8, se = 120, de = 300;
258
- class Le {
257
+ const pe = 0.8, be = 120, we = 300;
258
+ class st {
259
259
  constructor(t) {
260
260
  this.base = t, this.moving = !1, this.start = 0, this.duration = 0, this.from = t, this.to = t;
261
261
  }
@@ -264,7 +264,7 @@ class Le {
264
264
  this.base = t, this.moving || (this.from = t, this.to = t, this.duration = 0);
265
265
  }
266
266
  setMoving(t, r) {
267
- t !== this.moving && (this.from = this.value(r), this.moving = t, this.to = t ? oe : this.base, this.start = r, this.duration = t ? se : de);
267
+ t !== this.moving && (this.from = this.value(r), this.moving = t, this.to = t ? pe : this.base, this.start = r, this.duration = t ? be : we);
268
268
  }
269
269
  value(t) {
270
270
  if (this.duration === 0)
@@ -273,48 +273,21 @@ class Le {
273
273
  return r === 1 ? (this.duration = 0, this.from = this.to, this.to) : this.from + (this.to - this.from) * r * r * (3 - 2 * r);
274
274
  }
275
275
  }
276
- const S = {
277
- exposure: 0.8,
278
- contrast: 0.6,
279
- saturation: 0.4,
280
- highlights: 0.6
281
- }, ce = Object.freeze({
282
- enabled: !1,
283
- ...S
284
- }), fe = Object.freeze({
285
- enabled: !0,
286
- ...S
287
- }), U = {
288
- exposure: [0, 4],
289
- contrast: [0, 1],
290
- saturation: [-1, 1],
291
- highlights: [0, 1]
292
- };
293
- function Ve(e) {
294
- if (!e)
295
- return { ...ce };
296
- const t = {
297
- ...fe,
298
- enabled: e.enabled ?? !0
299
- };
300
- for (const r of Object.keys(U)) {
301
- const n = e[r];
302
- if (typeof n == "number" && Number.isFinite(n)) {
303
- const [a, i] = U[r];
304
- t[r] = Math.min(i, Math.max(a, n));
305
- }
306
- }
307
- return t;
308
- }
309
- function Be(e) {
310
- return [e.exposure, e.contrast, e.saturation, e.highlights];
276
+ function ct(e) {
277
+ if (e == null)
278
+ return null;
279
+ if (!Number.isFinite(e[0]) || !Number.isFinite(e[1]) || e[0] >= e[1])
280
+ throw new RangeError(
281
+ "colorDomain must contain two finite, increasing values"
282
+ );
283
+ return [e[0], e[1]];
311
284
  }
312
- function h(e, t) {
285
+ function m(e, t) {
313
286
  if (typeof e != "number" || !Number.isFinite(e))
314
287
  throw new Error(`Invalid GeoVideo manifest ${t}`);
315
288
  return e;
316
289
  }
317
- function b(e, t) {
290
+ function F(e, t) {
318
291
  if (typeof e != "string")
319
292
  throw new Error(`Invalid GeoVideo manifest ${t}`);
320
293
  const r = new Date(e).getTime();
@@ -322,12 +295,12 @@ function b(e, t) {
322
295
  throw new Error(`Invalid GeoVideo manifest ${t}`);
323
296
  return r;
324
297
  }
325
- function R(e) {
298
+ function D(e) {
326
299
  return typeof e == "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(
327
300
  e
328
301
  );
329
302
  }
330
- function v(e) {
303
+ function V(e) {
331
304
  if (!e || typeof e != "object")
332
305
  throw new Error("Invalid GeoVideo manifest");
333
306
  const t = e;
@@ -340,50 +313,50 @@ function v(e) {
340
313
  if (!Array.isArray(t.bounds) || t.bounds.length !== 4)
341
314
  throw new Error("Invalid GeoVideo manifest bounds");
342
315
  const [r, n, a, i] = t.bounds.map(
343
- (u, m) => h(u, `bounds[${m}]`)
316
+ (f, T) => m(f, `bounds[${T}]`)
344
317
  );
345
318
  if (n < -90 || i > 90 || n >= i || r === a)
346
319
  throw new Error("Invalid GeoVideo geographic bounds");
347
320
  const s = t.media;
348
321
  if (!s || typeof s.url != "string" || !s.url)
349
322
  throw new Error("Invalid GeoVideo media");
350
- for (const u of ["width", "height", "fps", "durationSeconds"])
351
- if (h(s[u], `media.${u}`) <= 0)
352
- throw new Error(`Invalid GeoVideo media.${u}`);
323
+ for (const f of ["width", "height", "fps", "durationSeconds"])
324
+ if (m(s[f], `media.${f}`) <= 0)
325
+ throw new Error(`Invalid GeoVideo media.${f}`);
353
326
  const o = t.encoding;
354
327
  if (!o || o.bits !== 8 || o.colorSpace !== "bt709" || o.colorRange !== "limited" && o.colorRange !== "full")
355
328
  throw new Error("Invalid GeoVideo encoding");
356
- const d = h(o.codeMin, "encoding.codeMin"), c = h(o.codeMax, "encoding.codeMax");
357
- if (d < 0 || c > 255 || d >= c)
329
+ const c = m(o.codeMin, "encoding.codeMin"), d = m(o.codeMax, "encoding.codeMax");
330
+ if (c < 0 || d > 255 || c >= d)
358
331
  throw new Error("Invalid GeoVideo code range");
359
- let f = s.height;
332
+ let h = s.height;
360
333
  if (o.kind === "scalar-luma") {
361
- if (o.transfer !== "linear" || h(o.valueMin, "encoding.valueMin") >= h(o.valueMax, "encoding.valueMax"))
334
+ if (o.transfer !== "linear" || m(o.valueMin, "encoding.valueMin") >= m(o.valueMax, "encoding.valueMax"))
362
335
  throw new Error("Invalid GeoVideo scalar-luma encoding");
363
336
  } else if (o.kind === "vector-luma") {
364
- if (o.transfer !== "linear" && o.transfer !== "sqrt" || o.layout !== "stacked-uv" || h(o.valueDomain, "encoding.valueDomain") <= 0 || s.height % 2 !== 0)
337
+ if (o.transfer !== "linear" && o.transfer !== "sqrt" || o.layout !== "stacked-uv" || m(o.valueDomain, "encoding.valueDomain") <= 0 || s.height % 2 !== 0)
365
338
  throw new Error("Invalid GeoVideo vector-luma encoding");
366
- f = s.height / 2;
339
+ h = s.height / 2;
367
340
  } else
368
341
  throw new Error("Unsupported GeoVideo encoding");
369
- const l = t.mask;
370
- if (!l || l.kind !== "static-validity" || typeof l.url != "string" || !l.url || h(l.width, "mask.width") !== s.width || h(l.height, "mask.height") !== f || h(l.threshold, "mask.threshold") < 0 || l.threshold > 1)
342
+ const u = t.mask;
343
+ if (!u || u.kind !== "static-validity" || typeof u.url != "string" || !u.url || m(u.width, "mask.width") !== s.width || m(u.height, "mask.height") !== h || m(u.threshold, "mask.threshold") < 0 || u.threshold > 1)
371
344
  throw new Error("Invalid GeoVideo static mask");
372
345
  if (t.timeline?.kind === "range") {
373
- const u = b(t.timeline.dateStart, "timeline.dateStart");
374
- if (b(t.timeline.dateEnd, "timeline.dateEnd") <= u)
346
+ const f = F(t.timeline.dateStart, "timeline.dateStart");
347
+ if (F(t.timeline.dateEnd, "timeline.dateEnd") <= f)
375
348
  throw new Error("GeoVideo timeline end must follow start");
376
349
  if (t.timeline.interpolation !== "linear" && t.timeline.interpolation !== "nearest")
377
350
  throw new Error("Invalid GeoVideo interpolation");
378
351
  } else if (t.timeline?.kind === "snapshot-loop")
379
- b(t.timeline.date, "timeline.date");
352
+ F(t.timeline.date, "timeline.date");
380
353
  else if (t.timeline?.kind === "sample-sequence") {
381
354
  if (!Array.isArray(t.timeline.values) || t.timeline.values.length === 0)
382
355
  throw new Error("GeoVideo sample sequence must contain values");
383
- const u = t.timeline.values.map(
384
- (m, T) => b(m, `timeline.values[${T}]`)
356
+ const f = t.timeline.values.map(
357
+ (T, b) => F(T, `timeline.values[${b}]`)
385
358
  );
386
- if (u.some((m, T) => T > 0 && m <= u[T - 1]))
359
+ if (f.some((T, b) => b > 0 && T <= f[b - 1]))
387
360
  throw new Error(
388
361
  "GeoVideo sample sequence values must be strictly increasing"
389
362
  );
@@ -392,26 +365,26 @@ function v(e) {
392
365
  const E = t.style?.colorDomain;
393
366
  if (!Array.isArray(E) || E.length !== 2 || !E.every(Number.isFinite) || E[0] >= E[1])
394
367
  throw new Error("Invalid GeoVideo color domain");
395
- if (!R(t.id) || !t.provenance || !R(t.provenance.catalogEntryId) || !R(t.provenance.inputSourceId) || !Array.isArray(t.provenance.variables) || t.provenance.variables.length === 0)
368
+ if (!D(t.id) || !t.provenance || !D(t.provenance.catalogEntryId) || !D(t.provenance.inputSourceId) || !Array.isArray(t.provenance.variables) || t.provenance.variables.length === 0)
396
369
  throw new Error("Invalid GeoVideo provenance");
397
370
  return { ...t, bounds: [r, n, a, i] };
398
371
  }
399
- async function ke(e, t) {
372
+ async function Re(e, t) {
400
373
  if (typeof e != "string")
401
- return v(e);
374
+ return V(e);
402
375
  const r = await fetch(e, { signal: t });
403
376
  if (!r.ok)
404
377
  throw new Error(
405
378
  `GeoVideo manifest request failed (${r.status}): ${e}`
406
379
  );
407
- const n = await r.json(), a = v(n), i = typeof document < "u" ? new URL(e, document.baseURI).href : e;
380
+ const n = await r.json(), a = V(n), i = typeof document < "u" ? new URL(e, document.baseURI).href : e;
408
381
  return {
409
382
  ...a,
410
383
  media: { ...a.media, url: new URL(a.media.url, i).href },
411
384
  mask: { ...a.mask, url: new URL(a.mask.url, i).href }
412
385
  };
413
386
  }
414
- function F(e) {
387
+ function _(e) {
415
388
  if (e.timeline.kind === "snapshot-loop")
416
389
  return [new Date(e.timeline.date).getTime()];
417
390
  if (e.timeline.kind === "sample-sequence")
@@ -425,40 +398,40 @@ function F(e) {
425
398
  (a, i) => t + (r - t) * i / (n - 1)
426
399
  );
427
400
  }
428
- function ue(e) {
401
+ function _e(e) {
429
402
  return e.timeline.kind === "sample-sequence" ? e.timeline.values.length / e.media.durationSeconds : e.media.fps;
430
403
  }
431
- function Xe(e, t) {
432
- return t / ue(e);
404
+ function dt(e, t) {
405
+ return t / _e(e);
433
406
  }
434
- function he(e, t) {
407
+ function Ae(e, t) {
435
408
  if (e.timeline.kind === "snapshot-loop")
436
409
  return 0;
437
410
  if (e.timeline.kind === "sample-sequence") {
438
- const i = F(e);
411
+ const i = _(e);
439
412
  let s = 0;
440
- for (let d = 1; d < i.length; d += 1)
441
- Math.abs(i[d] - t) < Math.abs(i[s] - t) && (s = d);
413
+ for (let c = 1; c < i.length; c += 1)
414
+ Math.abs(i[c] - t) < Math.abs(i[s] - t) && (s = c);
442
415
  const o = e.media.durationSeconds / i.length;
443
416
  return s * o + Math.min(o / 2, 0.5 / e.media.fps);
444
417
  }
445
418
  const r = new Date(e.timeline.dateStart).getTime(), n = new Date(e.timeline.dateEnd).getTime();
446
- return Math.max(0, Math.min(1, (t - r) / (n - r))) * P(e);
419
+ return Math.max(0, Math.min(1, (t - r) / (n - r))) * X(e);
447
420
  }
448
- function Ce(e, t) {
421
+ function ut(e, t) {
449
422
  if (e.timeline.kind === "snapshot-loop")
450
423
  return new Date(e.timeline.date).getTime();
451
424
  if (e.timeline.kind === "sample-sequence") {
452
- const s = F(e), o = e.media.durationSeconds / s.length, d = Math.floor((t + 0.25 / e.media.fps) / o);
453
- return s[Math.max(0, Math.min(s.length - 1, d))];
425
+ const s = _(e), o = e.media.durationSeconds / s.length, c = Math.floor((t + 0.25 / e.media.fps) / o);
426
+ return s[Math.max(0, Math.min(s.length - 1, c))];
454
427
  }
455
- const r = new Date(e.timeline.dateStart).getTime(), n = new Date(e.timeline.dateEnd).getTime(), a = P(e), i = a > 0 ? Math.max(0, Math.min(1, t / a)) : 0;
428
+ const r = new Date(e.timeline.dateStart).getTime(), n = new Date(e.timeline.dateEnd).getTime(), a = X(e), i = a > 0 ? Math.max(0, Math.min(1, t / a)) : 0;
456
429
  return r + (n - r) * i;
457
430
  }
458
- function P(e) {
431
+ function X(e) {
459
432
  return Math.max(0, e.media.durationSeconds - 1 / e.media.fps);
460
433
  }
461
- function le(e, t) {
434
+ function Fe(e, t) {
462
435
  const r = new Uint8Array(e.length / 4);
463
436
  for (let n = 0; n < r.length; n++) {
464
437
  const a = e[n * 4];
@@ -466,7 +439,7 @@ function le(e, t) {
466
439
  }
467
440
  return r;
468
441
  }
469
- class me {
442
+ class xe {
470
443
  constructor() {
471
444
  this.gl = null, this.texture = null, this.framebuffer = null;
472
445
  }
@@ -497,62 +470,105 @@ class me {
497
470
  return this.gl = n, this.texture = n.createTexture(), this.framebuffer = n.createFramebuffer(), n;
498
471
  }
499
472
  }
500
- function M(e) {
473
+ function C(e) {
501
474
  const t = Math.max(4, Math.floor(e.length / 4 / 997) * 4);
502
475
  for (let r = 3; r < e.length; r += t)
503
476
  if (e[r] !== 0)
504
477
  return !1;
505
478
  return !0;
506
479
  }
507
- function p() {
480
+ function l() {
508
481
  return new DOMException("GeoVideo frame request was cancelled", "AbortError");
509
482
  }
510
- function _(e, t) {
483
+ function R(e, t, r) {
484
+ return t ? t.aborted ? (e.catch(() => {
485
+ }), r?.(), Promise.reject(l())) : new Promise((n, a) => {
486
+ const i = () => {
487
+ r?.(), a(l());
488
+ };
489
+ t.addEventListener("abort", i, { once: !0 }), e.then(n, a).finally(() => {
490
+ t.removeEventListener("abort", i);
491
+ });
492
+ }) : e;
493
+ }
494
+ function M(e, t) {
511
495
  return new Promise(
512
496
  (r) => e.addEventListener(t, () => r(), { once: !0 })
513
497
  );
514
498
  }
515
- const Ee = 250;
516
- function Te(e) {
499
+ const ve = 250;
500
+ function ye(e) {
517
501
  return "requestVideoFrameCallback" in e ? Promise.race([
518
502
  new Promise(
519
503
  (t) => e.requestVideoFrameCallback(() => t())
520
504
  ),
521
- new Promise((t) => setTimeout(t, Ee))
505
+ new Promise((t) => setTimeout(t, ve))
522
506
  ]) : Promise.resolve();
523
507
  }
524
- class be {
508
+ class O {
525
509
  constructor(t, r, n = {}) {
526
- this.reader = new me(), this.video = null, this.mask = null, this.initPromise = null, this.presented = !1, this.primed = !1, this.queue = Promise.resolve(), this.epoch = 0, this.frames = /* @__PURE__ */ new Map(), this.manifest = t, this.planes = r, this.cacheSize = Math.max(1, n.cacheSize ?? 3), this.width = t.media.width, this.height = t.media.height / r, this.times = Float64Array.from(F(t));
510
+ this.reader = new xe(), this.video = null, this.mask = null, this.initPromise = null, this.presented = !1, this.primed = !1, this.queue = Promise.resolve(), this.frames = /* @__PURE__ */ new Map(), this.pending = /* @__PURE__ */ new Set(), this.manifest = t, this.planes = r, this.cacheSize = Math.max(1, n.cacheSize ?? 3), this.width = t.media.width, this.height = t.media.height / r, this.times = Float64Array.from(_(t));
527
511
  }
528
512
  init() {
529
513
  return this.initPromise ??= this.load().catch((t) => {
530
514
  throw this.initPromise = null, t;
531
515
  }), this.initPromise;
532
516
  }
533
- /** Abort queued frame decodes; frames already decoded stay cached. */
517
+ /** Abort every pending frame decode; frames already decoded stay cached. */
534
518
  cancelAll() {
535
- this.epoch++;
536
- for (const [t, r] of this.frames)
537
- r.catch(() => this.frames.delete(t));
519
+ for (const t of [...this.pending])
520
+ this.drop(t);
538
521
  }
539
522
  /** Release the video element and GL context; a later init() reloads them. */
540
523
  release() {
541
524
  this.cancelAll(), this.frames.clear(), this.video && (this.video.removeAttribute("src"), this.video.load()), this.video = null, this.mask = null, this.presented = !1, this.primed = !1, this.initPromise = null, this.reader.release();
542
525
  }
543
- /** One decode per time step, cached. */
544
- frame(t) {
545
- const r = this.frames.get(t);
546
- if (r)
547
- return this.frames.delete(t), this.frames.set(t, r), r;
548
- const n = this.epoch, a = this.queue.then(() => this.decode(t, n));
549
- for (this.queue = a.catch(() => {
550
- }), this.frames.set(t, a), a.catch(() => {
551
- this.frames.get(t) === a && this.frames.delete(t);
552
- }); this.frames.size > this.cacheSize; )
526
+ /**
527
+ * One decode per time step, cached and shared by concurrent requests.
528
+ * Aborting `request.signal` rejects this request with an AbortError; the
529
+ * decode goes on while another request waits for it.
530
+ */
531
+ frame(t, r = {}) {
532
+ const { signal: n } = r;
533
+ if (n?.aborted)
534
+ return Promise.reject(l());
535
+ let a = this.frames.get(t);
536
+ if (a ? (this.frames.delete(t), this.frames.set(t, a)) : a = this.enqueue(t), a.settled)
537
+ return a.promise;
538
+ const i = a;
539
+ return i.waiters++, R(i.promise, n, () => this.leave(i));
540
+ }
541
+ enqueue(t) {
542
+ const r = new AbortController(), n = this.queue.then(
543
+ () => r.signal.aborted ? Promise.reject(l()) : this.decode(t, r.signal)
544
+ );
545
+ this.queue = n.catch(() => {
546
+ });
547
+ const a = {
548
+ index: t,
549
+ controller: r,
550
+ promise: R(n, r.signal),
551
+ waiters: 0,
552
+ settled: !1
553
+ };
554
+ for (this.pending.add(a), a.promise.then(
555
+ () => {
556
+ a.settled = !0, this.pending.delete(a);
557
+ },
558
+ () => {
559
+ a.settled = !0, this.pending.delete(a), this.frames.get(t) === a && this.frames.delete(t);
560
+ }
561
+ ), this.frames.set(t, a); this.frames.size > this.cacheSize; )
553
562
  this.frames.delete(this.frames.keys().next().value);
554
563
  return a;
555
564
  }
565
+ /** A request left; drop the decode when it was the last one waiting. */
566
+ leave(t) {
567
+ t.waiters--, t.waiters <= 0 && !t.settled && this.drop(t);
568
+ }
569
+ drop(t) {
570
+ t.controller.abort(), this.pending.delete(t), this.frames.get(t.index) === t && this.frames.delete(t.index);
571
+ }
556
572
  async load() {
557
573
  const [t] = await Promise.all([this.loadMask(), this.loadVideo()]);
558
574
  this.mask = t;
@@ -594,8 +610,8 @@ class be {
594
610
  async presentFrame(t, r) {
595
611
  if (this.presented && Math.abs(t.currentTime - r) <= 1e-3 && !t.seeking)
596
612
  return;
597
- const n = Te(t), a = _(t, "seeked");
598
- t.currentTime = r, await a, t.readyState < HTMLMediaElement.HAVE_CURRENT_DATA && await Promise.race([_(t, "loadeddata"), _(t, "canplay")]), await n, this.presented = !0;
613
+ const n = ye(t), a = M(t, "seeked");
614
+ t.currentTime = r, await a, t.readyState < HTMLMediaElement.HAVE_CURRENT_DATA && await Promise.race([M(t, "loadeddata"), M(t, "canplay")]), await n, this.presented = !0;
599
615
  }
600
616
  /**
601
617
  * Some mobile browsers expose no decoded pixels to WebGL until playback
@@ -610,63 +626,69 @@ class be {
610
626
  }
611
627
  t.pause(), this.presented = !1;
612
628
  }
629
+ /**
630
+ * Seek, read back and decode one step. `signal` aborts it between steps;
631
+ * a seek already started completes first, keeping the queue serial.
632
+ */
613
633
  async decode(t, r) {
634
+ if (r.aborted)
635
+ throw l();
614
636
  await this.init();
615
637
  const n = this.video, a = this.mask;
616
- if (r !== this.epoch || !n || !a)
617
- throw p();
618
- const i = he(this.manifest, this.times[t]);
619
- if (await this.presentFrame(n, i), r !== this.epoch || n !== this.video)
620
- throw p();
638
+ if (r.aborted || !n || !a)
639
+ throw l();
640
+ const i = Ae(this.manifest, this.times[t]);
641
+ if (await this.presentFrame(n, i), r.aborted || n !== this.video)
642
+ throw l();
621
643
  const s = this.height * this.planes;
622
644
  let o = this.reader.read(n, this.width, s);
623
- if (M(o) && !this.primed) {
624
- if (await this.primeDecoder(n), await this.presentFrame(n, i), r !== this.epoch || n !== this.video)
625
- throw p();
645
+ if (C(o) && !this.primed) {
646
+ if (await this.primeDecoder(n), await this.presentFrame(n, i), r.aborted || n !== this.video)
647
+ throw l();
626
648
  o = this.reader.read(n, this.width, s);
627
649
  }
628
- if (M(o))
650
+ if (C(o))
629
651
  throw new Error("GeoVideo frame could not be read back from the decoder");
630
- const d = le(o, this.manifest.encoding.colorRange);
631
- return this.decodeCodes(d, a, this.manifest.mask.threshold);
652
+ const c = Fe(o, this.manifest.encoding.colorRange);
653
+ return this.decodeCodes(c, a, this.manifest.mask.threshold);
632
654
  }
633
655
  }
634
- function Re(e, t) {
656
+ function De(e, t) {
635
657
  let r = (e - t.codeMin) / (t.codeMax - t.codeMin) * 2 - 1;
636
658
  return r = Math.max(-1, Math.min(1, r)), t.transfer === "sqrt" && (r = Math.sign(r) * r * r), r * t.valueDomain;
637
659
  }
638
- function pe(e, t, r, n) {
660
+ function Me(e, t, r, n) {
639
661
  const a = t.length;
640
662
  if (e.length !== 2 * a)
641
663
  throw new Error(
642
664
  `GeoVideo vector frame has ${e.length} codes, expected ${2 * a}`
643
665
  );
644
666
  const i = new Float32Array(256);
645
- for (let c = 0; c < 256; c++)
646
- i[c] = Re(c, n);
647
- const s = r * 255, o = new Float32Array(a), d = new Float32Array(a);
648
- for (let c = 0; c < a; c++) {
649
- const f = t[c] >= s;
650
- o[c] = f ? i[e[c]] : NaN, d[c] = f ? i[e[a + c]] : NaN;
667
+ for (let d = 0; d < 256; d++)
668
+ i[d] = De(d, n);
669
+ const s = r * 255, o = new Float32Array(a), c = new Float32Array(a);
670
+ for (let d = 0; d < a; d++) {
671
+ const h = t[d] >= s;
672
+ o[d] = h ? i[e[d]] : NaN, c[d] = h ? i[e[a + d]] : NaN;
651
673
  }
652
- return { u: o, v: d };
674
+ return { u: o, v: c };
653
675
  }
654
- class Oe extends be {
676
+ class Ue extends O {
655
677
  constructor(t, r = {}) {
656
678
  if (t.encoding.kind !== "vector-luma")
657
679
  throw new Error("GeoVideoVectorSource requires a vector-luma manifest");
658
680
  super(t, 2, r), this.encoding = t.encoding;
659
- const [n, a, i, s] = t.bounds, o = (i - n) / this.width, d = (s - a) / this.height;
681
+ const [n, a, i, s] = t.bounds, o = (i - n) / this.width, c = (s - a) / this.height;
660
682
  this.coords = {
661
683
  time: this.times,
662
684
  vertical: new Float32Array([0]),
663
685
  latitude: Float32Array.from(
664
686
  { length: this.height },
665
- (c, f) => s - (f + 0.5) * d
687
+ (d, h) => s - (h + 0.5) * c
666
688
  ),
667
689
  longitude: Float32Array.from(
668
690
  { length: this.width },
669
- (c, f) => n + (f + 0.5) * o
691
+ (d, h) => n + (h + 0.5) * o
670
692
  )
671
693
  };
672
694
  }
@@ -716,67 +738,354 @@ class Oe extends be {
716
738
  };
717
739
  }
718
740
  decodeCodes(t, r, n) {
719
- return pe(t, r, n, this.encoding);
741
+ return Me(t, r, n, this.encoding);
720
742
  }
721
743
  }
722
- function w(e) {
723
- const { start: t, end: r } = e.temporal ?? {};
724
- return [Date.parse(t ?? ""), Date.parse(r ?? t ?? "")];
725
- }
726
- function qe(e, t, r = {}) {
727
- const [n, a] = r.range ?? [-1 / 0, 1 / 0], i = e.filter((d) => d.id === t.id && d.temporal?.start != null).map((d) => {
728
- const [c, f] = w(d);
729
- return { source: d, start: c, end: f };
730
- }).sort((d, c) => d.start - c.start), s = Date.parse(t.temporal?.end ?? ""), o = i.find(
731
- (d) => d.start > s && d.start <= a
744
+ function Se(e, t) {
745
+ const r = Math.max(
746
+ 0,
747
+ Math.min(
748
+ 1,
749
+ (e - t.codeMin) / (t.codeMax - t.codeMin)
750
+ )
751
+ );
752
+ return t.valueMin + r * (t.valueMax - t.valueMin);
753
+ }
754
+ function Ge(e, t, r, n) {
755
+ const a = t.length;
756
+ if (e.length !== a)
757
+ throw new Error(
758
+ `GeoVideo scalar frame has ${e.length} codes, expected ${a}`
759
+ );
760
+ const i = new Float32Array(256);
761
+ for (let c = 0; c < 256; c++)
762
+ i[c] = Se(c, n);
763
+ const s = r * 255, o = new Float32Array(a);
764
+ for (let c = 0; c < a; c++)
765
+ o[c] = t[c] >= s ? i[e[c]] : NaN;
766
+ return o;
767
+ }
768
+ class Pe extends O {
769
+ constructor(t, r = {}) {
770
+ if (t.encoding.kind !== "scalar-luma")
771
+ throw new Error("GeoVideoScalarSource requires a scalar-luma manifest");
772
+ super(t, 1, r), this.encoding = t.encoding;
773
+ }
774
+ decodeCodes(t, r, n) {
775
+ return Ge(t, r, n, this.encoding);
776
+ }
777
+ }
778
+ function ke(e, t, r = {}) {
779
+ const [n, a] = r.range ?? [-1 / 0, 1 / 0], i = [...e].sort((o, c) => o.start - c.start), s = i.find(
780
+ (o) => o.start > t && o.start <= a
732
781
  ) ?? (r.loop ? i.find(
733
- (d) => d.end >= n && d.start <= a
782
+ (o) => o.end >= n && o.start <= a
734
783
  ) : void 0);
735
- return o ? { source: o.source, time: Math.max(o.start, n) } : null;
784
+ return s ? { chunk: s, time: Math.max(s.start, n) } : null;
736
785
  }
737
- function ge(e, t) {
738
- const [r, n] = w(e);
739
- let a = null, i = -1 / 0;
740
- for (const s of t) {
741
- const [o, d] = w(s), c = Math.min(n, d) - Math.max(r, o);
742
- Number.isFinite(c) && c >= 0 && c > i && (a = s, i = c);
786
+ function Ie(e, t) {
787
+ let r = null, n = -1 / 0;
788
+ for (const a of t) {
789
+ const i = Math.min(e.end, a.end) - Math.max(e.start, a.start);
790
+ Number.isFinite(i) && i >= 0 && i > n && (r = a, n = i);
743
791
  }
744
- return a;
792
+ return r;
793
+ }
794
+ function Ne(e) {
795
+ return {
796
+ width: e.mask.width,
797
+ height: e.mask.height,
798
+ bounds: e.bounds,
799
+ rowOrder: "north-to-south"
800
+ };
801
+ }
802
+ function Le(e, t = {}) {
803
+ return e.encoding.kind === "vector-luma" ? new Ue(e, t) : new Pe(e, t);
745
804
  }
746
- function We(e) {
805
+ const Ve = 3, Ce = 3, Be = 0.6, ge = 1.5;
806
+ function Xe(e, t) {
807
+ const r = e.length - 1;
808
+ if (t <= e[0])
809
+ return { step: 0, fraction: 0 };
810
+ if (t >= e[r])
811
+ return { step: r, fraction: 0 };
812
+ let n = 0, a = r;
813
+ for (; a - n > 1; ) {
814
+ const i = n + a >> 1;
815
+ e[i] <= t ? n = i : a = i;
816
+ }
817
+ return { step: n, fraction: (t - e[n]) / (e[a] - e[n]) };
818
+ }
819
+ function Oe(e) {
820
+ const t = new AbortController();
821
+ if (!e)
822
+ return { controller: t, unlink: () => {
823
+ } };
824
+ const r = () => t.abort();
825
+ return e.aborted && r(), e.addEventListener("abort", r, { once: !0 }), {
826
+ controller: t,
827
+ unlink: () => e.removeEventListener("abort", r)
828
+ };
829
+ }
830
+ class ft {
831
+ constructor(t) {
832
+ this.manifests = /* @__PURE__ */ new Map(), this.open = /* @__PURE__ */ new Map(), this.id = t.id, this.chunks = t.chunks.filter(
833
+ (r) => Number.isFinite(r.start) && Number.isFinite(r.end) && r.end >= r.start
834
+ ).sort((r, n) => r.start - n.start), this.maxOpenChunks = Math.max(2, t.maxOpenChunks ?? Ve), this.frameCacheSize = Math.max(
835
+ 1,
836
+ t.frameCacheSize ?? Ce
837
+ ), this.prefetchAt = t.prefetchAt ?? Be, this.maxGap = t.maxGap, this.loadManifest = t.loadManifest ?? Re, this.createFrameSource = t.createFrameSource ?? ((r, n) => Le(
838
+ r,
839
+ n
840
+ ));
841
+ }
842
+ /** First and last sample of the archive, or null without chunks. */
843
+ get range() {
844
+ const { chunks: t } = this;
845
+ return t.length ? [t[0].start, Math.max(...t.map((r) => r.end))] : null;
846
+ }
847
+ /** The chunk whose sample range holds `time`, or null. */
848
+ chunkAt(t) {
849
+ const r = this.chunkIndexAt(t), n = r >= 0 ? this.chunks[r] : null;
850
+ return n && t <= n.end ? n : null;
851
+ }
852
+ /** Every step time of the archive; loads all chunk manifests. */
853
+ async steps(t = {}) {
854
+ if (t.signal?.aborted)
855
+ throw l();
856
+ const r = await R(
857
+ Promise.all(this.chunks.map((n) => this.manifest(n))),
858
+ t.signal
859
+ );
860
+ return Float64Array.from(r.flatMap(_));
861
+ }
862
+ /**
863
+ * The frames bracketing `time`, decoded; null out of coverage (before the
864
+ * first step, after the last, or in a gap wider than `maxGap`).
865
+ */
866
+ async sample(t, r = {}) {
867
+ const { signal: n } = r, a = r.mode ?? "interpolate";
868
+ if (n?.aborted)
869
+ throw l();
870
+ const i = this.chunkIndexAt(t);
871
+ if (i < 0)
872
+ return null;
873
+ const s = [], { controller: o, unlink: c } = Oe(n);
874
+ try {
875
+ const d = this.acquire(this.chunks[i], s), h = await R(d.ready, o.signal), { times: u } = h;
876
+ let E;
877
+ if (t <= u[u.length - 1]) {
878
+ const { step: p, fraction: w } = Xe(u, t);
879
+ E = a === "discrete" || w === 0 ? [d, p, d, p, 0] : [d, p, d, p + 1, w];
880
+ } else {
881
+ const p = this.chunks[i + 1];
882
+ if (!p)
883
+ return null;
884
+ const w = this.acquire(p, s), k = await R(w.ready, o.signal), A = u.length - 1, v = u[A], y = k.times[0];
885
+ if (y - v > this.gapLimit(u, k.times))
886
+ return null;
887
+ E = a === "discrete" ? [d, A, d, A, 0] : t >= y ? [w, 0, w, 0, 0] : [d, A, w, 0, (t - v) / (y - v)];
888
+ }
889
+ const [f, T, b, S, q] = E, G = f === b && T === S, P = [this.frame(f, T, o.signal)];
890
+ G || P.push(this.frame(b, S, o.signal));
891
+ let x;
892
+ try {
893
+ x = await Promise.all(P);
894
+ } catch (p) {
895
+ throw o.abort(), p;
896
+ }
897
+ return this.prefetchAfter(i, t), {
898
+ time: t,
899
+ a: x[0],
900
+ b: x[G ? 0 : 1],
901
+ mix: q
902
+ };
903
+ } finally {
904
+ c();
905
+ for (const d of s)
906
+ d.users--;
907
+ this.trim();
908
+ }
909
+ }
910
+ /** Open `chunk` and decode its first frame ahead of a request. */
911
+ prefetch(t) {
912
+ if (this.open.has(t.key))
913
+ return;
914
+ const r = this.touch(t), n = new AbortController();
915
+ r.prefetch = n, r.ready.then(({ source: a }) => a.frame(0, { signal: n.signal })).catch(() => {
916
+ }).finally(() => {
917
+ r.prefetch === n && (r.prefetch = null);
918
+ }), this.trim();
919
+ }
920
+ /** Release every open chunk source; later requests reopen them. */
921
+ release() {
922
+ for (const t of [...this.open.values()])
923
+ this.close(t);
924
+ }
925
+ chunkIndexAt(t) {
926
+ let r = 0, n = this.chunks.length - 1, a = -1;
927
+ for (; r <= n; ) {
928
+ const i = r + n >> 1;
929
+ this.chunks[i].start <= t ? (a = i, r = i + 1) : n = i - 1;
930
+ }
931
+ return a;
932
+ }
933
+ gapLimit(t, r) {
934
+ if (this.maxGap !== void 0)
935
+ return this.maxGap;
936
+ const n = [
937
+ t.length > 1 ? t[t.length - 1] - t[t.length - 2] : 0,
938
+ r.length > 1 ? r[1] - r[0] : 0
939
+ ], a = Math.max(...n);
940
+ return a > 0 ? a * ge : -1 / 0;
941
+ }
942
+ prefetchAfter(t, r) {
943
+ const n = this.chunks[t], a = this.chunks[t + 1], i = n.end - n.start, s = i > 0 ? (r - n.start) / i : 1;
944
+ a && s > this.prefetchAt && this.prefetch(a);
945
+ }
946
+ manifest(t) {
947
+ let r = this.manifests.get(t.manifestUrl);
948
+ return r || (r = this.loadManifest(t.manifestUrl), this.manifests.set(t.manifestUrl, r), r.catch(() => {
949
+ this.manifests.get(t.manifestUrl) === r && this.manifests.delete(t.manifestUrl);
950
+ })), r;
951
+ }
952
+ /** The open chunk, pinned for a running sample listed in `used`. */
953
+ acquire(t, r) {
954
+ const n = this.touch(t);
955
+ return n.users++, r.push(n), n;
956
+ }
957
+ /** The open chunk, opened when needed, most recently used; not pinned. */
958
+ touch(t) {
959
+ let r = this.open.get(t.key);
960
+ if (r)
961
+ this.open.delete(t.key);
962
+ else {
963
+ const n = {
964
+ chunk: t,
965
+ ready: null,
966
+ opened: null,
967
+ users: 0,
968
+ prefetch: null,
969
+ released: !1
970
+ };
971
+ n.ready = this.manifest(t).then((a) => {
972
+ if (n.released)
973
+ throw l();
974
+ return n.opened = {
975
+ manifest: a,
976
+ times: Float64Array.from(_(a)),
977
+ grid: Ne(a),
978
+ source: this.createFrameSource(a, {
979
+ cacheSize: this.frameCacheSize
980
+ })
981
+ }, n.opened;
982
+ }), n.ready.catch(() => {
983
+ this.open.get(t.key) === n && this.open.delete(t.key);
984
+ }), r = n;
985
+ }
986
+ return this.open.set(t.key, r), r;
987
+ }
988
+ async frame(t, r, n) {
989
+ const { manifest: a, times: i, grid: s, source: o } = await R(
990
+ t.ready,
991
+ n
992
+ );
993
+ if (t.released)
994
+ throw l();
995
+ const c = await o.frame(r, { signal: n });
996
+ return {
997
+ key: `${this.id}/${t.chunk.key}/${r}`,
998
+ chunk: t.chunk,
999
+ step: r,
1000
+ time: i[r],
1001
+ data: c,
1002
+ grid: s,
1003
+ manifest: a
1004
+ };
1005
+ }
1006
+ /** Release least recently used chunks beyond the bound, unless in use. */
1007
+ trim() {
1008
+ let t = this.open.size - this.maxOpenChunks;
1009
+ for (const r of [...this.open.values()]) {
1010
+ if (t <= 0)
1011
+ return;
1012
+ r.users === 0 && (this.close(r), t--);
1013
+ }
1014
+ }
1015
+ close(t) {
1016
+ t.released = !0, t.prefetch?.abort(), t.prefetch = null, t.opened?.source.release(), t.opened = null, this.open.get(t.chunk.key) === t && this.open.delete(t.chunk.key);
1017
+ }
1018
+ }
1019
+ function U(e) {
1020
+ const { start: t, end: r } = e.temporal ?? {};
1021
+ return {
1022
+ source: e,
1023
+ start: Date.parse(t ?? ""),
1024
+ end: Date.parse(r ?? t ?? "")
1025
+ };
1026
+ }
1027
+ function lt(e, t, r = {}) {
1028
+ const n = e.filter((i) => i.id === t.id && i.temporal?.start != null).map(U), a = ke(
1029
+ n,
1030
+ Date.parse(t.temporal?.end ?? ""),
1031
+ r
1032
+ );
1033
+ return a ? { source: a.chunk.source, time: a.time } : null;
1034
+ }
1035
+ function ht(e, t) {
1036
+ return Ie(U(e), t.map(U))?.source ?? null;
1037
+ }
1038
+ function mt(e) {
747
1039
  return e.type === "geovideo" && typeof e.indexUrl == "string";
748
1040
  }
749
- function $e(e, t) {
1041
+ function Et(e, t) {
750
1042
  return e.id === t.id && (e.type !== "geovideo" || t.type !== "geovideo" || e.manifestUrl === t.manifestUrl);
751
1043
  }
752
- function y(e) {
1044
+ function B(e) {
753
1045
  return typeof e == "string" && Number.isFinite(Date.parse(e));
754
1046
  }
755
- function _e(e) {
1047
+ function qe(e) {
756
1048
  const t = e;
757
1049
  if (!t || t.schemaVersion !== 1 || t.type !== "geovideo-index" || !Array.isArray(t.chunks))
758
1050
  throw new Error("Unsupported GeoVideo index");
759
1051
  for (const r of t.chunks)
760
- if (!y(r?.start) || !y(r.end) || Date.parse(r.end) < Date.parse(r.start) || typeof r.manifestUrl != "string")
1052
+ if (!B(r?.start) || !B(r.end) || Date.parse(r.end) < Date.parse(r.start) || typeof r.manifestUrl != "string")
761
1053
  throw new Error("Invalid GeoVideo index chunk");
762
1054
  return t;
763
1055
  }
764
- async function He(e, t) {
1056
+ async function Tt(e, t) {
765
1057
  const r = await fetch(e, { signal: t });
766
1058
  if (!r.ok)
767
1059
  throw new Error(
768
1060
  `GeoVideo index request failed (${r.status}): ${e}`
769
1061
  );
770
- return _e(await r.json());
1062
+ return qe(await r.json());
771
1063
  }
772
- function je(e, t, r) {
1064
+ function $e(e) {
1065
+ return typeof document < "u" ? new URL(e, document.baseURI).href : e;
1066
+ }
1067
+ function We(e, t) {
1068
+ const r = $e(t);
1069
+ return e.chunks.map((n) => ({
1070
+ key: n.key,
1071
+ manifestUrl: new URL(n.manifestUrl, r).href,
1072
+ start: Date.parse(n.start),
1073
+ end: Date.parse(n.end),
1074
+ samples: n.samples,
1075
+ ...n.provisional ? { provisional: !0 } : {}
1076
+ }));
1077
+ }
1078
+ function He(e, t, r) {
773
1079
  if (t.sourceId !== e.id || t.catalogEntryId !== r.id)
774
1080
  throw new Error(
775
1081
  `GeoVideo index identity does not match catalog entry/source: ${e.id}`
776
1082
  );
777
- const n = typeof document < "u" ? new URL(e.indexUrl, document.baseURI).href : e.indexUrl;
1083
+ }
1084
+ function pt(e, t, r) {
1085
+ He(e, t, r);
1086
+ const n = We(t, e.indexUrl);
778
1087
  return t.chunks.map(
779
- (a) => ({
1088
+ (a, i) => ({
780
1089
  id: e.id,
781
1090
  type: "geovideo",
782
1091
  title: e.title,
@@ -787,47 +1096,53 @@ function je(e, t, r) {
787
1096
  start: a.start,
788
1097
  end: a.end
789
1098
  },
790
- manifestUrl: new URL(a.manifestUrl, n).href
1099
+ manifestUrl: n[i].manifestUrl
791
1100
  })
792
1101
  );
793
1102
  }
794
1103
  export {
795
- ve as A,
796
- xe as B,
797
- ce as C,
798
- Pe as D,
799
- Ie as E,
800
- he as F,
801
- be as G,
802
- Ce as H,
803
- $e as I,
804
- Xe as J,
805
- ue as K,
806
- Le as T,
807
- fe as a,
808
- Oe as b,
809
- Be as c,
810
- Ge as d,
811
- Fe as e,
812
- ie as f,
813
- Ne as g,
1104
+ Tt as A,
1105
+ pt as B,
1106
+ V as C,
1107
+ ft as D,
1108
+ O as E,
1109
+ Pe as F,
1110
+ Ue as G,
1111
+ He as H,
1112
+ Le as I,
1113
+ N as J,
1114
+ Te as K,
1115
+ Ne as L,
1116
+ We as M,
1117
+ ke as N,
1118
+ ht as O,
1119
+ Ie as P,
1120
+ qe as Q,
1121
+ st as T,
1122
+ tt as a,
1123
+ rt as b,
1124
+ ze as c,
1125
+ Je as d,
1126
+ Qe as e,
1127
+ et as f,
1128
+ nt as g,
814
1129
  je as h,
815
- F as i,
816
- we as j,
817
- We as k,
818
- He as l,
819
- ke as m,
820
- qe as n,
821
- ee as o,
822
- ge as p,
823
- v as q,
824
- Ve as r,
825
- Se as s,
826
- re as t,
827
- De as u,
828
- _e as v,
829
- ye as w,
830
- Ue as x,
831
- Me as y,
832
- Ae as z
1130
+ Ze as i,
1131
+ Ke as j,
1132
+ it as k,
1133
+ ot as l,
1134
+ Re as m,
1135
+ Ae as n,
1136
+ fe as o,
1137
+ ut as p,
1138
+ _ as q,
1139
+ he as r,
1140
+ at as s,
1141
+ Et as t,
1142
+ dt as u,
1143
+ ct as v,
1144
+ _e as w,
1145
+ Ye as x,
1146
+ mt as y,
1147
+ lt as z
833
1148
  };