@ixfx/components 0.4.1 → 0.4.3

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 (61) hide show
  1. package/bundle/index.d.ts +238 -119
  2. package/bundle/index.d.ts.map +1 -1
  3. package/bundle/index.js +423 -245
  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/{icon-epZd-JIO.d.ts → icon-Bd5BiU4b.d.ts} +2 -2
  15. package/dist/{icon-epZd-JIO.d.ts.map → icon-Bd5BiU4b.d.ts.map} +1 -1
  16. package/dist/icons.d.ts +1 -1
  17. package/dist/incr-search.d.ts +1 -1
  18. package/dist/{index-BMjri2-S.d.ts → index-9fGVAg1d.d.ts} +2 -2
  19. package/dist/{index-BMjri2-S.d.ts.map → index-9fGVAg1d.d.ts.map} +1 -1
  20. package/dist/index-CowKi2mo.d.ts.map +1 -1
  21. package/dist/{index-CWpNcQKE.d.ts → index-_RTQSKHi.d.ts} +2 -2
  22. package/dist/{index-CWpNcQKE.d.ts.map → index-_RTQSKHi.d.ts.map} +1 -1
  23. package/dist/{index-JuEVfmr-.d.ts → index-s_IhSnwc.d.ts} +2 -2
  24. package/dist/{index-JuEVfmr-.d.ts.map → index-s_IhSnwc.d.ts.map} +1 -1
  25. package/dist/index.d.ts +13 -15
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +4 -4
  28. package/dist/index.js.map +1 -1
  29. package/dist/{labelled-input-base-Cz6qE6Dk.d.ts → labelled-input-base-ORb1rGq6.d.ts} +2 -2
  30. package/dist/{labelled-input-base-Cz6qE6Dk.d.ts.map → labelled-input-base-ORb1rGq6.d.ts.map} +1 -1
  31. package/dist/labelled-radial-input.d.ts +2 -2
  32. package/dist/labelled-radial-input.d.ts.map +1 -1
  33. package/dist/labelled-range-input.d.ts +1 -1
  34. package/dist/menu.d.ts +1 -1
  35. package/dist/miller.d.ts +1 -1
  36. package/dist/panel.d.ts.map +1 -1
  37. package/dist/panel.js.map +1 -1
  38. package/dist/plots.d.ts +1 -1
  39. package/dist/plots.js +1 -1
  40. package/dist/split-layout.js.map +1 -1
  41. package/dist/swipe.d.ts.map +1 -1
  42. package/dist/swipe.js.map +1 -1
  43. package/dist/timeline-2OFtN4Ta.js.map +1 -1
  44. package/dist/{tree-CJWpMUvD.js → tree-D84RUgFC.js} +2 -2
  45. package/dist/tree-D84RUgFC.js.map +1 -0
  46. package/dist/{tree-component-BcO26Xvt.d.ts → tree-component-BaCSPWg1.d.ts} +1 -6
  47. package/dist/tree-component-BaCSPWg1.d.ts.map +1 -0
  48. package/dist/tree.d.ts +1 -1
  49. package/dist/tree.d.ts.map +1 -1
  50. package/dist/tree.js +1 -1
  51. package/dist/{xy-axis-McdUpcYr.d.ts → xy-axis-BeWRMmbo.d.ts} +199 -73
  52. package/dist/xy-axis-BeWRMmbo.d.ts.map +1 -0
  53. package/dist/{xy-axis-CK64haaK.js → xy-axis-no0OL_O1.js} +254 -76
  54. package/dist/xy-axis-no0OL_O1.js.map +1 -0
  55. package/dist/xy-pad.d.ts.map +1 -1
  56. package/dist/xy-pad.js.map +1 -1
  57. package/package.json +2 -2
  58. package/dist/tree-CJWpMUvD.js.map +0 -1
  59. package/dist/tree-component-BcO26Xvt.d.ts.map +0 -1
  60. package/dist/xy-axis-CK64haaK.js.map +0 -1
  61. 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,42 +30790,107 @@ 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;
30798
+ #rangeAuto;
30799
+ #rangeManual;
30795
30800
  #options;
