@ixfx/components 0.4.1 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/bundle/index.d.ts +207 -111
  2. package/bundle/index.d.ts.map +1 -1
  3. package/bundle/index.js +357 -223
  4. package/bundle/index.js.map +1 -1
  5. package/dist/button.d.ts +1 -1
  6. package/dist/button.d.ts.map +1 -1
  7. package/dist/checkbox.d.ts.map +1 -1
  8. package/dist/checkbox.js.map +1 -1
  9. package/dist/crumbs.d.ts +1 -1
  10. package/dist/crumbs.d.ts.map +1 -1
  11. package/dist/crumbs.js +1 -1
  12. package/dist/crumbs.js.map +1 -1
  13. package/dist/data-display.js.map +1 -1
  14. package/dist/incr-search.d.ts +1 -1
  15. package/dist/{index-BMjri2-S.d.ts → index-9fGVAg1d.d.ts} +2 -2
  16. package/dist/{index-BMjri2-S.d.ts.map → index-9fGVAg1d.d.ts.map} +1 -1
  17. package/dist/index-CowKi2mo.d.ts.map +1 -1
  18. package/dist/{index-CWpNcQKE.d.ts → index-_RTQSKHi.d.ts} +2 -2
  19. package/dist/{index-CWpNcQKE.d.ts.map → index-_RTQSKHi.d.ts.map} +1 -1
  20. package/dist/index.d.ts +10 -12
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +4 -4
  23. package/dist/index.js.map +1 -1
  24. package/dist/menu.d.ts +1 -1
  25. package/dist/miller.d.ts +1 -1
  26. package/dist/panel.d.ts.map +1 -1
  27. package/dist/panel.js.map +1 -1
  28. package/dist/plots.d.ts +1 -1
  29. package/dist/plots.js +1 -1
  30. package/dist/split-layout.js.map +1 -1
  31. package/dist/swipe.d.ts.map +1 -1
  32. package/dist/swipe.js.map +1 -1
  33. package/dist/timeline-2OFtN4Ta.js.map +1 -1
  34. package/dist/{tree-CJWpMUvD.js → tree-D84RUgFC.js} +2 -2
  35. package/dist/tree-D84RUgFC.js.map +1 -0
  36. package/dist/{tree-component-BcO26Xvt.d.ts → tree-component-BaCSPWg1.d.ts} +1 -6
  37. package/dist/tree-component-BaCSPWg1.d.ts.map +1 -0
  38. package/dist/tree.d.ts +1 -1
  39. package/dist/tree.d.ts.map +1 -1
  40. package/dist/tree.js +1 -1
  41. package/dist/{xy-axis-McdUpcYr.d.ts → xy-axis-CEI7ojks.d.ts} +173 -70
  42. package/dist/xy-axis-CEI7ojks.d.ts.map +1 -0
  43. package/dist/{xy-axis-CK64haaK.js → xy-axis-DbPezP6A.js} +188 -54
  44. package/dist/xy-axis-DbPezP6A.js.map +1 -0
  45. package/dist/xy-pad.d.ts.map +1 -1
  46. package/dist/xy-pad.js.map +1 -1
  47. package/package.json +2 -2
  48. package/dist/tree-CJWpMUvD.js.map +0 -1
  49. package/dist/tree-component-BcO26Xvt.d.ts.map +0 -1
  50. package/dist/xy-axis-CK64haaK.js.map +0 -1
  51. package/dist/xy-axis-McdUpcYr.d.ts.map +0 -1
package/bundle/index.js CHANGED
@@ -1896,6 +1896,174 @@ __decorate$1([r$1()], AcTextElement.prototype, "_isOpen", void 0);
1896
1896
  __decorate$1([r$1()], AcTextElement.prototype, "_isLoading", void 0);
1897
1897
  AcTextElement = __decorate$1([safeCustomElement(`ixfx-ac-text`)], AcTextElement);
1898
1898
  //#endregion
