diff --git a/Cargo.lock b/Cargo.lock index 51a6241d7..0af7e53ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "adler2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aes" @@ -146,9 +146,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "async-compression" -version = "0.4.23" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b37fc50485c4f3f736a4fb14199f6d5f5ba008d7f28fe710306c92780f004c07" +checksum = "d615619615a650c571269c00dca41db04b9210037fa76ed8239f70404ab56985" dependencies = [ "brotli", "flate2", @@ -722,9 +722,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "cfg_aliases" @@ -757,18 +757,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.39" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd60e63e9be68e5fb56422e397cf9baddded06dae1d2e523401542383bc72a9f" +checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.39" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89cc6392a1f72bbeb820d71f32108f61fdaf18bc526e1d23954168a67759ef51" +checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" dependencies = [ "anstream", "anstyle", @@ -778,21 +778,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.32" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" +checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] name = "clap_lex" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "color-eyre" @@ -990,7 +990,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -1001,7 +1001,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -1042,7 +1042,7 @@ checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -1088,7 +1088,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -1258,7 +1258,7 @@ checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", ] [[package]] @@ -1547,7 +1547,7 @@ checksum = "6c6e1db7ed32c6c71b759497fae34bf7933636f75a251b9e736555da426f6442" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -1719,9 +1719,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", ] @@ -1747,7 +1747,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", "windows-sys 0.59.0", ] @@ -1876,7 +1876,7 @@ checksum = "3bd3da01a295024fa79e3b4aba14b590d91256a274ff29cc5ee8f55183b2df24" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -1918,7 +1918,7 @@ dependencies = [ "phf", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -2280,7 +2280,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -2359,7 +2359,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -2515,9 +2515,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" [[package]] name = "rustc-hash" @@ -2653,7 +2653,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -2726,7 +2726,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -2826,9 +2826,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.101" +version = "2.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +checksum = "f6397daf94fa90f058bd0fd88429dd9e5738999cca8d701813c80723add80462" dependencies = [ "proc-macro2", "quote", @@ -2862,7 +2862,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -2915,7 +2915,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -2982,7 +2982,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -3107,7 +3107,7 @@ checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -3167,9 +3167,9 @@ checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" [[package]] name = "unicode-width" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" +checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" [[package]] name = "untrusted" @@ -3238,9 +3238,9 @@ checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" @@ -3273,7 +3273,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", "wasm-bindgen-shared", ] @@ -3295,7 +3295,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3336,7 +3336,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -3347,7 +3347,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -3458,9 +3458,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" +checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" dependencies = [ "memchr", ] @@ -3497,7 +3497,7 @@ checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -3517,7 +3517,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 1550e37e1..aa27c6331 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,8 +36,8 @@ brk_state = { version = "0", path = "crates/brk_state" } brk_store = { version = "0", path = "crates/brk_store" } brk_vec = { version = "0", path = "crates/brk_vec" } byteview = "=0.6.1" -clap = { version = "4.5.39", features = ["string"] } -clap_derive = "4.5.32" +clap = { version = "4.5.40", features = ["string"] } +clap_derive = "4.5.40" color-eyre = "0.6.5" derive_deref = "1.1.1" fjall = "2.11.0" diff --git a/crates/brk_server/README.md b/crates/brk_server/README.md index 52bd656e6..ca61addc7 100644 --- a/crates/brk_server/README.md +++ b/crates/brk_server/README.md @@ -73,7 +73,7 @@ A list of all possible vec ids and their supported vec indexes A list of all possible vec indexes and their supported vec ids -#### `GET /api/{INDEX}-to-{VALUE}` +#### `GET /api/{INDEX}-to-{ID}` This endpoint retrieves data based on the specified vector index and id. diff --git a/websites/default/packages/lightweight-charts/wrapper.js b/websites/default/packages/lightweight-charts/wrapper.js index ee98329a4..17d8a62b2 100644 --- a/websites/default/packages/lightweight-charts/wrapper.js +++ b/websites/default/packages/lightweight-charts/wrapper.js @@ -1,6 +1,6 @@ // @ts-check -/** @import {IChartApi, ISeriesApi, SeriesDefinition, SingleValueData as _SingleValueData, CandlestickData as _CandlestickData, BaselineData, SeriesType, IPaneApi, BaselineStyleOptions} from './v5.0.7-treeshaked/types' */ +/** @import {IChartApi, ISeriesApi, SeriesDefinition, SingleValueData as _SingleValueData, CandlestickData as _CandlestickData, BaselineData, SeriesType, IPaneApi, BaselineStyleOptions, CandlestickStyleOptions, WhitespaceData} from './v5.0.7-treeshaked/types' */ /** * @typedef {[number, number, number, number]} OHLCTuple @@ -12,6 +12,14 @@ * @property {number} index */ +/** + * @typedef {Object} Series + * @property {ISeriesApi} inner + * @property {string} id + * @property {Signal} active + * @property {VoidFunction} remove + */ + /** * @template T * @typedef {T & Valued & Indexed} ChartData @@ -27,48 +35,100 @@ export default import("./v5.0.7-treeshaked/script.js").then((lc) => { /** * @param {Object} args - * @param {HTMLElement} args.element + * @param {string} args.id + * @param {HTMLElement} args.parent * @param {Signals} args.signals * @param {Colors} args.colors - * @param {Index} args.index * @param {Utilities} args.utils * @param {Elements} args.elements - * @param {DeepPartial} [args.options] + * @param {VecsResources} args.vecsResources + * @param {Accessor} args.index + * @param {((unknownTimeScaleCallback: VoidFunction) => void)} [args.timeScaleSetCallback] + * @param {Owner | null} args.owner + * @param {true} [args.fitContentOnResize] + * @param {{unit: Unit; blueprints: AnySeriesBlueprint[]}[]} [args.config] */ - function createLightweightChart({ - element, + function createChartElement({ + parent, signals, colors, - index, utils, elements, - options: _options = {}, + id, + index, + vecsResources, + timeScaleSetCallback, + owner: _owner, + fitContentOnResize, + config, }) { - /** @satisfies {DeepPartial} */ - const options = { - autoSize: true, - layout: { - fontFamily: elements.style.fontFamily, - background: { color: "transparent" }, - attributionLogo: false, - colorSpace: "display-p3", - colorParsers: [oklchToRGBA], - }, - grid: { - vertLines: { visible: false }, - horzLines: { visible: false }, - }, - localization: { - priceFormatter: numberToShortUSFormat, - locale: "en-us", - }, - ..._options, - }; + const owner = _owner || signals.getOwner(); + + const div = window.document.createElement("div"); + div.classList.add("chart"); + parent.append(div); + + const legendTop = createLegend({ + utils, + signals, + paneIndex: 0, + }); + div.append(legendTop.element); + + const chartDiv = window.document.createElement("div"); + chartDiv.classList.add("lightweight-chart"); + div.append(chartDiv); + + const legendBottom = createLegend({ + utils, + signals, + paneIndex: 1, + }); + div.append(legendBottom.element); /** @type {IChartApi} */ - const chart = lc.createChart(element, options); + const ichart = lc.createChart( + chartDiv, + /** @satisfies {DeepPartial} */ ({ + autoSize: true, + layout: { + fontFamily: elements.style.fontFamily, + background: { color: "transparent" }, + attributionLogo: false, + colorSpace: "display-p3", + colorParsers: [oklchToRGBA], + }, + grid: { + vertLines: { visible: false }, + horzLines: { visible: false }, + }, + rightPriceScale: { + borderVisible: false, + }, + timeScale: { + borderVisible: false, + }, + localization: { + priceFormatter: numberToShortUSFormat, + locale: "en-us", + }, + crosshair: { + mode: 3, + }, + ...(fitContentOnResize + ? { + handleScroll: false, + handleScale: false, + timeScale: { + minBarSpacing: 0.001, + }, + } + : {}), + // ..._options, + }), + ); - chart.priceScale("right").applyOptions({ + ichart.priceScale("right").applyOptions({ minimumWidth: 80, }); @@ -79,22 +139,39 @@ export default import("./v5.0.7-treeshaked/script.js").then((lc) => { borderColor: colors.border(), }), ({ defaultColor, offColor, borderColor }) => { - chart.applyOptions({ + ichart.applyOptions({ layout: { textColor: offColor, panes: { separatorColor: borderColor, }, }, - rightPriceScale: { - borderVisible: false, + crosshair: { + horzLine: { + color: offColor, + labelBackgroundColor: defaultColor, + }, + vertLine: { + color: offColor, + labelBackgroundColor: defaultColor, + }, }, + }); + }, + ); + + signals.createEffect(index, (index) => { + ichart.applyOptions({ + timeScale: { + timeVisible: + index === /** @satisfies {Height} */ (5) || + index === /** @satisfies {DifficultyEpoch} */ (2) || + index === /** @satisfies {HalvingEpoch} */ (4), + }, + }); + if (!fitContentOnResize) { + ichart.applyOptions({ timeScale: { - borderVisible: false, - timeVisible: - index === /** @satisfies {Height} */ (5) || - index === /** @satisfies {DifficultyEpoch} */ (2) || - index === /** @satisfies {HalvingEpoch} */ (4), minBarSpacing: index === /** @satisfies {MonthIndex} */ (7) ? 1 @@ -106,174 +183,12 @@ export default import("./v5.0.7-treeshaked/script.js").then((lc) => { ? 120 : undefined, }, - crosshair: { - horzLine: { - color: offColor, - labelBackgroundColor: defaultColor, - }, - vertLine: { - color: offColor, - labelBackgroundColor: defaultColor, - }, - mode: 3, - }, }); - }, - ); - - return chart; - } - - /** - * @param {Object} args - * @param {string} args.id - * @param {HTMLElement} args.parent - * @param {Signals} args.signals - * @param {Colors} args.colors - * @param {Utilities} args.utils - * @param {Elements} args.elements - * @param {VecsResources} args.vecsResources - * @param {Owner | null} [args.owner] - * @param {true} [args.fitContentOnResize] - * @param {{unit: Unit; blueprints: AnySeriesBlueprint[]}[]} [args.config] - */ - function createChartElement({ - parent, - signals, - colors, - utils, - elements, - id, - vecsResources, - owner: _owner, - fitContentOnResize, - config, - }) { - let owner = _owner || signals.getOwner(); - - const div = window.document.createElement("div"); - div.classList.add("chart"); - parent.append(div); - - const legendTop = createLegend({ - parent: div, - utils, - signals, - paneIndex: 0, + } }); - const chartDiv = window.document.createElement("div"); - chartDiv.classList.add("lightweight-chart"); - div.append(chartDiv); - - const legendBottom = createLegend({ - parent: div, - utils, - signals, - paneIndex: 1, - }); - - let ichart = /** @type {IChartApi | null} */ (null); - let timeScaleSet = false; - - if (fitContentOnResize) { - new ResizeObserver(() => ichart?.timeScale().fitContent()).observe( - chartDiv, - ); - } - - /** @type {Index} */ - let vecIndex = 0; // Default value, overwritten - - let timeResource = /** @type {VecResource| null} */ (null); - - let timeScaleSetCallback = - /** @type {((unknownTimeScaleCallback: VoidFunction) => void) | null} */ ( - null - ); - - /** - * @param {ISeriesApi} series - * @param {VecResource} valuesResource - */ - function createSetFetchedDataEffect(series, valuesResource) { - const fetchedKey = vecsResources.defaultFetchedKey; - - signals.runWithOwner(owner, () => - signals.createEffect( - () => [ - timeResource?.fetched[fetchedKey].vec(), - valuesResource.fetched[fetchedKey].vec(), - ], - ([indexes, _ohlcs]) => { - if (!ichart) throw Error("IChart should be initialized"); - - if (!indexes || !_ohlcs) return; - const ohlcs = /** @type {OHLCTuple[]} */ (_ohlcs); - let length = Math.min(indexes.length, ohlcs.length); - const data = new Array(length); - let prevTime = null; - let offset = 0; - - for (let i = 0; i < length; i++) { - const time = indexes[i]; - const sameTime = prevTime === time; - if (sameTime) { - offset += 1; - } - const v = ohlcs[i]; - const offsetedI = i - offset; - if (v === null) { - data[offsetedI] = { - time, - value: NaN, - }; - } else if (typeof v === "number") { - data[offsetedI] = { - time, - value: v, - }; - } else { - if (sameTime) { - console.log(data[offsetedI]); - } - // const prev = sameTime ? data[offsetedI] : undefined; - let [open, high, low, close] = v; - data[offsetedI] = { - time, - open: sameTime ? data[offsetedI].open : open, - high: sameTime ? Math.max(data[offsetedI].high, high) : high, - low: sameTime ? Math.min(data[offsetedI].low, low) : low, - close, - }; - } - prevTime = time; - } - - data.length -= offset; - series.setData(data); - - timeScaleSetCallback?.(() => { - if ( - !timeScaleSet && - (vecIndex === /** @satisfies {QuarterIndex} */ (19) || - vecIndex === /** @satisfies {YearIndex} */ (23) || - vecIndex === /** @satisfies {DecadeIndex} */ (1)) - ) { - ichart - ?.timeScale() - .setVisibleLogicalRange({ from: -1, to: data.length }); - } - }); - timeScaleSet = true; - }, - ), - ); - } - - const activeResources = /** @type {VecResource[]} */ ([]); - - ichart?.subscribeCrosshairMove( + const activeResources = /** @type {Set} */ (new Set()); + ichart.subscribeCrosshairMove( utils.debounce(() => { activeResources.forEach((v) => { v.fetch(); @@ -281,46 +196,298 @@ export default import("./v5.0.7-treeshaked/script.js").then((lc) => { }), ); - const chart = { - inner: () => ichart, - /** - * @param {Object} args - * @param {Index} args.index - * @param {((unknownTimeScaleCallback: VoidFunction) => void)} [args.timeScaleSetCallback] - */ - create({ index: _index, timeScaleSetCallback: _timeScaleSetCallback }) { - vecIndex = _index; - timeScaleSetCallback = _timeScaleSetCallback || null; + const timeResource = signals.createMemo(() => { + const i = index(); + const timeResource = vecsResources.getOrCreate( + i, + i === /** @satisfies {Height} */ (5) ? "timestamp-fixed" : "timestamp", + ); + timeResource.fetch(); + return timeResource; + }); - if (ichart) throw Error("IChart shouldn't be initialized"); + let timeScaleSet = false; - timeResource = vecsResources.getOrCreate( - vecIndex, - vecIndex === /** @satisfies {Height} */ (5) - ? "timestamp-fixed" - : "timestamp", - ); - timeResource.fetch(); + if (fitContentOnResize) { + new ResizeObserver(() => ichart.timeScale().fitContent()).observe( + chartDiv, + ); + } - ichart = createLightweightChart({ - index: vecIndex, - element: chartDiv, - signals, - colors, - utils, - elements, + /** + * @param {Object} args + * @param {string} args.id + * @param {number} args.paneIndex + * @param {"nw" | "ne" | "se" | "sw"} args.position + * @param {number} [args.timeout] + * @param {(args: {owner: Owner | null, pane: IPaneApi