30801
+ /**
30802
+ * Constructor.
30803
+ *
30804
+ * Default options:
30805
+ * - `capacityLimit`: 100
30806
+ * - `persistentScaling`: true
30807
+ * - `fixedRange`: null
30808
+ * @param options
30809
+ */
30796
30810
  constructor(options = {}) {
30797
30811
  this.values = [];
30798
30812
  this.#rangeStream = rangeStream();
30799
- this.range = {
30813
+ this.#rangeAuto = {
30800
30814
  min: 0,
30801
30815
  max: 0
30802
30816
  };
30817
+ this.#rangeManual = null;
30803
30818
  this.#options = {
30804
30819
  capacityLimit: 100,
30805
30820
  persistentScaling: true,
30821
+ fixedRange: null,
30806
30822
  ...options
30807
30823
  };
30824
+ if (this.#options.fixedRange !== null) this.#rangeManual = this.#options.fixedRange;
30825
+ }
30826
+ /**
30827
+ * Sets a manual range, this disabled auto-scaling.
30828
+ * Use {@link unsetRange} to re-enable auto-scaling.
30829
+ * @param min
30830
+ * @param max
30831
+ */
30832
+ setRange(min, max) {
30833
+ this.#rangeManual = {
30834
+ min,
30835
+ max
30836
+ };
30808
30837
  }