1899
+ //#region src/common/data-controller.ts
1900
+ function isAsyncIterable$1(v) {
1901
+ return typeof v === `object` && v !== null && Symbol.asyncIterator in v;
1902
+ }
1903
+ /**
1904
+ * Lit ReactiveController that manages one active data provider request at a time.
1905
+ *
1906
+ * Handles all three provider return modes (sync, async one-shot, streaming),
1907
+ * tracks progress, and cancels in-flight requests when a new one starts.
1908
+ * Calls host.requestUpdate() on every state change so the component re-renders
1909
+ * automatically.
1910
+ *
1911
+ * @typeParam TQuery - The query/scope type passed to the provider.
1912
+ * @typeParam TItem - The item type produced by the provider.
1913
+ *
1914
+ * @example
1915
+ * ```ts
1916
+ * class MyList extends LitElement {
1917
+ * #data = new DataController<string, MyItem>(this, myProvider);
1918
+ *
1919
+ * protected override render() {
1920
+ * return html`
1921
+ * ${this.#data.loading ? html`<span>Loading…</span>` : nothing}
1922
+ * ${this.#data.items.map(item => html`<div>${item.label}</div>`)}
1923
+ * `;
1924
+ * }
1925
+ * }
1926
+ * ```
1927
+ */
1928
+ var DataController = class {
1929
+ #host;
1930
+ #opts;
1931
+ #provider;
1932
+ #abort;
1933
+ #items = [];
1934
+ #loading = false;
1935
+ #loaded = 0;
1936
+ #total;
1937
+ #error;
1938
+ constructor(host, provider, options) {
1939
+ this.#host = host;
1940
+ this.#provider = provider;
1941
+ this.#opts = {
1942
+ clearOnRequest: options?.clearOnRequest ?? true,
1943
+ onError: options?.onError
1944
+ };
1945
+ host.addController(this);
1946
+ }
1947
+ hostConnected() {}
1948
+ hostDisconnected() {
1949
+ this.cancel();
1950
+ }
1951
+ get provider() {
1952
+ return this.#provider;
1953
+ }
1954
+ set provider(value) {
1955
+ this.#provider = value;
1956
+ }
1957
+ /** The currently accumulated items. */
1958
+ get items() {
1959
+ return this.#items;
1960
+ }
1961
+ /** True while a provider call is pending or a stream is still open. */
1962
+ get loading() {
1963
+ return this.#loading;
1964
+ }
1965
+ /** Number of items accumulated so far in the current request. */
1966
+ get loaded() {
1967
+ return this.#loaded;
1968
+ }
1969
+ /**
1970
+ * Provider's latest estimate of the total number of items expected.
1971
+ * Undefined when the provider has not reported a total.
1972
+ */
1973
+ get total() {
1974
+ return this.#total;
1975
+ }
1976
+ /**
1977
+ * Progress as a 0–1 value, or undefined when total is unknown.
1978
+ * Derived from loaded / total.
1979
+ */
1980
+ get progress() {
1981
+ if (this.#total === void 0 || this.#total === 0) return void 0;
1982
+ return Math.min(this.#loaded / this.#total, 1);
1983
+ }
1984
+ /** The last error thrown by the provider, or undefined if the last request succeeded. */
1985
+ get error() {
1986
+ return this.#error;
1987
+ }
1988
+ /**
1989
+ * Cancel any in-flight request and start a new one.
1990
+ * Clears items immediately unless clearOnRequest was set to false.
1991
+ */
1992
+ request(query) {
1993
+ this.cancel();
1994
+ if (!this.#provider) return;
1995
+ if (this.#opts.clearOnRequest) {
1996
+ this.#items = [];
1997
+ this.#loaded = 0;
1998
+ }
1999
+ this.#total = void 0;
2000
+ this.#error = void 0;
2001
+ this.#loading = true;
2002
+ this.#host.requestUpdate();
2003
+ this.#abort = new AbortController();
2004
+ const { signal } = this.#abort;
2005
+ this.#consume(this.#provider(query, signal), signal);
2006
+ }
2007
+ /** Abort any in-flight request without issuing a new one. */
2008
+ cancel() {
2009
+ this.#abort?.abort();
2010
+ this.#abort = void 0;
2011
+ if (this.#loading) {
2012
+ this.#loading = false;
2013
+ this.#host.requestUpdate();
2014
+ }
2015
+ }
2016
+ #consume(result, signal) {
2017
+ if (Array.isArray(result)) {
2018
+ this.#applyBatch({ items: result }, signal);
2019
+ this.#loading = false;
2020
+ this.#host.requestUpdate();
2021
+ } else if (isAsyncIterable$1(result)) this.#consumeStream(result, signal);
2022
+ else result.then((items) => {
2023
+ if (signal.aborted) return;
2024
+ this.#applyBatch({ items }, signal);
2025
+ this.#loading = false;
2026
+ this.#host.requestUpdate();
2027
+ }, (err) => {
2028
+ if (signal.aborted) return;
2029
+ this.#handleError(err);
2030
+ });
2031
+ }
2032
+ async #consumeStream(stream, signal) {
2033
+ try {
2034
+ for await (const batch of stream) {
2035
+ if (signal.aborted) return;
2036
+ this.#applyBatch(batch, signal);
2037
+ this.#host.requestUpdate();
2038
+ }
2039
+ } catch (err) {
2040
+ if (signal.aborted) return;
2041
+ this.#handleError(err);
2042
+ return;
2043
+ }
2044
+ if (!signal.aborted) {
2045
+ this.#loading = false;
2046
+ this.#host.requestUpdate();
2047
+ }
2048
+ }
2049
+ #applyBatch(batch, _signal) {
2050
+ if (batch.replace) {
2051
+ this.#items = [...batch.items];
2052
+ this.#loaded = batch.items.length;
2053
+ } else {
2054
+ this.#items = [...this.#items, ...batch.items];
2055
+ this.#loaded = this.#items.length;
2056
+ }
2057
+ if (batch.total !== void 0) this.#total = batch.total;
2058
+ }
2059
+ #handleError(err) {
2060
+ this.#error = err;
2061
+ this.#loading = false;
2062
+ this.#opts.onError?.(err);
2063
+ this.#host.requestUpdate();
2064
+ }
2065
+ };
2066
+ //#endregion
1899
2067
  //#region src/incr-search/fuzzy.ts