30809
- add(value) {
30810
- this.values.push(value);
30811
- this.range = this.#rangeStream.seen(value);
30838
+ /**
30839
+ * Disable the manual range
30840
+ */
30841
+ unsetRange() {
30842
+ this.#rangeManual = null;
30843
+ this.#recompute();
30844
+ }
30845
+ get isAutoRange() {
30846
+ return this.#rangeManual === null;
30847
+ }
30848
+ /**
30849
+ * Adds a single value
30850
+ * @param valueOrValues Value to add
30851
+ */
30852
+ add(valueOrValues) {
30853
+ if (typeof valueOrValues === `number`) {
30854
+ this.values.push(valueOrValues);
30855
+ if (this.isAutoRange) this.#rangeAuto = this.#rangeStream.seen(valueOrValues);
30856
+ } else {
30857
+ this.values.push(...valueOrValues);
30858
+ if (this.isAutoRange) for (const v of valueOrValues) this.#rangeAuto = this.#rangeStream.seen(v);
30859
+ }
30812
30860
  if (this.values.length > this.#options.capacityLimit) {
30813
- this.values.shift();
30814
- if (!this.#options.persistentScaling) this.#recompute();
30861
+ this.values = this.values.slice(this.values.length - this.#options.capacityLimit);
30862
+ if (!this.#options.persistentScaling && this.isAutoRange) this.#recompute();
30815
30863
  }
30816
30864
  }
30817
30865
  #recompute() {
30818
30866
  if (!this.#options.persistentScaling) this.#rangeStream = rangeStream();
30819
- for (let i = 0; i < this.values.length; i++) this.range = this.#rangeStream.seen(this.values[i]);
30867
+ for (let i = 0; i < this.values.length; i++) this.#rangeAuto = this.#rangeStream.seen(this.values[i]);
30820
30868
  }
30869
+ /**
30870
+ * 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.
30871
+ * @param values
30872
+ */
30821
30873
  set(values) {
30822
30874
  if (values.length > this.#options.capacityLimit) values = values.slice(values.length - this.#options.capacityLimit);
30823
30875
  this.values = values;
30824
30876
  this.#recompute();
30825
30877
  }
30878
+ /**
30879
+ * Returns the manual range if this is in effect, or the automatic
30880
+ */
30881
+ get range() {
30882
+ if (this.#rangeManual) return this.#rangeManual;
30883
+ return this.#rangeAuto;
30884
+ }
30885
+ /**
30886
+ * Clear all data and reset range. If `persistentScaling` is _false_, also resets scaling to initial state.
30887
+ * @returns _true_ if there was data to clear
30888
+ */
30826
30889
  clear() {
30890
+ const empty = this.values.length === 0;
30827
30891
  this.values = [];
30828
30892
  if (!this.#options.persistentScaling) this.#recompute();
30893
+ return !empty;
30829
30894
  }
30830
30895
  };
30831
30896
  //#endregion
@@ -30923,44 +30988,104 @@ let PlotMultiAxis = class PlotMultiAxis extends i$4 {
30923
30988
  #seriesOrder;
30924
30989
  #seriesSet;
30925
30990
  #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();
30991
+ /**
30992
+ * Adds a single data point
30993
+ * @param name Series name
30994
+ * @param value Value
30995
+ * @param witholdRedraw If _false_ (default) plot is automatically redrawn
30996
+ */
30997
+ addData(name, value, witholdRedraw = false) {
30998
+ return this.#addToSeries(name, value, witholdRedraw);
30999
+ }
31000
+ setData(name, values, witholdRedraw = false) {
31001
+ const [el, created] = this.#ensurePlot(name);
31002
+ if (!this.#seriesSet.has(name)) {
31003
+ this.#seriesSet.add(name);
31004
+ this.#seriesOrder.push(name);
31005
+ }
31006
+ el.set(values, witholdRedraw);
31007
+ if (created) this.requestUpdate();
31008
+ return el;
31009
+ }
31010
+ setObjects(data, witholdRedraw = false) {
31011
+ const entries = Object.entries(data);
31012
+ for (const [name, vals] of entries) this.setData(name, vals, true);
31013
+ if (witholdRedraw) return;
31014
+ this.redraw();
31015
+ }
31016
+ /**
31017
+ * Calls redraw() on all subplots.
31018
+ */
31019
+ redraw() {
31020
+ for (const el of this.#instances.values()) el.redraw();
31021
+ }
31022
+ /**
31023
+ * 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.
31024
+ * @param data Data to add
31025
+ * @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.
31026
+ */
31027
+ addObject(data, witholdRedraw = false) {
31028
+ const entries = Object.entries(data);
31029
+ for (const [name, val] of entries) this.#addToSeries(name, val, true);
31030
+ if (witholdRedraw) return;
31031
+ this.redraw();
30932
31032
  }
31033
+ /**
31034
+ * Styles a series by setting CSS variables on the subplot.
31035
+ * @param name Name of series
31036
+ * @param styles Styles to apply
31037
+ */
30933
31038
  styleSeries(name, styles) {
30934
- const normalized = {};
30935
- for (const [key, val] of Object.entries(styles)) normalized[key.startsWith(`--`) ? key : `--${key}`] = val;
31039
+ const normalised = {};
31040
+ for (const [key, val] of Object.entries(styles)) normalised[key.startsWith(`--`) ? key : `--${key}`] = val;
30936
31041
  const el = this.#instances.get(name);
30937
31042
  if (!el) {
30938
- this.#pendingStyles.set(name, normalized);
31043
+ this.#pendingStyles.set(name, normalised);
30939
31044
  return;
30940
31045
  }
30941
- for (const [key, val] of Object.entries(normalized)) el.style.setProperty(key, val);
31046
+ for (const [key, val] of Object.entries(normalised)) el.style.setProperty(key, val);
30942
31047
  }
31048
+ /**
31049
+ * Clears data from all sub-plots
31050
+ * @returns _True_ if there was data to clear
31051
+ */
30943
31052
  clear() {
30944
- for (const el of this.#instances.values()) el.clear();
31053
+ let cleared = false;
31054
+ for (const el of this.#instances.values()) cleared = cleared || el.clear();
31055
+ return cleared;
30945
31056
  }
31057
+ /**
31058
+ * Clears data from a given series
31059
+ * @param name Series name
31060
+ * @returns _True_ if series was found and had data
31061
+ */
30946
31062
  clearSeries(name) {
30947
31063
  const el = this.#instances.get(name);
30948
- if (el) el.clear();
31064
+ if (el) {
31065
+ el.clear();
31066
+ return true;
31067
+ }
31068
+ return false;
30949
31069
  }
31070
+ /**
31071
+ * Returns a copy of the series names
31072
+ */
30950
31073
  get series() {
30951
31074
  return [...this.#seriesOrder];
30952
31075
  }
30953
- #addToSeries(name, value) {
30954
- const el = this.#ensurePlot(name);
31076
+ #addToSeries(name, valueOrValues, withholdRedraw = false) {
31077
+ const [el, created] = this.#ensurePlot(name);
30955
31078
  if (!this.#seriesSet.has(name)) {
30956
31079
  this.#seriesSet.add(name);
30957
31080
  this.#seriesOrder.push(name);
30958
31081
  }
30959
- el.add(value);
31082
+ el.add(valueOrValues, withholdRedraw);
31083
+ if (created) this.requestUpdate();
31084
+ return el;
30960
31085
  }
30961
31086
  #ensurePlot(name) {
30962
31087
  let el = this.#instances.get(name);
30963
- if (el) return el;
31088
+ if (el) return [el, false];
30964
31089
  el = document.createElement(`ixfx-plot-single-axis`);
30965
31090
  el.tooltips = false;
30966
31091
  this.#instances.set(name, el);
@@ -30989,7 +31114,7 @@ let PlotMultiAxis = class PlotMultiAxis extends i$4 {
30989
31114
  el.addEventListener(`plot-pointer-leave`, () => {
30990
31115
  this.#onSubPlotPointerLeave();
30991
31116
  });
30992
- return el;
31117
+ return [el, true];
30993
31118
  }
30994
31119
  #onSubPlotPointerMove(clientX, clientY, index) {
30995
31120
  if (index < 0) {
@@ -31024,7 +31149,7 @@ let PlotMultiAxis = class PlotMultiAxis extends i$4 {
31024
31149
  part="container"
31025
31150
  style=${gridStyle}
31026
31151
  >
31027
- ${c(this.#seriesOrder, (name) => name, (name) => this.#ensurePlot(name))}
31152
+ ${c(this.#seriesOrder, (name) => name, (name) => this.#ensurePlot(name)[0])}
31028
31153
  </div>
31029
31154
  `;
31030
31155
  }
@@ -31090,10 +31215,10 @@ PlotMultiAxis = __decorate$1([safeCustomElement(`ixfx-plot-multi-axis`)], PlotMu
31090
31215
  let PlotHistogram = class PlotHistogram extends i$4 {
31091
31216
  constructor(..._args) {
31092
31217
  super(..._args);
31093
- this.orientation = "horizontal";
31218
+ this.orientation = `horizontal`;
31094
31219
  this.resolution = .1;
31095
31220
  this.capacity = 100;
31096
- this.title = "";
31221
+ this.title = ``;
31097
31222
  this.paused = false;
31098
31223
  this._width = 100;
31099
31224
  this._height = 40;
@@ -31107,7 +31232,7 @@ let PlotHistogram = class PlotHistogram extends i$4 {
31107
31232
  #hasProgrammaticData;
31108
31233
  #parseDeclarativeData(text) {
31109
31234
  if (!text) return [];
31110
- return text.trim().split(/[,\s;]+/).map((t) => Number.parseFloat(t)).filter((n) => !isNaN(n));
31235
+ return text.trim().split(/[,\s;]+/).map((t) => Number.parseFloat(t)).filter((n) => !Number.isNaN(n));
31111
31236
  }
31112
31237
  add(v) {
31113
31238
  this.#hasProgrammaticData = true;
@@ -31134,12 +31259,12 @@ let PlotHistogram = class PlotHistogram extends i$4 {
31134
31259
  this._height = e.contentRect.height;
31135
31260
  }).observe(this);
31136
31261
  if (!this.#hasProgrammaticData) {
31137
- const data = this.#parseDeclarativeData(this.textContent ?? "");
31262
+ const data = this.#parseDeclarativeData(this.textContent ?? ``);
31138
31263
  if (data.length > 0) this.#series.set(data);
31139
31264
  }
31140
31265
  }
31141
31266
  updated(changed) {
31142
- if (changed.has("capacity")) {
31267
+ if (changed.has(`capacity`)) {
31143
31268
  const old = [...this.#series.values];
31144
31269
  this.#series = new PlotDataSeries({
31145
31270
  capacityLimit: this.capacity,
@@ -31152,19 +31277,19 @@ let PlotHistogram = class PlotHistogram extends i$4 {
31152
31277
  return getComputedStyle(this).getPropertyValue(name).trim();
31153
31278
  }
31154
31279
  #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;
31280
+ const val = this.#readCssVar(`--plot-histogram-gap`);
31281
+ if (val === ``) return 1;
31282
+ const parsed = Number.parseFloat(val);
31283
+ return Number.isFinite(parsed) ? Math.max(0, parsed) : 1;
31159
31284
  }
31160
31285
  #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;
31286
+ const val = this.#readCssVar(`--plot-histogram-bar-length`);
31287
+ if (val === `` || val === `auto`) return null;
31288
+ const parsed = Number.parseFloat(val);
31289
+ return Number.isFinite(parsed) ? Math.max(0, Math.min(1, parsed)) : null;
31165
31290
  }
31166
31291
  #emitClick(i, valueMin, valueMax, relativeValue) {
31167
- this.dispatchEvent(new CustomEvent("plot-bucket-click", {
31292
+ this.dispatchEvent(new CustomEvent(`plot-bucket-click`, {
31168
31293
  detail: {
31169
31294
  bucketIndex: i,
31170
31295
  valueMin,
@@ -31179,7 +31304,7 @@ let PlotHistogram = class PlotHistogram extends i$4 {
31179
31304
  const { values, range } = this.#series;
31180
31305
  const w$7 = this._width;
31181
31306
  const h = this._height;
31182
- const isHorizontal = this.orientation === "horizontal";
31307
+ const isHorizontal = this.orientation === `horizontal`;
31183
31308
  const padding = Math.min(4, (isHorizontal ? h : w$7) * .05);
31184
31309
  const dataMin = this.min ?? range.min;
31185
31310
  const dataSpan = (this.max ?? range.max) - dataMin || 1;
@@ -31189,7 +31314,7 @@ let PlotHistogram = class PlotHistogram extends i$4 {
31189
31314
  const bucketSize = availableMain / bucketCount;
31190
31315
  const gap = this.#getGapPx();
31191
31316
  const barLengthOverride = this.#getBarLengthOverride();
31192
- const buckets = new Array(bucketCount).fill(0);
31317
+ const buckets = Array.from({ length: bucketCount }).fill(0);
31193
31318
  for (const v of values) {
31194
31319
  const normalized = (v - dataMin) / dataSpan;
31195
31320
  const index = Math.min(bucketCount - 1, Math.max(0, Math.floor(normalized * bucketCount)));
@@ -31223,7 +31348,7 @@ let PlotHistogram = class PlotHistogram extends i$4 {
31223
31348
  }
31224
31349
  })}
31225
31350
  ${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))"}
31351
+ class="overlay-text" fill=${`var(--plot-text, var(--surface-2-text, #fff))`}
31227
31352
  style="opacity: 0.6">${this.title}</text>` : w``}
31228
31353
  </svg>
31229
31354
  `;
@@ -31264,7 +31389,7 @@ let PlotHistogram = class PlotHistogram extends i$4 {
31264
31389
  `;
31265
31390
  }
31266
31391
  };
31267
- __decorate$1([n$2({ attribute: "orientation" })], PlotHistogram.prototype, "orientation", void 0);
31392
+ __decorate$1([n$2({ attribute: `orientation` })], PlotHistogram.prototype, "orientation", void 0);
31268
31393
  __decorate$1([n$2({ type: Number })], PlotHistogram.prototype, "resolution", void 0);
31269
31394
  __decorate$1([n$2({ type: Number })], PlotHistogram.prototype, "min", void 0);
31270
31395
  __decorate$1([n$2({ type: Number })], PlotHistogram.prototype, "max", void 0);
@@ -31276,7 +31401,7 @@ __decorate$1([n$2({
31276
31401
  })], PlotHistogram.prototype, "paused", void 0);
31277
31402
  __decorate$1([r$1()], PlotHistogram.prototype, "_width", void 0);
31278
31403
  __decorate$1([r$1()], PlotHistogram.prototype, "_height", void 0);
31279
- PlotHistogram = __decorate$1([safeCustomElement("ixfx-plot-histogram")], PlotHistogram);
31404
+ PlotHistogram = __decorate$1([safeCustomElement(`ixfx-plot-histogram`)], PlotHistogram);
31280
31405
  //#endregion
31281
31406
  //#region src/plots/single-axis.ts
31282
31407
  function buildLinePath(points) {
@@ -31375,6 +31500,8 @@ let PlotSingleAxis = class PlotSingleAxis extends i$4 {
31375
31500
  this.precise = false;
31376
31501
  this.tooltips = true;
31377
31502
  this.capacity = 100;
31503
+ this.rangeMin = NaN;
31504
+ this.rangeMax = NaN;
31378
31505
  this.persistentScale = true;
31379
31506
  this.paused = false;
31380
31507
  this.clickPauses = false;
@@ -31386,14 +31513,11 @@ let PlotSingleAxis = class PlotSingleAxis extends i$4 {
31386
31513
  this.colorValueMap = null;
31387
31514
  this._width = 100;
31388
31515
  this._height = 40;
31389
- this.#series = new PlotDataSeries({
31390
- capacityLimit: 100,
31391
- persistentScaling: true
31392
- });
31516
+ this.#series = new PlotDataSeries();
31393
31517
  this.#hasProgrammaticData = false;
31394
- this.valueFormat = (v) => v ? v.toFixed(2) : ``;
31395
31518
  this.#lastClientX = null;
31396
31519
  this.#lastClientY = null;
31520
+ this.valueFormat = (v) => v ? v.toFixed(2) : ``;
31397
31521
  this.#onPointerMove = (e) => {
31398
31522
  this.#lastClientX = e.clientX;
31399
31523
  this.#lastClientY = e.clientY;
@@ -31434,41 +31558,59 @@ let PlotSingleAxis = class PlotSingleAxis extends i$4 {
31434
31558
  }
31435
31559
  #series;
31436
31560
  #hasProgrammaticData;
31561
+ #lastClientX;
31562
+ #lastClientY;
31437
31563
  #parseDeclarativeData(text) {
31438
31564
  if (!text) return [];
31439
- return text.trim().split(/[,\s;]+/).map((t) => Number.parseFloat(t)).filter((n) => !isNaN(n));
31440
- }
31441
- get values() {
31442
- return this.#series.values;
31443
- }
31444
- get dataCount() {
31445
- return this.#series.values.length;
31565
+ return text.trim().split(/[,\s;]+/).map((t) => Number.parseFloat(t)).filter((n) => !Number.isNaN(n));
31446
31566
  }
31447
- getValueAt(index) {
31448
- return this.#series.values[index];
31449
- }
31450
- getIndexFromClientX(clientX) {
31451
- return this.#getIndexFromX(clientX, this.getBoundingClientRect());
31452
- }
31453
- #lastClientX;
31454
- #lastClientY;
31455
- add(v) {
31567
+ /**
31568
+ * Adds a value to the data series.
31569
+ *
31570
+ * 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.
31571
+ *
31572
+ * Use {@link set} to replace the entire data series at once.
31573
+ * @param valueOrValues Single value, or several values
31574
+ * @param withholdRedraw If _false_ (default) plot is automatically redrawn
31575
+ */
31576
+ add(valueOrValues, withholdRedraw = false) {
31456
31577
  this.#hasProgrammaticData = true;
31457
- this.#series.add(v);
31578
+ this.#series.add(valueOrValues);
31458
31579
  if (this.paused) return;
31580
+ if (withholdRedraw) return;
31581
+ this.redraw();
31582
+ }
31583
+ /**
31584
+ * Redraws the plot.
31585
+ * Normally not needed, unless add() is called with withholdRedraw = true, or styleSeries() is used to update series styles.
31586
+ */
31587
+ redraw() {
31459
31588
  this.requestUpdate();
31460
31589
  this.#updateTooltipAtLastPos();
31461
31590
  }
31462
- set(values) {
31591
+ /**
31592
+ * Sets the entire data for a series at once, replacing contents.
31593
+ *
31594
+ * Use add() to add values one by one.
31595
+ *
31596
+ * 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.
31597
+ * @param values Values
31598
+ * @param withholdRedraw If _false_ (default) plot is automatically redrawn
31599
+ */
31600
+ set(values, withholdRedraw = false) {
31463
31601
  this.#hasProgrammaticData = true;
31464
31602
  this.#series.set(values);
31465
31603
  if (this.paused) return;
31466
- this.requestUpdate();
31467
- this.#updateTooltipAtLastPos();
31604
+ if (withholdRedraw) return;
31605
+ this.redraw();
31468
31606
  }
31607
+ /**
31608
+ * Clears all data and redraws
31609
+ */
31469
31610
  clear() {
31470
- this.#series.clear();
31611
+ const result = this.#series.clear();
31471
31612
  this.requestUpdate();
31613
+ return result;
31472
31614
  }
31473
31615
  firstUpdated(_changed) {
31474
31616
  this._width = this.clientWidth || 100;
@@ -31484,11 +31626,16 @@ let PlotSingleAxis = class PlotSingleAxis extends i$4 {
31484
31626
  }
31485
31627
  }
31486
31628
  updated(changed) {
31487
- if (changed.has(`capacity`) || changed.has(`persistentScale`)) {
31629
+ if (changed.has(`capacity`) || changed.has(`persistentScale`) || changed.has(`rangeMin`) || changed.has(`rangeMax`)) {
31488
31630
  const old = [...this.#series.values];
31631
+ const fixedRange = !Number.isNaN(this.rangeMin) && !Number.isNaN(this.rangeMax) ? {
31632
+ min: this.rangeMin,
31633
+ max: this.rangeMax
31634
+ } : null;
31489
31635
  this.#series = new PlotDataSeries({
31490
31636
  capacityLimit: this.capacity,
31491
- persistentScaling: this.persistentScale
31637
+ persistentScaling: this.persistentScale,
31638
+ fixedRange
31492
31639
  });
31493
31640
  if (old.length > 0) this.#series.set(old);
31494
31641
  }
@@ -31525,7 +31672,7 @@ let PlotSingleAxis = class PlotSingleAxis extends i$4 {
31525
31672
  const widthPerPoint = n > 0 ? plotW / n : plotW;
31526
31673
  const scaleX = (i) => padding + (i + .5) * widthPerPoint;
31527
31674
  return values.map((value, index) => {
31528
- const sv = scaleValue(value, min, max);
31675
+ const sv = clamp$3(scaleValue(value, min, max));
31529
31676
  const ageFraction = n > 1 ? index / (n - 1) : 1;
31530
31677
  return {
31531
31678
  x: scaleX(index),
@@ -31537,6 +31684,35 @@ let PlotSingleAxis = class PlotSingleAxis extends i$4 {
31537
31684
  };
31538
31685
  });
31539
31686
  }
31687
+ get series() {
31688
+ return this.#series;
31689
+ }
31690
+ /**
31691
+ * Get all values in the data series as a readonly array.
31692
+ */
31693
+ get values() {
31694
+ return this.#series.values;
31695
+ }
31696
+ /**
31697
+ * Get length of data series
31698
+ */
31699
+ get dataLength() {
31700
+ return this.#series.values.length;
31701
+ }
31702
+ /**
31703
+ * Get value at specific index of data series
31704
+ * @param index
31705
+ */
31706
+ getValueAt(index) {
31707
+ return this.#series.values[index];
31708
+ }
31709
+ /**
31710
+ * Get value index based on client X position
31711
+ * @param clientX
31712
+ */
31713
+ getIndexFromClientX(clientX) {
31714
+ return this.#getIndexFromX(clientX, this.getBoundingClientRect());
31715
+ }
31540
31716
  #renderByStyle(points, crs, strokeW, radius, barW, bottom, top, mid) {
31541
31717
  const lineCr = crs.at(-1) ?? {
31542
31718
  fill: `currentColor`,
@@ -31647,6 +31823,8 @@ __decorate$1([n$2()], PlotSingleAxis.prototype, "title", void 0);
31647
31823
  __decorate$1([n$2({ type: Boolean })], PlotSingleAxis.prototype, "precise", void 0);
31648
31824
  __decorate$1([n$2({ type: Boolean })], PlotSingleAxis.prototype, "tooltips", void 0);
31649
31825
  __decorate$1([n$2({ type: Number })], PlotSingleAxis.prototype, "capacity", void 0);
31826
+ __decorate$1([n$2({ type: Number })], PlotSingleAxis.prototype, "rangeMin", void 0);
31827
+ __decorate$1([n$2({ type: Number })], PlotSingleAxis.prototype, "rangeMax", void 0);
31650
31828
  __decorate$1([n$2({
31651
31829
  type: Boolean,
31652
31830
  attribute: `persistent-scale`