1900
2068
  function defaultSelector(item) {
1901
2069
  if (typeof item === `string`) return item;
@@ -2204,174 +2372,6 @@ function createElementIncrSearch(opts) {
2204
2372
  };
2205
2373
  }
2206
2374
  //#endregion
2207
- //#region src/common/data-controller.ts
2208
- function isAsyncIterable$1(v) {
2209
- return typeof v === `object` && v !== null && Symbol.asyncIterator in v;
2210
- }
2211
- /**
2212
- * Lit ReactiveController that manages one active data provider request at a time.
2213
- *
2214
- * Handles all three provider return modes (sync, async one-shot, streaming),
2215
- * tracks progress, and cancels in-flight requests when a new one starts.
2216
- * Calls host.requestUpdate() on every state change so the component re-renders
2217
- * automatically.
2218
- *
2219
- * @typeParam TQuery - The query/scope type passed to the provider.
2220
- * @typeParam TItem - The item type produced by the provider.
2221
- *
2222
- * @example
2223
- * ```ts
2224
- * class MyList extends LitElement {
2225
- * #data = new DataController<string, MyItem>(this, myProvider);
2226
- *
2227
- * protected override render() {
2228
- * return html`
2229
- * ${this.#data.loading ? html`<span>Loading…</span>` : nothing}
2230
- * ${this.#data.items.map(item => html`<div>${item.label}</div>`)}
2231
- * `;
2232
- * }
2233
- * }
2234
- * ```
2235
- */
2236
- var DataController = class {
2237
- #host;
2238
- #opts;
2239
- #provider;
2240
- #abort;
2241
- #items = [];
2242
- #loading = false;
2243
- #loaded = 0;
2244
- #total;
2245
- #error;
2246
- constructor(host, provider, options) {
2247
- this.#host = host;
2248
- this.#provider = provider;
2249
- this.#opts = {
2250
- clearOnRequest: options?.clearOnRequest ?? true,
2251
- onError: options?.onError
2252
- };
2253
- host.addController(this);
2254
- }
2255
- hostConnected() {}
2256
- hostDisconnected() {
2257
- this.cancel();
2258
- }
2259
- get provider() {
2260
- return this.#provider;
2261
- }
2262
- set provider(value) {
2263
- this.#provider = value;
2264
- }
2265
- /** The currently accumulated items. */
2266
- get items() {
2267
- return this.#items;
2268
- }
2269
- /** True while a provider call is pending or a stream is still open. */
2270
- get loading() {
2271
- return this.#loading;
2272
- }
2273
- /** Number of items accumulated so far in the current request. */
2274
- get loaded() {
2275
- return this.#loaded;
2276
- }
2277
- /**
2278
- * Provider's latest estimate of the total number of items expected.
2279
- * Undefined when the provider has not reported a total.
2280
- */
2281
- get total() {
2282
- return this.#total;
2283
- }
2284
- /**
2285
- * Progress as a 0–1 value, or undefined when total is unknown.
2286
- * Derived from loaded / total.
2287
- */
2288
- get progress() {
2289
- if (this.#total === void 0 || this.#total === 0) return void 0;
2290
- return Math.min(this.#loaded / this.#total, 1);
2291
- }
2292
- /** The last error thrown by the provider, or undefined if the last request succeeded. */
2293
- get error() {
2294
- return this.#error;
2295
- }
2296
- /**
2297
- * Cancel any in-flight request and start a new one.
2298
- * Clears items immediately unless clearOnRequest was set to false.
2299
- */
2300
- request(query) {
2301
- this.cancel();
2302
- if (!this.#provider) return;
2303
- if (this.#opts.clearOnRequest) {
2304
- this.#items = [];
2305
- this.#loaded = 0;
2306
- }
2307
- this.#total = void 0;
2308
- this.#error = void 0;
2309
- this.#loading = true;
2310
- this.#host.requestUpdate();
2311
- this.#abort = new AbortController();
2312
- const { signal } = this.#abort;
2313
- this.#consume(this.#provider(query, signal), signal);
2314
- }
2315
- /** Abort any in-flight request without issuing a new one. */
2316
- cancel() {
2317
- this.#abort?.abort();
2318
- this.#abort = void 0;
2319
- if (this.#loading) {
2320
- this.#loading = false;
2321
- this.#host.requestUpdate();
2322
- }
2323
- }
2324
- #consume(result, signal) {
2325
- if (Array.isArray(result)) {
2326
- this.#applyBatch({ items: result }, signal);
2327
- this.#loading = false;
2328
- this.#host.requestUpdate();
2329
- } else if (isAsyncIterable$1(result)) this.#consumeStream(result, signal);
2330
- else result.then((items) => {
2331
- if (signal.aborted) return;
2332
- this.#applyBatch({ items }, signal);
2333
- this.#loading = false;
2334
- this.#host.requestUpdate();
2335
- }, (err) => {
2336
- if (signal.aborted) return;
2337
- this.#handleError(err);
2338
- });
2339
- }
2340
- async #consumeStream(stream, signal) {
2341
- try {
2342
- for await (const batch of stream) {
2343
- if (signal.aborted) return;
2344
- this.#applyBatch(batch, signal);
2345
- this.#host.requestUpdate();
2346
- }
2347
- } catch (err) {
2348
- if (signal.aborted) return;
2349
- this.#handleError(err);
2350
- return;
2351
- }
2352
- if (!signal.aborted) {
2353
- this.#loading = false;
2354
- this.#host.requestUpdate();
2355
- }
2356
- }
2357
- #applyBatch(batch, _signal) {
2358
- if (batch.replace) {
2359
- this.#items = [...batch.items];
2360
- this.#loaded = batch.items.length;
2361
- } else {
2362
- this.#items = [...this.#items, ...batch.items];
2363
- this.#loaded = this.#items.length;
2364
- }
2365
- if (batch.total !== void 0) this.#total = batch.total;
2366
- }
2367
- #handleError(err) {
2368
- this.#error = err;
2369
- this.#loading = false;
2370
- this.#opts.onError?.(err);
2371
- this.#host.requestUpdate();
2372
- }
2373
- };
2374
- //#endregion
2375
2375
  //#region src/ac-token/ac-token.ts
2376
2376
  const DEFAULT_TOKENIZER = (text) => text.split(/[\s,;]+/);
2377
2377
  function makeLruCache(maxSize) {
@@ -2708,7 +2708,7 @@ let AcTokenElement = class AcTokenElement extends i$4 {
2708
2708
  const hit = this.#cache.get(query);
2709
2709
  if (hit !== void 0) return this.#filterUsed(hit);
2710
2710
  const result = raw(query, signal);
2711
- if (Symbol.asyncIterator in Object(result)) return result;
2711
+ if (Symbol.asyncIterator in new Object(result)) return result;
2712
2712
  if (Array.isArray(result)) {
2713
2713
  this.#cache.set(query, result);
2714
2714
  return this.#filterUsed(result);
@@ -20769,7 +20769,7 @@ let CrumbNavigationElement = class CrumbNavigationElement extends i$4 {
20769
20769
  composed: true
20770
20770
  }));
20771
20771
  this.requestUpdate();
20772
- } catch (err) {
20772
+ } catch {
20773
20773
  if (controller.signal.aborted) return;
20774
20774
  node.children = [];
20775
20775
  this.#pendingNode = void 0;
@@ -23707,7 +23707,7 @@ let GroupedItemListerElement = class GroupedItemListerElement extends i$4 {
23707
23707
  this.#subComponents.delete(key);
23708
23708
  }
23709
23709
  for (const [key, items] of groups) {
23710
- const panel = [...this.children].find((el) => el instanceof HTMLElement && el.dataset[`groupKey`] === key);
23710
+ const panel = [...this.children].find((el) => el instanceof HTMLElement && el.dataset.groupKey === key);
23711
23711
  if (!panel) continue;
23712
23712
  let subEl = this.#subComponents.get(key);
23713
23713
  if (!subEl) {
@@ -24297,7 +24297,7 @@ let TreeBaseElement = class TreeBaseElement extends i$4 {
24297
24297
  composed: true
24298
24298
  }));
24299
24299
  this.requestUpdate();
24300
- } catch (err) {
24300
+ } catch {
24301
24301
  if (controller.signal.aborted) return;
24302
24302
  node.children = [];
24303
24303
  this.#pendingNode = void 0;
@@ -30790,9 +30790,20 @@ function applyAgeModification(base, ageFraction, ageStyle) {
30790
30790
  }
30791
30791
  //#endregion
30792
30792
  //#region src/plots/data.ts
30793
+ /**
30794
+ * A data series
30795
+ */
30793
30796
  var PlotDataSeries = class {
30794
30797
  #rangeStream;
30795
30798
  #options;
30799
+ /**
30800
+ * Constructor.
30801
+ *
30802
+ * Default options:
30803
+ * - `capacityLimit`: 100
30804
+ * - `persistentScaling`: true
30805
+ * @param options
30806
+ */
30796
30807
  constructor(options = {}) {
30797
30808
  this.values = [];
30798
30809
  this.#rangeStream = rangeStream();
@@ -30806,11 +30817,20 @@ var PlotDataSeries = class {
30806
30817
  ...options
30807
30818
  };
30808
30819
  }
30809
- add(value) {
30810
- this.values.push(value);
30811
- this.range = this.#rangeStream.seen(value);
30820
+ /**
30821
+ * Adds a single value
30822
+ * @param valueOrValues Value to add
30823
+ */
30824
+ add(valueOrValues) {
30825
+ if (typeof valueOrValues === `number`) {
30826
+ this.values.push(valueOrValues);
30827
+ this.range = this.#rangeStream.seen(valueOrValues);
30828
+ } else {
30829
+ this.values.push(...valueOrValues);
30830
+ for (const v of valueOrValues) this.range = this.#rangeStream.seen(v);
30831
+ }
30812
30832
  if (this.values.length > this.#options.capacityLimit) {
30813
- this.values.shift();
30833
+ this.values = this.values.slice(this.values.length - this.#options.capacityLimit);
30814
30834
  if (!this.#options.persistentScaling) this.#recompute();
30815
30835
  }
30816
30836
  }
@@ -30818,14 +30838,24 @@ var PlotDataSeries = class {
30818
30838
  if (!this.#options.persistentScaling) this.#rangeStream = rangeStream();
30819
30839
  for (let i = 0; i < this.values.length; i++) this.range = this.#rangeStream.seen(this.values[i]);
30820
30840
  }
30841
+ /**
30842
+ * Sets the entire data series at once, replacing any existing data. If the number of values exceeds the `capacityLimit`, only the most recent values up to the limit are kept.
30843
+ * @param values
30844
+ */
30821
30845
  set(values) {
30822
30846
  if (values.length > this.#options.capacityLimit) values = values.slice(values.length - this.#options.capacityLimit);
30823
30847
  this.values = values;
30824
30848
  this.#recompute();
30825
30849
  }
30850
+ /**
30851
+ * Clear all data and reset range. If `persistentScaling` is _false_, also resets scaling to initial state.
30852
+ * @returns _true_ if there was data to clear
30853
+ */
30826
30854
  clear() {
30855
+ const empty = this.values.length === 0;
30827
30856
  this.values = [];
30828
30857
  if (!this.#options.persistentScaling) this.#recompute();
30858
+ return !empty;
30829
30859
  }
30830
30860
  };
30831
30861
  //#endregion
@@ -30923,44 +30953,104 @@ let PlotMultiAxis = class PlotMultiAxis extends i$4 {
30923
30953
  #seriesOrder;
30924
30954
  #seriesSet;
30925
30955
  #pendingStyles;
30926
- addData(nameOrData, value) {
30927
- if (typeof nameOrData === `object` && nameOrData !== null) {
30928
- const entries = Object.entries(nameOrData);
30929
- for (const [name, val] of entries) this.#addToSeries(name, val);
30930
- } else this.#addToSeries(nameOrData, value);
30931
- this.requestUpdate();
30956
+ /**
30957
+ * Adds a single data point
30958
+ * @param name Series name
30959
+ * @param value Value
30960
+ * @param witholdRedraw If _false_ (default) plot is automatically redrawn
30961
+ */
30962
+ addData(name, value, witholdRedraw = false) {
30963
+ return this.#addToSeries(name, value, witholdRedraw);
30964
+ }
30965
+ setData(name, values, witholdRedraw = false) {
30966
+ const [el, created] = this.#ensurePlot(name);
30967
+ if (!this.#seriesSet.has(name)) {
30968
+ this.#seriesSet.add(name);
30969
+ this.#seriesOrder.push(name);
30970
+ }
30971
+ el.set(values, witholdRedraw);
30972
+ if (created) this.requestUpdate();
30973
+ return el;
30974
+ }
30975
+ setObjects(data, witholdRedraw = false) {
30976
+ const entries = Object.entries(data);
30977
+ for (const [name, vals] of entries) this.setData(name, vals, true);
30978
+ if (witholdRedraw) return;
30979
+ this.redraw();
30932
30980
  }
30981
+ /**
30982
+ * Calls redraw() on all subplots.
30983
+ */
30984
+ redraw() {
30985
+ for (const el of this.#instances.values()) el.redraw();
30986
+ }
30987
+ /**
30988
+ * Adds a record of data points to the plot. Each key in the record corresponds to a series name, and its value is added as a data point to that series. If a series does not exist for a given key, it will be created.
30989
+ * @param data Data to add
30990
+ * @param witholdRedraw If _false_ (default) plot is automatically redrawn after adding the data. If _true_, plot is not redrawn automatically, and you need to call `redraw()` manually to update the plot after adding the data.
30991
+ */
30992
+ addObject(data, witholdRedraw = false) {
30993
+ const entries = Object.entries(data);
30994
+ for (const [name, val] of entries) this.#addToSeries(name, val, true);
30995
+ if (witholdRedraw) return;
30996
+ this.redraw();
30997
+ }
30998
+ /**
30999
+ * Styles a series by setting CSS variables on the subplot.
31000
+ * @param name Name of series
31001
+ * @param styles Styles to apply
31002
+ */
30933
31003
  styleSeries(name, styles) {
30934
- const normalized = {};
30935
- for (const [key, val] of Object.entries(styles)) normalized[key.startsWith(`--`) ? key : `--${key}`] = val;
31004
+ const normalised = {};
31005
+ for (const [key, val] of Object.entries(styles)) normalised[key.startsWith(`--`) ? key : `--${key}`] = val;
30936
31006
  const el = this.#instances.get(name);
30937
31007
  if (!el) {
30938
- this.#pendingStyles.set(name, normalized);
31008
+ this.#pendingStyles.set(name, normalised);
30939
31009
  return;
30940
31010
  }
30941
- for (const [key, val] of Object.entries(normalized)) el.style.setProperty(key, val);
31011
+ for (const [key, val] of Object.entries(normalised)) el.style.setProperty(key, val);
30942
31012
  }
31013
+ /**
31014
+ * Clears data from all sub-plots
31015
+ * @returns _True_ if there was data to clear
31016
+ */
30943
31017
  clear() {
30944
- for (const el of this.#instances.values()) el.clear();
31018
+ let cleared = false;
31019
+ for (const el of this.#instances.values()) cleared = cleared || el.clear();
31020
+ return cleared;
30945
31021
  }
31022
+ /**
31023
+ * Clears data from a given series
31024
+ * @param name Series name
31025
+ * @returns _True_ if series was found and had data
31026
+ */
30946
31027
  clearSeries(name) {
30947
31028
  const el = this.#instances.get(name);
30948
- if (el) el.clear();
31029
+ if (el) {
31030
+ el.clear();
31031
+ return true;
31032
+ }
31033
+ return false;
30949
31034
  }
31035
+ /**
31036
+ * Returns a copy of the series names
31037
+ */
30950
31038
  get series() {
30951
31039
  return [...this.#seriesOrder];
30952
31040
  }
30953
- #addToSeries(name, value) {
30954
- const el = this.#ensurePlot(name);
31041
+ #addToSeries(name, valueOrValues, withholdRedraw = false) {
31042
+ const [el, created] = this.#ensurePlot(name);
30955
31043
  if (!this.#seriesSet.has(name)) {
30956
31044
  this.#seriesSet.add(name);
30957
31045
  this.#seriesOrder.push(name);
30958
31046
  }
30959
- el.add(value);
31047
+ el.add(valueOrValues, withholdRedraw);
31048
+ if (created) this.requestUpdate();
31049
+ return el;
30960
31050
  }
30961
31051
  #ensurePlot(name) {
30962
31052
  let el = this.#instances.get(name);
30963
- if (el) return el;
31053
+ if (el) return [el, false];
30964
31054
  el = document.createElement(`ixfx-plot-single-axis`);
30965
31055
  el.tooltips = false;
30966
31056
  this.#instances.set(name, el);
@@ -30989,7 +31079,7 @@ let PlotMultiAxis = class PlotMultiAxis extends i$4 {
30989
31079
  el.addEventListener(`plot-pointer-leave`, () => {
30990
31080
  this.#onSubPlotPointerLeave();
30991
31081
  });
30992
- return el;
31082
+ return [el, true];
30993
31083
  }
30994
31084
  #onSubPlotPointerMove(clientX, clientY, index) {
30995
31085
  if (index < 0) {
@@ -31024,7 +31114,7 @@ let PlotMultiAxis = class PlotMultiAxis extends i$4 {
31024
31114
  part="container"
31025
31115
  style=${gridStyle}
31026
31116
  >
31027
- ${c(this.#seriesOrder, (name) => name, (name) => this.#ensurePlot(name))}
31117
+ ${c(this.#seriesOrder, (name) => name, (name) => this.#ensurePlot(name)[0])}
31028
31118
  </div>
31029
31119
  `;
31030
31120
  }
@@ -31090,10 +31180,10 @@ PlotMultiAxis = __decorate$1([safeCustomElement(`ixfx-plot-multi-axis`)], PlotMu
31090
31180
  let PlotHistogram = class PlotHistogram extends i$4 {
31091
31181
  constructor(..._args) {
31092
31182
  super(..._args);
31093
- this.orientation = "horizontal";
31183
+ this.orientation = `horizontal`;
31094
31184
  this.resolution = .1;
31095
31185
  this.capacity = 100;
31096
- this.title = "";
31186
+ this.title = ``;
31097
31187
  this.paused = false;
31098
31188
  this._width = 100;
31099
31189
  this._height = 40;
@@ -31107,7 +31197,7 @@ let PlotHistogram = class PlotHistogram extends i$4 {
31107
31197
  #hasProgrammaticData;
31108
31198
  #parseDeclarativeData(text) {
31109
31199
  if (!text) return [];
31110
- return text.trim().split(/[,\s;]+/).map((t) => Number.parseFloat(t)).filter((n) => !isNaN(n));
31200
+ return text.trim().split(/[,\s;]+/).map((t) => Number.parseFloat(t)).filter((n) => !Number.isNaN(n));
31111
31201
  }
31112
31202
  add(v) {
31113
31203
  this.#hasProgrammaticData = true;
@@ -31134,12 +31224,12 @@ let PlotHistogram = class PlotHistogram extends i$4 {
31134
31224
  this._height = e.contentRect.height;
31135
31225
  }).observe(this);
31136
31226
  if (!this.#hasProgrammaticData) {
31137
- const data = this.#parseDeclarativeData(this.textContent ?? "");
31227
+ const data = this.#parseDeclarativeData(this.textContent ?? ``);
31138
31228
  if (data.length > 0) this.#series.set(data);
31139
31229
  }
31140
31230
  }
31141
31231
  updated(changed) {
31142
- if (changed.has("capacity")) {
31232
+ if (changed.has(`capacity`)) {
31143
31233
  const old = [...this.#series.values];
31144
31234
  this.#series = new PlotDataSeries({
31145
31235
  capacityLimit: this.capacity,
@@ -31152,19 +31242,19 @@ let PlotHistogram = class PlotHistogram extends i$4 {
31152
31242
  return getComputedStyle(this).getPropertyValue(name).trim();
31153
31243
  }
31154
31244
  #getGapPx() {
31155
- const val = this.#readCssVar("--plot-histogram-gap");
31156
- if (val === "") return 1;
31157
- const parsed = parseFloat(val);
31158
- return isFinite(parsed) ? Math.max(0, parsed) : 1;
31245
+ const val = this.#readCssVar(`--plot-histogram-gap`);
31246
+ if (val === ``) return 1;
31247
+ const parsed = Number.parseFloat(val);
31248
+ return Number.isFinite(parsed) ? Math.max(0, parsed) : 1;
31159
31249
  }
31160
31250
  #getBarLengthOverride() {
31161
- const val = this.#readCssVar("--plot-histogram-bar-length");
31162
- if (val === "" || val === "auto") return null;
31163
- const parsed = parseFloat(val);
31164
- return isFinite(parsed) ? Math.max(0, Math.min(1, parsed)) : null;
31251
+ const val = this.#readCssVar(`--plot-histogram-bar-length`);
31252
+ if (val === `` || val === `auto`) return null;
31253
+ const parsed = Number.parseFloat(val);
31254
+ return Number.isFinite(parsed) ? Math.max(0, Math.min(1, parsed)) : null;
31165
31255
  }
31166
31256
  #emitClick(i, valueMin, valueMax, relativeValue) {
31167
- this.dispatchEvent(new CustomEvent("plot-bucket-click", {
31257
+ this.dispatchEvent(new CustomEvent(`plot-bucket-click`, {
31168
31258
  detail: {
31169
31259
  bucketIndex: i,
31170
31260
  valueMin,
@@ -31179,7 +31269,7 @@ let PlotHistogram = class PlotHistogram extends i$4 {
31179
31269
  const { values, range } = this.#series;
31180
31270
  const w$7 = this._width;
31181
31271
  const h = this._height;
31182
- const isHorizontal = this.orientation === "horizontal";
31272
+ const isHorizontal = this.orientation === `horizontal`;
31183
31273
  const padding = Math.min(4, (isHorizontal ? h : w$7) * .05);
31184
31274
  const dataMin = this.min ?? range.min;
31185
31275
  const dataSpan = (this.max ?? range.max) - dataMin || 1;
@@ -31189,7 +31279,7 @@ let PlotHistogram = class PlotHistogram extends i$4 {
31189
31279
  const bucketSize = availableMain / bucketCount;
31190
31280
  const gap = this.#getGapPx();
31191
31281
  const barLengthOverride = this.#getBarLengthOverride();
31192
- const buckets = new Array(bucketCount).fill(0);
31282
+ const buckets = Array.from({ length: bucketCount }).fill(0);
31193
31283
  for (const v of values) {
31194
31284
  const normalized = (v - dataMin) / dataSpan;
31195
31285
  const index = Math.min(bucketCount - 1, Math.max(0, Math.floor(normalized * bucketCount)));
@@ -31223,7 +31313,7 @@ let PlotHistogram = class PlotHistogram extends i$4 {
31223
31313
  }
31224
31314
  })}
31225
31315
  ${this.title ? w`<text x=${padding + 2} y=${padding + Math.min(10, h * .6)}
31226
- class="overlay-text" fill=${"var(--plot-text, var(--surface-2-text, #fff))"}
31316
+ class="overlay-text" fill=${`var(--plot-text, var(--surface-2-text, #fff))`}
31227
31317
  style="opacity: 0.6">${this.title}</text>` : w``}
31228
31318
  </svg>
31229
31319
  `;
@@ -31264,7 +31354,7 @@ let PlotHistogram = class PlotHistogram extends i$4 {
31264
31354
  `;
31265
31355
  }
31266
31356
  };
31267
- __decorate$1([n$2({ attribute: "orientation" })], PlotHistogram.prototype, "orientation", void 0);
31357
+ __decorate$1([n$2({ attribute: `orientation` })], PlotHistogram.prototype, "orientation", void 0);
31268
31358
  __decorate$1([n$2({ type: Number })], PlotHistogram.prototype, "resolution", void 0);
31269
31359
  __decorate$1([n$2({ type: Number })], PlotHistogram.prototype, "min", void 0);
31270
31360
  __decorate$1([n$2({ type: Number })], PlotHistogram.prototype, "max", void 0);
@@ -31276,7 +31366,7 @@ __decorate$1([n$2({
31276
31366
  })], PlotHistogram.prototype, "paused", void 0);
31277
31367
  __decorate$1([r$1()], PlotHistogram.prototype, "_width", void 0);
31278
31368
  __decorate$1([r$1()], PlotHistogram.prototype, "_height", void 0);
31279
- PlotHistogram = __decorate$1([safeCustomElement("ixfx-plot-histogram")], PlotHistogram);
31369
+ PlotHistogram = __decorate$1([safeCustomElement(`ixfx-plot-histogram`)], PlotHistogram);
31280
31370
  //#endregion
31281
31371
  //#region src/plots/single-axis.ts
31282
31372
  function buildLinePath(points) {
@@ -31391,9 +31481,9 @@ let PlotSingleAxis = class PlotSingleAxis extends i$4 {
31391
31481
  persistentScaling: true
31392
31482
  });
31393
31483
  this.#hasProgrammaticData = false;
31394
- this.valueFormat = (v) => v ? v.toFixed(2) : ``;
31395
31484
  this.#lastClientX = null;
31396
31485
  this.#lastClientY = null;
31486
+ this.valueFormat = (v) => v ? v.toFixed(2) : ``;
31397
31487
  this.#onPointerMove = (e) => {
31398
31488
  this.#lastClientX = e.clientX;
31399
31489
  this.#lastClientY = e.clientY;
@@ -31434,41 +31524,85 @@ let PlotSingleAxis = class PlotSingleAxis extends i$4 {
31434
31524
  }
31435
31525
  #series;
31436
31526
  #hasProgrammaticData;
31527
+ #lastClientX;
31528
+ #lastClientY;
31437
31529
  #parseDeclarativeData(text) {
31438
31530
  if (!text) return [];
31439
- return text.trim().split(/[,\s;]+/).map((t) => Number.parseFloat(t)).filter((n) => !isNaN(n));
31531
+ return text.trim().split(/[,\s;]+/).map((t) => Number.parseFloat(t)).filter((n) => !Number.isNaN(n));
31440
31532
  }
31533
+ /**
31534
+ * Get all values in the data series as a readonly array.
31535
+ */
31441
31536
  get values() {
31442
31537
  return this.#series.values;
31443
31538
  }
31539
+ /**
31540
+ * Get length of data series
31541
+ */
31444
31542
  get dataCount() {
31445
31543
  return this.#series.values.length;
31446
31544
  }
31545
+ /**
31546
+ * Get value at specific index of data series
31547
+ * @param index
31548
+ */
31447
31549
  getValueAt(index) {
31448
31550
  return this.#series.values[index];
31449
31551
  }
31552
+ /**
31553
+ * Get value index based on client X position
31554
+ * @param clientX
31555
+ */
31450
31556
  getIndexFromClientX(clientX) {
31451
31557
  return this.#getIndexFromX(clientX, this.getBoundingClientRect());
31452
31558
  }
31453
- #lastClientX;
31454
- #lastClientY;
31455
- add(v) {
31559
+ /**
31560
+ * Adds a value to the data series.
31561
+ *
31562
+ * Pass `withholdRedraw = true` to prevent automatic redraw after adding the value. In this case, call `redraw()` manually after adding all values to update the plot.
31563
+ *
31564
+ * Use {@link set} to replace the entire data series at once.
31565
+ * @param valueOrValues Single value, or several values
31566
+ * @param withholdRedraw If _false_ (default) plot is automatically redrawn
31567
+ */
31568
+ add(valueOrValues, withholdRedraw = false) {
31456
31569
  this.#hasProgrammaticData = true;
31457
- this.#series.add(v);
31570
+ this.#series.add(valueOrValues);
31458
31571
  if (this.paused) return;
31572
+ if (withholdRedraw) return;
31573
+ this.redraw();
31574
+ }
31575
+ /**
31576
+ * Redraws the plot.
31577
+ * Normally not needed, unless add() is called with withholdRedraw = true, or styleSeries() is used to update series styles.
31578
+ */
31579
+ redraw() {
31459
31580
  this.requestUpdate();
31460
31581
  this.#updateTooltipAtLastPos();
31461
31582
  }
31462
- set(values) {
31583
+ /**
31584
+ * Sets the entire data for a series at once, replacing contents.
31585
+ *
31586
+ * Use add() to add values one by one.
31587
+ *
31588
+ * Pass `withholdRedraw = true` to prevent automatic redraw after setting the values. In this case, call `redraw()` manually after setting the values to update the plot.
31589
+ * @param values Values
31590
+ * @param withholdRedraw If _false_ (default) plot is automatically redrawn
31591
+ */
31592
+ set(values, withholdRedraw = false) {
31463
31593
  this.#hasProgrammaticData = true;
31464
31594
  this.#series.set(values);
31465
31595
  if (this.paused) return;
31466
- this.requestUpdate();
31467
- this.#updateTooltipAtLastPos();
31596
+ if (withholdRedraw) return;
31597
+ this.redraw();
31468
31598
  }
31599
+ /**
31600
+ * Clears all data and redraws
31601
+ */
31469
31602
  clear() {
31470
- this.#series.clear();
31603
+ const result = this.#series.clear();
31471
31604
  this.requestUpdate();
31605
+ return result;
31472
31606
  }
31473
31607
  firstUpdated(_changed) {
31474
31608
  this._width = this.clientWidth || 100;