diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c7567b8..c78ac29 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,13 +1,24 @@ name: ci +# Pull requests run on the PR; a push runs only on main. (Both triggers on every branch ran everything twice per PR push.) on: push: + branches: [main] pull_request: +# The workflow reads the repository and nothing else: no secrets, no writes. +permissions: + contents: read + +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + jobs: plugin: name: plugin (harness) runs-on: ubuntu-latest + timeout-minutes: 10 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -20,9 +31,32 @@ jobs: # The harness's crafted-copy battery: every evasion must fail, every lookalike must pass. - run: node tools/verify-plugin-selftest.mjs + lint: + name: lint (names, syntax) + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: '20' + - uses: actions/setup-python@v5 + with: + python-version: '3.11' + # Undefined and unused names, and syntax errors: the class of defect that needs no test to find. + - run: pip install ruff && ruff check --select F,E9 console tools + # Every first-party script must at least parse. + - run: for f in console/frontend/*.js plugin/plugin.js; do node --check "$f"; done + - run: for f in install.sh console/start.sh tools/sync-live.sh bin/is-enabled.sh; do bash -n "$f"; done + # The vendored bundles are what was recorded (a hand edit or a half-applied upgrade fails here), and the + # generated preload list follows the module graph. + - run: python tools/vendor-sums.py --check + - run: python tools/modulepreload.py --check + tests: - name: tests (unit suite, py${{ matrix.python }}) + name: tests (py${{ matrix.python }}) runs-on: ubuntu-latest + timeout-minutes: 25 strategy: fail-fast: false # 3.14 is the interpreter the operator actually runs: argparse there rejects a bare `%` in a help @@ -34,46 +68,64 @@ jobs: - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - # The suite is stdlib-only by design: the study store, the chat bridge, the chart bridge and - # the push channel are all covered without a browser, a network, or the app — so this step - # installs nothing at all. - - name: unit suite (no dependencies) - run: python -m unittest discover -s console/backend/tests -t console/backend/tests -v - # The MCP wrapper is the one piece that needs a library (fastmcp). REQUIRE_MCP makes a missing - # fastmcp a failure instead of a silent skip, so the layer can never go untested by accident. - - name: MCP tool layer, against a stub console + cache: pip + cache-dependency-path: console/requirements-test.txt + - uses: actions/setup-node@v4 + with: + node-version: '20' + - run: pip install -r console/requirements-test.txt + # ONE run of the whole suite with everything it can use. REQUIRE_* turn a missing fastmcp or node into a + # failure instead of 155 + 77 silent skips (the suite used to end OK with 164 tests skipped). + - name: unit suite env: TRADER_CHART_REQUIRE_MCP: '1' + TRADER_CHART_REQUIRE_NODE: '1' + TRADER_CONSOLE_TOKEN_FILE: /tmp/ci-console.token # the suite starts servers: keep their token off $HOME run: | - pip install fastmcp - python -m unittest discover -s console/backend/tests -t console/backend/tests \ - -p 'test_mcp_server.py' -v - # The tool contract (annotations) and the Edge Stats tools, end to end: tool -> console -> a fake - # engine speaking the real engine's responses. Both skip without fastmcp, so they live here. - python -m unittest discover -s console/backend/tests -t console/backend/tests \ - -p 'test_mcp_tool_annotations.py' -v - python -m unittest discover -s console/backend/tests -t console/backend/tests \ - -p 'test_edgestats_mcp.py' -v + python -m unittest discover -s console/backend/tests -t console/backend/tests 2>&1 | tee /tmp/suite.log + tail -3 /tmp/suite.log + # With fastmcp and node present only the real-engine tests (needs `--with-edge`) and the live-tree test skip. + # A larger number means a tool went missing. + skipped=$(grep -Eo 'skipped=[0-9]+' /tmp/suite.log | tail -1 | cut -d= -f2) + if [ "${skipped:-0}" -gt 12 ]; then echo "too many skipped tests: $skipped (expected <= 12)"; exit 1; fi + - name: stdlib only (the console's own promise) + if: matrix.python == '3.11' + run: | + python -m venv /tmp/bare + /tmp/bare/bin/python -m unittest discover -s console/backend/tests -t console/backend/tests 2>&1 | tail -3 backend: - name: backend (compile + boot) + name: backend (compile + boot, mcp ${{ matrix.mcp }}) runs-on: ubuntu-latest + timeout-minutes: 10 + strategy: + fail-fast: false + matrix: + mcp: ['>=1,<2', '>=2,<3'] # users get whatever pip resolves today: test both majors steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: '3.11' - name: the one non-stdlib dependency - run: pip install 'mcp>=1,<2' + run: pip install "mcp${{ matrix.mcp }}" - name: syntax run: python -m compileall -q console/backend console/mcp - name: boots and answers /api/health without an MCP session run: | cd console/backend - python server.py --port 8899 --frontend ../frontend --no-mcp & - for i in $(seq 1 20); do - if curl -fsS http://127.0.0.1:8899/api/health > /tmp/health.json; then break; fi + python server.py --port 8899 --frontend ../frontend --no-mcp > /tmp/console.log 2>&1 & + pid=$! + ready=0 + for i in $(seq 1 40); do + if curl -fsS http://127.0.0.1:8899/api/health > /tmp/health.json; then ready=1; break; fi + kill -0 "$pid" 2>/dev/null || break # the server died: stop waiting sleep 0.5 done - cat /tmp/health.json - kill %1 + cat /tmp/health.json 2>/dev/null || true + if [ "$ready" != 1 ]; then echo "the console never answered /api/health"; cat /tmp/console.log; exit 1; fi + python -c "import json; d = json.load(open('/tmp/health.json')); assert d['ok'] is True, d" + # the page itself, with its security headers + curl -fsS -D - -o /dev/null http://127.0.0.1:8899/ | tee /tmp/headers.txt + grep -qi '^content-security-policy:' /tmp/headers.txt + kill "$pid" diff --git a/.gitignore b/.gitignore index 1199711..95f8353 100644 --- a/.gitignore +++ b/.gitignore @@ -25,7 +25,7 @@ venv/ /tmp/ # local test screenshots (grim captures from UI verification runs) /shots/ -docs/shots/ +# docs/shots/ holds the README's images: they ARE tracked (ignoring the folder left three of them out of every clone) # PR Lens writes its previews here. They are rebuilt on demand. .pr-lens/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 2aeff67..8483894 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,79 @@ All notable changes to this project are documented here. Format: [Keep a Changel ## [Unreleased] +### Changed + +- **Vela 0.8.1 → 0.8.3** (`@luxalgo/vela`, published 5 and 7 Oct; vela-pinets 0.2.15 already accepts it and is unchanged). The + files are LuxAlgo's, byte for byte (nothing in `vendor/vela/` is patched); only the vendored set moved: the ES modules, the + Binance / Coinbase / Hyperliquid providers and the global build (`chunk-*.js` names changed; the preload list, the vendor + checksums and the docs follow). What 0.8.2/0.8.3 bring arrives with it: the maximise / restore control on Vela's panels, the + price-axis tick hook and price-style change events in the renderer API, surface open / close events, a "Reverse" action, touch-only + pan inertia (a mouse release now stops dead). **Nothing of ours was touched to take it**, and it was held to that: the same 56 + agent actions (add / remove studies, layouts, 10 drawing types, marks, view settings, themes, replay, fullscreen, a Pine run + with inputs, the drawer, a screenshot) answer identically on both versions; the keyboard focus ring, the ⋯ menu band, the 200 % zoom + layout, the drawer and Edge sheet focus handling all pass unchanged; the CSP blocks nothing; first canvas is 1,544 ms against + 1,549 ms (median of six, alternating runs) for +58 KB. `test_vela_doors` now finds Vela's drawings chunk by content, because its + hashed file name changes with every release. + +### Fixed (the 8 Oct 2026 full audit: seven read-only lanes over `3c2ad34`, handed to Hermes as a report) + +- **The chart bridge no longer loses or duplicates commands.** Its three files were read-modify-written with no lock and one + shared temp name: 60 parallel command POSTs gave 11 to 23 HTTP 500s and duplicate ids (the page drops a duplicate id, so a + command silently never ran). One lock, a temp file of its own per write, and command ids from a counter that only grows. + A result must name the command it answers (400 otherwise) and now keeps the fields the page reports (`trades`, `overlay`…). +- **Replay prices only the symbol being replayed.** An ETH order used to fill at the BTC cursor price. The page sends the + symbol with the push; another symbol is priced live. +- **Paper broker:** the entry fee is in `realized` (it now reconciles with equity); an approve that cannot be saved leaves the + account exactly as it was; a read error on `paper.json` no longer resets the account to 10,000; large quantities sell + without a ghost position; prices are read outside the lock; order ids continue across a reset. +- **`once_per_view` now reaches the stream** (`reload` runs in every view). **A month is a month:** `1M` was mapped to one minute. + Intervals Binance does not serve are refused with the list. A partial catalogue is no longer cached for 12 h. +- **The console listens at once** (it waited up to 60 s for the LuxAlgo MCP first); SIGTERM now stops it cleanly; a busy port + is one line, not a traceback; bad numbers are a 400, not a 500. +- **Trust boundaries.** `GET /api/session` goes to the console's own page and to local tools, not to other pages or LAN + peers (`--host 0.0.0.0` no longer hands out the token; `TRADERS_AGENT_ALLOW_LAN=1` opts in). The Origin check compares the + port, so another localhost app cannot post. Cross-site `/api` GETs are refused (`Sec-Fetch-Site`). The page carries a + Content-Security-Policy; every answer is `nosniff`. Idle sockets time out (30 s), connections are capped, SSE queues are + bounded. `run_id` and the backtest service's `local:` names cannot leave their folder; the backtest service answers the + console only; thumbnails come from exact hosts, are content-sniffed, follow no redirect and are written atomically. Agent + definitions are validated (a toolset such as `--yolo` is refused); the chat route's workdir and timeout are the operator's. + Loopback calls from the MCP server and CLIs bypass `http_proxy`. +- **The agent is no longer told things that are not true.** `library_source` / `library_indicator` cut long scripts silently + at 6,000 / 8,000 characters while claiming the full source: they now return up to 60,000 and say `truncated … offset=N` + (as do the edge, prop-firm and related lists). The tool and skill no longer say `while` / `for…in` cannot run (only + `import` is refused). `bt_*` answer instead of raising; `chart_shot` uses the same view gate as every tool; `chart_batch` + takes a list; all 54 tools state `destructiveHint`; an empty chart is called empty; `chart_add_indicator` refuses an unknown + name before Vela is asked (no ghost study row) and suggests the lower-case spelling. +- **Docs match the code.** The skill is 139 lines (the history moved to `docs/desk-engineering-notes.md`) and covers the paper + broker and replay; README corrects "no order placement", "nothing written outside the repo", "synthetic bars", the removed + buttons, ports and `LUXALGO_CONSOLE`; `docs/MCP-TOOLS.md` groups tools by their real annotations. +- **Installer:** flags are parsed (an unknown flag or `--help` no longer installs), `--uninstall`, `PORT=` is baked into the + installed plugin, `--doctor` no longer `eval`s paths and checks the Python version and the MCP registration. +- **UI and accessibility:** the Vela top bar has a keyboard focus ring; the ⋯ menu is no longer covered by the pane at 1020-1069 px; + the run status stays on screen at 200 % zoom; the highlight layer is no longer a Tab stop; the drawer and Edge sheet are + dialogs that make the rest inert and return focus to what opened them; Esc from ⋯ returns focus; filled buttons are 4.9:1 + in the dark theme; inputs keep a forced-colours focus outline; `` is "Trader's Agent". +- **Frontend races:** a market switch during a re-run no longer leaves another symbol's labels; the newest run wins; a failed + first `/api/session` is retried; the poll loop cannot stall on a hung request; the stream no longer moves the poll's + high-water mark; the library detail pane shows the last row opened; the script draft is saved when the page goes away; + catalogue links must be `https:`; two untitled inline inputs no longer share one override. +- **Plugin:** the reveal-on-launch default is off, as documented, and waits for the stored choice. + +### Removed + +- `docs/studies/luxalgo-reference/smart-money-concepts-smc.pine`: LuxAlgo's CC BY-NC-SA 4.0 script was committed in this (public) + repository. It remains in git history; rewriting history is the maintainer's call. +- `./install.sh --vendor` (it rewrote committed files without checking them). See `console/frontend/vendor/VENDORING.md`. + +### Added (from the same audit) + +- `NOTICE` (the AGPL status of the distribution and the source offer for the patched engine), the MIT texts of the vendored Zag + packages, `console/frontend/vendor/SHA256SUMS` with `tools/vendor-sums.py --check`, a "Network" section in `THIRD-PARTY.md`. +- CI: `permissions: contents: read`, one run per PR, a lint job (`ruff F,E9`, `node --check`, `bash -n`, vendor sums, preload list), + the whole suite once with fastmcp and node REQUIRED and a skip ceiling, both `mcp` majors, pinned test dependencies + (`console/requirements*.txt`), and a boot check that fails when the server never answers. +- About 130 new tests that drive the real code: threads against the bridge, a live socket for the gates, a fastmcp stub console. + ### Added - **Syntax colouring in the script editor.** Comments, `//@directives`, strings, numbers and `#RRGGBB` diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..5cd987c --- /dev/null +++ b/NOTICE @@ -0,0 +1,27 @@ +Trader's Agent: licence notice +============================== + +1. This project's own code (everything outside console/frontend/vendor/) is MIT-licensed: see LICENSE. + +2. The distribution as a whole is NOT only MIT. It redistributes, unmodified or patched, these components: + + console/frontend/vendor/pinets/ PineTS, patched build (AGPL-3.0-only; LICENSE beside it) + console/frontend/vendor/vela-pinets/ Vela-PineTS (AGPL-3.0-only; LICENSE beside it) + console/frontend/vendor/vela/ Vela (Apache-2.0; LICENSE and NOTICE beside it) + console/frontend/vendor/zag/ Zag, Floating UI, proxy-compare (MIT; texts in THIRD-PARTY-LICENSES.md) + + Because AGPL-3.0 code is redistributed here, the combined distribution (this repository with its vendor/ folder, and a + console served from it) is offered under the AGPL-3.0 terms for those parts: anyone who receives it, including a person + using a console reached over a network, may ask for the complete corresponding source. Details: THIRD-PARTY.md. + +3. Written offer of source for the patched engine (console/frontend/vendor/pinets/pinets.min.browser.es.js): + repository https://github.com/godzillacode0000/PineTS (fork of https://github.com/LuxAlgo/PineTS) + branch fix/p1-p8-on-0.11 + built from commit f5ec571 + build npm ci && npm run build:prod:browser-es + console/frontend/vendor/pinets/PROVENANCE.md records the patches, the file's size and its sha256. The source for the + rest of this distribution is this repository. + +4. Third-party content that is deliberately NOT in this repository: LuxAlgo Library indicators (CC BY-NC-SA 4.0). They are + fetched on demand at run time and never committed or redistributed here. Product names (TradingView, LuxAlgo, Hermes, + Binance) belong to their owners; this is an unofficial plugin. diff --git a/README.md b/README.md index a2ab0b2..57233c5 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ **A Hermes Desktop plugin that opens a chart-first trading console: Vela-rendered candlesticks, and the LuxAlgo Library on top of them.** -![licence: MIT](https://img.shields.io/badge/licence-MIT-3da639?style=flat-square) +![licence: MIT + vendored AGPL-3.0](https://img.shields.io/badge/licence-MIT%20%2B%20vendored%20AGPL--3.0-3da639?style=flat-square) ![python: 3.11+](https://img.shields.io/badge/python-3.11%2B-3776ab?style=flat-square&logo=python&logoColor=white) ![hermes desktop: 0.21.3+](https://img.shields.io/badge/hermes%20desktop-%E2%89%A50.21.3-6b6b74?style=flat-square) ![kind: desktop plugin](https://img.shields.io/badge/hermes%20plugin-desktop-f2a83b?style=flat-square) @@ -37,7 +37,8 @@ MCP server) in one local web app — your chat session is left exactly where it > **Unofficial.** This project is not affiliated with, endorsed by, or sponsored by LuxAlgo. It uses > the LuxAlgo name descriptively ("compatible with LuxAlgo MCP") and ships no LuxAlgo logo. See -> [`THIRD-PARTY.md`](THIRD-PARTY.md) for the licences and the attribution each piece requires. +> [`THIRD-PARTY.md`](THIRD-PARTY.md) and [`NOTICE`](NOTICE) for the licences, the attribution each piece requires and the +> source offer for the patched engine (the distribution as a whole carries AGPL-3.0 parts). ## Requirements @@ -45,7 +46,7 @@ MCP server) in one local web app — your chat session is left exactly where it |---|---| | **Hermes Desktop** | v0.21.3 or newer (the plugin uses the `sidebar.nav` + `routes` contribution areas) | | **Python** | 3.11+ with the `mcp` client: `pip install mcp` (a venv is fine — point `PY=` at it) | -| **Network** | for LuxAlgo's MCP endpoint and the Binance data feed; the chart falls back to synthetic bars when the provider is unreachable. The chart engine and Pine runtime are served locally | +| **Network** | for LuxAlgo's MCP endpoint and the Binance data feed; with no market feed the chart stays empty (`chart_state` says `bars None`). The chart engine and Pine runtime are served locally | | **Node 20+** *(optional)* | only for [Edge Stats](#edge-stats--how-often-did-it-actually-happen) — `./install.sh --with-edge` installs LuxAlgo's engine (~300 MB with its dependencies) next to the console. Without it everything else works and the sheet explains what is missing | | **Preview resizer** *(optional)* | `libvips` (or ImageMagick, or `ffmpeg`) — see [Catalogue previews](#catalogue-previews-are-kept-on-your-machine). With none of them the console still shows every preview, just at the catalogue's original size | | **OS** | Linux — built and verified on Omarchy (Arch + Hyprland). macOS and Windows are out of scope. | @@ -80,14 +81,14 @@ If the pane is enabled but still does not dock, that is a different, app-side in see [`docs/INSTALL-ENABLE.md`](docs/INSTALL-ENABLE.md) for both failure modes side by side. The browser builds are committed under `console/frontend/vendor/` — the console loads them from there. -`./install.sh --vendor` refreshes those exact files from the pinned CDN versions (see the licence note -in `THIRD-PARTY.md`). +Their checksums are in `console/frontend/vendor/SHA256SUMS` (`tools/vendor-sums.py --check`; the test suite runs it), and +`console/frontend/vendor/VENDORING.md` says how to refresh them (see the licence note in `THIRD-PARTY.md`). ### Verify it worked ```bash curl -s localhost:8787/api/health # {"ok": true, "data": {"status": "ok", ...}} -node tools/verify-plugin.mjs plugin/plugin.js # OK — 7 contributions +node tools/verify-plugin.mjs plugin/plugin.js # OK — 8 contributions console/bin/trader-chart state # symbol, timeframe, price, bars, indicators on ``` @@ -124,10 +125,9 @@ systemctl --user enable --now traders-agent.service | Status bar → **Trader's Agent** chip | same, from anywhere in the app | | `Ctrl+K` → **Trading: open Trader's Agent** | same, from the palette | | `Ctrl+K` → **Trading: toggle chart reveal on launch** | stop the console opening by itself at app start | -| Top bar → `☰ Library` | the Library panel: search 800+ concepts and indicators | -| Top bar → `▤ Details` | the selected item: write-up, **full Pine source**, licence badge, **Run PineTS** | +| Chart top bar → **⌗ Indicators** | opens the **drawer**: search the 806-row LuxAlgo catalogue, star favourites, mount Vela's built-ins, or open a Library row's Details (write-up, **full Pine source**, licence badge, **Run PineTS** / Add to chart) | | Chart top bar → **Layout** | Vela's own grid picker — presets and custom `g<cols>x<rows>` grids. The console boots at `2h` (two side by side); the same door is `chart_set_layout` / `trader-chart layout` | -| Chart top bar → **⌗ Indicators** | One surface for both halves: **Favourites** (your own ☆), **BUILT-INS** (Vela's natives for this market, read live from the frame) and **LIBRARY** (the 806-row LuxAlgo catalogue). Every LIBRARY card carries the catalogue's own **chart preview** above its name — and the Details pane shows it full size — so "how does this look applied?" is answered before running anything. The LIBRARY arrives **grouped into families** (SMC / ICT 74, Trend 108, Volume & Flow 96, …) with a rail down the left to jump between them, and each family opens into its own **clusters** ("Moving-average lineage", "Candlestick catalog"); every card has a **Reading** button that unfolds what the indicator is and how it is read, in place. Star the ones you reach for; clicking a built-in mounts it, a Library row opens the Details pane with its Run PineTS / Add to chart. The same door is `chart_indicators` / `trader-chart indicators` (`--family trend --reading mlma --fold trend:on`) | +| Chart top bar → **<> Script** | the Pine script pane: write or paste Pine, **Run**, tweak the script's own **Settings**, save and reopen scripts | | Chart top bar → **⛶ Full screen** | Gives the chart the whole pane — and the whole display: the console's chrome, panels and statusbar step aside and the page asks the browser for fullscreen. `Esc` (or the floating `✕`, or the same button) comes back. Docked on Vela's own toolbar row beside `<> Script` and `☰ catalogue`; the door is `chart_fullscreen` / `trader-chart fullscreen [--off]` | | Chart ⋯ menu → **Edge Stats** | the Edge Stats sheet: ask a question, run one of the 42 catalogue reports, group by weekday / month / year, open any historical session on a chart. [Details below](#edge-stats--how-often-did-it-actually-happen) | | The chart's own bottom bar | Vela's range buttons, timezone clock and settings (not ours) | @@ -224,7 +224,7 @@ hermes mcp test traders-chart # start a new session afterwards | `chart_remove_indicator` | take indicators **off** the chart — one by name, or `all` for every study (reports the chart's before → after list) | | `chart_set_market` | switch symbol / timeframe | | `chart_set_layout` | read or set the workspace **grid** — `1`, `2h`, `2v`, `4`, `8`, or `g<cols>x<rows>` (no argument reads it) | -| `chart_indicators` | the **Indicators** surface — sections `favorites`/`builtins`/`library`, `q` for the search box, `family` to open one group of the catalogue, `reading SLUG` to unfold a card's write-up, `fold FAMILY[:on]` to fold a group, `star`/`unstar KIND:ID`, `mount` a built-in; answers with the rows it painted, the groups it drew and the reading it left open | +| `chart_indicators` | the **Indicators** drawer — sections `favorites`/`builtins`/`library`, `q` for the search box, `family` to open one group of the catalogue, `star`/`unstar KIND:ID`, `mount` a built-in; answers with the rows it painted | | `chart_fullscreen` | give the chart the whole pane / the whole screen (`on=False` comes back) — hides the console chrome and asks the browser for fullscreen; the answer says whether the display was taken or only the page | | `chart_reload` | remount every attached console (picks up new frontend files) | | `chart_palette` | what colours the chart is wearing (`try_apply` asserts the console theme) | @@ -233,7 +233,7 @@ hermes mcp test traders-chart # start a new session afterwards | `chart_drawing` | draw with Vela's own **drawing tools** — 76 types (trend line, channel, fib, Gann, Elliott, XABCD …), placed by `bars_ago` + price, real objects the operator can drag; a wrong anchor count is refused before drawing | | `chart_view` | read or set a **view setting** — chart type, log / invert / percent scale, countdown, time zone, session, watermark, status line, grid sync, the `?` shortcuts panel; every write is read back. Vela cannot *create* a price alert, so `alerts` only reads / clears the indicator-alert inbox | | `chart_marks` | event **marks** on the time axis, in one "Trader's Agent" group (`clear` only touches its own) | -| `chart_browse` | open the Library concept list in the pane (optional `family`) | +| `chart_browse` | open the catalogue in the drawer (optional `family`) | | `broker_state` | the paper (simulated Binance) account: cash, equity, positions, orders waiting for you | | `broker_propose` | propose a paper order — it only puts an Approve/Reject card on the chart; the agent cannot approve it | | `chart_draw` | run Pine and paint the boxes/lines/labels it builds on the chart overlay (optional `inputs`, as above) | @@ -276,7 +276,7 @@ and which calls return cleanly while doing nothing — is written down in Every tool carries MCP annotations (title, `readOnlyHint`, `destructiveHint`, `openWorldHint`), and the mutating ones answer with what the chart looks like *after* the call — a request echoed back is not a painted pane. Failures come back as a code beside the prose -(`NOT_RUNNABLE[while]`, `RUNTIME_CRASH[pinets-get_v]`, `TOO_FEW_BARS`, `ENGINE_UNAVAILABLE`, `TIMEOUT`), +(`NOT_RUNNABLE[import]`, `RUNTIME_CRASH[pinets-get_v]`, `TOO_FEW_BARS`, `ENGINE_UNAVAILABLE`, `TIMEOUT`), so a caller can branch without regex-matching a sentence. **Or the CLIs**, if you would rather shell out: @@ -316,7 +316,10 @@ systemctl --user restart traders-agent.service # only if you run the console a Uninstall: delete `~/.hermes/desktop-plugins/traders-desk/` in Hermes Desktop (**Capabilities → Plugins**), then remove the console's service (`systemctl --user disable --now traders-agent.service`). -Nothing else is written outside the repo; `console/agents/` holds the runtime state you can delete. +Outside the repo the console writes: `~/.local/state/traders-agent/` (`console.token`, the paper account `paper.json`), +`~/.local/share/traders-agent/` (preview cache `thumbs/`, Edge Stats `edge/`, the optional backtest venv `bt/`), +`~/.hermes/skills/trading/trader-desk/` (the skill, copied by `install.sh`) and, for shots the MCP server saves, +`/tmp`. `console/agents/` holds the runtime state. Delete those to remove every trace. ## Repository layout @@ -338,7 +341,12 @@ install.sh installs the plugin into $HERMES_HOME/desktop-plugins/ | Env | Default | Meaning | |---|---|---| | `PY` | `python3` | the interpreter for `console/start.sh` (must have `mcp`) | -| `PORT` | `8787` | console port — the plugin's frame points at `http://127.0.0.1:8787/` | +| `PORT` | `8787` | console port. `./install.sh` bakes `PORT` into the installed plugin's frame (re-run it after changing); the MCP server and `trader-chart` follow `LUXALGO_CONSOLE` | +| `LUXALGO_CONSOLE` | `http://127.0.0.1:8787` | where the MCP server, `trader-chart` and `library-indicator` find the console (set it with `hermes mcp add … --env LUXALGO_CONSOLE=http://127.0.0.1:9000` when `PORT` is not 8787) | +| `TRADER_CONSOLE_TOKEN_FILE` | `~/.local/state/traders-agent/console.token` | the POST token the console mints and the MCP server and CLI read | +| `TRADERS_AGENT_WORKDIR` | `~/Projects/luxalgo-web` if it exists, else `console/agents` | the folder the in-app study bridge runs the agent CLI in (never taken from a request) | +| `TRADERS_AGENT_ALLOW_LAN` | unset | with `--host 0.0.0.0`, let LAN peers receive the POST token; without it they get a read-only console | +| `TRADER_PAPER_FILE` | `~/.local/state/traders-agent/paper.json` | the paper account (use another path for a second test console) | | `LUXALGO_AGENTS_DIR` | `console/agents` | runtime state: chart bridge files, study threads, shots | | `HERMES_CLI` | `hermes` on `PATH` | CLI the in-app study bridge shells out to | | `LUXALGO_CHART_INLINE_WAIT` | `8` | seconds a command holds its request open waiting for the chart's pushed answer | @@ -353,7 +361,7 @@ install.sh installs the plugin into $HERMES_HOME/desktop-plugins/ ## Catalogue previews are kept on your machine -The Indicators modal shows each card the way LuxAlgo's own library does, with a chart preview. Those +The Indicators drawer shows each card the way LuxAlgo's own library does, with a chart preview. Those pictures are 1600×1000 PNGs on LuxAlgo's S3 (~29 KB each) and they are **slow to fetch one by one** — about 1–2 s each from a home connection, and a browser only opens six connections per host, so sixty cards used to fill in while you watched. The console therefore fetches each picture **once**, shrinks @@ -381,8 +389,9 @@ it from `http://127.0.0.1:8787/api/library/thumb`: **~5 ms warm instead of ~2 s* - **The bridge is not a headless renderer.** `trader-chart` and the MCP tools only take effect while a chart view is mounted (the Hermes pane or a browser tab); with none attached they fail fast with "no chart view attached" rather than hanging. Commands are pushed, so a view answers in tens of ms. -- **One console per machine** on one port. No order placement, no account, no positions — it is - read-only market data plus rendering. +- **One console per machine** on one port. No real orders and no brokerage account exist: the only trading is a + **simulated Binance spot paper account** (`broker_*`), where the agent can only propose and you approve. The rest is + market data plus rendering. - **The Library is non-commercial.** Its content is CC BY-NC-SA 4.0 — fine to read and cite here, not to resell or ship inside a paid product. - **Linux only, on purpose.** Built and verified on Omarchy (Arch + Hyprland) with Hermes Desktop. @@ -403,7 +412,7 @@ python3 -m compileall console/backend The suite is stdlib-only on purpose — the study store, the chat bridge, the chart bridge and the push channel are covered without a browser, a network, or the app — and the MCP tool layer runs against a -stub console. ≈700 tests; the MCP ones skip themselves when `fastmcp` is absent (CI sets +stub console. about 1,050 tests; the MCP ones skip themselves when `fastmcp` is absent (CI sets `TRADER_CHART_REQUIRE_MCP=1` so they cannot silently skip there). CI (`.github/workflows/ci.yml`) has three jobs: the plugin harness (Node 20 — the real plugin first, @@ -421,9 +430,10 @@ frame remounted (switch session and back). - **The plugin never appears in Capabilities → Plugins.** `Ctrl+K` → *Reload desktop plugins*; if it still does not show up, the folder was dropped after a failed load — rename `~/.hermes/desktop-plugins/traders-desk` and set `id:` inside `plugin.js` to the same new name. -- **The chart is empty and the log says `provider: synthetic`.** Binance's data provider was - unreachable; the chart still renders deterministic bars so the page never comes up blank. -- **Port 8787 busy.** `PORT=9000 ./console/start.sh`, then point the plugin's `CONSOLE_ORIGIN` at it. +- **The chart is empty.** Binance's data feed was unreachable (`chart_state` says `bars None`); the console does not + invent bars. Check the network, then `chart_reload`. +- **Port 8787 busy.** `PORT=9000 ./console/start.sh`, then `PORT=9000 ./install.sh` (it points the installed plugin at that + port) and set `LUXALGO_CONSOLE=http://127.0.0.1:9000` for the MCP server and CLI. ## Licence & credits @@ -454,8 +464,7 @@ pane beside the chat as intended. The plugin handles it as far as it can: the page asks for adoption and reveal, retries once a beat later (the app may still be rebuilding the tree when a page mounts), and when the pane is still not -visible it renders the console itself under a short note that says why — with *Ask again* and *Open in -a browser* in reach. The note only appears when the pane API exists and reports the pane hidden, so a +visible it renders the console itself under a short note that says why — with *Ask again* in reach. The note only appears when the pane API exists and reports the pane hidden, so a build without panes gets the plain console and no nagging. Recovery for a user who hits it: un-minimize the pane's group in `hermes.desktop.layoutTree.v2` diff --git a/THIRD-PARTY.md b/THIRD-PARTY.md index 9026ffd..074a775 100644 --- a/THIRD-PARTY.md +++ b/THIRD-PARTY.md @@ -176,7 +176,7 @@ The pane's chart surface is not fetched from a CDN — the page has to boot iden CDN failure used to look exactly like a broken chart. The vendor directory therefore carries the third-party browser builds, each beside its licence: -- **`vela/` — `@luxalgo/vela` 0.8.1** (chart, workspace, plugin SDK, Binance provider). +- **`vela/` — `@luxalgo/vela` 0.8.3** (chart, workspace, plugin SDK, Binance provider). **Licence: Apache-2.0** — commercial use included, attribution kept (`vela/LICENSE`, `vela/NOTICE`; 0.8.1 moves the NOTICE's attribution URL `luxalgo.com/vela` → `velacharts.dev`); LuxAlgo's Vela page states the invitation in its own words ("Ship it in an afternoon"; "Free, open source" — luxalgo.com/vela, read 2 Oct 2026). *(A "Fork it, vendor it, @@ -214,3 +214,26 @@ its exotic 15d/45d/15w higher-timeframe fetches falling back to the chart's bars reported). Scripts from the same four source repos that are GPL-3.0 or unlicensed (JustExecution's HTF suite, ict2023trader's set, fxraptor's `fractal-model`) are **not** bundled — concepts only, and any reimplementation is our own Pine (see `docs/PLAN-pinets-bump-and-indicator-pack.md`). + +## Network: every host this software contacts + +No account, no key and no telemetry. These are all the hosts, and what each sees. + +| Host | Who contacts it | What it sees | +|---|---|---| +| `127.0.0.1:8787` (console), `:8788` (optional backtest tier), `:8789` (optional Edge Stats engine) | plugin, console, MCP server, CLIs | local only | +| `mcp.luxalgo.com` | the console's MCP client (keyless) | Library searches and source requests | +| `api.binance.com` (and `api.binance.us` as Vela's fallback, `fapi`/`dapi` for futures) | the console's `/api/bars` and paper-broker price; also Vela and PineTS **from the browser** | the symbols and intervals you view, from your IP | +| `stream.binance.com`, `fstream.binance.com`, `stream.binance.us` | Vela, from the browser (live candles) | the symbols you view | +| `crypto-icons.ledger.com` | Vela, from the browser (symbol logos; also pre-connected by `index.html`) | the ticker you view | +| `luxalgo-production.s3.amazonaws.com`, `luxalgo-images-production.s3.us-east-1.amazonaws.com` | the console's preview cache | catalogue picture URLs | +| `data.binance.vision`, Dukascopy | the optional Edge Stats engine, only when you start a download | the symbol and range you ask for | +| GitHub, npm, PyPI | `install.sh` flags (`--with-edge`, `--with-backtest`) at install time | an ordinary download | + +The vendored bundles also contain code for Alpaca, Coinbase, Hyperliquid and Financial Modeling Prep providers. This console +registers none of them and none needs a key here, so they are never contacted. The console's page carries a +`Content-Security-Policy` whose `connect-src` lists exactly the hosts above that the browser itself contacts. + +## Vendored Zag packages: licence texts + +`console/frontend/vendor/zag/THIRD-PARTY-LICENSES.md` reproduces the MIT notice each package ships with. diff --git a/console/backend/agents_store.py b/console/backend/agents_store.py index 1b23f52..30de446 100644 --- a/console/backend/agents_store.py +++ b/console/backend/agents_store.py @@ -39,6 +39,17 @@ def _now() -> str: return time.strftime("%Y-%m-%dT%H:%M:%S%z") +NAME_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._:/-]{0,63}$") +SESSION_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$") + + +def _count(v) -> int: + try: + return max(0, int(v or 0)) + except (TypeError, ValueError, OverflowError): + raise ValueError("counters must be whole numbers") from None + + def validate(record: dict) -> dict: """Normalise a record or raise ValueError. Never trust the browser.""" if not isinstance(record, dict): @@ -57,6 +68,16 @@ def validate(record: dict) -> dict: if not isinstance(skills, list) or not isinstance(toolsets, list): raise ValueError("skills and toolsets must be lists of strings") counters = record.get("counters") or {} + if not isinstance(counters, dict): + raise ValueError("counters must be an object") + # These become argv for the agent CLI (`-s`, `-t`, `--resume`). A value that begins with "-" would be read there + # as another option (`-t --yolo`), so each must look like a name (audit SEC-2). + for label, values in (("skills", skills), ("toolsets", toolsets)): + for v in values[:8]: + if not isinstance(v, str) or not NAME_RE.match(v): + raise ValueError(f"each of {label} must be a plain name (letters, digits, . _ : / -, no leading dash), got {v!r}") + if record.get("session_id") and not SESSION_RE.match(str(record["session_id"])): + raise ValueError("session_id must be a plain token (letters, digits, . _ : -, no leading dash)") return { "id": sid, "name": name[:64], @@ -67,8 +88,8 @@ def validate(record: dict) -> dict: "session_id": (str(record["session_id"]) if record.get("session_id") else None), "created_at": str(record.get("created_at") or _now()), "last_active": record.get("last_active"), - "counters": {"runs": int(counters.get("runs", 0)), - "backtests": int(counters.get("backtests", 0))}, + "counters": {"runs": _count(counters.get("runs")), + "backtests": _count(counters.get("backtests"))}, } diff --git a/console/backend/backtest_service.py b/console/backend/backtest_service.py index f876609..8726886 100644 --- a/console/backend/backtest_service.py +++ b/console/backend/backtest_service.py @@ -26,6 +26,7 @@ import argparse import json +import re import os import threading import time @@ -47,9 +48,14 @@ def _klines_binance(symbol: str, interval: str, bars: int) -> "object": """Public klines REST, paginated. No key, no account — the same feed the chart itself uses.""" + import urllib.parse import urllib.request import pandas as pd + if not _SYMBOL.match(symbol or "") or not _INTERVAL.match(interval or ""): + raise ValueError(f"not a Binance symbol / interval: {symbol!r} {interval!r}") + bars = max(1, min(MAX_BARS, int(bars))) + symbol, interval = urllib.parse.quote(symbol), urllib.parse.quote(interval) out, end = [], None while len(out) < bars: want = min(1000, bars - len(out)) @@ -71,13 +77,29 @@ def _klines_binance(symbol: str, interval: str, bars: int) -> "object": return df +_LOCAL_NAME = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$") +_SYMBOL = re.compile(r"^[A-Z0-9]{3,20}$") +_INTERVAL = re.compile(r"^[0-9]{1,2}[smhdwM]$") +MAX_BARS = 20000 +MAX_COMBOS_SPAN = 120 # a sweep window wider than this is ~7,000 pairs; [1, 5000] was ~12.5 million +MAX_TOP = 50 +MAX_BODY = 4 * 1024 * 1024 + + def _bars_local(name: str) -> "object": - """A file the operator owns: CSV or Parquet in the data dir. Same schema the chart uses.""" + """A file the operator owns: CSV or Parquet in the data dir. Same schema the chart uses. + + The name is a bare file name: `local:../../etc/passwd` and `local:/etc/hostname` used to read any file (audit + SEC-7).""" import pandas as pd - base = Path(_DATA_DIR) + if not _LOCAL_NAME.match(name or ""): + raise ValueError(f"local data names are plain file names (letters, digits, . _ -), got {name!r}") + base = Path(_DATA_DIR).resolve() for suffix in (".parquet", ".csv", ""): - p = base / (name if name.endswith(suffix) and suffix else name + suffix) + p = (base / (name if name.endswith(suffix) and suffix else name + suffix)).resolve() + if base not in p.parents: + continue if p.exists(): df = pd.read_parquet(p) if p.suffix == ".parquet" else pd.read_csv(p, index_col=0) df.index = pd.to_datetime(df.index, utc=True) @@ -90,6 +112,7 @@ def _bars_local(name: str) -> "object": def load_bars(source: str, bars: int, inline: list | None = None): + bars = max(0, min(MAX_BARS, int(bars or 0))) if inline: import pandas as _pd df = _pd.DataFrame(inline) @@ -111,6 +134,18 @@ def load_bars(source: str, bars: int, inline: list | None = None): # ─────────────────────────── engine ─────────────────────────── +def _clean_nan(v): + """JSON has no NaN / Infinity: a run with no trades has NaN Sharpe and an infinite profit factor, which + json.dumps wrote as bare `NaN` / `Infinity` that strict parsers refuse (audit BE-18).""" + if isinstance(v, float): + return v if v == v and v not in (float("inf"), float("-inf")) else None + if isinstance(v, dict): + return {k: _clean_nan(x) for k, x in v.items()} + if isinstance(v, (list, tuple)): + return [_clean_nan(x) for x in v] + return v + + def _num(x, default: float = 0.0) -> float: """vectorbt hands back a Series in places even for a single column — take the last value. @@ -183,9 +218,12 @@ def run_ma_cross_sweep(spec: dict) -> dict: import vectorbt as vbt lo, hi = spec.get("window", [5, 60]) + lo, hi = int(lo), int(hi) + if lo < 1 or hi < lo or hi - lo > MAX_COMBOS_SPAN: + raise ValueError(f"window must satisfy 1 <= lo <= hi and hi - lo <= {MAX_COMBOS_SPAN}") fee = float(spec.get("fee", 0.001)) init = float(spec.get("init_cash", 10000)) - top_n = int(spec.get("top", 10)) + top_n = max(1, min(MAX_TOP, int(spec.get("top", 10)))) df = load_bars(str(spec.get("source", "binance:BTCUSDT:30m")), int(spec.get("bars", 1000)), inline=spec.get("inline") or None) price = df["close"] @@ -219,7 +257,7 @@ def run_signals(spec: dict) -> dict: summary cannot carry. Entries and exits are matched onto the chart's own bar timestamps, and timestamps that land on no bar are reported rather than silently dropped. """ - import numpy as _np + import numpy as _np # noqa: F401 import pandas as _pd import vectorbt as _vbt fee = float(spec.get("fee", 0.001)) @@ -313,8 +351,20 @@ class Handler(BaseHTTPRequestHandler): def log_message(self, fmt, *args): # keep the journal readable print(f"[backtest] {fmt % args}", flush=True) + def _gate(self) -> bool: + """The same door as the console's: a local Host, and no browser page (no Origin). This service has no token, + so without this any web page could POST `text/plain` to 127.0.0.1:8788/run, and a DNS-rebinding page could + read the answers (audit SEC-7). The console proxies with urllib, which sends neither Origin nor a foreign + Host.""" + host = (self.headers.get("Host") or "").strip().lower() + name = host.rsplit(":", 1)[0].strip("[]") if not host.startswith("[") else host.split("]")[0].lstrip("[") + if name not in ("127.0.0.1", "localhost", "::1", "0.0.0.0") or self.headers.get("Origin"): + self._send(403, {"ok": False, "error": "refused: this service answers the Trader's Agent console only"}) + return False + return True + def _send(self, code: int, body: dict): - raw = json.dumps(body).encode("utf-8") + raw = json.dumps(_clean_nan(body), allow_nan=False).encode("utf-8") self.send_response(code) self.send_header("Content-Type", "application/json") self.send_header("Content-Length", str(len(raw))) @@ -322,6 +372,8 @@ def _send(self, code: int, body: dict): self.wfile.write(raw) def do_GET(self): # noqa: N802 + if not self._gate(): + return if self.path.rstrip("/") in ("/health", "/api/backtest/health"): self._send(200, {"ok": True, "version": VERSION, "vectorbt": _STATE["vectorbt"], "warm": _STATE["warm"], "jit_ms": _STATE["jit_ms"], @@ -331,12 +383,20 @@ def do_GET(self): # noqa: N802 self._send(404, {"ok": False, "error": "GET /health"}) def do_POST(self): # noqa: N802 + if not self._gate(): + return path = self.path.rstrip("/") or "/" if path not in ("/run", "/sweep", "/api/backtest", "/api/backtest/sweep"): self._send(404, {"ok": False, "error": "POST /run or /sweep"}) return try: length = int(self.headers.get("Content-Length") or 0) + if length < 0 or length > MAX_BODY: + self._send(413, {"ok": False, "error": f"body over {MAX_BODY} bytes"}) + return + if "json" not in (self.headers.get("Content-Type") or "").lower(): + self._send(415, {"ok": False, "error": "Content-Type must be application/json"}) + return spec = json.loads(self.rfile.read(length).decode("utf-8") or "{}") except (ValueError, UnicodeDecodeError) as exc: self._send(400, {"ok": False, "error": f"bad JSON body: {exc}"}) diff --git a/console/backend/broker.py b/console/backend/broker.py index 45f9135..0fbeadf 100644 --- a/console/backend/broker.py +++ b/console/backend/broker.py @@ -11,6 +11,7 @@ (ccxt + vault keys) are a later step and would sit behind this same propose → approve gate. """ +import copy import json import math import os @@ -54,17 +55,27 @@ def _load(self) -> dict: with open(self.path, encoding="utf-8") as fh: s = json.load(fh) if not isinstance(s, dict) or not isinstance(s.get("orders"), list) \ - or not isinstance(s.get("positions"), dict) or not isinstance(s.get("cash"), (int, float)): + or not isinstance(s.get("positions"), dict) or not isinstance(s.get("cash"), (int, float)) \ + or not math.isfinite(s["cash"]): raise ValueError("shape") + # A hand-edited or older file may miss keys; fill them instead of answering 500 later (audit BE-12). + s.setdefault("start_cash", self.start_cash) + s.setdefault("realized", 0.0) + ids = [o.get("id", 0) for o in s["orders"] if isinstance(o, dict) and isinstance(o.get("id"), int)] + s["next_id"] = max(int(s.get("next_id") or 1), (max(ids) + 1) if ids else 1) return s except FileNotFoundError: return _fresh(self.start_cash) - except (ValueError, OSError): - try: # keep the broken file for inspection + except ValueError: # really unparsable: keep the broken file for inspection + try: os.replace(self.path, f"{self.path}.bad{int(time.time())}") except OSError: pass return _fresh(self.start_cash) + except OSError as exc: + # A transient read error (EIO, EACCES) is NOT corruption: starting a fresh 10,000 account over a good + # file would silently throw the real one away. Refuse instead (audit BE-12). + raise BrokerError("broker_unavailable", f"cannot read the paper account at {self.path}: {exc}") def _save(self) -> None: d = os.path.dirname(self.path) or "." @@ -73,6 +84,8 @@ def _save(self) -> None: try: with os.fdopen(fd, "w", encoding="utf-8") as fh: json.dump(self._s, fh, separators=(",", ":")) + fh.flush() + os.fsync(fh.fileno()) os.chmod(tmp, 0o600) os.replace(tmp, self.path) except BaseException: @@ -82,6 +95,21 @@ def _save(self) -> None: pass raise + def _commit(self, before: dict) -> None: + """Save, or put the account back exactly as it was. A failed write used to leave the fill in memory (and a + retry answering "already filled") while the file still showed the order pending (audit BE-8).""" + try: + self._save() + except BaseException: + self._s = before + raise + + @staticmethod + def _dust(qty: float) -> float: + """Float error grows with the size: 1e-12 absolute left ghost positions and refused legitimate sells for + quantities in the millions (audit BE-13).""" + return max(1e-12, 1e-9 * abs(qty)) + def _trim(self) -> None: done = [o for o in self._s["orders"] if o["status"] != "pending"] if len(done) > self.keep: @@ -105,24 +133,27 @@ def propose(self, symbol, side, qty, note: str = "") -> dict: with self._lock: if sum(1 for o in self._s["orders"] if o["status"] == "pending") >= self.max_pending: raise BrokerError("too_many_pending", f"{self.max_pending} proposals are waiting — approve or reject some first") + before = copy.deepcopy(self._s) o = {"id": self._s["next_id"], "symbol": sym, "side": sd, "qty": q, "note": str(note or "")[:200], "status": "pending", "ts": time.time()} self._s["next_id"] += 1 self._s["orders"].append(o) - self._save() + self._commit(before) return dict(o) def reject(self, order_id) -> dict: with self._lock: + before = copy.deepcopy(self._s) o = self._pending(order_id) o["status"] = "rejected" o["closed"] = time.time() self._trim() - self._save() + self._commit(before) return dict(o) def approve(self, order_id) -> dict: with self._lock: + before = copy.deepcopy(self._s) o = self._pending(order_id) px = float(self.price_of(o["symbol"])) # may raise no_price → the card stays if not math.isfinite(px) or px <= 0: @@ -135,6 +166,9 @@ def approve(self, order_id) -> dict: raise BrokerError("insufficient_cash", f"needs {gross + fee:,.2f} but cash is {self._s['cash']:,.2f}") self._s["cash"] -= gross + fee + # The entry fee is a cost the moment it is paid. It used to appear nowhere in P&L, so `realized` + # understated a round trip by it and never reconciled with equity (audit BE-3). + self._s["realized"] -= fee if pos: tot = pos["qty"] + o["qty"] pos["avg"] = (pos["avg"] * pos["qty"] + px * o["qty"]) / tot @@ -142,17 +176,17 @@ def approve(self, order_id) -> dict: else: self._s["positions"][o["symbol"]] = {"qty": o["qty"], "avg": px} else: - if not pos or pos["qty"] + 1e-12 < o["qty"]: + if not pos or pos["qty"] + self._dust(pos["qty"]) < o["qty"]: have = pos["qty"] if pos else 0 raise BrokerError("insufficient_position", f"cannot sell {o['qty']} — holding {have} (spot, no shorting)") self._s["cash"] += gross - fee self._s["realized"] += (px - pos["avg"]) * o["qty"] - fee pos["qty"] -= o["qty"] - if pos["qty"] <= 1e-12: + if pos["qty"] <= self._dust(o["qty"]): del self._s["positions"][o["symbol"]] o.update(status="filled", price=px, fee=fee, closed=time.time()) self._trim() - self._save() + self._commit(before) return dict(o) def _pending(self, order_id) -> dict: @@ -176,13 +210,20 @@ def get(self, order_id) -> dict: raise BrokerError("unknown_order", f"no order {order_id}") def state(self) -> dict: + # Prices are read OUTSIDE the lock: one blocking ticker call per position under it made propose / approve + # wait behind a slow exchange (audit BE-7). + with self._lock: + held = {sym: dict(p) for sym, p in self._s["positions"].items()} + marks = {} + for sym, p in sorted(held.items()): + try: + marks[sym] = float(self.price_of(sym)) + except BrokerError: + marks[sym] = p["avg"] # no price: show cost, not a made-up number with self._lock: positions, equity = [], self._s["cash"] for sym, p in sorted(self._s["positions"].items()): - try: - mark = float(self.price_of(sym)) - except BrokerError: - mark = p["avg"] # no price: show cost, not a made-up number + mark = marks.get(sym, p["avg"]) positions.append({"symbol": sym, "qty": p["qty"], "avg": p["avg"], "mark": mark, "unrealized": (mark - p["avg"]) * p["qty"]}) equity += mark * p["qty"] @@ -195,5 +236,7 @@ def state(self) -> dict: def reset(self) -> None: with self._lock: + nxt = self._s.get("next_id", 1) self._s = _fresh(self.start_cash) + self._s["next_id"] = nxt # ids never restart: a stale card for old #1 must not approve a new #1 self._save() diff --git a/console/backend/chart_bridge.py b/console/backend/chart_bridge.py index 592abde..3c131c9 100755 --- a/console/backend/chart_bridge.py +++ b/console/backend/chart_bridge.py @@ -17,7 +17,10 @@ import base64 import json +import os import re +import tempfile +import threading import time from pathlib import Path from typing import Any @@ -25,6 +28,11 @@ STATE_FILE = "state.json" COMMANDS_FILE = "commands.json" RESULTS_FILE = "results.json" +NEXT_ID_FILE = "next_id.json" +# Every read-modify-write below runs under this lock: ThreadingHTTPServer gives each request its own thread, and +# two agent calls in parallel used to share one fixed temp name (HTTP 500s), read the same last id (duplicate +# ids, so the page dropped the second command) and overwrite each other's list (lost commands). Audit 8 Oct, BE-1. +_LOCK = threading.RLock() MAX_SHOTS = 12 # keep the last handful of pictures; this box has a small disk MAX_RESULTS = 60 # the agent only ever reads the newest results STALE_AFTER = 30.0 # a state older than this means "no chart is open" @@ -50,9 +58,18 @@ def _read(path: Path, default: Any) -> Any: def _write(path: Path, value: Any) -> None: - tmp = path.with_suffix(path.suffix + ".tmp") - tmp.write_text(json.dumps(value, ensure_ascii=False), "utf-8") - tmp.replace(path) + """Atomic: a temp file of its OWN name (never shared between two writers), then a rename.""" + fd, name = tempfile.mkstemp(dir=str(path.parent), prefix=path.name + ".", suffix=".tmp") + try: + with os.fdopen(fd, "w", encoding="utf-8") as fh: + fh.write(json.dumps(value, ensure_ascii=False)) + os.replace(name, path) + except BaseException: + try: + os.unlink(name) + except OSError: + pass + raise def _decode_shot(root: str | Path, name: str, data_url: str) -> str | None: @@ -101,6 +118,11 @@ def _shot_mtime(path: Path) -> float: def save_state(root: str | Path, payload: dict) -> dict: """The page's heartbeat: what the chart is showing. Never raises on odd input.""" + with _LOCK: + return _save_state(root, payload) + + +def _save_state(root: str | Path, payload: dict) -> dict: d = _chart_dir(root) prev = _read(d / STATE_FILE, {}) or {} state = { @@ -164,13 +186,33 @@ def load_state(root: str | Path, max_age: float = STALE_AFTER) -> dict: def enqueue(root: str | Path, command: dict) -> dict: """Queue one action for the live chart. Returns the command with the id the page will report back.""" - d = _chart_dir(root) - cmds = _read(d / COMMANDS_FILE, []) or [] - cid = int(cmds[-1]["id"]) + 1 if cmds else 1 - entry = {"id": cid, "at": time.time(), **{k: v for k, v in command.items() if k != "id"}} - cmds.append(entry) - _write(d / COMMANDS_FILE, cmds[-MAX_RESULTS:]) - return entry + with _LOCK: + d = _chart_dir(root) + cmds = _read(d / COMMANDS_FILE, []) or [] + cid = _next_id(d, cmds) + entry = {"id": cid, "at": time.time(), **{k: v for k, v in command.items() if k != "id"}} + cmds.append(entry) + _write(d / COMMANDS_FILE, cmds[-MAX_RESULTS:]) + return entry + + +def _next_id(d: Path, cmds: list) -> int: + """The next command id. It lives in its own file and only ever grows: derived from the (capped, and + recreated-empty-on-a-parse-error) command list, ids restarted at 1 and an old result answered for a new + command (BE-16).""" + last = 0 + try: + last = int((_read(d / NEXT_ID_FILE, {}) or {}).get("last") or 0) + except (TypeError, ValueError): + last = 0 + for c in cmds: + try: + last = max(last, int(c.get("id") or 0)) + except (TypeError, ValueError): + continue + cid = last + 1 + _write(d / NEXT_ID_FILE, {"last": cid}) + return cid def commands_since(root: str | Path, since: int = 0) -> list[dict]: @@ -181,8 +223,18 @@ def commands_since(root: str | Path, since: int = 0) -> list[dict]: def record_result(root: str | Path, payload: dict) -> dict: """The page's report for one command. A picture in the payload is decoded and replaced by its path.""" + try: + rid = int(payload.get("id")) + except (TypeError, ValueError, OverflowError): + raise ValueError("a result needs the integer id of the command it answers") from None + if rid <= 0: + raise ValueError("a result needs the id of the command it answers (a positive integer)") + with _LOCK: + return _record_result(root, payload, rid) + + +def _record_result(root: str | Path, payload: dict, rid: int) -> dict: d = _chart_dir(root) - rid = int(payload.get("id") or 0) result = { "id": rid, "at": time.time(), @@ -238,6 +290,20 @@ def record_result(root: str | Path, payload: dict) -> dict: # why, and the settings the script does declare. Named here because the store whitelists — without # it the agent is told "ok" and never that a label it sent was ignored. "inputs": payload.get("inputs"), + # Reported by the page, dropped by this whitelist until the 8 Oct audit (BE-15): `trades` is the whole + # point of the `signals` op (the trades the backtester prices), the rest are the after-state of their doors. + "count": payload.get("count"), + "trades": payload.get("trades"), + "theme": payload.get("theme"), + "replay": payload.get("replay"), + "reloading": payload.get("reloading"), + "rect": payload.get("rect"), + "palette": payload.get("palette"), + "overlay": payload.get("overlay"), + "opened": payload.get("opened"), + "lines": payload.get("lines"), + "drawer": payload.get("drawer"), + "alreadyPresent": payload.get("alreadyPresent"), } if payload.get("shot"): path = _decode_shot(root, f"shot-{rid}", str(payload["shot"])) diff --git a/console/backend/chart_stream.py b/console/backend/chart_stream.py index 27858ff..fc5c0a2 100644 --- a/console/backend/chart_stream.py +++ b/console/backend/chart_stream.py @@ -49,7 +49,7 @@ def attach(self) -> tuple[int, queue.Queue]: with self._lock: cid = self._next self._next += 1 - inbox: queue.Queue = queue.Queue() + inbox: queue.Queue = queue.Queue(maxsize=256) # bounded: a half-open peer must not grow memory for ever self._clients[cid] = inbox return cid, inbox @@ -131,7 +131,14 @@ def publish(self, payload: dict, command_id: int | None = None) -> int: sent = 0 for inbox in targets: try: - inbox.put_nowait(blob) + try: + inbox.put_nowait(blob) + except queue.Full: # a stuck view: drop its OLDEST event, keep the newest + try: + inbox.get_nowait() + except queue.Empty: + pass + inbox.put_nowait(blob) sent += 1 except Exception: # noqa: BLE001 — a dead client must never break the caller self.dropped += 1 diff --git a/console/backend/chat.py b/console/backend/chat.py index a719a4d..c46b7dd 100644 --- a/console/backend/chat.py +++ b/console/backend/chat.py @@ -16,6 +16,7 @@ import re import shutil import subprocess +import tempfile import time DEFAULT_CLI = os.environ.get( @@ -54,7 +55,8 @@ def extract_pine(reply: str) -> str: return match.group(1).strip() if match else "" -CHART_ACTION_RE = re.compile(r"^\s*CHART:\s*(.+?)\s*$", re.I | re.M) +# [ \t] not \s: with \s a 20 KB reply of blank lines took ~1.5 s here and held the GIL for all of it (audit SEC-17). +CHART_ACTION_RE = re.compile(r"^[ \t]*CHART:[ \t]*(.*\S)[ \t]*$", re.I | re.M) MARKET_KV_RE = re.compile(r"(\w+)\s*=\s*([A-Za-z0-9._\-/]+)") ADD_RE = re.compile(r"^add\s+([a-z0-9\-]+)", re.I) @@ -95,7 +97,9 @@ def run_agent(cli: str, agent: dict, message: str, context: dict | None = None, learnings: str = "", extra_args: list[str] | None = None) -> dict: """Run one prompt through `hermes -z`. Never raises; always returns a reportable dict.""" prompt = compose_prompt(agent, message, context, learnings=learnings) - usage_file = os.path.join("/tmp", f"hermes-usage-{os.getpid()}-{int(time.time() * 1000)}.json") + # A private 0700 directory, not a guessable name in /tmp (audit SEC-14). + usage_dir = tempfile.mkdtemp(prefix="hermes-usage-") + usage_file = os.path.join(usage_dir, "usage.json") cmd = [cli, "-z", prompt, "--usage-file", usage_file] for skill in agent.get("skills") or []: cmd += ["-s", skill] @@ -104,6 +108,10 @@ def run_agent(cli: str, agent: dict, message: str, context: dict | None = None, if resume: cmd += ["--resume", resume] if workdir: + if not os.path.isdir(workdir): + shutil.rmtree(usage_dir, ignore_errors=True) + return {"ok": False, "reason": f"the agent's working folder does not exist: {workdir} " + "(set TRADERS_AGENT_WORKDIR)", "elapsed_ms": 0} cmd += ["--in", workdir] cmd += list(extra_args or []) @@ -112,9 +120,11 @@ def run_agent(cli: str, agent: dict, message: str, context: dict | None = None, proc = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout, cwd=workdir or None, stdin=subprocess.DEVNULL) except subprocess.TimeoutExpired: + shutil.rmtree(usage_dir, ignore_errors=True) return {"ok": False, "reason": f"agent timed out after {timeout}s", "elapsed_ms": int((time.time() - started) * 1000)} except OSError as exc: + shutil.rmtree(usage_dir, ignore_errors=True) return {"ok": False, "reason": f"could not start the agent CLI: {exc}", "elapsed_ms": 0} elapsed_ms = int((time.time() - started) * 1000) @@ -125,10 +135,7 @@ def run_agent(cli: str, agent: dict, message: str, context: dict | None = None, except (OSError, json.JSONDecodeError): usage = None finally: - try: - os.unlink(usage_file) - except OSError: - pass + shutil.rmtree(usage_dir, ignore_errors=True) session_id = usage.get("session_id") if isinstance(usage, dict) else None diff --git a/console/backend/library_thumbs.py b/console/backend/library_thumbs.py index 3923bdf..abbf9be 100644 --- a/console/backend/library_thumbs.py +++ b/console/backend/library_thumbs.py @@ -22,6 +22,7 @@ import re import shutil import subprocess +import tempfile import threading import time import urllib.error @@ -40,7 +41,7 @@ "luxalgo-production.s3.amazonaws.com", "luxalgo-images-production.s3.us-east-1.amazonaws.com", ) -_HOST_RULE = re.compile(r"^https?://(?:[a-z0-9-]+\.)*s3(?:[.-][a-z0-9-]+)*\.amazonaws\.com/", re.I) +MAX_BYTES = 4_000_000 # a card is ~30 KB; nothing legitimate here is bigger than a few MB CACHE_DIR = Path(os.environ.get("TRADERS_AGENT_THUMBS") or Path.home() / ".local" / "share" / "traders-agent" / "thumbs") @@ -72,12 +73,27 @@ def _clamp(width: int) -> int: def _allowed(url: str) -> bool: - """LuxAlgo's own buckets only, and only over https. Anything else is refused, not fetched.""" - if not url.startswith("https://"): + """LuxAlgo's two buckets only, over https, by EXACT host. A "contains luxalgo" rule on any S3 host let someone + else's bucket (or an S3 website endpoint that redirects) through (audit SEC-8).""" + if not isinstance(url, str) or not url.startswith("https://"): return False - if any(url.startswith(f"https://{host}/") for host in ALLOWED_HOSTS): - return True - return bool(_HOST_RULE.match(url)) and "luxalgo" in url.split("//", 1)[1].split("/", 1)[0] + return any(url.startswith(f"https://{host}/") for host in ALLOWED_HOSTS) + + +def _kind(raw: bytes) -> str | None: + """The picture type by its first bytes, never by name. Only these reach vips / ImageMagick / ffmpeg.""" + if raw[:8] == b"\x89PNG\r\n\x1a\n": + return "png" + if raw[:3] == b"\xff\xd8\xff": + return "jpg" + if raw[:4] == b"RIFF" and raw[8:12] == b"WEBP": + return "webp" + return None + + +class _NoRedirect(urllib.request.HTTPRedirectHandler): + def redirect_request(self, *args, **kwargs): # a 30x from the bucket is an answer, not a path to follow + return None def _tag(url: str) -> str: @@ -113,11 +129,13 @@ def _fetch(url: str) -> bytes | None: # URL with a space in it, so quote the unsafe characters and keep the ones that mean structure. safe = urllib.parse.quote(url, safe=":/?&=#%+,;@[]~") request = urllib.request.Request(safe, headers={"User-Agent": "traders-agent-console/1.0"}) + opener = urllib.request.build_opener(_NoRedirect) try: - with urllib.request.urlopen(request, timeout=FETCH_TIMEOUT) as response: # noqa: S310 + with opener.open(request, timeout=FETCH_TIMEOUT) as response: # noqa: S310 if response.status != 200: return None - return response.read() + raw = response.read(MAX_BYTES + 1) + return raw if len(raw) <= MAX_BYTES else None except (urllib.error.URLError, urllib.error.HTTPError, TimeoutError, OSError, ValueError): return None @@ -135,6 +153,16 @@ def _shrink(src: Path, dst: Path, width: int) -> bool: return done.returncode == 0 and dst.exists() and dst.stat().st_size > 0 +_KEY_LOCKS: dict[str, threading.Lock] = {} + + +def _key_lock(name: str) -> threading.Lock: + with _LOCK: + if len(_KEY_LOCKS) > 512: + _KEY_LOCKS.clear() + return _KEY_LOCKS.setdefault(name, threading.Lock()) + + def thumb(slug: str, url: str, width: int = DEFAULT_WIDTH) -> tuple[bytes, str] | None: """The bytes to send for one card. `None` means "no preview, say so" — never a stand-in image.""" width = _clamp(width) @@ -146,24 +174,38 @@ def thumb(slug: str, url: str, width: int = DEFAULT_WIDTH) -> tuple[bytes, str] pass if not _allowed(url): return None - raw = _fetch(url) - if raw is None: - return None - CACHE_DIR.mkdir(parents=True, exist_ok=True) - tmp_png = dst.with_suffix(".src.png") - try: - tmp_png.write_bytes(raw) - if _shrink(tmp_png, dst, width): - return dst.read_bytes(), "image/jpeg" - # No converter on this machine: the original is bigger but it is the real picture. - return raw, "image/png" - except OSError: - return raw, "image/png" - finally: + # One build per picture at a time: the modal and the background warmer ask for the same key together, and the + # second used to read the first's half-written file, which the browser then kept for a year (audit BE-10). + with _key_lock(dst.name): try: - tmp_png.unlink() + if dst.exists() and dst.stat().st_size > 0: + return dst.read_bytes(), "image/jpeg" except OSError: pass + raw = _fetch(url) + kind = _kind(raw) if raw else None + if raw is None or kind is None: + return None + CACHE_DIR.mkdir(parents=True, exist_ok=True) + fd, name = tempfile.mkstemp(dir=str(CACHE_DIR), prefix=".src-", suffix="." + kind) + tmp_src = Path(name) + tmp_dst = tmp_src.with_name(tmp_src.name + ".jpg") + try: + with os.fdopen(fd, "wb") as fh: + fh.write(raw) + if _shrink(tmp_src, tmp_dst, width): + os.replace(tmp_dst, dst) # atomic: nobody ever reads a partial file + return dst.read_bytes(), "image/jpeg" + # No converter on this machine: the original is bigger but it is the real picture. + return raw, ("image/" + ("jpeg" if kind == "jpg" else kind)) + except OSError: + return raw, ("image/" + ("jpeg" if kind == "jpg" else kind)) + finally: + for f in (tmp_src, tmp_dst): + try: + f.unlink() + except OSError: + pass def _build(key: str, slug: str, url: str, width: int) -> None: diff --git a/console/backend/mvp_server.py b/console/backend/mvp_server.py index 403fcd9..7da494f 100644 --- a/console/backend/mvp_server.py +++ b/console/backend/mvp_server.py @@ -119,6 +119,9 @@ def cached(key: str, producer): value = producer() with CACHE_LOCK: CACHE[key] = (now, value) + if len(CACHE) > 256: # bounded: every distinct query used to stay in memory for good + for old in sorted(CACHE, key=lambda k: CACHE[k][0])[:len(CACHE) - 192]: + CACHE.pop(old, None) return value @@ -133,6 +136,13 @@ def _as_list(payload, *keys): return [] +def _int(value, default: int, lo: int, hi: int) -> int: + try: + return max(lo, min(hi, int(value))) + except (TypeError, ValueError): + return default + + def build_router(frontend: Path): """Return a handler class bound to the given frontend directory.""" @@ -145,7 +155,6 @@ def _send(self, status: int, body: bytes, ctype: str) -> None: self.send_response(status) self.send_header("Content-Type", ctype) self.send_header("Content-Length", str(len(body))) - self.send_header("Access-Control-Allow-Origin", "*") self.send_header("Cache-Control", "no-store") self.end_headers() if self.command != "HEAD": @@ -165,6 +174,12 @@ def log_message(self, fmt, *args): # quieter console # ---------- routing ---------- def do_GET(self) -> None: # noqa: N802 + # The same Host gate as the main console: a DNS-rebinding page reaches 127.0.0.1 with its own name as Host. + host = (self.headers.get("Host") or "").strip().lower() + name = host.split("]")[0].lstrip("[") if host.startswith("[") else host.rsplit(":", 1)[0] + if name not in ("127.0.0.1", "localhost", "::1"): + self.json_err("refused: non-local Host", 403) + return parsed = urllib.parse.urlparse(self.path) path = parsed.path query = {k: v[0] for k, v in urllib.parse.parse_qs(parsed.query).items()} @@ -196,7 +211,7 @@ def route_api(self, path: str, q: dict) -> None: if not term: self.json_err("q is required", 400) return - args = {"query": term, "limit": int(q.get("limit", 12))} + args = {"query": term, "limit": _int(q.get("limit"), 12, 1, 50)} if q.get("type") in {"all", "concepts", "indicators"}: args["type"] = q["type"] if q.get("family"): @@ -206,7 +221,7 @@ def route_api(self, path: str, q: dict) -> None: return if path == "/api/indicators": - args = {"page_size": min(int(q.get("page_size", 24)), 100)} + args = {"page_size": _int(q.get("page_size"), 24, 1, 100)} if q.get("family"): args["family"] = q["family"] if q.get("text"): diff --git a/console/backend/server.py b/console/backend/server.py index fceed7f..97ea2c0 100755 --- a/console/backend/server.py +++ b/console/backend/server.py @@ -37,11 +37,11 @@ import argparse import asyncio import concurrent.futures +import ipaddress import json import secrets import os import re -import socketserver import sys import threading import time @@ -172,6 +172,8 @@ def _study_input(fn, *args, **kwargs): return fn(*args, **kwargs) except ValueError as exc: raise ApiError(str(exc), HTTPStatus.BAD_REQUEST, "bad_request") from exc + except FileNotFoundError as exc: + raise ApiError("no such study", HTTPStatus.NOT_FOUND, "unknown_agent") from exc class MCPUnavailable(ApiError): @@ -393,7 +395,7 @@ async def _run_forever(self) -> None: self.last_error = f"{type(exc).__name__}: {exc}" self._ready.clear() self._session = None - self._fail_pending(self.last_error or "MCP session closed") + await self._fail_pending(self.last_error or "MCP session closed") if self._shutdown.is_set(): break self._reconnects += 1 @@ -630,7 +632,17 @@ def ep_indicators(params: dict) -> dict: } +_CATALOGUE_LOCK = threading.Lock() + + def ep_catalogue(params: dict) -> dict: + """One walk at a time: every concurrent first call used to do its own nine-plus serial MCP calls (audit BE-11); + the callers that wait find the finished answer on disk.""" + with _CATALOGUE_LOCK: + return _ep_catalogue(params) + + +def _ep_catalogue(params: dict) -> dict: """Every row of the catalogue in one answer — families, counts, descriptions. Why one call instead of paging: the grid wants to group by family and show a reading under each @@ -652,6 +664,8 @@ def ep_catalogue(params: dict) -> dict: rows: list[dict] = [] page = 0 + upstream_total = None + last_full = False while page < CATALOGUE_MAX_PAGES: # `ep_indicators` reads the shape a query string produces (a list per key — see `_one`), so # pass lists even though this call never came from HTTP. Handing it bare strings is how @@ -659,10 +673,16 @@ def ep_catalogue(params: dict) -> dict: data = ep_indicators({"page": [str(page)], "page_size": [str(CATALOGUE_PAGE)], "sort": ["family"], "direction": ["asc"]}) chunk = (data or {}).get("indicators") or [] + if page == 0: + try: + upstream_total = int((data or {}).get("total")) + except (TypeError, ValueError): + upstream_total = None if not chunk: break rows.extend(chunk) page += 1 + last_full = len(chunk) >= CATALOGUE_PAGE if len(chunk) < CATALOGUE_PAGE: break @@ -722,6 +742,12 @@ def ep_catalogue(params: dict) -> dict: out = {"rows": rows, "total": len(rows), "groups": groups, "pages": page, "fetched_at": time.time(), "cached": False} + # A page that came back empty or unparsable (a rate-limit sentence, a hiccup) ends the walk early, and the short + # answer used to be saved and served as complete for 12 h (audit BE-11). Compare with what the upstream said. + if (upstream_total is not None and len(rows) < upstream_total) or (last_full and page >= CATALOGUE_MAX_PAGES): + out["partial"] = True + out["upstream_total"] = upstream_total + return out # served, but never kept: the next ask walks again try: os.makedirs(AGENTS_ROOT, exist_ok=True) tmp = path + ".tmp" @@ -1107,11 +1133,24 @@ def ep_chart_state(params: dict) -> dict: return load_chart_state(AGENTS_ROOT) +# What Binance spot actually serves. A capital M here is a MONTH (Binance's own spelling, and what the page and the +# Pine worker send); the display form below ("30M") is minutes. The old table turned "1M" into one MINUTE, so a +# monthly chart or request.security(..., "M") got 1-minute bars with no error (audit 8 Oct, BE-6). +BINANCE_INTERVALS = frozenset(("1s", "1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "6h", "8h", "12h", "1d", "3d", "1w", "1M")) + + +def normalise_interval(interval: str) -> str: + iv = str(interval or "1h").strip() or "1h" + if iv in BINANCE_INTERVALS: + return iv # already Binance's spelling ("1M" is a month) + return _BINANCE_TF.get(iv, iv.lower()) + + # Binance only accepts lowercase intervals. The chart reports its own timeframe in display form # ("30M", "4H", "1D"), so normalise before the request instead of trusting the caller. _BINANCE_TF = { - "1M": "1m", "3M": "3m", "5M": "5m", "15M": "15m", "30M": "30m", "45M": "45m", - "1H": "1h", "2H": "2h", "3H": "3h", "4H": "4h", "6H": "6h", "8H": "8h", "12H": "12h", + "3M": "3m", "5M": "5m", "15M": "15m", "30M": "30m", + "1H": "1h", "2H": "2h", "4H": "4h", "6H": "6h", "8H": "8h", "12H": "12h", "1D": "1d", "3D": "3d", "1W": "1w", } @@ -1219,19 +1258,22 @@ def ep_bars(params: dict) -> dict: if not symbol: return {"bars": [], "symbol": symbol, "interval": interval, "error": "symbol_required"} - interval = _BINANCE_TF.get(interval, interval) or "1h" + interval = normalise_interval(interval) + if interval not in BINANCE_INTERVALS: + return {"bars": [], "symbol": symbol, "interval": interval, + "error": "bad_interval: Binance serves " + ", ".join(sorted(BINANCE_INTERVALS, key=lambda v: (v[-1], len(v), v)))} return fetch_bars(symbol, interval, limit) def ep_chart_commands(params: dict) -> dict: """Commands the chart page has not executed yet (it passes the last id it handled).""" - since = int((params.get("since") or ["0"])[0] or 0) + since = _int_param(params, "since") return {"commands": chart_commands_since(AGENTS_ROOT, since)} def ep_chart_result(params: dict) -> dict: """The outcome of one command: ok, a plain-language detail, and what it painted.""" - rid = int((params.get("id") or ["0"])[0] or 0) + rid = _int_param(params, "id") found = get_chart_result(AGENTS_ROOT, rid) if found is None: return {"id": rid, "pending": True} @@ -1256,7 +1298,10 @@ def frontend_build() -> str: from hours ago and no amount of reloading from the page side reaches it. With the stamp in the heartbeat, "this view is running build X while the server serves Y" is a fact, not a guess. """ - frontend = Path(DEFAULT_FRONTEND) + # The folder actually being served (--frontend), not the default relative path: from another working directory the + # default matched nothing and the stamp was always "0", which defeats the stale-frame check (audit BE-21). + served = getattr(getattr(Handler, "static", None), "root", None) + frontend = Path(served) if served else Path(DEFAULT_FRONTEND) try: js_files = list(frontend.glob("*.js")) newest = max((f.stat().st_mtime for f in js_files), default=0.0) @@ -1299,7 +1344,7 @@ def _library_pairs(params: dict) -> list[tuple[str, str]]: def ep_library_warm(params: dict) -> dict: """Fetch + shrink a page of catalogue pictures in the background, so the next open is instant.""" pairs = _library_pairs(params) - width = int((params.get("w") or [library_thumbs.DEFAULT_WIDTH])[0] or library_thumbs.DEFAULT_WIDTH) + width = _int_param(params, "w", library_thumbs.DEFAULT_WIDTH) or library_thumbs.DEFAULT_WIDTH queued = library_thumbs.warm(pairs, width) return {"queued": queued, "asked": len(pairs), "cache": library_thumbs.stats()} @@ -1370,12 +1415,13 @@ def warm_catalogue_thumbs(pages: int = 0) -> None: _BROKER = None _BROKER_LOCK = threading.Lock() _BROKER_HTTP = {"unknown_order": 404, "not_pending": 409, "insufficient_cash": 409, - "insufficient_position": 409, "no_price": 503, "too_many_pending": 429} + "insufficient_position": 409, "no_price": 503, "too_many_pending": 429, + "broker_unavailable": 503} _BROKER_NEEDS_PAGE = ("approve", "reject", "reset", "replay") # While the operator replays, a paper fill uses the REPLAY cursor's price — the strip in the chart # pushes it here (page-only, like approve). `broker_price` below is what makes approve() and the # marks read it; nothing else may. -_REPLAY = {"active": False, "price": None, "time": None} +_REPLAY = {"active": False, "price": None, "time": None, "symbol": None} def _http_json(url: str): @@ -1402,7 +1448,12 @@ def broker_price(symbol: str) -> float: """The price a paper fill (and a position's mark) uses: the REPLAY cursor price while the operator is replaying — pushed by the page, see _REPLAY — else Binance's public ticker.""" if _REPLAY.get("active") and _REPLAY.get("price"): - return float(_REPLAY["price"]) + # The cursor price belongs to the symbol being replayed. Applied to any other one, an ETH order filled at the + # BTC price and every position was marked at it (audit 8 Oct, BE-2). A push with no symbol (an older page) + # still prices everything, as before. + replayed = _REPLAY.get("symbol") + if not replayed or str(replayed).upper() == str(symbol).upper(): + return float(_REPLAY["price"]) return binance_price(symbol) @@ -1430,7 +1481,11 @@ def _set_replay(body: dict) -> dict: 400, "replay_needs_price") if not (price > 0): raise ApiError("the replay cursor price must be positive", 400, "replay_needs_price") - _REPLAY.update(active=active, price=(price if active else None), time=(when if active else None)) + sym = str(body.get("symbol") or "").strip().upper() + if sym and not re.fullmatch(r"[A-Z0-9._-]{1,32}", sym): + raise ApiError("replay symbol is not a market name", 400, "bad_request") + _REPLAY.update(active=active, price=(price if active else None), time=(when if active else None), + symbol=(sym or None) if active else None) STREAM.publish({"type": "broker", "event": "replay", "replay": dict(_REPLAY)}) return {"replay": dict(_REPLAY)} @@ -1761,8 +1816,11 @@ def console_token() -> str: pass fresh = secrets.token_urlsafe(32) try: - TOKEN_PATH.parent.mkdir(parents=True, exist_ok=True) - TOKEN_PATH.write_text(fresh + "\n", encoding="utf-8") + TOKEN_PATH.parent.mkdir(parents=True, exist_ok=True, mode=0o700) + # Created 0600 from the first byte: write_text then chmod left a window at the default umask (audit SEC-14). + fd = os.open(str(TOKEN_PATH), os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600) + with os.fdopen(fd, "w", encoding="utf-8") as fh: + fh.write(fresh + "\n") os.chmod(TOKEN_PATH, 0o600) log(f"console token minted at {TOKEN_PATH} — POSTs need it (the page receives it as a cookie)") except OSError as exc: @@ -1771,12 +1829,33 @@ def console_token() -> str: CONSOLE_TOKEN = console_token() +# `--host 0.0.0.0` exposes the page to the LAN, but a LAN peer is not handed the POST token unless the operator also sets +# this: the console is then read-only to it rather than "authenticated" by a token anybody can fetch. +ALLOW_LAN = os.environ.get("TRADERS_AGENT_ALLOW_LAN", "") not in ("", "0", "false") + + +# What the console's page may load and talk to. 'unsafe-eval' is needed by the Pine engine (it compiles Pine to JS) and +# 'unsafe-inline' by the import map / inline boot script, so this does not stop script injection by itself; it does stop +# the page sending anything to a host that is not listed (audit 8 Oct, SEC-1 defence in depth). It deliberately has no +# frame-ancestors: the Hermes pane embeds this page. +CSP = ("default-src 'self'; " + "script-src 'self' 'unsafe-inline' 'unsafe-eval' blob:; " + "worker-src 'self' blob:; " + "style-src 'self' 'unsafe-inline'; " + "img-src 'self' data: blob: https://crypto-icons.ledger.com; " + "font-src 'self' data:; " + "connect-src 'self' https://api.binance.com https://api.binance.us https://fapi.binance.com https://dapi.binance.com " + "wss://stream.binance.com:* wss://stream.binance.us:* wss://fstream.binance.com:* https://crypto-icons.ledger.com; " + "object-src 'none'; base-uri 'none'; form-action 'self'") class Handler(BaseHTTPRequestHandler): server_version = f"luxalgo-web/{SERVER_VERSION}" protocol_version = "HTTP/1.1" static: StaticFiles = StaticFiles(DEFAULT_FRONTEND) + # A socket that sends nothing (or trickles a header / body) used to hold its thread for ever (audit SEC-10). The + # long-lived chart stream only writes, so this does not touch it. + timeout = 30 # -- helpers --------------------------------------------------------- @@ -1813,10 +1892,34 @@ def _origin_ok(self) -> bool: if origin.strip().lower() == "null": return False try: - return (urlparse(origin).hostname or "") in LOCAL_HOSTS + parsed = urlparse(origin) + if (parsed.hostname or "") not in LOCAL_HOSTS: + return False + # The PORT counts too: any other web app on localhost (a dev server, a notebook) is "a local name" but is + # not this console's page, and used to pass with the user's cookie (audit 8 Oct, SEC-4). The page's own + # Origin always equals the Host it was served from. + host = (self.headers.get("Host") or "").strip().lower() + return parsed.scheme in ("http", "https") and bool(host) and parsed.netloc.lower() == host except ValueError: return False + def _peer_is_local(self) -> bool: + try: + return ipaddress.ip_address(self.client_address[0]).is_loopback + except (ValueError, IndexError, TypeError): + return False + + def _session_ok(self) -> bool: + """May this caller be handed the POST token? Only a page this console served (same-origin fetch), or a local + non-browser (CLI, curl) on loopback. It used to answer anyone with a local Host, so `--host 0.0.0.0` gave every + LAN peer the token and the "still authenticated" claim was false (audit 8 Oct, SEC-3).""" + if not self._peer_is_local() and not ALLOW_LAN: + return False + site = (self.headers.get("Sec-Fetch-Site") or "").strip().lower() + if site: + return site in ("same-origin", "none") + return not self.headers.get("Origin") or self._origin_ok() + def _token_ok(self) -> bool: header = (self.headers.get("X-Trader-Token") or "").strip() if header and secrets.compare_digest(header, CONSOLE_TOKEN): @@ -1836,6 +1939,8 @@ def _send(self, status: int, body: bytes, content_type: str, extra: dict | None self.send_header(key, value) for key, value in (extra or {}).items(): self.send_header(key, value) + self.send_header("X-Content-Type-Options", "nosniff") + self.send_header("Referrer-Policy", "no-referrer") self.end_headers() if not head_only and body: try: @@ -1902,7 +2007,7 @@ def _backtest_proxy(self, path: str, payload: dict): # a symbol mapping (the chart knows whether it is BTCUSD or BTCUSDT). src = str(payload.get("source") or "") if src.startswith("chart:"): - want = int(payload.get("bars") or 1000) + want = _clamped_int(payload.get("bars"), 1000, 1, BARS_MAX) queued = enqueue_chart_command(AGENTS_ROOT, {"action": "bars", "count": want}) rid = int((queued or {}).get("id") or 0) res = None @@ -2015,7 +2120,10 @@ def do_POST(self): # noqa: N802 "source": "page heartbeat" if supported != CHART_ACTIONS_FALLBACK else "built-in fallback"}) return command = enqueue_chart_command(AGENTS_ROOT, payload) - pushed = STREAM.publish({"type": "command", "command": command}, + # `once_per_view` is read at the TOP level of the pushed payload (chart_stream.publish). It used to + # be left inside `command`, so a `reload` was claimed by one view only (audit 8 Oct, BE-4). + pushed = STREAM.publish({"type": "command", "command": command, + "once_per_view": bool(command.get("once_per_view")) if isinstance(command, dict) else False}, command_id=command.get("id") if isinstance(command, dict) else None) inline = self._await_chart_result(command, payload) if pushed else None self._ok({"command": command, "views": STREAM.client_count(), @@ -2025,7 +2133,11 @@ def do_POST(self): # noqa: N802 self._backtest_proxy(path, payload) return if path == "/api/chart/result": - recorded = record_chart_result(AGENTS_ROOT, payload) + try: + recorded = record_chart_result(AGENTS_ROOT, payload) + except ValueError as exc: + self._fail(str(exc), HTTPStatus.BAD_REQUEST, "bad_request") + return if isinstance(recorded, dict): # resolves whoever is waiting on this command (the push path's fast answer) recorded = STREAM.deliver_result(recorded) @@ -2034,7 +2146,10 @@ def do_POST(self): # noqa: N802 if path == "/api/chart/claim": # Several consoles can be alive at once (the Hermes pane, the HUD's pane, a browser # tab). They all get the same push, so one of them must win the right to execute it. - rid = payload.get("id") + try: + rid = int(payload.get("id")) + except (TypeError, ValueError, OverflowError): + raise ApiError("claim needs the integer id of a command", 400, "bad_request") from None viewer = str(payload.get("viewer") or "") self._ok({"id": rid, "claimed": STREAM.claim(rid, viewer, once=STREAM.is_once(rid)), "viewer": viewer}) return @@ -2084,8 +2199,8 @@ def _chat(self, payload: dict): agent=agent, message=message, context=context, - timeout=int(payload.get("timeout") or 180), - workdir=str(payload.get("workdir") or os.path.expanduser("~/Projects/luxalgo-web")), + timeout=_clamped_int(payload.get("timeout"), 180, 10, 600), + workdir=_agent_workdir(), resume=None if fresh else agent.get("session_id"), learnings=learnings_tail(AGENTS_ROOT, agent_id), extra_args=[], @@ -2167,6 +2282,16 @@ def _handle(self, head_only: bool): self._fail("refused: non-local Host", HTTPStatus.FORBIDDEN, "non_local_host", head_only=head_only) return + # A browser tells us which kind of page is asking. This console's own page is `same-origin`; an <img> or + # fetch from another site is `cross-site` / `same-site` and could only ever cause side effects here (Binance + # requests from the user's IP, the Edge engine spawned, the LuxAlgo quota burned): refuse those. A CLI or + # curl sends no such header and is unaffected (audit 8 Oct, SEC-9). + fetch_site = (self.headers.get("Sec-Fetch-Site") or "").strip().lower() + if parsed.path.startswith("/api") and fetch_site and fetch_site not in ("same-origin", "none"): + self.close_connection = True + self._fail("refused: this route is for the console's own page and local tools", HTTPStatus.FORBIDDEN, + "cross_site", head_only=head_only) + return if parsed.path.rstrip("/") == "/api/backtest/health": self._backtest_proxy("/api/backtest/health", {}) return @@ -2197,6 +2322,10 @@ def _handle(self, head_only: bool): if not self._host_ok(): self._fail("refused: non-local Host", HTTPStatus.FORBIDDEN, "non_local_host", head_only=head_only) return + if not self._session_ok(): + self._fail("the token is given to this console's own page and to local tools, not to other pages " + "or machines", HTTPStatus.FORBIDDEN, "session_refused", head_only=head_only) + return self._ok({"token": CONSOLE_TOKEN}, head_only=head_only) return @@ -2294,8 +2423,11 @@ def _serve_static(self, url_path: str, head_only: bool): return extra = {"Cache-Control": "no-store"} if os.path.basename(target) == "index.html": - # The page's own POSTs carry this cookie; a cross-site request never does (SameSite=Strict). - extra["Set-Cookie"] = f"trader_token={CONSOLE_TOKEN}; Path=/; SameSite=Strict; HttpOnly" + # The page's own POSTs carry this cookie; a cross-site request never does (SameSite=Strict). A LAN peer is + # not handed it either (see _session_ok). + if self._peer_is_local() or ALLOW_LAN: + extra["Set-Cookie"] = f"trader_token={CONSOLE_TOKEN}; Path=/; SameSite=Strict; HttpOnly" + extra["Content-Security-Policy"] = CSP self._send(200, body, ctype, extra, head_only) @@ -2304,6 +2436,25 @@ class Server(ThreadingHTTPServer): allow_reuse_address = True request_queue_size = 64 + MAX_CONNECTIONS = 128 + _slots = threading.BoundedSemaphore(MAX_CONNECTIONS) + + def process_request(self, request, client_address): + # One thread per connection and no cap let a few hundred idle sockets pin memory and file descriptors. + if not self._slots.acquire(blocking=False): + try: + request.close() + except OSError: + pass + return + super().process_request(request, client_address) + + def process_request_thread(self, request, client_address): + try: + super().process_request_thread(request, client_address) + finally: + self._slots.release() + def handle_error(self, request, client_address): exc = sys.exc_info()[1] if isinstance(exc, (BrokenPipeError, ConnectionResetError)): @@ -2369,6 +2520,8 @@ def load_backtest_result(root: str = "", run_id: str = "") -> dict: if base is None: return {"ok": False, "error": "no backtest results found in " + ", ".join(str(c) for c in cands if c)} + if run_id and not re.fullmatch(r"[0-9A-Za-z_-]{1,64}", str(run_id)): + return {"ok": False, "error": "run_id must be letters, digits, _ or - (up to 64)"} try: if not run_id: latest = base / "latest.json" @@ -2406,6 +2559,43 @@ def list_local_data(data_dir: str = "") -> dict: "use": 'source="local:NAME" in bt_run / bt_optimize'} +def _clamped_int(value, default: int, lo: int, hi: int) -> int: + """A client-supplied number, held to a sane range. A body may not ask for a timeout of 99999 s (a thread held that + long) and a word is a 400, not a 500.""" + if value in (None, ""): + return default + try: + return max(lo, min(hi, int(value))) + except (TypeError, ValueError, OverflowError): + raise ApiError("expected a whole number", 400, "bad_request") from None + + +def _int_param(params: dict, name: str, default: int = 0) -> int: + raw = (params.get(name) or [str(default)])[0] or str(default) + try: + return int(raw) + except (TypeError, ValueError, OverflowError): + raise ApiError(f"{name} must be a whole number", 400, "bad_request") from None + + +def _agent_workdir() -> str: + """Where the agent CLI runs. It is the OPERATOR's setting, never the request's: a token holder used to choose any + folder (audit SEC-2).""" + env = os.environ.get("TRADERS_AGENT_WORKDIR") + if env: + return env + legacy = os.path.expanduser("~/Projects/luxalgo-web") + return legacy if os.path.isdir(legacy) else str(AGENTS_ROOT) + + +def _env_int(name: str, default: int) -> int: + """An integer from the environment; a typo falls back to the default instead of a traceback after the port is bound.""" + try: + return int(os.environ.get(name, "") or default) + except ValueError: + return default + + def main(argv=None) -> int: args = build_parser().parse_args(argv) @@ -2420,23 +2610,42 @@ def main(argv=None) -> int: if MCP_IMPORT_ERROR: log(f"WARNING: mcp package not importable ({MCP_IMPORT_ERROR})") + log(f"frontend dir: {frontend_root} " + f"({'ok' if Handler.static.exists() else 'MISSING'})") + + # Bind FIRST. The MCP session is only the Library's; the chart, bars, broker and the agent bridge need none of + # it, and waiting up to 60 s for it before opening the port left the pane and every tool failing for a minute + # (audit 8 Oct, BE-5). A busy port is also found at once, with one line instead of a traceback. + try: + httpd = Server((args.host, args.port), Handler) + except (OSError, OverflowError) as exc: + log(f"cannot listen on {args.host}:{args.port}: {exc}") + return 2 + log(f"listening on http://{args.host}:{args.port} (Ctrl-C to stop)") + if args.no_mcp: log("starting WITHOUT an MCP session (--no-mcp)") else: - log(f"connecting to MCP at {args.mcp_url} ...") - started = time.time() - ready = BRIDGE.start() - if ready: - log(f"MCP session established in {time.time() - started:.1f}s") - else: - log(f"WARNING: MCP session not ready after {MCP_CONNECT_WAIT:.0f}s " - f"({BRIDGE.last_error}); the server will keep retrying in the background") + def connect_mcp(): + log(f"connecting to MCP at {args.mcp_url} ...") + started = time.time() + if BRIDGE.start(): + log(f"MCP session established in {time.time() - started:.1f}s") + else: + log(f"WARNING: MCP session not ready after {MCP_CONNECT_WAIT:.0f}s " + f"({BRIDGE.last_error}); the server will keep retrying in the background") + threading.Thread(target=connect_mcp, name="mcp-connect", daemon=True).start() - log(f"frontend dir: {frontend_root} " - f"({'ok' if Handler.static.exists() else 'MISSING'})") + # `systemctl stop` sends SIGTERM, which used to end the process with no cleanup (the Edge Stats engine was + # left running). Treat it like Ctrl-C so the finally block below runs. + try: + import signal as _signal - httpd = Server((args.host, args.port), Handler) - log(f"listening on http://{args.host}:{args.port} (Ctrl-C to stop)") + def _term(_signum, _frame): + raise KeyboardInterrupt + _signal.signal(_signal.SIGTERM, _term) + except (ValueError, OSError, AttributeError): + pass # not the main thread / not supported here # Preview pictures, fetched once and kept: the operator's first open of the Indicators modal used # to fill in picture by picture (60 × ~1–2 s from S3 on this link). Warming starts here, in the @@ -2445,7 +2654,7 @@ def main(argv=None) -> int: threading.Thread( target=warm_catalogue_thumbs, # 0 = every page of the catalogue (the default). Set a small number on a metered link. - kwargs={"pages": int(os.environ.get("TRADERS_AGENT_THUMB_WARM_PAGES", "0") or 0)}, + kwargs={"pages": _env_int("TRADERS_AGENT_THUMB_WARM_PAGES", 0)}, name="thumb-warmer", daemon=True, ).start() try: diff --git a/console/backend/tests/test_agent_inputs.py b/console/backend/tests/test_agent_inputs.py index 163f8b8..44b22c9 100644 --- a/console/backend/tests/test_agent_inputs.py +++ b/console/backend/tests/test_agent_inputs.py @@ -15,8 +15,6 @@ import importlib.machinery import importlib.util import io -import os -import re import sys import tempfile import threading diff --git a/console/backend/tests/test_audit_8oct_fixes.py b/console/backend/tests/test_audit_8oct_fixes.py new file mode 100644 index 0000000..ce8a87d --- /dev/null +++ b/console/backend/tests/test_audit_8oct_fixes.py @@ -0,0 +1,686 @@ +"""The 8 Oct 2026 full audit: the findings that were ours on the backend, fixed and held. + +Each test drives the real code (threads, a real socket, the real handler) rather than grepping for a string, +because the audit's own finding about the suite was that string pins stay green while behaviour breaks. + + BE-1/SEC-11 chart bridge: parallel writers (500s, duplicate ids, lost commands) + BE-16 command ids never restart + BE-15 a result keeps what the page reported; an id is required + BE-4 `once_per_view` reaches the stream (through the HTTP handler) + BE-2 the replay price belongs to the replayed symbol + BE-3/8/12/13 broker: entry fee in P&L, transactional approve, read errors, large quantities + BE-6 "1M" is a month; unknown intervals are refused with the list + BE-11 a partial catalogue is not kept + SEC-3/4/9 the token, the Origin port, cross-site GETs + SEC-6/2/17 run_id, agent definitions, the quadratic regex + SEC-8 thumbnails: exact hosts, content sniffing + TC-2 static-file traversal has a test +""" +import json +import os +import socket +import sys +import tempfile +import threading +import time +import unittest +from pathlib import Path +from unittest import mock + +BACKEND = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(BACKEND)) + +import agents_store # noqa: E402 +import chart_bridge as cb # noqa: E402 +import chat # noqa: E402 +import library_thumbs # noqa: E402 +import server as srv # noqa: E402 +from broker import BrokerError, PaperBroker # noqa: E402 + + +# ── chart bridge ─────────────────────────────────────────────────────────────────────────────────────── + +class ChartBridgeUnderParallelCalls(unittest.TestCase): + def test_sixty_parallel_commands_all_land_with_their_own_id(self): + with tempfile.TemporaryDirectory() as root: + ids, errors = [], [] + lock = threading.Lock() + start = threading.Barrier(20) + + def worker(n): + start.wait() + for k in range(3): + try: + entry = cb.enqueue(root, {"action": "clear", "tag": f"{n}-{k}"}) + with lock: + ids.append(entry["id"]) + except Exception as exc: # noqa: BLE001 + with lock: + errors.append(repr(exc)) + + threads = [threading.Thread(target=worker, args=(n,)) for n in range(20)] + [t.start() for t in threads] + [t.join() for t in threads] + self.assertEqual(errors, []) + self.assertEqual(len(ids), 60) + self.assertEqual(len(set(ids)), 60, "no two commands share an id") + self.assertEqual(sorted(ids), list(range(1, 61))) + self.assertEqual(len(cb.commands_since(root, 0)), cb.MAX_RESULTS) # the newest 60 survive + + def test_heartbeats_and_results_in_parallel_never_error(self): + with tempfile.TemporaryDirectory() as root: + cmd = cb.enqueue(root, {"action": "clear"}) + errors = [] + + def beat(): + for _ in range(15): + try: + cb.save_state(root, {"symbol": "BTCUSDT", "timeframe": "1h"}) + cb.record_result(root, {"id": cmd["id"], "ok": True}) + except Exception as exc: # noqa: BLE001 + errors.append(repr(exc)) + + threads = [threading.Thread(target=beat) for _ in range(8)] + [t.start() for t in threads] + [t.join() for t in threads] + self.assertEqual(errors, []) + + def test_ids_never_restart_even_if_the_queue_file_is_lost(self): + with tempfile.TemporaryDirectory() as root: + for _ in range(3): + cb.enqueue(root, {"action": "clear"}) + (cb._chart_dir(root) / cb.COMMANDS_FILE).write_text("{not json", "utf-8") + self.assertEqual(cb.enqueue(root, {"action": "clear"})["id"], 4) + + def test_a_result_needs_a_positive_integer_id_and_keeps_what_the_page_reported(self): + with tempfile.TemporaryDirectory() as root: + for bad in ({}, {"id": 0}, {"id": -3}, {"id": "abc"}, {"id": None}, {"id": float("inf")}): + with self.assertRaises(ValueError, msg=repr(bad)): + cb.record_result(root, bad) + out = cb.record_result(root, {"id": 7, "ok": True, "trades": [{"t": 1}], "count": 1, + "overlay": {"a": 1}, "palette": {"b": 2}}) + self.assertEqual(out["trades"], [{"t": 1}]) + self.assertEqual(cb.get_result(root, 7)["overlay"], {"a": 1}) + + +# ── a live console ───────────────────────────────────────────────────────────────────────────────────── + +class LiveConsole(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.tmp = tempfile.TemporaryDirectory() + frontend = Path(cls.tmp.name) / "frontend" + (frontend / "vendor").mkdir(parents=True) + (frontend / "index.html").write_text("<!doctype html><title>console", encoding="utf-8") + (frontend / "app.js").write_text("// app", encoding="utf-8") + (Path(cls.tmp.name) / "secret.txt").write_text("OUTSIDE", encoding="utf-8") + cls._orig_static = srv.Handler.static + srv.Handler.static = srv.StaticFiles(str(frontend)) + cls.token = "audit-token-0123456789" + cls.patches = [ + mock.patch.object(srv, "CONSOLE_TOKEN", cls.token), + mock.patch.object(srv, "AGENTS_ROOT", cls.tmp.name), + mock.patch.dict(os.environ, {"LUXALGO_CHART_ROOT": cls.tmp.name}), + ] + for p in cls.patches: + p.start() + cls.httpd = srv.Server(("127.0.0.1", 0), srv.Handler) + cls.port = cls.httpd.server_address[1] + cls.thread = threading.Thread(target=cls.httpd.serve_forever, daemon=True) + cls.thread.start() + + @classmethod + def tearDownClass(cls): + cls.httpd.shutdown() + cls.httpd.server_close() + srv.Handler.static = cls._orig_static + for p in cls.patches: + p.stop() + cls.tmp.cleanup() + + def call(self, path, method="GET", headers=None, body=None, host=None): + """A raw request, so Host / Origin / Sec-Fetch-* are exactly what we set.""" + data = json.dumps(body).encode() if body is not None else b"" + head = {"Host": host or f"127.0.0.1:{self.port}", "Connection": "close"} + head.update(headers or {}) + if body is not None: + head.setdefault("Content-Type", "application/json") + head["Content-Length"] = str(len(data)) + with socket.create_connection(("127.0.0.1", self.port), timeout=10) as sock: + sock.sendall((f"{method} {path} HTTP/1.1\r\n" + "".join(f"{k}: {v}\r\n" for k, v in head.items()) + "\r\n").encode() + data) + reply = sock.makefile("rb").read() + top, _, payload = reply.partition(b"\r\n\r\n") + lines = top.decode("latin-1").split("\r\n") + status = int(lines[0].split()[1]) + hdrs = {k.lower(): v for k, v in (l.split(": ", 1) for l in lines[1:] if ": " in l)} + try: + return status, json.loads(payload.decode() or "null"), hdrs + except ValueError: + return status, payload, hdrs + + def post(self, path, body, **extra): + headers = {"X-Trader-Token": self.token} + headers.update(extra.pop("headers", {})) + return self.call(path, "POST", headers, body, **extra) + + # SEC-3 ---------------------------------------------------------------------------------------------- + def test_the_token_goes_to_the_own_page_and_to_local_tools_only(self): + code, body, _ = self.call("/api/session") # curl / CLI + self.assertEqual((code, body["data"]["token"]), (200, self.token)) + code, body, _ = self.call("/api/session", headers={"Sec-Fetch-Site": "same-origin"}) + self.assertEqual(code, 200) + for site in ("cross-site", "same-site"): + code, body, _ = self.call("/api/session", headers={"Sec-Fetch-Site": site}) + self.assertEqual(code, 403, site) + self.assertNotIn(self.token, json.dumps(body)) + code, _, _ = self.call("/api/session", headers={"Origin": "http://127.0.0.1:1"}) # another localhost app + self.assertEqual(code, 403) + code, _, _ = self.call("/api/session", host="evil.example") + self.assertEqual(code, 403) + + def test_a_lan_peer_is_not_handed_the_token(self): + with mock.patch.object(srv.Handler, "_peer_is_local", lambda self: False): + code, body, _ = self.call("/api/session") + self.assertEqual(code, 403) + self.assertNotIn(self.token, json.dumps(body)) + with mock.patch.object(srv, "ALLOW_LAN", True): + self.assertEqual(self.call("/api/session")[0], 200) + + # SEC-4 ---------------------------------------------------------------------------------------------- + def test_another_localhost_port_cannot_post(self): + mine = f"http://127.0.0.1:{self.port}" + self.assertEqual(self.post("/api/chart/state", {}, headers={"Origin": mine})[0], 200) + code, body, _ = self.post("/api/chart/state", {}, headers={"Origin": "http://127.0.0.1:9999"}) + self.assertEqual(code, 403) + self.assertEqual(self.post("/api/chart/state", {}, headers={"Origin": "http://localhost:" + str(self.port)})[0], 403) + + # SEC-9 ---------------------------------------------------------------------------------------------- + def test_a_cross_site_get_of_an_api_route_is_refused_but_a_local_tool_is_not(self): + self.assertEqual(self.call("/api/chart/state")[0], 200) + self.assertEqual(self.call("/api/chart/state", headers={"Sec-Fetch-Site": "same-origin"})[0], 200) + for site in ("cross-site", "same-site"): + code, body, _ = self.call("/api/chart/state", headers={"Sec-Fetch-Site": site}) + self.assertEqual((code, body["code"]), (403, "cross_site")) + + # headers -------------------------------------------------------------------------------------------- + def test_the_page_carries_a_csp_and_every_answer_is_nosniff(self): + code, _, hdrs = self.call("/") + self.assertEqual(code, 200) + self.assertIn("default-src 'self'", hdrs["content-security-policy"]) + self.assertNotIn("frame-ancestors", hdrs["content-security-policy"]) # Hermes embeds the page + self.assertEqual(hdrs["x-content-type-options"], "nosniff") + self.assertEqual(hdrs["referrer-policy"], "no-referrer") + self.assertEqual(self.call("/api/health")[2]["x-content-type-options"], "nosniff") + + def test_the_cookie_is_set_for_a_local_peer_only(self): + self.assertIn("trader_token=", self.call("/")[2].get("set-cookie", "")) + with mock.patch.object(srv.Handler, "_peer_is_local", lambda self: False): + self.assertNotIn("set-cookie", self.call("/")[2]) + + # BE-4 ----------------------------------------------------------------------------------------------- + def test_once_per_view_reaches_the_stream_so_every_view_may_reload(self): + cid_a, _ = srv.STREAM.attach() + cid_b, _ = srv.STREAM.attach() + try: + code, body, _ = self.post("/api/chart/command", {"action": "reload", "once_per_view": True}) + self.assertEqual(code, 200, body) + rid = body["data"]["command"]["id"] + self.assertTrue(srv.STREAM.is_once(rid)) + self.assertTrue(srv.STREAM.claim(rid, "viewA", once=True)) + self.assertTrue(srv.STREAM.claim(rid, "viewB", once=True), "a second view may run a once-per-view command") + finally: + srv.STREAM.detach(cid_a) + srv.STREAM.detach(cid_b) + + # 400s ----------------------------------------------------------------------------------------------- + def test_bad_numbers_are_a_400_not_a_500(self): + for path in ("/api/chart/commands?since=abc", "/api/chart/result?id=abc", "/api/library/warm?w=abc"): + self.assertEqual(self.call(path)[0], 400, path) + for body in ({"id": "abc"}, {"id": None}, {"id": 0}, {}): + self.assertEqual(self.post("/api/chart/result", body)[0], 400, body) + self.assertEqual(self.post("/api/chart/claim", {"id": "x"})[0], 400) + self.assertEqual(self.post("/api/agents", {"id": "ab", "name": "n", "instruction": "i", "counters": [1]})[0], 400) + self.assertEqual(self.post("/api/agents/learning", {"agent_id": "no-such-study", "text": "x"})[0], 404) + + # SEC-6 ---------------------------------------------------------------------------------------------- + def test_run_id_cannot_leave_the_results_folder(self): + base = Path(self.tmp.name) / "_chart" / "backtest" + base.mkdir(parents=True, exist_ok=True) + (base / "good.json").write_text('{"ok": 1}', "utf-8") + (Path(self.tmp.name) / "outside.json").write_text('{"secret": 1}', "utf-8") + got = srv.load_backtest_result(self.tmp.name, "good") + self.assertTrue(got["ok"]) + for bad in ("../../outside", "../outside", "/etc/passwd", "a/b", "good.json", "x" * 80): + got = srv.load_backtest_result(self.tmp.name, bad) + self.assertFalse(got["ok"], bad) + self.assertNotIn("secret", json.dumps(got)) + + # SEC-2 ---------------------------------------------------------------------------------------------- + def test_chat_ignores_a_client_workdir_and_clamps_the_timeout(self): + seen = {} + + def fake_run(**kw): + seen.update(kw) + return {"ok": True, "reply": "hi", "pine": None, "actions": [], "elapsed_ms": 1, "usage": None, "session_id": None} + + agents_store.ensure_seed(self.tmp.name) + with mock.patch.object(srv, "run_agent", fake_run): + self.post("/api/chat", {"agent_id": "desk", "message": "hi", "workdir": "/etc", "timeout": 99999}) + self.assertTrue(seen, "the chat call must have reached run_agent") + self.assertNotEqual(seen["workdir"], "/etc") + self.assertLessEqual(seen["timeout"], 600) + self.assertEqual(self.post("/api/chat", {"agent_id": "desk", "message": "hi", "timeout": "abc"})[0], 400) + + # SEC-10 --------------------------------------------------------------------------------------------- + def test_a_silent_socket_is_dropped_rather_than_held_for_ever(self): + self.assertEqual(srv.Handler.timeout, 30) + self.assertLessEqual(srv.Server.MAX_CONNECTIONS, 256) + + # TC-2 ----------------------------------------------------------------------------------------------- + def test_static_files_cannot_be_traversed_out_of_the_frontend_root(self): + static = srv.Handler.static + secret = str(Path(self.tmp.name) / "secret.txt") + for url in ("/../secret.txt", "/%2e%2e/secret.txt", "/..%2fsecret.txt", "/%2e%2e%2fsecret.txt", "/..%5csecret.txt", + "//etc/passwd", "///etc/passwd", "/index.html%00.png", "/%00", "/vendor/../../secret.txt", + "/%252e%252e/secret.txt", "/../frontend2/x", "/" + "%2e%2e/" * 14 + "etc/passwd"): + got = static.resolve(url) + self.assertTrue(got is None or Path(got).resolve() != Path(secret).resolve(), url) + if got: + self.assertTrue(os.path.realpath(got).startswith(os.path.realpath(static.root) + os.sep), (url, got)) + self.assertTrue(static.resolve("/app.js").endswith("app.js")) + self.assertTrue(static.resolve("/").endswith("index.html")) + + def test_the_mjs_type_and_the_cookie_only_on_the_page(self): + self.assertNotIn("set-cookie", self.call("/app.js")[2]) + self.assertIn("javascript", srv.CONTENT_TYPES.get(".mjs", "")) + + +# ── replay price ─────────────────────────────────────────────────────────────────────────────────────── + +class ReplayPriceIsPerSymbol(unittest.TestCase): + def setUp(self): + srv._REPLAY.update(active=False, price=None, time=None, symbol=None) + self._real = srv.binance_price + srv.binance_price = lambda symbol: {"BTCUSDT": 60000.0, "ETHUSDT": 3000.0}[symbol] + self._pub = srv.STREAM.publish + srv.STREAM.publish = lambda *a, **k: 0 + + def tearDown(self): + srv.binance_price = self._real + srv.STREAM.publish = self._pub + srv._REPLAY.update(active=False, price=None, time=None, symbol=None) + + def test_an_eth_order_does_not_fill_at_the_btc_cursor_price(self): + srv.broker_action("replay", {"active": True, "price": 50000, "time": 1, "symbol": "BTCUSDT"}, from_page=True) + self.assertEqual(srv.broker_price("BTCUSDT"), 50000.0) + self.assertEqual(srv.broker_price("ETHUSDT"), 3000.0, "another symbol is priced live") + srv.broker_action("replay", {"active": False}, from_page=True) + self.assertEqual(srv.broker_price("BTCUSDT"), 60000.0) + self.assertIsNone(srv._REPLAY["symbol"]) + + def test_a_push_with_no_symbol_still_prices_everything(self): + srv.broker_action("replay", {"active": True, "price": 123.0}, from_page=True) + self.assertEqual(srv.broker_price("ETHUSDT"), 123.0) + + def test_a_silly_symbol_is_refused(self): + with self.assertRaises(srv.ApiError): + srv.broker_action("replay", {"active": True, "price": 1, "symbol": "../x"}, from_page=True) + + +# ── paper broker ─────────────────────────────────────────────────────────────────────────────────────── + +class BrokerMoney(unittest.TestCase): + def setUp(self): + self.dir = tempfile.mkdtemp() + self.path = os.path.join(self.dir, "paper.json") + self.px = {"XYZ": 100.0} + self.b = PaperBroker(self.path, lambda s: self.px[s]) + + def fill(self, side, qty, sym="XYZ"): + return self.b.approve(self.b.propose(sym, side, qty)["id"]) + + def test_realized_includes_the_entry_fee_and_reconciles_with_equity(self): + self.fill("buy", 10) + self.fill("sell", 10) + st = self.b.state() + self.assertAlmostEqual(st["realized"], -2.0, places=9) # 1.0 in + 1.0 out + self.assertAlmostEqual(st["equity"] - st["start_cash"], st["realized"] + sum(p["unrealized"] for p in st["positions"]), places=9) + self.fill("buy", 5) + self.px["XYZ"] = 110.0 + st = self.b.state() + self.assertAlmostEqual(st["equity"] - st["start_cash"], st["realized"] + sum(p["unrealized"] for p in st["positions"]), places=9) + + def test_a_failed_save_leaves_the_account_exactly_as_it_was(self): + oid = self.b.propose("XYZ", "buy", 1)["id"] + with mock.patch.object(PaperBroker, "_save", side_effect=OSError("disk full")): + with self.assertRaises(OSError): + self.b.approve(oid) + st = self.b.state() + self.assertEqual((st["cash"], st["positions"], [o["id"] for o in st["pending"]]), (10000.0, [], [oid])) + self.assertEqual(self.b.approve(oid)["status"], "filled", "the retry works") + + def test_large_quantities_sell_cleanly_with_no_ghost_position(self): + self.px["XYZ"] = 0.00001 + for _ in range(3): + self.fill("buy", 1234567.891) + self.fill("sell", 3703703.673) + self.assertEqual(self.b.state()["positions"], []) + for _ in range(3): + self.fill("buy", 1234567.891) + for _ in range(3): + self.fill("sell", 1234567.891) + self.assertEqual(self.b.state()["positions"], []) + + def test_a_read_error_does_not_reset_the_account(self): + self.fill("buy", 1) + with mock.patch("builtins.open", side_effect=OSError(5, "EIO")): + with self.assertRaises(BrokerError) as cm: + PaperBroker(self.path, lambda s: 1.0) + self.assertEqual(cm.exception.code, "broker_unavailable") + self.assertEqual([f for f in os.listdir(self.dir) if ".bad" in f], []) + self.assertEqual(PaperBroker(self.path, lambda s: 100.0).state()["positions"][0]["qty"], 1.0) + + def test_an_unparsable_file_is_still_set_aside_and_a_thin_one_is_completed(self): + with open(self.path, "w", encoding="utf-8") as fh: + fh.write("{not json") + PaperBroker(self.path, lambda s: 1.0) + self.assertTrue([f for f in os.listdir(self.dir) if ".bad" in f]) + with open(self.path, "w", encoding="utf-8") as fh: + json.dump({"cash": 500.0, "orders": [{"id": 4, "status": "filled"}], "positions": {}}, fh) + b = PaperBroker(self.path, lambda s: 1.0) + st = b.state() + self.assertEqual((st["cash"], st["realized"]), (500.0, 0.0)) + self.assertEqual(b.propose("XYZ", "buy", 1)["id"], 5, "ids continue after the highest seen") + + def test_ids_continue_across_a_reset(self): + a = self.b.propose("XYZ", "buy", 1)["id"] + self.b.reset() + self.assertGreater(self.b.propose("XYZ", "buy", 1)["id"], a) + + def test_state_does_not_hold_the_lock_while_pricing(self): + self.fill("buy", 1) + gate = threading.Event() + release = threading.Event() + + def slow(sym): + gate.set() + release.wait(5) + return 100.0 + + self.b.price_of = slow + t = threading.Thread(target=self.b.state) + t.start() + self.assertTrue(gate.wait(5)) + started = time.time() + self.b.propose("XYZ", "buy", 1) # would block until `release` if the lock were held + self.assertLess(time.time() - started, 2.0) + release.set() + t.join() + + +# ── intervals ────────────────────────────────────────────────────────────────────────────────────────── + +class Intervals(unittest.TestCase): + def test_one_capital_m_is_a_month_and_display_forms_are_minutes(self): + n = srv.normalise_interval + self.assertEqual((n("1M"), n("30M"), n("3M"), n("15m"), n("1h"), n("4H"), n("1D"), n("1W"), n("1d")), + ("1M", "30m", "3m", "15m", "1h", "4h", "1d", "1w", "1d")) + self.assertEqual(n(""), "1h") + + def test_an_interval_binance_does_not_serve_is_refused_with_the_list(self): + for bad in ("45M", "3H", "2D", "60", "banana"): + out = srv.ep_bars({"symbol": ["BTCUSDT"], "interval": [bad]}) + self.assertEqual(out["bars"], [], bad) + self.assertIn("bad_interval", out["error"]) + self.assertIn("1M", out["error"]) + + def test_a_month_is_asked_of_binance_as_a_month(self): + seen = [] + srv._BARS_MEMO.clear() + with mock.patch.object(srv, "_fetch_klines", lambda s, i, l, end_time=None: seen.append(i) or []): + srv.ep_bars({"symbol": ["BTCUSDT"], "interval": ["1M"]}) + self.assertEqual(seen, ["1M"]) + + +# ── catalogue ────────────────────────────────────────────────────────────────────────────────────────── + +class CatalogueIsNotKeptWhenPartial(unittest.TestCase): + def test_a_short_walk_is_served_but_not_saved(self): + with tempfile.TemporaryDirectory() as root: + def pages(params): + page = int(params["page"][0]) + if page == 0: + return {"indicators": [{"slug": f"s{i}"} for i in range(srv.CATALOGUE_PAGE)], "total": 806} + return {"indicators": [], "total": 806} # a hiccup on page 1 + with mock.patch.object(srv, "AGENTS_ROOT", root), mock.patch.object(srv, "ep_indicators", pages), \ + mock.patch.object(srv, "ep_concepts", lambda p: {"concepts": []}), \ + mock.patch.object(srv, "ep_families", lambda p: {"families": []}): + out = srv.ep_catalogue({}) + self.assertTrue(out["partial"]) + self.assertEqual(out["upstream_total"], 806) + self.assertFalse(os.path.exists(os.path.join(root, "catalogue.json"))) + + def test_a_complete_walk_is_saved(self): + with tempfile.TemporaryDirectory() as root: + def pages(params): + return {"indicators": [{"slug": "a"}] if params["page"][0] == "0" else [], "total": 1} + with mock.patch.object(srv, "AGENTS_ROOT", root), mock.patch.object(srv, "ep_indicators", pages), \ + mock.patch.object(srv, "ep_concepts", lambda p: {"concepts": []}), \ + mock.patch.object(srv, "ep_families", lambda p: {"families": []}): + out = srv.ep_catalogue({}) + self.assertNotIn("partial", out) + self.assertTrue(os.path.exists(os.path.join(root, "catalogue.json"))) + + +# ── agents, chat, thumbnails ─────────────────────────────────────────────────────────────────────────── + +class AgentDefinitions(unittest.TestCase): + BASE = {"id": "ab", "name": "n", "instruction": "i"} + + def test_names_that_would_read_as_options_are_refused(self): + for field, value in (("toolsets", ["-t", "--yolo"]), ("toolsets", ["--yolo"]), ("skills", ["-x"]), + ("skills", ["a b"]), ("skills", [5]), ("session_id", "--dangerous"), ("session_id", "a b")): + with self.assertRaises(ValueError, msg=(field, value)): + agents_store.validate({**self.BASE, field: value}) + + def test_ordinary_names_pass(self): + out = agents_store.validate({**self.BASE, "skills": ["trader-desk", "trading/trader-desk"], "toolsets": ["terminal"], + "session_id": "20260508_101314_ab12cd"}) + self.assertEqual(out["skills"], ["trader-desk", "trading/trader-desk"]) + + +class ChatParsing(unittest.TestCase): + def test_a_reply_of_blank_lines_does_not_stall_the_server(self): + for reply in ("\n" * 20000, "CHART: a" + " " * 19980 + "x", " \t" * 10000 + "\nCHART: add rsi"): + t0 = time.time() + chat.parse_actions(reply) + self.assertLess(time.time() - t0, 0.3) + self.assertEqual(chat.parse_actions("hello\n CHART: add supertrend \nbye"), [{"kind": "add", "type": "supertrend"}]) + + def test_the_usage_file_lives_in_a_private_directory_that_is_removed(self): + seen = {} + + def fake_run(cmd, **kw): + usage = cmd[cmd.index("--usage-file") + 1] + seen["dir"] = os.path.dirname(usage) + seen["mode"] = os.stat(seen["dir"]).st_mode & 0o777 + return mock.Mock(returncode=0, stdout="hi", stderr="") + with mock.patch.object(chat.subprocess, "run", fake_run): + out = chat.run_agent("hermes", {"skills": [], "toolsets": [], "instruction": "x"}, "hi", workdir=None) + self.assertTrue(out["ok"]) + self.assertEqual(seen["mode"], 0o700) + self.assertFalse(os.path.exists(seen["dir"])) + + def test_a_missing_workdir_is_said_plainly(self): + out = chat.run_agent("hermes", {"skills": [], "toolsets": [], "instruction": "x"}, "hi", workdir="/no/such/folder") + self.assertFalse(out["ok"]) + self.assertIn("working folder does not exist", out["reason"]) + + +class Thumbnails(unittest.TestCase): + PNG = b"\x89PNG\r\n\x1a\n" + b"0" * 64 + + def test_only_a_real_picture_is_kept_and_a_concurrent_second_ask_never_sees_a_partial_file(self): + with tempfile.TemporaryDirectory() as cache: + url = "https://luxalgo-production.s3.amazonaws.com/a.png" + calls = [] + + def shrink(src, dst, width): + calls.append(1) + dst.write_bytes(b"\xff\xd8\xff" + b"1" * 10) + time.sleep(0.3) + dst.write_bytes(b"\xff\xd8\xff" + b"1" * 1000) # the whole file arrives later + return True + + got = [] + with mock.patch.object(library_thumbs, "CACHE_DIR", Path(cache)), \ + mock.patch.object(library_thumbs, "_fetch", lambda u: self.PNG), \ + mock.patch.object(library_thumbs, "_shrink", shrink): + t = threading.Thread(target=lambda: got.append(library_thumbs.thumb("s", url, 320))) + t.start() + time.sleep(0.1) + got.append(library_thumbs.thumb("s", url, 320)) # while the first is mid-build + t.join() + self.assertEqual([len(g[0]) for g in got], [1003, 1003]) + self.assertEqual(len(calls), 1, "built once") + + def test_html_or_svg_bytes_never_reach_the_converters(self): + with tempfile.TemporaryDirectory() as cache: + url = "https://luxalgo-production.s3.amazonaws.com/a.png" + for payload in (b"", b"#!/bin/sh\n", b"push graphic-context"): + with mock.patch.object(library_thumbs, "CACHE_DIR", Path(cache)), \ + mock.patch.object(library_thumbs, "_fetch", lambda u, p=payload: p), \ + mock.patch.object(library_thumbs, "_shrink", side_effect=AssertionError("converter reached")): + self.assertIsNone(library_thumbs.thumb("s", url, 320)) + + def test_a_redirect_is_not_followed_and_the_body_is_capped(self): + handler = library_thumbs._NoRedirect() + self.assertIsNone(handler.redirect_request(None, None, 301, "x", {}, "http://127.0.0.1/")) + self.assertLessEqual(library_thumbs.MAX_BYTES, 8_000_000) + + +# ── backtest service (pandas is not installed in the console venv; the checks need none) ────────────── + +class BacktestService(unittest.TestCase): + @classmethod + def setUpClass(cls): + import importlib.util + spec = importlib.util.spec_from_file_location("backtest_service_audit", BACKEND / "backtest_service.py") + cls.mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(cls.mod) + + def test_a_local_name_is_a_bare_file_name(self): + for bad in ("../../etc/passwd", "/etc/hostname", "a/b", "..", ".hidden/x", ""): + with self.assertRaises((ValueError, ImportError), msg=bad): + self.mod._bars_local(bad) + + def test_symbol_and_interval_are_validated_before_they_reach_a_url(self): + for symbol, interval in (("BTC&limit=1", "1h"), ("BTCUSDT", "1h&x=1"), ("", "1h"), ("BTCUSDT", "")): + with self.assertRaises((ValueError, ImportError)): + self.mod._klines_binance(symbol, interval, 10) + + def test_json_never_carries_nan(self): + out = self.mod._clean_nan({"a": float("nan"), "b": [float("inf"), 1.5], "c": {"d": float("-inf")}}) + self.assertEqual(out, {"a": None, "b": [None, 1.5], "c": {"d": None}}) + json.dumps(out, allow_nan=False) + + +if __name__ == "__main__": + unittest.main() + + +# ── the agent-facing layer (needs fastmcp; CI's second step has it) ──────────────────────────────────── + +from http.server import ThreadingHTTPServer # noqa: E402 + +sys.path.insert(0, str(Path(__file__).resolve().parent)) # a sibling test module, whichever way the suite is started +from test_mcp_server import HAVE_FASTMCP, _Stub, load_mcp, text_of # noqa: E402 + + +@unittest.skipUnless(HAVE_FASTMCP, "fastmcp is not installed") +class AgentSurface(unittest.TestCase): + def setUp(self): + self.shots = tempfile.mkdtemp() + _Stub.routes = {} + _Stub.posts = [] + self.server = ThreadingHTTPServer(("127.0.0.1", 0), _Stub) + threading.Thread(target=self.server.serve_forever, daemon=True).start() + self.base = f"http://127.0.0.1:{self.server.server_address[1]}" + self.mcp = load_mcp(self.base, self.shots) + + def tearDown(self): + self.server.shutdown() + self.server.server_close() + + def test_a_long_library_script_is_cut_and_says_so_and_the_rest_can_be_read(self): + pine = "//@version=6\n" + "x = 1\n" * 14000 # ~84,000 characters + _Stub.routes = {"/api/source": {"ok": True, "data": {"source": pine}}} + first = text_of(self.mcp.library_source("big-one")) + self.assertIn("truncated: showing characters 0-60000 of", first) + self.assertIn("offset=60000", first) + self.assertIn("Do NOT run or port this fragment", first) + rest = text_of(self.mcp.library_source("big-one", offset=60000)) + self.assertNotIn("truncated", rest) + self.assertIn("characters 60000-", rest) + + def test_a_script_that_fits_comes_back_whole_with_no_notice(self): + pine = "//@version=6\nplot(close)\n" * 600 # ~15,000 characters, over the old 8,000 cap + _Stub.routes = {"/api/source": {"ok": True, "data": {"source": pine}}} + out = text_of(self.mcp.library_source("mid-one")) + self.assertNotIn("truncated", out) + self.assertEqual(out.count("plot(close)"), 600) + + def test_a_cut_list_says_how_many_there_were(self): + _Stub.routes = {"/api/edge/presets": {"ok": True, "data": {"count": 40, "presets": [{"name": f"p{i}"} for i in range(40)]}}} + out = text_of(self.mcp.edge_presets()) + self.assertIn("30 of 40 preset(s) shown", out) + + def test_a_one_word_name_that_is_not_a_slug_falls_back_to_a_search(self): + calls = [] + + class Routes(dict): + def get(self, key, default=None): + calls.append(key) + if key == "/api/indicator": + return {"ok": False, "error": "not found"} if len([c for c in calls if c == key]) == 1 else {"ok": True, "data": {"title": "Killzones"}} + if key == "/api/search": + return {"ok": True, "data": {"results": [{"slug": "killzones-ict"}]}} + if key == "/api/source": + return {"ok": True, "data": {"source": "plot(1)"}} + return default + _Stub.routes = Routes() + out = text_of(self.mcp.library_indicator("killzone")) + self.assertIn("killzones-ict", out) + self.assertIn("plot(1)", out) + + def test_the_backtest_tools_answer_with_a_sentence_when_the_tier_is_down(self): + _Stub.routes = {"/api/backtest": {"ok": False, "error": "backtest service unreachable (URLError)"}, + "/api/backtest/sweep": {"ok": False, "error": "backtest service unreachable (URLError)"}, + "/api/backtest/results": {"ok": False, "error": "backtest service unreachable (URLError)"}} + for out in (self.mcp.bt_run(), self.mcp.bt_optimize(), self.mcp.bt_status()): + self.assertIsInstance(out, str) + self.assertIn("unreachable", out) + self.assertIn("optional", out) + + def test_chart_batch_takes_a_list_as_documented(self): + _Stub.routes = {"/api/chart/state": {"ok": True, "data": {"open": True, "age_s": 1.0}}, + "/api/chart/command": {"ok": True, "data": {"pushed": 1, "command": {"id": 1}, "result": {"ok": True, "detail": "cleared"}}}} + out = text_of(self.mcp.chart_batch([{"action": "clear"}])) + self.assertNotIn("not valid JSON", out) + self.assertIn("clear", out.lower()) + + def test_chart_shot_says_when_no_view_is_attached(self): + _Stub.routes = {"/api/chart/state": {"ok": True, "data": {"open": True, "age_s": 1.0}}, + "/api/chart/command": {"ok": True, "data": {"pushed": 0, "command": {"id": 1}, "result": None}}} + out = text_of(self.mcp.chart_shot()) + self.assertIn("no chart view is attached", out) + + def test_an_empty_chart_is_called_empty(self): + _Stub.routes = {"/api/chart/state": {"ok": True, "data": {"open": True, "age_s": 1.0, "symbol": "BTCUSDT", "timeframe": "1h", + "bars": None, "last": None, "studies": []}}} + self.assertIn("holds no bars", text_of(self.mcp.chart_state())) + + def test_calls_to_the_console_do_not_go_through_a_proxy(self): + _Stub.routes = {"/api/chart/stream/status": {"ok": True, "data": {"views": 1, "pushes": 0, "keepalive_s": 8.0}}} + with mock.patch.dict(os.environ, {"http_proxy": "http://127.0.0.1:9", "HTTP_PROXY": "http://127.0.0.1:9"}): + self.assertIn("1 view(s) attached", text_of(self.mcp.chart_views())) diff --git a/console/backend/tests/test_audit_8oct_frontend.py b/console/backend/tests/test_audit_8oct_frontend.py new file mode 100644 index 0000000..8b51472 --- /dev/null +++ b/console/backend/tests/test_audit_8oct_frontend.py @@ -0,0 +1,151 @@ +"""The 8 Oct 2026 audit, frontend half: the findings that are ours, held under Node where the logic can be lifted out. + +(The layout and keyboard fixes - the top-bar focus ring, the ⋯ button at 1024 px, the status line at 200% zoom, focus +restore, inert background - were verified in a real Chromium; their rules are pinned here as the cheapest guard that +survives, and the audit's own point stands that a string pin is weaker than a browser test.) +""" +import json +import re +import shutil +import subprocess +import unittest +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[3] +FRONT = ROOT / "console" / "frontend" +NODE = shutil.which("node") + + +def read(name): + return (FRONT / name).read_text(encoding="utf-8") + + +def node(script): + done = subprocess.run([NODE, "-"], input=script, capture_output=True, text=True, timeout=60) + if done.returncode != 0: + raise AssertionError((done.stderr or done.stdout)[-1500:]) + return json.loads(done.stdout.strip().splitlines()[-1]) + + +@unittest.skipUnless(NODE, "node is not installed") +class ScriptTools(unittest.TestCase): + def test_two_untitled_inline_inputs_get_different_keys_and_named_ones_keep_theirs(self): + got = node(f""" + const S = require({json.dumps(str(FRONT / 'script-tools.js'))}); + console.log(JSON.stringify({{ + a: S.inputKey({{ type: 'int', id: 'in_0' }}), b: S.inputKey({{ type: 'int', id: 'in_1' }}), + named: S.inputKey({{ varId: 'len', title: 'Length', type: 'int', id: 'in_7' }}), + titled: S.inputKey({{ title: 'Length', type: 'int', id: 'in_7' }}) }}));""") + self.assertNotEqual(got["a"], got["b"]) + self.assertEqual(got["named"], "len|Length|int", "stored values for named inputs must keep matching") + self.assertEqual(got["titled"], "|Length|int") + + def test_a_double_slash_inside_the_title_is_not_a_comment(self): + got = node(f""" + const S = require({json.dumps(str(FRONT / 'script-tools.js'))}); + console.log(JSON.stringify([ + S.declaredName('indicator("A // B", overlay=true)'), S.declaredName('indicator("Plain") // trailing'), + S.declaredName('// indicator("x")\\nindicator(title="Real")'), S.declaredName('plot(close)')]));""") + self.assertEqual(got, ["A // B", "Plain", "Real", ""]) + + +@unittest.skipUnless(NODE, "node is not installed") +class BridgeToken(unittest.TestCase): + def test_a_failed_session_fetch_is_not_remembered(self): + src = read("chart-bridge.js") + m = re.search(r" let TOKEN = null;\n const token = async \(\) => \{.*?\n \};\n", src, re.S) + self.assertTrue(m, "token() not found in chart-bridge.js") + got = node(m.group(0) + """ + let calls = 0, mode = 'fail'; + globalThis.fetch = async () => { calls++; if (mode === 'fail') throw new TypeError('network'); return { json: async () => ({ data: { token: 'T' } }) }; }; + (async () => { + const first = await token(); // the first fetch fails + mode = 'ok'; + const second = await token(); // it must ask again, not serve the failure + const third = await token(); // and now it is cached + console.log(JSON.stringify({ first, second, third, calls })); + })();""") + self.assertEqual(got, {"first": "", "second": "T", "third": "T", "calls": 2}) + + +class Pins(unittest.TestCase): + """Cheap guards for what a browser verified.""" + + def test_the_stream_no_longer_moves_the_polls_high_water_mark(self): + body = read("chart-bridge.js").split("stream.onmessage = async (event) => {", 1)[1].split("connectStream()", 1)[0] + code = re.sub(r"/\*.*?\*/", "", body.split("await run(payload.command)")[0].split("seen.add(id);")[1], flags=re.S) + self.assertNotIn("lastCommandId", code) + + def test_a_reschedule_cannot_be_skipped_by_a_throw(self): + self.assertIn("try { await poll(); } finally { setTimeout(tick, pollDelay); }", read("chart-bridge.js")) + + def test_the_rerun_waits_for_the_one_in_flight(self): + src = read("unified.js") + self.assertIn("if (rerunning) { check(); return; }", src) + self.assertLess(src.index("if (rerunning) { check(); return; }"), src.index("marketSig = now;\n /* The new bars load")) + + def test_the_newest_run_wins(self): + src = read("unified.js") + self.assertIn("const mySeq = ++runSeq;", src) + self.assertIn("if (mySeq !== runSeq) {", src) + + def test_catalogue_links_must_be_https(self): + src = read("app.js") + self.assertIn("function safeHref(u)", src) + self.assertNotIn("href=\"${esc(row.url || '#')}\"", src) + self.assertIn("\"'\": '''", src, "esc() must escape the single quote too") + + def test_the_draft_is_flushed_when_the_page_goes_away(self): + src = read("app.js") + self.assertIn("window.addEventListener('pagehide', flushDraft)", src) + + def test_the_highlight_layer_is_not_a_tab_stop(self): + self.assertIn('class="script__clip" aria-hidden="true" tabindex="-1" inert', read("index.html")) + + def test_the_sheets_are_dialogs_and_make_the_rest_inert(self): + html = read("index.html") + for ident in ("lib-drawer", "edge-sheet"): + self.assertRegex(html, rf'id="{ident}" role="dialog" aria-modal="true"') + self.assertIn("window.taModal.enter(", read("drawer.js") + read("edge.js")) + + def test_the_top_bar_has_a_focus_ring_that_beats_all_unset(self): + css = read("styles.css") + i = css.index(".vela-widget-symbol:focus-visible") + self.assertIn("outline: var(--lx-focus-ring) !important", css[i:i + 700]) + + def test_inputs_keep_a_transparent_outline_for_forced_colours(self): + css = read("styles.css") + self.assertIn("input:focus-visible, textarea:focus-visible {\n /* transparent", css) + + def test_the_dock_band_and_the_short_viewport_rules_exist(self): + css = read("styles.css") + self.assertIn("@media (min-width: 1020px) and (max-width: 1069px)", css) + self.assertIn("calc(100vw - 630px)", css) + self.assertIn("@media (max-height: 560px)", css) + + def test_the_console_has_a_title_and_an_icon(self): + html = read("index.html") + self.assertIn("Trader's Agent", html) + self.assertIn('rel="icon"', html) + + +class PluginReveal(unittest.TestCase): + def test_the_launch_reveal_waits_for_the_stored_choice_and_defaults_to_off(self): + src = (ROOT / "plugin" / "plugin.js").read_text(encoding="utf-8") + self.assertIn("autoRevealOn = value === true", src) + self.assertIn("autoRevealReady.then(", src) + self.assertNotIn("autoRevealOn = value !== false", src) + + + +class AddDoor(unittest.TestCase): + def test_an_unknown_native_is_refused_before_vela_is_asked(self): + src = read("chart-bridge.js") + i = src.index("case 'add': {") + block = src[i:i + 4200] + self.assertLess(block.index("availableNativeIndicators"), block.index("c.addNativeIndicator(name);")) + self.assertIn("did you mean", block) + + +if __name__ == "__main__": + unittest.main() diff --git a/console/backend/tests/test_catalogue_groups.py b/console/backend/tests/test_catalogue_groups.py index cef8687..845b508 100644 --- a/console/backend/tests/test_catalogue_groups.py +++ b/console/backend/tests/test_catalogue_groups.py @@ -39,7 +39,7 @@ class TheCatalogueComesInOnePiece(unittest.TestCase): def test_the_endpoint_walks_the_pages_once_and_keeps_them(self): src = read(SERVER) self.assertIn('"/api/catalogue"', src) - body = src.split("def ep_catalogue(", 1)[1].split("\ndef ", 1)[0] + body = src.split("def _ep_catalogue(", 1)[1].split("\ndef ", 1)[0] self.assertIn('"sort": ["family"]', body, "the server's own grouping means the rows arrive clustered and the page can walk them") self.assertIn("CATALOGUE_PAGE", body, "the MCP caps a page at 100 rows; the walk has to loop") @@ -51,7 +51,7 @@ def test_the_second_walk_is_what_files_the_unfiled(self): """Half the catalogue carries no family; its CONCEPTS do. Walk them and 390 of 414 rows land in a real group (measured 27 Sep) — otherwise the rail opens with a 414-row "Unfiled".""" src = read(SERVER) - body = src.split("def ep_catalogue(", 1)[1].split("\ndef ", 1)[0] + body = src.split("def _ep_catalogue(", 1)[1].split("\ndef ", 1)[0] self.assertIn("ep_concepts(", body, "the concept walk shares the catalogue's cache and TTL") self.assertIn('concept = concepts.get(row.get("slug") or "")', body) self.assertIn('row["family"] = concept.get("family")', body) diff --git a/console/backend/tests/test_chart_bridge_idempotence.py b/console/backend/tests/test_chart_bridge_idempotence.py index 6e97438..17739bd 100644 --- a/console/backend/tests/test_chart_bridge_idempotence.py +++ b/console/backend/tests/test_chart_bridge_idempotence.py @@ -147,11 +147,11 @@ def test_the_market_switch_guard_is_still_here(self): self.assertIn("SWITCH_DEADLINE_MS", source) def test_the_live_tree_matches_the_repo_when_present(self): - live = os.environ.get("LUXALGO_LIVE") or os.path.expanduser( - "~/Projects/luxalgo-web/frontend/chart-bridge.js" - ) - if not os.path.exists(live): - self.skipTest("no live tree on this machine") + # Opt-in: it compares against ONE person's served tree, so it must never fail by accident on that machine (or + # on any other). `LUXALGO_LIVE=/path/to/chart-bridge.js python -m unittest ...` runs it. + live = os.environ.get("LUXALGO_LIVE") + if not live or not os.path.exists(live): + self.skipTest("set LUXALGO_LIVE to a served chart-bridge.js to compare it with the repo") with open(live, encoding="utf-8") as fh: live_source = fh.read() self.assertEqual( diff --git a/console/backend/tests/test_console_hardening.py b/console/backend/tests/test_console_hardening.py index a8afdec..01acc87 100644 --- a/console/backend/tests/test_console_hardening.py +++ b/console/backend/tests/test_console_hardening.py @@ -21,7 +21,6 @@ the fix, its review, and the same door in `script` are pinned here. """ -import io import os import socket import sys @@ -88,7 +87,11 @@ def test_host_must_be_local(self): def test_origin_may_be_absent_or_local_only(self): self.assertTrue(srv.Handler._origin_ok(fake_request())) # CLI, MCP, curl - self.assertTrue(srv.Handler._origin_ok(fake_request(origin="http://127.0.0.1:8787"))) + self.assertTrue(srv.Handler._origin_ok(fake_request(host="127.0.0.1:8787", origin="http://127.0.0.1:8787"))) + # the PORT counts: another web app on localhost is a "local name" but not this console's page (audit SEC-4) + self.assertFalse(srv.Handler._origin_ok(fake_request(host="127.0.0.1:8787", origin="http://127.0.0.1:9999"))) + self.assertFalse(srv.Handler._origin_ok(fake_request(host="127.0.0.1:8787", origin="http://localhost:8787"))) + self.assertFalse(srv.Handler._origin_ok(fake_request(origin="http://127.0.0.1:8787"))) # no Host to compare with self.assertFalse(srv.Handler._origin_ok(fake_request(origin="null"))) # sandboxed page self.assertFalse(srv.Handler._origin_ok(fake_request(origin="http://evil.example"))) diff --git a/console/backend/tests/test_edgestats.py b/console/backend/tests/test_edgestats.py index e18c940..fe890a1 100644 --- a/console/backend/tests/test_edgestats.py +++ b/console/backend/tests/test_edgestats.py @@ -165,7 +165,7 @@ def test_installed_but_empty_says_load_data(self): self.assertEqual((cm.exception.status, cm.exception.code), (409, "edge_no_data")) def test_it_starts_lazily_once_and_stays_up(self): - with FakeEdgeHome(with_config=True) as fake: + with FakeEdgeHome(with_config=True): self.assertEqual(edgestats.SIDECAR.state()["state"], "stopped") edgestats.SIDECAR.ensure() self.assertEqual(edgestats.SIDECAR.state()["state"], "ready") diff --git a/console/backend/tests/test_edgestats_ui.py b/console/backend/tests/test_edgestats_ui.py index 132fb74..f5eeec0 100644 --- a/console/backend/tests/test_edgestats_ui.py +++ b/console/backend/tests/test_edgestats_ui.py @@ -40,7 +40,7 @@ class Markup(unittest.TestCase): def test_the_sheet_and_its_scrim_exist_and_start_hidden(self): for ident in ("edge-sheet", "edge-scrim", "edge-bar", "edge-body", "edge-close", "edge-data", "edge-sub"): self.assertIn(f'id="{ident}"', HTML) - self.assertIn('id="edge-sheet" aria-hidden="true"', HTML) + self.assertIn('id="edge-sheet" role="dialog" aria-modal="true" aria-hidden="true"', HTML) self.assertIn('href="./edge.css"', HTML) self.assertIn('src="./edge.js"', HTML) diff --git a/console/backend/tests/test_environment_guard.py b/console/backend/tests/test_environment_guard.py new file mode 100644 index 0000000..f25f7e1 --- /dev/null +++ b/console/backend/tests/test_environment_guard.py @@ -0,0 +1,30 @@ +"""CI sets these so that a missing tool is a FAILURE, not a quiet skip. Without them 155 Node-driven tests (and the MCP layer) +skip themselves when `node` / `fastmcp` is absent and the suite still ends OK (audit 8 Oct, TC-5).""" +import os +import shutil +import unittest + + +class RequiredToolsAreThere(unittest.TestCase): + def test_node_is_installed_when_ci_requires_it(self): + if os.environ.get("TRADER_CHART_REQUIRE_NODE") == "1": + self.assertTrue(shutil.which("node"), "TRADER_CHART_REQUIRE_NODE=1 but node is not on PATH: 155 tests would skip") + + def test_fastmcp_is_importable_when_ci_requires_it(self): + if os.environ.get("TRADER_CHART_REQUIRE_MCP") == "1": + import fastmcp # noqa: F401 (ImportError is the failure) + + + +class VendoredFilesAreWhatWasRecorded(unittest.TestCase): + def test_vendor_sums_match(self): + import subprocess + import sys + from pathlib import Path + tool = Path(__file__).resolve().parents[3] / "tools" / "vendor-sums.py" + done = subprocess.run([sys.executable, str(tool), "--check"], capture_output=True, text=True) + self.assertEqual(done.returncode, 0, done.stderr or "tools/vendor-sums.py --write after a deliberate vendor change") + + +if __name__ == "__main__": + unittest.main() diff --git a/console/backend/tests/test_mcp_server.py b/console/backend/tests/test_mcp_server.py index f7fd49d..0556867 100644 --- a/console/backend/tests/test_mcp_server.py +++ b/console/backend/tests/test_mcp_server.py @@ -13,7 +13,6 @@ import json import os import socket -import sys import tempfile import threading import time diff --git a/console/backend/tests/test_mcp_tool_annotations.py b/console/backend/tests/test_mcp_tool_annotations.py index 37cbd18..031dd0e 100644 --- a/console/backend/tests/test_mcp_tool_annotations.py +++ b/console/backend/tests/test_mcp_tool_annotations.py @@ -12,7 +12,6 @@ import importlib.util import os -import sys import unittest HERE = os.path.dirname(os.path.abspath(__file__)) @@ -96,13 +95,32 @@ def test_read_only_tools_change_nothing(self): self.assertTrue(hint(self.ann(name), "read_only_hint"), f"{name} should be read-only") def test_chart_mutating_tools_say_so(self): - for name in ("chart_apply_pine", "chart_add_indicator", "chart_set_market", + for name in ("chart_apply_pine", "chart_set_market", "chart_draw", "chart_clear", "chart_remove_indicator", "chart_reload"): annotations = self.ann(name) self.assertFalse(hint(annotations, "read_only_hint"), f"{name} changes the chart") self.assertTrue(hint(annotations, "destructive_hint"), f"{name} should declare destructiveHint") + def test_every_writer_states_whether_it_destroys(self): + """An unset destructiveHint reads as TRUE to a client (the MCP default for a non-read-only tool), so a writer that + does not say is treated as destructive. All 54 say (audit 8 Oct, AS-19).""" + for name, tool in self.tools.items(): + a = tool.annotations if hasattr(tool, "annotations") else None + if hint(a, "read_only_hint"): + continue + self.assertIsNotNone(hint(a, "destructive_hint"), f"{name} does not state destructiveHint") + + def test_additive_tools_are_not_destructive_and_the_ones_that_delete_work_are(self): + for name in ("chart_add_indicator", "chart_theme", "chart_fullscreen", "chart_replay", "chart_snapshot"): + self.assertFalse(hint(self.ann(name), "destructive_hint"), f"{name} only adds or toggles") + for name in ("chart_drawing", "chart_marks", "chart_clear", "chart_remove_indicator", "chart_undo"): + self.assertTrue(hint(self.ann(name), "destructive_hint"), f"{name} can delete the operator's work") + + def test_the_backtest_tools_reach_binance(self): + for name in ("bt_run", "bt_optimize"): + self.assertTrue(hint(self.ann(name), "open_world_hint"), f"{name} fetches klines from Binance") + def test_replay_is_a_chart_mutation(self): self.assertFalse(hint(self.ann("chart_replay"), "read_only_hint")) diff --git a/console/backend/tests/test_preview_cache.py b/console/backend/tests/test_preview_cache.py index 0700804..a73c9e8 100644 --- a/console/backend/tests/test_preview_cache.py +++ b/console/backend/tests/test_preview_cache.py @@ -78,7 +78,7 @@ def test_the_thumb_cache_module_is_stdlib_only(self): """The console's rule: no third-party imports (the resizer is a CLI, not a Python dep).""" src = read(THUMBS) allowed = {"__future__", "hashlib", "os", "re", "shutil", "subprocess", "threading", "time", - "urllib", "concurrent", "pathlib"} + "urllib", "concurrent", "pathlib", "tempfile"} for line in src.splitlines(): match = re.match(r"^(?:import|from)\s+([a-zA-Z_][\w.]*)", line) if match: @@ -112,7 +112,18 @@ def test_only_luxalgo_is_ever_fetched(self): self.assertIn("def _allowed(", src) body = src.split("def thumb(", 1)[1] self.assertIn("if not _allowed(url):", body, "thumb() must refuse a foreign URL, not fetch it") - self.assertIn('if not url.startswith("https://"):', src, "https only, even for a friendly host") + # behaviour, not a string: https only, exact hosts only (a "contains luxalgo" rule let other buckets in) + import importlib.util + spec = importlib.util.spec_from_file_location("library_thumbs_allow", THUMBS) + mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(mod) + self.assertTrue(mod._allowed("https://luxalgo-production.s3.amazonaws.com/a.png")) + for url in ("http://luxalgo-production.s3.amazonaws.com/a.png", + "https://luxalgo-evil.s3.amazonaws.com/a.png", + "https://attacker-luxalgo.s3.eu-west-1.amazonaws.com/a.svg", + "https://luxalgo.s3-website-us-east-1.amazonaws.com/a", + "https://evil.com/luxalgo-production.s3.amazonaws.com/", "", None): + self.assertFalse(mod._allowed(url), url) def test_the_second_bucket_is_actually_fetched(self): """Refusing it was a live bug: four cards on page one had no picture (measured 27 Sep).""" @@ -145,14 +156,14 @@ def test_the_warmer_walks_the_whole_catalogue_by_default(self): self.assertIn("def warm_catalogue_thumbs(pages: int = 0) -> None:", src) self.assertIn("limit = pages or MAX_WARM_PAGES", src) self.assertIn("MAX_WARM_PAGES = 40", src, "a runaway page walk needs a guard rail") - self.assertIn('os.environ.get("TRADERS_AGENT_THUMB_WARM_PAGES", "0")', src) + self.assertIn('_env_int("TRADERS_AGENT_THUMB_WARM_PAGES", 0)', src) self.assertIn('out["warmer"] = dict(_WARM)', src, "progress must be observable, not guessed") def test_the_resizer_is_a_cli_with_a_honest_fallback(self): src = read(THUMBS) for tool in ("vips", "magick", "convert", "ffmpeg"): self.assertIn(f'"{tool}"', src, f"{tool} is part of the fallback chain") - self.assertIn('return raw, "image/png"', src, + self.assertIn('return raw, ("image/"', src, "no converter on a machine must serve the real picture, not a blank tile") def test_a_missing_preview_is_a_404_not_a_placeholder(self): diff --git a/console/backend/tests/test_script_highlight.py b/console/backend/tests/test_script_highlight.py index d1994fb..91370f1 100644 --- a/console/backend/tests/test_script_highlight.py +++ b/console/backend/tests/test_script_highlight.py @@ -112,6 +112,9 @@ def test_the_tokens_always_join_back_to_the_line(self): pine = sorted(ROOT.glob("docs/studies/**/*.pine")) self.assertTrue(pine, "no Pine in the repo to read") corpus = [line for f in pine for line in f.read_text().split("\n")] + # The repo's own studies are few now (the committed LuxAlgo script was removed, 8 Oct): every line is also cut at + # several points, which is how a half-typed line reaches the tokenizer in the editor. + corpus += [line[:k] for line in list(corpus) for k in (1, len(line) // 3, len(line) // 2, len(line) - 1) if 0 < k < len(line)] corpus += ["", " ", "\t\t", " ", "é = 1 // ünï", "emoji 😀 \"😀\" // 😀", "nul \u0000 byte", "cr \r in the line", '"', "'", "\\", "//", "///", "#", "#fff", "#12345", "#2157f3ff1", "@", "@@", "..", ".5.5", "1.2.3", "1e", "1e+", '"\\', '"\\"', "'\\'", "x" * 5000, "ta." * 2000] @@ -385,7 +388,7 @@ def test_it_loads_after_the_pane_and_the_markup_has_its_three_parts(self): order = [HTML.index(f'src="./{name}"') for name in ("app.js", "script-library.js", "script-highlight.js")] self.assertEqual(order, sorted(order)) m = re.search(r'
\s*' - r'\s*' + r'\s*' r' @@ -231,7 +232,7 @@

Nothing selected

workspace module dies with "process is not defined" and the page falls back to the bare chart. --> - @@ -302,14 +303,14 @@

Nothing selected

- - - - - - - + + + + + + + diff --git a/console/frontend/replay.js b/console/frontend/replay.js index 3cacf71..7679dc4 100644 --- a/console/frontend/replay.js +++ b/console/frontend/replay.js @@ -110,7 +110,9 @@ {active:false} clears whatever was left over (a reload mid-replay, a killed page). */ async function push(px) { if (state.active && px == null) return; // nothing to price the fills with yet - const body = { active: !!state.active, price: state.active ? px : null, time: state.active ? state.cursorTime : null }; + let sym = null; + try { const m = typeof window.chartMarket === 'function' ? window.chartMarket() : null; sym = (m && m.symbol) || null; } catch (err) { sym = null; } + const body = { active: !!state.active, price: state.active ? px : null, time: state.active ? state.cursorTime : null, symbol: state.active ? sym : null }; const key = JSON.stringify(body); if (key === lastPush) return; try { await post('/api/broker/replay', body); lastPush = key; } diff --git a/console/frontend/script-tools.js b/console/frontend/script-tools.js index be97795..ca6d984 100644 --- a/console/frontend/script-tools.js +++ b/console/frontend/script-tools.js @@ -25,6 +25,18 @@ const lineOf = (text) => String(text).split('\n'); /** A line with its `//` comment and its string literals taken out, so a name inside either never matches. */ + /** A line without its trailing `//` comment, KEEPING its strings (a `//` inside "A // B" is text, not a comment). */ + function dropComment(line) { + let quote = ''; + for (let i = 0; i < line.length; i++) { + const c = line[i]; + if (quote) { if (c === '\\') i++; else if (c === quote) quote = ''; } + else if (c === '"' || c === "'") quote = c; + else if (c === '/' && line[i + 1] === '/') return line.slice(0, i); + } + return line; + } + function codeOnly(line) { return String(line) .replace(/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'/g, '""') @@ -63,7 +75,11 @@ /** A stable handle for one input across edits. The engine's ids (`in_0`, `in_1`) are positions, so adding * an input above shifts them all; the variable it is assigned to, its label and its type do not move. */ function inputKey(meta) { - return [meta.varId || '', meta.title || meta.name || '', meta.type || ''].join('|'); + const named = !!(meta.varId || meta.title || meta.name); + /* An input with neither a variable nor a label (`ta.sma(close, input.int(5)) + ta.ema(close, input.int(9))`) has only + its type to go by, so two of them shared one key and an override for one reached both. Its position tells them + apart; named inputs keep the key they always had, so stored values still match. */ + return [meta.varId || '', meta.title || meta.name || '', meta.type || '', named ? '' : (meta.id || '')].join('|').replace(/\|$/, ''); } const NUMERIC = new Set(['int', 'float', 'price']); @@ -309,7 +325,7 @@ /** The title a script declares for itself: indicator('Smart Money Concepts', …). Changed values belong to * that script — a different script that happens to have an input called "Length" must not inherit them. */ function declaredName(source) { - const m = String(source || '').replace(/\/\/[^\n]*/g, '').match(/\b(?:indicator|strategy|library)\s*\(\s*(?:title\s*=\s*)?(['"])((?:(?!\1).)*)\1/); + const m = String(source || '').split('\n').map(dropComment).join('\n').match(/\b(?:indicator|strategy|library)\s*\(\s*(?:title\s*=\s*)?(['"])((?:(?!\1).)*)\1/); return m ? m[2].trim() : ''; } diff --git a/console/frontend/styles.css b/console/frontend/styles.css index 9188db4..4cd9ddb 100644 --- a/console/frontend/styles.css +++ b/console/frontend/styles.css @@ -40,6 +40,9 @@ --lx-fg-bright: #f0f3fa; --lx-chart-ink: #d1d4dc; --lx-fg-on-fill: #ffffff; + /* A filled button's colour: the accent itself is 3.2:1 under white text in the dark theme (audit 8 Oct); this is 4.9:1. */ + --lx-accent-fill: #0e76b4; + --lx-accent-fill-hover: #0b659c; /* exactly one accent (trade-journal's dark brand blue) */ --lx-accent: #1197e2; @@ -197,6 +200,8 @@ --lx-fg-bright: #000000; --lx-chart-ink: #0b0b0b; --lx-fg-on-fill: #ffffff; + --lx-accent-fill: var(--lx-accent); + --lx-accent-fill-hover: var(--lx-accent-hover); --lx-accent: #0071b2; --lx-accent-hover: #0a6ba3; @@ -310,10 +315,22 @@ body { box-shadow: var(--lx-focus-halo); } input:focus-visible, textarea:focus-visible { - outline: none; + /* transparent, not none: in forced-colors (Windows high contrast) box-shadow and border colour are dropped, and an + outline that is transparent here is drawn in the system colour, so the focused field is still visible. */ + outline: 2px solid transparent; border-color: var(--lx-accent); box-shadow: var(--lx-focus-halo); } +/* Vela's top bar (Symbol, timeframes, Indicators, Script, Agent, Replay, ⋯) is built with `all: unset`, which beats the + zero-specificity :where() rule above, so keyboard focus on the main toolbar showed nothing at all (audit 8 Oct, G1). + Higher specificity and !important on the outline, because `all: unset` is what we are overriding. */ +.vela-widget-symbol:focus-visible, .vela-widget-tf:focus-visible, .vela-topbar-tf:focus-visible, +.vela-widget-action:focus-visible, .vela-widget-action-left:focus-visible, +[id^="vela-action-"]:focus-visible, [class*="vela-widget-"]:is(button, [role="button"]):focus-visible { + outline: var(--lx-focus-ring) !important; + outline-offset: -2px !important; + box-shadow: var(--lx-focus-halo); +} .panel:has(:focus-visible) { outline: 2px solid var(--lx-accent); outline-offset: var(--lx-focus-inset); } * { scrollbar-width: thin; scrollbar-color: var(--lx-border-strong) transparent; } @@ -419,6 +436,21 @@ pre, .detail { overscroll-behavior: contain; } padding-top: var(--lx-strip-h, 0px); } +/* Between ~1020 and ~1069 px the docked chart column is 640 to 690 px: too wide for Vela's compact toolbar (under ~640) and + too narrow for its desktop one (~670), so the toolbar spilled under the pane and the ⋯ menu, the only door to Edge Stats, + was covered (audit 8 Oct, G2). In that band the pane takes the extra width and the chart column stays at 630 px, which + Vela renders in its compact mode. Outside it nothing changes. */ +@media (min-width: 1020px) and (max-width: 1069px) { + .main[data-dock="on"][data-detail="on"] { grid-template-columns: minmax(320px, 1fr) calc(100vw - 630px); } + .main[data-dock="on"][data-library="on"][data-detail="on"] { grid-template-columns: 300px minmax(320px, 1fr) calc(100vw - 930px); } +} +/* A short viewport (a 1440x900 monitor at 200% zoom is 720x450 CSS px): the editor's 160 px floor plus the bar pushed the run + status, and with it any error, below the visible page. Let the editor give way and the pane scroll (audit G3). */ +@media (max-height: 560px) { + .panel--right .script__edit { min-height: 72px; } /* (more specific than the base rule further down, which comes later) */ + .panel--right { overflow-y: auto; } +} + @media (max-width: 1099px) { /* The chart keeps the height (operator's call, 15 Sep): the app stays viewport-tall and the stacked main grid hands the chart every row that is left, instead of sizing to content. The @@ -569,8 +601,8 @@ input[type="text"]:hover { border-color: var(--lx-border-strong); } transition: background var(--lx-dur-90) var(--lx-ease), border-color var(--lx-dur-90) var(--lx-ease); } .btn:hover { background: var(--lx-bg-hover-strong); } -.btn--primary { background: var(--lx-accent); border-color: var(--lx-accent); color: var(--lx-fg-on-fill); } -.btn--primary:hover { background: var(--lx-accent-hover); border-color: var(--lx-accent-hover); } +.btn--primary { background: var(--lx-accent-fill); border-color: var(--lx-accent-fill); color: var(--lx-fg-on-fill); } +.btn--primary:hover { background: var(--lx-accent-fill-hover); border-color: var(--lx-accent-fill-hover); } .btn--ghost { background: transparent; } /* Topbar panel toggles: a notch smaller than a form button, so the bar stays a bar. */ .btn--toggle { height: var(--lx-control-h-sm); padding: 0 var(--lx-space-2); font-size: var(--lx-fs-xs); color: var(--lx-fg-muted); } diff --git a/console/frontend/unified.js b/console/frontend/unified.js index d6f2c46..07660bf 100644 --- a/console/frontend/unified.js +++ b/console/frontend/unified.js @@ -318,9 +318,11 @@ window.TraderRun = (function () { return out; } + let runSeq = 0; // the newest run STARTED wins: two overlapping runs used to paint in the order they FINISHED async function run(pine, name, opts) { + const mySeq = ++runSeq; name = name || 'agent'; - if (!pine || !String(pine).trim()) return { ok: false, reason: 'no Pine source in the command' }; + if (!pine || !String(pine).trim()) return { ok: false, reason: 'nothing to run yet \u2014 paste some Pine into the editor, then press Run' }; if (typeof window.chartBars !== 'function') return { ok: false, reason: 'no chart on this page' }; if (!window.PineTSRunner) return { ok: false, reason: 'Pine engine missing — indicators cannot be mounted' }; @@ -335,6 +337,9 @@ window.TraderRun = (function () { if (!res.ok) { return { ok: false, name, reason: res.reason || 'not runnable: unknown', error: res.error || null, ms: res.ms || null }; } + if (mySeq !== runSeq) { + return { ok: false, name, superseded: true, reason: 'a newer run started while this one was computing, so this one was not drawn', ms: res.ms || null }; + } /* The provider's clean return can lie: it reported a healthy run while its data never reached the constructors (every container kept only its pre-created placeholder row), @@ -585,6 +590,10 @@ window.TraderRun = (function () { timer = setTimeout(async () => { pendingSig = null; if (sigNow() !== now) { check(); return; } + /* A re-run for the PREVIOUS market may still be computing: rerun() would answer null and, with marketSig already + moved on, nothing would ever redraw (ETH labels stayed on a SOL chart). Leave marketSig as it was so the + next check arms again, until the in-flight run ends. */ + if (rerunning) { check(); return; } marketSig = now; /* The new bars load and Vela's visible window settles first: drawing against the old window put boxes at the wrong bars. A quick script gets a second pass after the chart has surely settled. */ diff --git a/console/frontend/vendor/SHA256SUMS b/console/frontend/vendor/SHA256SUMS new file mode 100644 index 0000000..da735c0 --- /dev/null +++ b/console/frontend/vendor/SHA256SUMS @@ -0,0 +1,333 @@ +8486a10c4393cee1c25392769ddd3b2d6c242d6ec7928e1414efff7dfb2f07ef pinets/LICENSE +eb1df2646ea42fb7c32745c4dcaaca233059a4e71ac63e46552a712f39172d26 pinets/pinets.min.browser.es.js +1eb85fc97224598dad1852b5d6483bbcf0aa8608790dcc657a5a2a761ae9c8c6 vela/LICENSE +943b246985e5f0fc3b3291b2326eb05163ed36e2cfce4921688e4330edf53236 vela/NOTICE +d570fc63a4c820059163b0ecb6efd2b43452f268347e5e7344fd949ecb18d785 vela/dist/chunk-2IPXYM4B.js +55b203ab86f14d5fae2b8fa4f566c7264cb3280636e01123047bb26b50367349 vela/dist/chunk-G7B7ZCBF.js +995272ddc2cf97d666c35b6882ba2e1848fc58512106138b23a363adcf311ee8 vela/dist/chunk-HMHA733L.js +d79c40a264cae1f7a9c36242d9adc9ca5577a2aa5b10f1d9530c8e0b74a81d38 vela/dist/chunk-KWI3YDBW.js +e5e092b38ce68a8152be974bc6d35cdf131e44d4d046953bda1f9103489bcc2d vela/dist/chunk-TO3GIK7Z.js +0587f73defeb0caf25260e57c8d77f2e0a57d5af8198de759fe920c7aa467478 vela/dist/chunk-VHGACEHO.js +135b607d129e57d02e32cd7b7e35fc34f92aaa6387445e5f4933aab4665331cb vela/dist/chunk-W4EJWLEO.js +01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b vela/dist/chunk-W5YPYZ2P.js +2ca052d8ed26a43e0ac47973b7f7141c9c1f0e7fc023fec77d76b12e14036bae vela/dist/index.js +1ad8ad1fee9ff79ff3747a3d68b568747ba608cc7f29bcad6b806de06a973626 vela/dist/plugin.js +e53ca2500d24303675d0a6eb9c33c15b457b267b34120404dd2a629b1a01d2ce vela/dist/providers/binance.js +b1bd83e850ec3983bc75dd10f3573e4ad49962f6d87f8dcb49e28511f845a68a vela/dist/providers/coinbase.js +1f7475930360d6600b7b58eef9a2696c5d4063f3ddac1663975d1bd5565ff023 vela/dist/providers/hyperliquid.js +fc8dc2b3caf6455332836d89f5e3bcca3c54e810eccc12be064632c199171557 vela/dist/ui.js +4e732bbb648aefc6f330d1e5b74aefa39bc4ab322d1a9ddd46a654856fd77fdf vela/dist/vela.global.min.js +5601eb95331f43e252df0d1400b80a400171600ce4a20d92a78809f74c4d50b9 vela/dist/widget.js +010bf95aed54a1f2a067ab32c0f55586a0d21d9700edbb9b6c1d505bd784138b vela/dist/workspace.js +6f1e622c82a380075843bb084a7ec3b1f1d12a4a02526d75e78b0924a860aa75 vela-pinets/LICENSE +b8c3fe052ea231953b6063525c352e4fb5d83a25559765736847842f6be80748 vela-pinets/dist/index.js +0e27267650510d0de49ce1122b3370106b24c0b502d9b892b3374d9c5e1cd9a3 vela-pinets/dist/vela-pinets.global.min.js +895286af18d41dd1d59d8bca70f5d6ccee1c0d3c8ae41b8e5075758bf8c13f7e zag/floating-ui-core/floating-ui.core.browser.min.mjs +9e666a7acc8479ea73b84c7ec1cbe000159897d671ff240c48f105a5db438044 zag/floating-ui-core/floating-ui.core.browser.mjs +c6c359d91fbc6636f6143aae9ff47105eeacea869b14afe7d54e120444ab8f37 zag/floating-ui-core/floating-ui.core.esm.js +c6c359d91fbc6636f6143aae9ff47105eeacea869b14afe7d54e120444ab8f37 zag/floating-ui-core/floating-ui.core.mjs +c059eb702039c238f40f1a54e79ef78765ea36f442ca243e57175184f0df5ac3 zag/floating-ui-core/floating-ui.core.umd.js +65940d866a6b6d831394a4bbed99ed0a39330bac98b643386d9a2f87a1a1d5da zag/floating-ui-core/floating-ui.core.umd.min.js +96c4bf63ebf119c1575ee930e0b0ae76bc4eaf84f33d6cc55398cf15ef986a17 zag/floating-ui-dom/floating-ui.dom.browser.min.mjs +d32f5c2de15ab385de24a5b158619a59e55767e268dcb18d421d71a4a6746a0f zag/floating-ui-dom/floating-ui.dom.browser.mjs +a1c916ed18ed8bb2c586079f7946d35797b45bc79eafae1d99ec6f812672ef54 zag/floating-ui-dom/floating-ui.dom.esm.js +a1c916ed18ed8bb2c586079f7946d35797b45bc79eafae1d99ec6f812672ef54 zag/floating-ui-dom/floating-ui.dom.mjs +6601cfb1a56557f988a727eaf609f93c78a854f1c668208c831dda52a16fcf92 zag/floating-ui-dom/floating-ui.dom.umd.js +61a46f943c4e99379eaf073447811aec7e8b8f120d2f646316e01b7694bc90a3 zag/floating-ui-dom/floating-ui.dom.umd.min.js +b6658b1eac47e2917e6d10ebbeefb9c4ac9a166f0052bed6e08c871ed848b680 zag/floating-ui-utils/floating-ui.utils.dom.esm.js +b6658b1eac47e2917e6d10ebbeefb9c4ac9a166f0052bed6e08c871ed848b680 zag/floating-ui-utils/floating-ui.utils.dom.mjs +125bdf99b20878cb6f15ec3db9050c893c11942ea57bd3acbbb4d5a24e48733c zag/floating-ui-utils/floating-ui.utils.dom.umd.js +58487f55c03fece0e577e17fea85a9076db368777193440889e79161d16c7665 zag/floating-ui-utils/floating-ui.utils.dom.umd.min.js +f53b3ea1eec15af77ca9def295b8f40f6d65706acfc5aaac4801ca3ca21ef7bd zag/floating-ui-utils/floating-ui.utils.esm.js +f53b3ea1eec15af77ca9def295b8f40f6d65706acfc5aaac4801ca3ca21ef7bd zag/floating-ui-utils/floating-ui.utils.mjs +46d7f11efc704bd7b14ab5894384c2ae34b1f2ac9a16da637ff1a261fb9b7959 zag/floating-ui-utils/floating-ui.utils.umd.js +83c4c07e8bbeb76cc2f184401d01f9beb5263f4499df9b3ef6bf467eb6b0fb41 zag/floating-ui-utils/floating-ui.utils.umd.min.js +8c08fa2b2d2f73cf5b122172bfa6f34863ee56c004fe72557748ca2e99acf039 zag/proxy-compare/cjs/index.js +e0c33788a8003ae37cdd1b82a4349f71df8cab15dac47f07e6d6954b510f02c0 zag/proxy-compare/index.js +03edeacfdb66e40777f1babbceca180dfcf489d1c21a95cfcbd41024c3d46a90 zag/zag-js-anatomy/create-anatomy.js +0a42233d7ef48b1bd766dce63d107620347ebed83a22afb06fce293f7b15254f zag/zag-js-anatomy/create-anatomy.mjs +183b439e4405ce8fa2961844faefdddffbe4247bf7f735bcf09354a1e9ecb49a zag/zag-js-anatomy/index.js +dc13a39eafa9f9071a472ac8efcfcf78f79e1c9025616c906d6d952641025696 zag/zag-js-anatomy/index.mjs +2790627fe23144a8c79f112484e96b1ed5b6905b1c221031c41f0e3d9581548e zag/zag-js-aria-hidden/aria-hidden.js +94cdbaf5d61091c86118f274ca546898401456f19c96f40810780b994de35b41 zag/zag-js-aria-hidden/aria-hidden.mjs +44286ddffab024dafc88f22f189077e913dc23ffee2e439b0e955431e46a7166 zag/zag-js-aria-hidden/index.js +4d2edcbbaeb98e969d4a8ab154618ba1668c00d7e6cbe8a5a97dfc56c68cda38 zag/zag-js-aria-hidden/index.mjs +60afb38febb25a8daa73131061d30259f39f278f0bdc5b18181cf542f0806d96 zag/zag-js-aria-hidden/walk-tree-outside.js +465db988b77fc0fed0d82c667f49d3931d8bc2800022a66d77c22476db4a23a1 zag/zag-js-aria-hidden/walk-tree-outside.mjs +27f55cc9525cc928cc76ff0abd69f14e5f4810d8c68b48ad670f50b05de9fc32 zag/zag-js-core/create-machine.js +de4984968f3c555898c1e72406d617f115d87bea5ad10fe10f69f901967a0795 zag/zag-js-core/create-machine.mjs +f4de679fc8f87e591d19b2771f1496abaede307d5c8978e6f23dbfdd6433eba8 zag/zag-js-core/index.js +65795860ddb5733bd5fd0a846f8233ef511f50b59094f4ac1e1da1787bc401c3 zag/zag-js-core/index.mjs +34975c872ad1b2ddf9a7a9936359a959c17ee34637fc70bc1370dfbf1f0801a1 zag/zag-js-core/memo.js +27fc581b624c25dc884818a6aaeaf9c54565baa60f07821cda5cf923587afbcc zag/zag-js-core/memo.mjs +c719ff7c9f9804559b8a093f48cd934f4d6601a13b26ff0a71126de0621119e8 zag/zag-js-core/merge-props.js +0049e89119060cb8d8548cef96078f978600f41176e0eda51650a998bf2c6308 zag/zag-js-core/merge-props.mjs +bac5df7dafeae9154e789e694273ae73c9d00cbdeb5a058aae83556d7e4052c8 zag/zag-js-core/replace-tracker.js +3bed327b3119d7b361c62ab6707309be23e7b42d9018af031c9bd3fcd5fc7882 zag/zag-js-core/replace-tracker.mjs +8f89b8331610fe3bfdf1eac5f75e78adbf6950c338c1accbe3c00e1068525969 zag/zag-js-core/scope.js +04318fec83bd6f83ab5d885e573dbfb1a52be5668fed4c6c5f58ba1fbc6b1ce9 zag/zag-js-core/scope.mjs +99d6b1188076a72a91387771d8238c60e5b8ce88d21f02e10403db504a6f71c5 zag/zag-js-core/state.js +26da08824339269a12f4f9a96b4b00b396f9f7f60cc8fe2d1d524e6f8b2faad2 zag/zag-js-core/state.mjs +2326d113dac4f9b808a8a4425cab2c260927d6862e9e3eb78a79008e0edf4b39 zag/zag-js-core/types.js +19d015aa015aa8a3eafc94b04ecdd32307155a5dcc20ce9d6a3d6373c768ec19 zag/zag-js-core/types.mjs +d322347b804682e418f3f165a5c13b5740cc22cda76f551e5fddc06420389ba5 zag/zag-js-dialog/dialog.anatomy.js +5ef2e16513f2a402e4942546dd00f0386f94ae62e3dd2b89104369bf2f4f0526 zag/zag-js-dialog/dialog.anatomy.mjs +ff6657b00bb46068d46f15f2927077b56aa842ba93a4d7b2704aa25914956025 zag/zag-js-dialog/dialog.connect.js +d270690aad3d023efd4fddae065b34c411bfa130f8611c54c9acec34eebc99f1 zag/zag-js-dialog/dialog.connect.mjs +a7705c703d06def81b939725b8665a1db6b14205dc9ca5ec9520e7e80d5184cb zag/zag-js-dialog/dialog.dom.js +87892c16d8774ccea010a784533e6faf8960afaf6e5bc53b46f432a8048f36b6 zag/zag-js-dialog/dialog.dom.mjs +9e16d14f81c707c1d35fcb8244b9adcb88226b648555e83069e11edf324dd849 zag/zag-js-dialog/dialog.machine.js +a33dfbc697c6409abcf63e56f99dc999410ba4f3936250861b63c69b19922214 zag/zag-js-dialog/dialog.machine.mjs +cbf23513ea9d914ecb6c77a4a12af2004df96cb340656221bdd2c72c6538d49b zag/zag-js-dialog/dialog.props.js +cff61961246cfcfc17eaa38487d4c0a74d32bf19a3f4bd0b5183b3c9ce5ddec3 zag/zag-js-dialog/dialog.props.mjs +4a36d6806d480b4b30728fdf9e3853ecfe7895df84f2d56fa7bb2196fd667252 zag/zag-js-dialog/dialog.types.js +e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 zag/zag-js-dialog/dialog.types.mjs +2d857f03954acd8cdf4316edce0f95ed4c44ae9fc90746bc5193958d7ab3148f zag/zag-js-dialog/index.js +10126f19e6bbf58dfc8db9131a441a2658a63a5f7c3866557c292f5bea02aae1 zag/zag-js-dialog/index.mjs +aa450b18a7be6334ce869d135d47757a4f384284f09825c07d026a4ee77b24ef zag/zag-js-dismissable/dismissable-layer.js +7043c2b36f5fa6d203d6dc5294146f126b6cf4319e045ea41b1b065d5e16ee72 zag/zag-js-dismissable/dismissable-layer.mjs +39a957057a671b015f115ca077f1ddf34a783e683b5bf6107bad8f768c85b4ba zag/zag-js-dismissable/escape-keydown.js +0f4c26b30227b6ed30313a971222f03530d7b750a90b5ef9dc6e77fadfea6167 zag/zag-js-dismissable/escape-keydown.mjs +1bec9a147cfbf420c2c7aff05d351eeb8da117fde07c561446b255306aa7e08e zag/zag-js-dismissable/index.js +e371781fa70c9b1400759953d8f01fb80e1f19d080fa58e88014833acafa6b0f zag/zag-js-dismissable/index.mjs +695f7176d8fedd5b0a54f0fd2862621e9c6eb7c4fef957079cb34c4eb777f004 zag/zag-js-dismissable/layer-stack.js +0a615fdeb141886ee7cdacaa50cf4339dcca7eeab81dbe79599f886d00aa6bcd zag/zag-js-dismissable/layer-stack.mjs +c38ea9cfde3e82bc2a52f8e55a6618d1f6c5980d6787179cdbc84f9ccba29f91 zag/zag-js-dismissable/pointer-event-outside.js +ec5a0770761d28be773a5d9f903eee09e2caf49e92ff32c4f49d5ebaec7a26fa zag/zag-js-dismissable/pointer-event-outside.mjs +9832f0f17063bfbc0ad7b74efd87fade05ab8dca7b90e832fb304654f4bcd251 zag/zag-js-dom-query/caret.js +cd73a82f419291daa363901571048d1060cd5d29c45dabb5c068047890469d95 zag/zag-js-dom-query/caret.mjs +5943dc01ce5ae389402596403935174ac7199a985937c1e2a314784c05f78023 zag/zag-js-dom-query/chunk-QZ7TP4HQ.mjs +3fbc483564ea8c88f5eafb682964115efe2c31c40b727a3feb6df1916e6f1678 zag/zag-js-dom-query/computed-style.js +819c33eeef2c59fd6cec2f69d8cd04a60fc41d45e2ff6fac50b395b0bcfdb344 zag/zag-js-dom-query/computed-style.mjs +ca32dd0402e83b58b520dd94772a32aa3c8823a1ba87081989d01dfd1060651f zag/zag-js-dom-query/controller.js +5f294112a57b82ba0b5b364ea80a64fd29fd8b0587450af4c5352be487000832 zag/zag-js-dom-query/controller.mjs +77b0ab9e71ed4f54ed665bc7947797c3fc119afb71f62fa0b5d08b867ec09684 zag/zag-js-dom-query/data-url.js +3147bb03b7b27fb61eb58a65dff686e379f90e8a85c144214854d3e3c2ec71c8 zag/zag-js-dom-query/data-url.mjs +de8a5421ff01c0835846d664cc94be350ff4f401793f92869e7b4db57b6ad83f zag/zag-js-dom-query/event.js +e78e0c88be0b170f2713eed4a6166e5ec2bfe36f7b838f13f0f5c8c8be3f0208 zag/zag-js-dom-query/event.mjs +8668837f75f3592f769b692425123c8ff859b2f02eafa5fa52dc1575bac7fd71 zag/zag-js-dom-query/form.js +94ba042885a88cce08a2ccf558a5d7db9606313173f559c8d46033af576a4001 zag/zag-js-dom-query/form.mjs +fd7cb2b479e76ae6508a02b3d72975b7a5be11d8be6228fe8d9a2a73eca8a611 zag/zag-js-dom-query/index.js +77ae1045d57191b746e33b21db6f788a6ae0c5730f149f4f518ce3cd3c70762c zag/zag-js-dom-query/index.mjs +fb4afe4b3158644528c0f01fbd04115b8524ccd72404bba22efe4422c2c73344 zag/zag-js-dom-query/initial-focus.js +f03dc80a4202573f25c514916cc4f7de7e77ee63c0904aa5648dd8200ec0aa71 zag/zag-js-dom-query/initial-focus.mjs +af8ea6a1b77315a5fb3091c8c441ecd79a960a28566bd4bb2d332ea2db99b31d zag/zag-js-dom-query/mutation-observer.js +b0d1fb94c0dcb1e0bbdc3079e89086261fed4060ff88181ea4f0ee8e4f582f95 zag/zag-js-dom-query/mutation-observer.mjs +a5493b49664bfc2546388e669885c67ae5954a895afc6f6b0cc1670a68c426d4 zag/zag-js-dom-query/navigate.js +e2ce285896626af7ba42ce6ac25ba32f0bbfa9ea508aae8f525a209820361d8c zag/zag-js-dom-query/navigate.mjs +5d16594993105982cd899bfa4a6c353aa6819c30e74d1071c0fc1159b7427f74 zag/zag-js-dom-query/node.js +e00a7bbd4cc3b5cf6d2fb31beb03beafb75bbf44cfea6c4ebb1c6e91708450c4 zag/zag-js-dom-query/node.mjs +012324a49763a681f059e5f6cbb0a0b32039f8f07659d16490011ca6a7aca236 zag/zag-js-dom-query/overflow.js +538b8d5fe06cbc9c89a9ee3ce9e8806d8eafb469957c9ade9d76344e8b906aec zag/zag-js-dom-query/overflow.mjs +9a7de7cc55a104cce30f2307ee4b924889ba0d4c7cec0fb0aa492ccb269d3312 zag/zag-js-dom-query/platform.js +8dbc5d5991c128f33818efcffbc89c8dd298616c2e21fe8127ede9ae87b5ec7d zag/zag-js-dom-query/platform.mjs +2d75aaca81126eaee6f809ea7287b3f2347502eb160087391a53bdb1c1f11f49 zag/zag-js-dom-query/point.js +1551ccc50e27636bff4a8bf29e7d5dbf5bd9da90dfd42dfe64fb7ab79c2cd459 zag/zag-js-dom-query/point.mjs +d9e9c7486f8e4f14b63f5e1685820df17be9aa1d4a419b0bf6c844a8258def84 zag/zag-js-dom-query/pointer-lock.js +7b1240f7d7aadcfc103b413c583156b456cbcbd6403bbf2a6c67d417b2d94790 zag/zag-js-dom-query/pointer-lock.mjs +908eadd8a0ce82e18d271096e592bebd86eb05485afad62808bd1eb9582c0f59 zag/zag-js-dom-query/pointer-move.js +e31a18e9a7f75e36e5306247d499777456f710391d2c41deca86d8c103f8dd78 zag/zag-js-dom-query/pointer-move.mjs +9d2093b6b3470787f4f358f2547580c2799deb480dd8c04ae165e5802d8d81af zag/zag-js-dom-query/press.js +1cdfb8aad8036b861c4579495dc164ec66b50fb9531a9b8e4b55e5e5f9e013db zag/zag-js-dom-query/press.mjs +c57b565ca7af21034f7244c9355dbc66fa428cef4936132dcadf88446343de43 zag/zag-js-dom-query/proxy-tab-focus.js +1dd8239841e07e99c3a5f85d5e0bd3ac62392aa8d165c53edbc8983c3ff866c6 zag/zag-js-dom-query/proxy-tab-focus.mjs +5741645cd181ecb6c952c45ebc4fc41ccdfe58085db4cb795e7942e00da44bdd zag/zag-js-dom-query/query.js +6fe075f089977b0b1c9518f3cf5b741cf03a7ec5945093eb3ece42566fc17bf3 zag/zag-js-dom-query/query.mjs +e945c6e922dafdc32d58d0a53f00fb1212c449e6a1cc8ef1c941ab97e69d4158 zag/zag-js-dom-query/raf.js +82b816196b6f0d77714f21a2673f96f2a92d0144d3ba398364b50efe09c36ab4 zag/zag-js-dom-query/raf.mjs +1dfe9e4ef485a227b5535f8c90340249f3a8c2b9f5500a513d7c318502f55c2a zag/zag-js-dom-query/resize-observer.js +573c3341c7b4c98202df5a38fdf8a83b059ef69e35ddbdb603d47b95c40aab5d zag/zag-js-dom-query/resize-observer.mjs +2dbd813ed8bbefaefde0a823b2e92c97792565d739bbf6d2b738c1bffe00198a zag/zag-js-dom-query/scale.js +4fe1cd9e0761c67adbe39095281ad7d2df640310c276ee8ba90e248a74a66809 zag/zag-js-dom-query/scale.mjs +50761160b88ff00126b7879c75c41d59d5f1f309b1452c80c87c6d1104eed4f9 zag/zag-js-dom-query/scope.js +6923b8814b9323e9d531bde86b5da8b9724133437bf90ec09897339dc539a493 zag/zag-js-dom-query/scope.mjs +d2dd3218a871f41c5f30b5893190c66cbbcb3b2c8dc64c7b7e8ff58ed3bc4fb0 zag/zag-js-dom-query/scroll.js +177a1e33b1e8e9efef6d31e806385c5346e0a48a27469861ae85443ea9de6617 zag/zag-js-dom-query/scroll.mjs +63dc7227908d1093d84807f108c9b27170106035ea1d9bacc6d4c55e129bdebe zag/zag-js-dom-query/searchable.js +ec8204a08ab9b3774b68b871a3165120c90b0d428b8d81799abb2b44d14eb5b9 zag/zag-js-dom-query/searchable.mjs +dc965e7c4698126cd57d3499e22569c82cc81bd9364358dc08b6790e3b8420a8 zag/zag-js-dom-query/set.js +f4231f02faf7d48418dd21f8f42cb40adf4b5bc31d80eff781183576ff9636de zag/zag-js-dom-query/set.mjs +f5aea4173e5a371005c2133a3dab0e6680b2155367872d26fe96f5f4cb7b511e zag/zag-js-dom-query/shared.js +58801de221ee6ae1f84211bf1fb440b3c263f28c7a6673920abba1376816ff45 zag/zag-js-dom-query/shared.mjs +9984d3ff3622ed35510de7a7c51e91d3d16c0e1518b104aab496f80fa02c0e69 zag/zag-js-dom-query/tabbable.js +df6b17cf5c162956560219015df4134ef8c9615cd992eb9fe14995b8599ba66a zag/zag-js-dom-query/tabbable.mjs +7215b0a9a8b4344d0aa13542f8d321d1e2cc389531cabcee21df3390e42b0a25 zag/zag-js-dom-query/text-selection.js +980ffd811fda2bfbaa80ef31a78bb4eb505cc44861e3be9a481ce11a0b023da7 zag/zag-js-dom-query/text-selection.mjs +c2818f41dd0d2b3ce1449d810ac766abfaaeb80610e924c979fe5b19242cd3cb zag/zag-js-dom-query/typeahead.js +1a30433ea5fc8580970b9c6ba635a4955a8b883ca54867f6caaf5e4c226de6e2 zag/zag-js-dom-query/typeahead.mjs +7222b5629d31ed31408f5a62486de82165fdfd405aef2c7043ec6fe8ceb4b762 zag/zag-js-dom-query/types.js +e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 zag/zag-js-dom-query/types.mjs +5400903861f0e9b5eec8061a918722ffb4584ef1754c53c9dee065012eca8458 zag/zag-js-dom-query/visual-viewport.js +2bceecb09dc4267df0c516e6f283f42010cb0a0f38a7da45f9d96e8d9977f27a zag/zag-js-dom-query/visual-viewport.mjs +e20c44281efb42b17cd52a7c485f3eb5465bd76f19238157f5a2ad600dea3933 zag/zag-js-dom-query/visually-hidden.js +88825afc0313900b46699b5b1f309e1692fd3366dffef4a0d2badc18764f501e zag/zag-js-dom-query/visually-hidden.mjs +e79fec0e8162ccf2c3fb6eb56ab4cc14ee58b555326ded0d8b2b209b6310caa6 zag/zag-js-dom-query/wait-for.js +feeeaa5af61a8ef689581e1496eb7b6270004cadaaa55a51c718b0c0ae9eb445 zag/zag-js-dom-query/wait-for.mjs +36cb3246b1e71c0891cbaf05d7276e09c5ed39f20fd54efa6c539b0dde5bd1d3 zag/zag-js-dom-query/when-node.js +3130463f8135282c8b67b6615f6f5aed272f035e0c2f1a7f0a4d9dedc96be99f zag/zag-js-dom-query/when-node.mjs +5943dc01ce5ae389402596403935174ac7199a985937c1e2a314784c05f78023 zag/zag-js-focus-trap/chunk-QZ7TP4HQ.mjs +74443073bfdfe17eaa804eb23aef0bfca4014cb1fb8209f5064c5f3aa5bd6f46 zag/zag-js-focus-trap/focus-trap.js +af89e81ede23ed054fee424202308a1cb179d324e49fcbfe73f46659bf1d90df zag/zag-js-focus-trap/focus-trap.mjs +6b1326e45cfd22a0e62b355fce61354a0fc5100c8d8c689345b9aabd846487b4 zag/zag-js-focus-trap/index.js +b22e188f6bb16a6e1e188379a6755ff1d253317afae11a416a39ca71de4a00b0 zag/zag-js-focus-trap/index.mjs +7222b5629d31ed31408f5a62486de82165fdfd405aef2c7043ec6fe8ceb4b762 zag/zag-js-focus-trap/types.js +e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 zag/zag-js-focus-trap/types.mjs +6b3ad31c8ff3894acfab21ebc9dd758a90845a9412124d630f98ffb59b3173b7 zag/zag-js-focus-visible/index.js +e8650c92eb05d5f822ccf0732d07a8559e5d1fc3caefde12d54ddb34470aeecc zag/zag-js-focus-visible/index.mjs +533fe0c5f0772400de803ca6cd6a12c588e763678815659dd588eb1d150e8e2c zag/zag-js-interact-outside/frame-utils.js +05dd99b9da2701e324f5cdf8df6186d0ae3e8819b94a547cb7d5c3ee316475fb zag/zag-js-interact-outside/frame-utils.mjs +6b22851cde8259b5bd01b73cdac51b05baf7e98493fe7c35229ce2e0a73a16fd zag/zag-js-interact-outside/index.js +d1f8d11b5c55322f6e4d8ddbfbbda6015f4c18a905bea8ec1ddfadb4ce809678 zag/zag-js-interact-outside/index.mjs +31f4d1c8328264bc40856e80a2a3a94ef6a2f3ee979dac4f656fce395b45968e zag/zag-js-menu/index.js +36dff20c26b00b9b66f99f853ab3bb57b1fb1bb3d3efd8706dc1669aff02722c zag/zag-js-menu/index.mjs +018361a166a19025076d8e96cb9663c4264e27a444fbce22baa225328cfe2467 zag/zag-js-menu/menu.anatomy.js +128beae87bf20d5bb0437084810207cd45c3978bc67bda8403ea845a82fbc78d zag/zag-js-menu/menu.anatomy.mjs +fc69221c2a53c81c0069345a07333951aee6bb883115ecc9a3a622b68e377202 zag/zag-js-menu/menu.connect.js +ca9a147abab273cd7f49b0d952c9d5fceea8ad0fa45b80f1eb66d99d459a2030 zag/zag-js-menu/menu.connect.mjs +123748203d400d7ff5d894811833924febde22ce224d9de4610164e6c1017b01 zag/zag-js-menu/menu.dom.js +ad2483c0c7dfae379c5be711aa135ec11987588ec73d9c3e758f777686179c56 zag/zag-js-menu/menu.dom.mjs +2a842dbaa306fb36a4ddcd37d25c8b2e0ffdac59b0c7c1ef53188760b64b8f65 zag/zag-js-menu/menu.machine.js +c3cf9a165b79ed3ab8489e9af7772441fb3f790e7506c58f032cc1d1380efabf zag/zag-js-menu/menu.machine.mjs +e20d0c67afbddf13cf7b611c4bfaf0798762b7c430f379c6fb1275a4f425190d zag/zag-js-menu/menu.props.js +fdd3d3f12572d14f2a7c84380e8ad9fbbb8517154d3167e2e1d5ba4fce990f4e zag/zag-js-menu/menu.props.mjs +367d39aff54920f3523b5e3ff610a2b4e257cbbb9d4bdc375aa3a9e985b7baf4 zag/zag-js-menu/menu.types.js +e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 zag/zag-js-menu/menu.types.mjs +2c07ac5e51fa007a672023ca0753915c23f13e21b873189d5c169c28fb143777 zag/zag-js-menu/menu.utils.js +86d7e44adbf953599c24447572a72ad003633762e8261cd89ba5ab6fcdab3eca zag/zag-js-menu/menu.utils.mjs +b5790c33079efad58f5f3cd10a1858d275e799f733321211eaa2dbd475c1dea6 zag/zag-js-popper/get-anchor.js +4103020ad12d2f2f5e0e661bb006d241a9d6b292bc5320a2a7ec62158d53dc5b zag/zag-js-popper/get-anchor.mjs +963d40010eea6ca3a73fce5e0d81fcdd0799d66f91b2087da51c93f7a683e43e zag/zag-js-popper/get-placement.js +fb438d07f2d3182bda53da234e0e041aee024dde9a3be20c5c945233d04238b1 zag/zag-js-popper/get-placement.mjs +d59948320e89c67e1a03d35c963657cc38e8c055fbfb4605ed32d3263952b0e4 zag/zag-js-popper/get-styles.js +644537ed12526f78945f914267e3456b41e7336aef8d63e8b81285a864e07699 zag/zag-js-popper/get-styles.mjs +0b41ab133e678f13474f8b05d7ba66d977cc88212f8600e580ead7c7cd62a0e5 zag/zag-js-popper/index.js +d509de578506000a9a64059713ee68b32623b06b5c047e61d37d5c7cde85b7c5 zag/zag-js-popper/index.mjs +ffcbbe0164cd456668e89d32d83b768668e776a1e78c1d93e9ea40505cd69b3c zag/zag-js-popper/middleware.js +768756ed2d757acc3fd57ee3350b7ec0c1203c2dff7c2b10a65cde24bf42667a zag/zag-js-popper/middleware.mjs +b0e6f7b2efa90f7236c53ccd04b11ca20ad6d3e65e0841927e8d06a8df1a6665 zag/zag-js-popper/placement.js +22012f24cb6a28c98805bae254476183d1cf3572c81553491e35424b9b71631b zag/zag-js-popper/placement.mjs +7222b5629d31ed31408f5a62486de82165fdfd405aef2c7043ec6fe8ceb4b762 zag/zag-js-popper/types.js +e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 zag/zag-js-popper/types.mjs +e2f9a31d062bccce863549d4c22a34aee0d3de96c22c7a2a58ce2e7d6d393f9b zag/zag-js-rect-utils/affine-transform.js +0b9a158f5009705d0d5905358b9635ca0d3bdcdff76d4388b60ed0ba05f83d8d zag/zag-js-rect-utils/affine-transform.mjs +028df6eeb213e93cae9e5a777994601a08e7f6c896e3dfcca4a33db9643e8477 zag/zag-js-rect-utils/align.js +bc0ee49d355d2777668812220604b7d88650cff7177431e56f1bd9502a42996a zag/zag-js-rect-utils/align.mjs +f2c87ddde55bf23b336cf4614984dafa3b36bf2e6646d740e5e639741612fe58 zag/zag-js-rect-utils/angle.js +2ef246c9813d676bae0b5ddbae6b5a0ac1a60bbf5e4519d07ffd9eaaa3177c0e zag/zag-js-rect-utils/angle.mjs +5943dc01ce5ae389402596403935174ac7199a985937c1e2a314784c05f78023 zag/zag-js-rect-utils/chunk-QZ7TP4HQ.mjs +c6c4b3f3829424f7600b23b9eced9d7cc13444915cfd1fa8b2c426010f5a2fba zag/zag-js-rect-utils/clamp.js +e79c6cd3d4da7e8c2207988b557e280de45976e136ca71afa6b024ae9cbc967e zag/zag-js-rect-utils/clamp.mjs +fe07e8efe0cdd066132e8a563ec89b758527f3aacc20c312b35b88f9f646c211 zag/zag-js-rect-utils/closest.js +a59a8ac907942b180a53ad66654d19f19d2ab2c80b00090e005af155c98acdde zag/zag-js-rect-utils/closest.mjs +95f4ffd9d3d1d5690b4c9ac73f4106073c12b248eee004d47ae07b9330bbabdc zag/zag-js-rect-utils/compass.js +b468ffe90057532184576d1062529a0eec1a0e2481554c6104494b504b39c23a zag/zag-js-rect-utils/compass.mjs +dc6d10008b7f9b642f77f235284a2164c9564a406a80ead74d1aabc4f35b0894 zag/zag-js-rect-utils/constrain.js +03b14cae056bec83a0763153bb2374f2bf436c01cf95db0076dfc6af649da20e zag/zag-js-rect-utils/constrain.mjs +c7fd0b70363482ddad110288189274ee4aea746919be4fdbf21f69d8fe34715e zag/zag-js-rect-utils/contains.js +7aecdf1e235927ec3fa9e1b38d5006bb27c0939607e8658b0ccb97641beecb80 zag/zag-js-rect-utils/contains.mjs +4c84560fe2c52884f0f3290bd375a65d551684a2d36ef6883aaf4a6c16592d7a zag/zag-js-rect-utils/distance.js +26e40a05da04c51dc2edaec77b8c9b2cbc7ce10fcb7df051d2dc84e61edc9df3 zag/zag-js-rect-utils/distance.mjs +5760525ea7f0b2e561ee6d8745f489e59b1c5ef85b21aece78a4de216afafef9 zag/zag-js-rect-utils/equality.js +8e714f115ecf09e577e9ad25f5664420d6959e3b601f0d12a066457c26d1d106 zag/zag-js-rect-utils/equality.mjs +c3b1756ff9529847a9bff9003092463635f1c79af7084f68df1001bf0bb22e31 zag/zag-js-rect-utils/from-element.js +628912f6932d5dc3fd1b511b6f43ce2283f1142bd7a3c23068a82034a41eec2a zag/zag-js-rect-utils/from-element.mjs +d6dea678cad76623f476fc4f683f7f7544ae79b9f71cc39699aa616b8a3f25c9 zag/zag-js-rect-utils/from-points.js +671bca4f993f5974486cffdd1ad2eebe71dc37855499ce4a0e15158721289533 zag/zag-js-rect-utils/from-points.mjs +3ea9ffb22f604beac11548190a949fca22412835d5e0dc26222d2a6207cac7e5 zag/zag-js-rect-utils/from-range.js +e68688142d4e5f8734c2674a93c08647892eee1f639afd789e61cb63e665d293 zag/zag-js-rect-utils/from-range.mjs +80373df8a66822483cd6ae4eac929017c58b814933494f0137c3ae7fc9440e2d zag/zag-js-rect-utils/from-rotation.js +3b24c447219f160ade5b96a9e7bda7b2505d5475aa8b29133dbfc898b781a62b zag/zag-js-rect-utils/from-rotation.mjs +eb4193d5919b6d4574cdf238803b91e162d36ff6194e40d04d81c5eeff18c316 zag/zag-js-rect-utils/from-window.js +699223ea7b2d6613c7751b16d608df3e95f6c7a760f23937da2b20cd8adfa05c zag/zag-js-rect-utils/from-window.mjs +f9ca76dfc19b2c4cc095289878d8825fd42d8ce7458266a53a3fa76e7aaa393d zag/zag-js-rect-utils/index.js +0e7e8564197e0dca1fede9fc5f83b9bdc4944c90e53f0264f7b0a06b1b5a7bb6 zag/zag-js-rect-utils/index.mjs +d02407f383b8e917c5231fd92bf7f060a247c005bd346d40d4b6a4c4ef06a730 zag/zag-js-rect-utils/intersection.js +5a064d2aee748057b35e587841f12b8145d77f24a0ddde3dd41afbcff498f796 zag/zag-js-rect-utils/intersection.mjs +da5e24816ca3fb685ea904562433842f6f03573bb0200002ec4eab2305ae97f3 zag/zag-js-rect-utils/operations.js +660094bb2b219892eb403069f21b2f49ed480e33b47e62f212813a484f5becc8 zag/zag-js-rect-utils/operations.mjs +0ba7dcb5fd5467978519ca5306ecd0a86440688a61ae349870bbbb3ad0407634 zag/zag-js-rect-utils/polygon.js +605b8a28574014bf6bdee40c409567b196322b0b9f734ff862813eb1fcd56649 zag/zag-js-rect-utils/polygon.mjs +ed6a8c3046d782f6829cf0c253c3fce45b5a9a18a3048eac3335677887b7ca1a zag/zag-js-rect-utils/rect.js +473a42fca94eeaa1c7b92564bc8d039ed8ad6666577e5ad08fe579831175d873 zag/zag-js-rect-utils/rect.mjs +9c126fa321054010222d62925554e406b7670be0d0d908f8ae153f796fb68b41 zag/zag-js-rect-utils/resize.js +0db211e7cddc05bde23fa80b8a9f8201958e3fb13f2822c725e21b036121566b zag/zag-js-rect-utils/resize.mjs +7222b5629d31ed31408f5a62486de82165fdfd405aef2c7043ec6fe8ceb4b762 zag/zag-js-rect-utils/types.js +e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 zag/zag-js-rect-utils/types.mjs +be1b951d294b0c0d5781c3eb21fc4a0acbf7d769a7e6ef45d94c4a37e02b8448 zag/zag-js-rect-utils/union.js +632663c34f5e4336a92049c2d14e31bf69a660138d03252132595c428734c026 zag/zag-js-rect-utils/union.mjs +b5143ccbf82c7174c75e6178370d536fa14cfaac2c5d7f42757389d8152509a6 zag/zag-js-remove-scroll/index.js +a796c6c5d40f6225d4f6e53363339de2aaeec6da4115004d1f0d8c3fcfc7c062 zag/zag-js-remove-scroll/index.mjs +acaf57583779ee2f3bf67c6a6840f334dd0539a81835f846bd91b7d67ad29556 zag/zag-js-store/clone.js +cd2ebf1ee8749a4f8a72ed4787f47c07031b4246eab5757e9b4cee50f0903fdc zag/zag-js-store/clone.mjs +0910a45be68f245660fa0139777704b2896cbff01f7bb0096f3030c5c259ba89 zag/zag-js-store/global.js +82fd1ba75d778182d6a1bc3c24681d6cc72a35f9c24d7df118364f8c4fd605bb zag/zag-js-store/global.mjs +9b9ef9bc4a18d64aaf7b8def88b2e8578dfa1a52d442447c0b46b2c443705824 zag/zag-js-store/index.js +6089c7a0e0d2bb9c88514fd207a0ca637c11e98fb7f01f6fe4ad5a25eaf59c16 zag/zag-js-store/index.mjs +f737a28c375588fa467b3029d5c239a07d2b2158a3aebca92cfeafa27934fcc2 zag/zag-js-store/proxy-computed.js +04ddbe3a1dad2cd0188e8e528f06ca2ca9c4d0e2c0c0764984f5ebdffc3be142 zag/zag-js-store/proxy-computed.mjs +9284b5dd06badea15ca567fca082db10600546c2be00102a2fd83ad82319ab03 zag/zag-js-store/proxy.js +de88fae6bf6e2ec73eb42bc4b74a31dc2729bd9b2bf9f801385ac65ac4311f90 zag/zag-js-store/proxy.mjs +c316f675e218eb069f0fd8f0864a37e7c4be12e5d034cdc6a9686d14d01e6459 zag/zag-js-store/utils.js +e582b8b1b03434a89cfaa8c9cd27b21ac6f6a4c9c6e1a50c15b1f11417b779e2 zag/zag-js-store/utils.mjs +c5078c069804019680d28d6f20395c143e6f2460d0048580795e63b44771f405 zag/zag-js-tooltip/index.js +8c7650e9985e6ce80f14518f17e4ba60d3a48fb17b51fdd8f285b9241498f732 zag/zag-js-tooltip/index.mjs +018bc6f835495c843082af27cff0a943f2fc33d001582d4f3b5609a82af3958f zag/zag-js-tooltip/tooltip.anatomy.js +057fe33fde3743decee01a2d32a507125cddc8ac2fad6b4d6919b5ca16feccb5 zag/zag-js-tooltip/tooltip.anatomy.mjs +db843d2cfed61b8b6a097d64329f24935f3a68a137261bf800e3ec8573a9f051 zag/zag-js-tooltip/tooltip.connect.js +57e0832369fbbe87d70df26f1b1d5b6c2d99854afb0a379ec35372a713434d94 zag/zag-js-tooltip/tooltip.connect.mjs +fcc4c151f0ec4b3d8d0970e42cc89eadcc31eac0eeb2246a5966477eba1cc1b5 zag/zag-js-tooltip/tooltip.dom.js +7735bcec709ea89c5ef90127e5bd0bba38771a5c37b1ef06fa1564326f8bf1f6 zag/zag-js-tooltip/tooltip.dom.mjs +ca0a9c0680081b7c7cc991772e751ac0031ce8ed2c6ce8030dcf8523d833ac2d zag/zag-js-tooltip/tooltip.machine.js +8ff7a58b16d27c2bb8604aca91a268ee7f3cdbf042cf8f5c9309f33184ecfcc1 zag/zag-js-tooltip/tooltip.machine.mjs +e4e7c484c5e4511b9ccab9d8e12e60d7211f228736bc8d6db7107a3a6136867a zag/zag-js-tooltip/tooltip.props.js +a276baaf7561f535fcb01c235ff2333663b8b67134846f8f219b7db46c3b0ee0 zag/zag-js-tooltip/tooltip.props.mjs +8bf5285e7a41ee407830f34e0699b231864829eb7e63da3abb87476b550f8a93 zag/zag-js-tooltip/tooltip.store.js +d04c1addf45ca99a73717d1cad3f69e14147f554d12f56c66aac130f095e99dd zag/zag-js-tooltip/tooltip.store.mjs +e95111ac6562112c3ed3edc6c5909e0f6fde1a693b526991c69cde21609010b2 zag/zag-js-tooltip/tooltip.types.js +e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 zag/zag-js-tooltip/tooltip.types.mjs +3f35c734c7466532e7218e741661d7165a924aef704d34fd23333998d761c43b zag/zag-js-types/create-props.js +1155c4fd604f40bafe814e066f5fce5d6fd1a8af25bf298d1c5e2493028ac944 zag/zag-js-types/create-props.mjs +d86dba4f06e0ccbe6daeffa24411f3eac3219ff7311220864f77f104bf98149f zag/zag-js-types/index.js +357e686f803a18f165d94ca5b06ad956a3f48308a413afd8ff51b2e2b799bbfa zag/zag-js-types/index.mjs +7dbfef2eb1539294adf4b600faa10f961c443845e1fe7509f9592f3f254ad5b5 zag/zag-js-types/jsx.js +e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 zag/zag-js-types/jsx.mjs +4da4060603fcb372d525fca5da5a5a76810f49eda0a2d1283ea9d206df5cb4bc zag/zag-js-types/prop-types.js +9537c57c0a8dcb48f185d5018392731a01aefe2331dd9ddabd18591fdcb641f7 zag/zag-js-types/prop-types.mjs +ff1d4744db096521fd85c1ec2a1f158a1f0efd50076aedd4ca78b15ccda98b19 zag/zag-js-utils/array.js +f5195f06112d522ebafb49990d9af54bea284f6e83fa8334a8605fef9ccbc6d4 zag/zag-js-utils/array.mjs +00a5c51771989d747fe346c783860646f14db05e1ca6ea22c72e8e56dafa64bb zag/zag-js-utils/chunk-MXGZDBDQ.mjs +b75bd3e8ac29d85435a13db7c2a769b72ceb0bc11e585b762f17e9986e319235 zag/zag-js-utils/equal.js +5077ba6b0dec22f81322deadc8d4155a346e36fddf4af33b8b83cfbb553122e5 zag/zag-js-utils/equal.mjs +a133791655ad9d30aac75bb686948b9ee52d87f6d8759e6b96d1900864cf76cd zag/zag-js-utils/functions.js +8d4deb1e1d6e6758e8da53592576f0347ea925929b9b6ff82b5bfc9a7576d09e zag/zag-js-utils/functions.mjs +53e6ba8527eba12ccd5d0969e8144c3bed8ec6e981ad7154bc3a66dca13c1aa9 zag/zag-js-utils/guard.js +e2d4d63c298fb15158c00599cebce5adf78cbb2c079006960b80e53398ccb586 zag/zag-js-utils/guard.mjs +81cf63434099a9b061915900f1700b0c9105983152ab9a80785cfe08ce463b14 zag/zag-js-utils/index.js +11f2eaddc7a5c99fd5562428565be1aa2958356a7415839d0e12b547d519f758 zag/zag-js-utils/index.mjs +5016cd8822397eec22b010f27d083448076c43420d6e7a57c263452db9eee3f6 zag/zag-js-utils/number.js +a21006b3fe96e17cb780234163dcfc382c7e4e0e55a30f08cb13d7b66c6b0638 zag/zag-js-utils/number.mjs +2d30e013ffbfab8c06ba0152e229df6e22b225c3b78a7c0d38f409f460e30512 zag/zag-js-utils/object.js +33a552f9134ce4fded4e5414d5598476418d30dca4464e9f457a975ec661eb48 zag/zag-js-utils/object.mjs +428761c013572b64d0160716213f44e1e47277f5750e5ccf2ab390caaae9e671 zag/zag-js-utils/store.js +194dbc0c91ec0620860432bed790d3d0087aa0127af5878ccbd70b0d52ba7b4f zag/zag-js-utils/store.mjs +eb3b79c894afa8d204421a7d54378f794959d0be870492c3d67442dfed850859 zag/zag-js-utils/timers.js +a0bb84babddf71bb707e84c78e1846b299f0fe7a8b3fd6ada5a7da2a650be92d zag/zag-js-utils/timers.mjs +0a458a1d794916d015a29d0d0d0dc1bffe137e85f8bd216f5a29f256af0456b3 zag/zag-js-utils/warning.js +0431c9c616daed83a791bf9c3de415914a835c55b6c4058699c9cea70332f0f4 zag/zag-js-utils/warning.mjs +1cea3c3cad7877542676a28119050cc117a5ede1ed03cbe764fad0f6b85699ee zag/zag-js-vanilla/bindable.js +0d840fd0d9c5abaa8ef85069d8c706ae6f6c563b0786fa4fc224c1b56040f8c1 zag/zag-js-vanilla/bindable.mjs +5943dc01ce5ae389402596403935174ac7199a985937c1e2a314784c05f78023 zag/zag-js-vanilla/chunk-QZ7TP4HQ.mjs +55fea7763d8ff96c6962018b01a43d438b2bccb8b6e6c41edf9954afc13b3044 zag/zag-js-vanilla/index.js +a003078bfacee1f5c069b3864784b3ae8fc21d66ebf6cd1434b24e933ecbd54b zag/zag-js-vanilla/index.mjs +e82b93a8a2d560919da2868dc4853d6a530456a1b97ca6684763a6fa5c0680fb zag/zag-js-vanilla/machine.js +444433fed5f354c59c0a1542de3582344fec7efb266912c58df924e8d4177cf3 zag/zag-js-vanilla/machine.mjs +4db78d53613117fec13fa09b8343568e1523bbdf7e82f71bc9dca769ef8ab8b8 zag/zag-js-vanilla/merge-machine-props.js +47d52eeba18bbc4c178a320a25f822798bed975d44e832fa9c8d14567f798c35 zag/zag-js-vanilla/merge-machine-props.mjs +585d3baea3c22fc538bba0f3d61dd7381862dae66844cd0e5d1faa04d34fcf9a zag/zag-js-vanilla/merge-props.js +1ff4a2b5654353137e4452a6088a27a74aa85f00dfc63f4c5b56800572a55a53 zag/zag-js-vanilla/merge-props.mjs +05502d1a0cc3414ebc460127b3810d88bfb4cf79aaf932f72c2e4a5200880d58 zag/zag-js-vanilla/normalize-props.js +862e6d1141ef9100ef68e8b8857de7e5513fb6eebc6bd80c7067407109049015 zag/zag-js-vanilla/normalize-props.mjs +4473c9083b0a6a1258153e80b52f0e55300a26abfabf75081a7f2c4f0d68aaad zag/zag-js-vanilla/refs.js +35f84e83890afbf96eae6d570d41fe772a81d62122c9a99db967f2dae0df35c0 zag/zag-js-vanilla/refs.mjs +c7ec1ce4c7191488ac09aa87ff0a8c223ab39c9ef24263e7c0a978e214100721 zag/zag-js-vanilla/spread-props.js +d62bfa52a902d6d3ed05d63b9e9cabc134b0da0f1ac968889588db29655adfc3 zag/zag-js-vanilla/spread-props.mjs diff --git a/console/frontend/vendor/VENDORING.md b/console/frontend/vendor/VENDORING.md index d78a4c2..e5356a6 100644 --- a/console/frontend/vendor/VENDORING.md +++ b/console/frontend/vendor/VENDORING.md @@ -17,7 +17,7 @@ so the page boots the same way offline as online. | `zag/` | the module closure Vela's ES modules import: `@zag-js/*` 1.44.0 (18 packages), `@floating-ui/{core,dom}` 1.8.0, `@floating-ui/utils` 0.2.12, `proxy-compare` 3.0.1 | all MIT | | `pinets/pinets.min.browser.es.js` | **our patch of LuxAlgo's PineTS** (Library path) — not a stock build; see `pinets/PROVENANCE.md` and `THIRD-PARTY.md` | AGPL-3.0-only | -Versions are pinned: **vela 0.8.1, vela-pinets 0.2.15** (whose inlined worker engine is PineTS +Versions are pinned: **vela 0.8.3, vela-pinets 0.2.15** (whose inlined worker engine is PineTS **0.11.0**; see `THIRD-PARTY.md`). The `zag/` closure is not optional — the browser cannot resolve a bare specifier on its own and Vela's ES modules import these by name; the import map in `index.html` carries one entry per specifier (`@floating-ui/utils/dom` is a subpath @@ -27,7 +27,7 @@ entry, not a typo). ```bash # the two LuxAlgo packages: registry tarballs, dist/ + licences only -curl -sL https://registry.npmjs.org/@luxalgo/vela/-/vela-0.8.1.tgz | tar xz -C vela +curl -sL https://registry.npmjs.org/@luxalgo/vela/-/vela-0.8.3.tgz | tar xz -C vela curl -sL https://registry.npmjs.org/@luxalgo/vela-pinets/-/vela-pinets-0.2.15.tgz | tar xz -C vela-pinets # the module closure: install the four entry packages, then vendor every package npm pulled in npm install --no-audit --no-fund @zag-js/vanilla @zag-js/dialog @zag-js/menu @zag-js/tooltip @@ -67,3 +67,10 @@ parallel (see CHANGELOG, 6 Oct). When a vendored family changes its files, regen python3 tools/modulepreload.py --write `test_boot_speed.py` runs `--check`, so a stale list fails the suite instead of quietly slowing the boot. + +## After a vendor change: refresh the checksums + +`console/frontend/vendor/SHA256SUMS` lists every vendored file. The test suite (and CI) run `tools/vendor-sums.py --check`, so a +hand edit or a half-applied upgrade fails there. After a deliberate change: `tools/vendor-sums.py --write`, then +`tools/modulepreload.py --write` (the preload list follows the module graph), and review the diff of both. The `zag/` +licence texts are in `zag/THIRD-PARTY-LICENSES.md`; re-copy each package's LICENSE into it when the versions change. diff --git a/console/frontend/vendor/vela/dist/chunk-DBDXKZUF.js b/console/frontend/vendor/vela/dist/chunk-2IPXYM4B.js similarity index 96% rename from console/frontend/vendor/vela/dist/chunk-DBDXKZUF.js rename to console/frontend/vendor/vela/dist/chunk-2IPXYM4B.js index 1af78b7..69fdb6e 100644 --- a/console/frontend/vendor/vela/dist/chunk-DBDXKZUF.js +++ b/console/frontend/vendor/vela/dist/chunk-2IPXYM4B.js @@ -1,8 +1,8 @@ -import { parseSymbol, priceStyleIds, BUILTIN_PRICE_STYLES, tzButtonLabel, SecondClock, resolveTimezone, timezoneMenuRows, isGroupRow, defaultMemberOf, groupKeyOf, groupMembers, LEGEND_AT_TOP_ATTR, normalizeSession, Vela, normalizeTimezone, isExchangeTimezone, TypedEventBus, timeframeToMs, MultiProviderFeed, registerBuiltinChartTypes, resolveTheme, buildToolbar, createCustomMark, createAttributionMark, DrawingToolbar, applyAttributionMarkTheme, sharedBarStore } from './chunk-ATGTCWHJ.js'; -import { chartType, resolveTopbarComposition, topbarActionOverride, TOPBAR_BUILTIN_IDS, widgetActions, SidePanel, sidePanels, DEFAULT_PANEL_ORDER, symbolRanking, resolveEngines, legendActionsProviderFor, legendCalloutsProviderFor, statePersistenceHandlers, topbarHas, rendererDefaults, mobilePlacement, widgetAttachments, getDrawingType, inputDeltas } from './chunk-EZ5FWVLA.js'; -import { Tooltip, KeymapManager, isEditableTarget, Drawer } from './chunk-LMBYEGUR.js'; -import { Menu, Dialog, CalloutBubble, applyPlotOverlayTokens, ensureUIHost } from './chunk-NELQJCGK.js'; -import { registerIcon, svg16, injectStyles, iconEl, iconMarkup, iconAt, SESSION_OFF, SESSION_POST, SESSION_PRE, icon, categoricalColor } from './chunk-BZQM2XO7.js'; +import { parseSymbol, priceStyleIds, BUILTIN_PRICE_STYLES, SecondClock, isGroupRow, defaultMemberOf, groupKeyOf, groupMembers, LEGEND_AT_TOP_ATTR, normalizeSession, Vela, TypedEventBus, timeframeToMs, MultiProviderFeed, registerBuiltinChartTypes, resolveTheme, buildToolbar, createCustomMark, createAttributionMark, DrawingToolbar, applyAttributionMarkTheme, sharedBarStore, CANDLE_OVERRIDE_KEYS } from './chunk-HMHA733L.js'; +import { chartType, resolveTopbarComposition, topbarActionOverride, TOPBAR_BUILTIN_IDS, widgetActions, tzButtonLabel, resolveTimezone, timezoneMenuRows, SidePanel, sidePanels, DEFAULT_PANEL_ORDER, symbolRanking, paneScaleAt, composeMenu, priceAxisItems, scaleChoiceOf, timeAxisItems, bodyItems, scaleWrites, invertWrite, settingsSectionOf, resolveEngines, legendActionsProviderFor, legendCalloutsProviderFor, normalizeTimezone, isExchangeTimezone, statePersistenceHandlers, topbarHas, rendererDefaults, mobilePlacement, widgetAttachments, getDrawingType, inputDeltas } from './chunk-KWI3YDBW.js'; +import { Tooltip, KeymapManager, isEditableTarget, Drawer } from './chunk-TO3GIK7Z.js'; +import { Menu, Dialog, CalloutBubble, applyPlotOverlayTokens, ensureUIHost } from './chunk-G7B7ZCBF.js'; +import { registerIcon, svg16, injectStyles, iconEl, iconMarkup, iconAt, SESSION_OFF, SESSION_POST, SESSION_PRE, announceSurface, holdForExit, icon, categoricalColor } from './chunk-VHGACEHO.js'; import { baseOf } from './chunk-W4EJWLEO.js'; // src/widget/timeframe.ts @@ -108,11 +108,11 @@ function timeframeLabel(value) { } // src/widget/layout-picker.ts -var STYLE_ID = "vela-widget-layout-picker-v14"; +var STYLE_ID = "vela-widget-layout-picker-v15"; var CSS = ` .vela-lp-layer { position: absolute; z-index: var(--vela-z-menu); } .vela-lp { - background: var(--vela-surface-elev); + background: var(--vela-surface); color: var(--vela-fg); border: 1px solid var(--vela-border-strong); border-radius: 8px; @@ -241,6 +241,8 @@ var LayoutPicker = class { constructor(opts) { this.squares = []; this.isOpen = false; + /** The card's exit animation after a close; a reopen cancels it. */ + this.exit = null; /** Hover preview (1-based rows/cols), null = show current shape. */ this.hover = null; this.onDocPointerDown = (e) => { @@ -261,6 +263,7 @@ var LayoutPicker = class { const panel = doc.createElement("div"); panel.className = "vela-lp"; this.layer.appendChild(panel); + this.panel = panel; const cols = doc.createElement("div"); cols.className = "vela-lp-cols"; panel.appendChild(cols); @@ -334,6 +337,8 @@ var LayoutPicker = class { open() { if (this.isOpen) return; this.isOpen = true; + this.exit?.cancel(); + this.exit = null; this.hover = null; this.refresh(); this.layer.style.display = ""; @@ -342,11 +347,16 @@ var LayoutPicker = class { this.doc.addEventListener("pointerdown", this.onDocPointerDown, true); this.doc.addEventListener("keydown", this.onDocKeydown, true); this.opts.onOpenChange?.(true); + if (this.isOpen) announceSurface(this.panel, true, "popover", this.opts.trigger); } close() { if (!this.isOpen) return; this.isOpen = false; - this.layer.style.display = "none"; + announceSurface(this.panel, false, "popover", this.opts.trigger); + this.exit = holdForExit(this.panel, () => { + this.exit = null; + if (!this.isOpen) this.layer.style.display = "none"; + }); this.opts.trigger.setAttribute("aria-expanded", "false"); this.doc.removeEventListener("pointerdown", this.onDocPointerDown, true); this.doc.removeEventListener("keydown", this.onDocKeydown, true); @@ -361,6 +371,7 @@ var LayoutPicker = class { } destroy() { this.close(); + this.exit?.finish(); this.infoTip.destroy(); this.layer.remove(); } @@ -427,7 +438,7 @@ var LayoutPicker = class { const hostRect = this.opts.host.getBoundingClientRect(); const trigRect = this.opts.trigger.getBoundingClientRect(); let left = trigRect.left - hostRect.left; - const top = trigRect.bottom - hostRect.top + 4; + const top = trigRect.bottom - hostRect.top + 8; const width = this.layer.offsetWidth; if (left + width > hostRect.width - 8) left = Math.max(8, hostRect.width - 8 - width); this.layer.style.left = `${left}px`; @@ -780,7 +791,8 @@ var Topbar = class { triggerId: "vela-topbar-style", host, items: this.styleItems(), - onSelect: (id) => opts.onPriceStyle(id) + onSelect: (id) => opts.onPriceStyle(id), + iconBadges: true }); } setSymbol(symbol) { @@ -846,8 +858,14 @@ var Topbar = class { renderLayoutButton(doc) { if (!this.layoutButton) return; this.layoutButton.replaceChildren(); - if (iconMarkup("layout")) this.layoutButton.appendChild(iconEl("layout", doc)); - else this.layoutButton.appendChild(doc.createTextNode(this.layoutId ?? "")); + const glyph = this.opts.layout?.glyph?.(); + if (glyph || iconMarkup("layout")) { + const icon2 = iconEl("layout", doc); + if (glyph) icon2.innerHTML = glyph; + this.layoutButton.appendChild(icon2); + } else { + this.layoutButton.appendChild(doc.createTextNode(this.layoutId ?? "")); + } this.layoutButton.setAttribute("aria-label", `Layout \u2014 ${this.layoutId ?? ""}`); } renderStyleButton(doc) { @@ -1701,8 +1719,8 @@ var ObjectTree = class extends SidePanel { set groups(next) { if (this.chart) this.groupsPerChart.set(this.chart, next); } - toggle(open = this.el.hidden) { - super.toggle(open); + toggle(open = !this.open, instant = false) { + super.toggle(open, instant); if (open) this.refresh(); } setSymbol(symbol) { @@ -2736,8 +2754,8 @@ var DataWindow = class extends SidePanel { this.unsubs = []; injectStyles(STYLE_ID5, CSS5, host.ownerDocument); } - toggle(open = this.el.hidden) { - super.toggle(open); + toggle(open = !this.open, instant = false) { + super.toggle(open, instant); if (open) this.refresh(); } /** (Re)bind to a chart instance — called after every widget rebuild. */ @@ -2813,19 +2831,22 @@ var PanelDock = class { /** * (Re)build the CONTRIBUTED panels from the registry — call once after the built-ins, and * again on `refreshActions()` so a late registration appears. Contributed panels that are - * gone from the registry are dropped; the ones still there are rebuilt, so a replaced - * descriptor takes effect. + * gone from the registry are dropped and a REPLACED descriptor is rebuilt; a panel whose + * descriptor is unchanged stays mounted as it is, so its content and state survive. */ refresh() { const openBefore = this.openId; - for (const entry of [...this.entries]) if (entry.contributed) this.drop(entry); - for (const desc of sidePanels()) { + const registered = sidePanels(); + for (const entry of [...this.entries]) if (entry.contributed && !registered.includes(entry.desc)) this.drop(entry); + for (const desc of registered) { + if (this.entries.some((e) => e.desc === desc)) continue; const panel = new SidePanel(this.host, desc.title, `vela-panel-${desc.id}`, { width: desc.width, resizable: desc.resizable, minWidth: desc.minWidth, maxWidth: desc.maxWidth, - overlay: desc.overlay + overlay: desc.overlay, + maximizable: desc.maximizable }); const entry = { id: desc.id, @@ -2833,10 +2854,19 @@ var PanelDock = class { icon: desc.icon, order: desc.order ?? DEFAULT_PANEL_ORDER, panel, - contributed: true + contributed: true, + desc }; try { - entry.handle = desc.mount(this.deps.context(), panel.content, { slot: panel.headerSlot, setTitle: (t) => panel.setTitle(t) }) ?? void 0; + const header = { + slot: panel.headerSlot, + setTitle: (t) => panel.setTitle(t), + get maximized() { + return panel.maximized; + }, + setMaximized: (on) => panel.setMaximized(on) + }; + entry.handle = desc.mount(this.deps.context(), panel.content, header) ?? void 0; if (this.chart) entry.handle?.onChart?.(this.chart); } catch (err) { console.warn(`[vela] side panel "${desc.id}" failed to mount`, err); @@ -2895,7 +2925,7 @@ var PanelDock = class { } this.pinned = new Set(state.pinned ?? []); for (const entry of this.entries) entry.panel.setOverlay(!this.pinned.has(entry.id)); - for (const entry of this.entries) entry.panel.toggle(entry.id === state.open); + for (const entry of this.entries) entry.panel.toggle(entry.id === state.open, true); this.pendingOpen = state.open && !this.entries.some((e) => e.id === state.open) ? state.open : null; } /** Drop the contributed panels (the shell destroys its own). */ @@ -2911,7 +2941,7 @@ var PanelDock = class { if (this.pinned.has(entry.id)) entry.panel.setOverlay(false); entry.panel.onOpenChange = (open) => { if (open) { - for (const other of this.entries) if (other !== entry) other.panel.toggle(false); + for (const other of this.entries) if (other !== entry) other.panel.toggle(false, true); this.pendingOpen = null; } this.deps.chrome.setPanelActive(entry.id, open); @@ -4027,15 +4057,48 @@ function syncTargets(originId, setting, cellIds) { function rangesWithin(a, b, epsMs) { return Math.abs(a.from - b.from) <= epsMs && Math.abs(a.to - b.to) <= epsMs; } -var STYLE_SYNC_CONFIG_KEYS = ["layout", "panes", "grid", "priceScale", "crosshair"]; -function styleConfigSlice(config) { - if (config == null || typeof config !== "object") return null; - const doc = config; - const out = {}; +var STYLE_SYNC_CONFIG_KEYS = [ + "layout", + "panes", + "grid", + "margins", + "priceScale", + "crosshair", + "animations", + "candles", + "bars", + "line", + "area", + "baseline", + "sessions" +]; +function styleConfigPatch(origin, follower) { + const from = asRecord(origin); + const to = asRecord(follower); + if (!from || !to) return null; + const patch = {}; for (const key of STYLE_SYNC_CONFIG_KEYS) { - if (doc[key] != null && typeof doc[key] === "object") out[key] = doc[key]; + const block = asRecord(from[key]); + if (block && JSON.stringify(block) !== JSON.stringify(to[key])) patch[key] = block; } - return Object.keys(out).length > 0 ? out : null; + const spacing = asRecord(from.series)?.spacing; + if (typeof spacing === "number" && spacing !== asRecord(to.series)?.spacing) patch.series = { spacing }; + const fromTypes = asRecord(from.chartTypes) ?? {}; + const toTypes = asRecord(to.chartTypes) ?? {}; + const types = {}; + for (const typeId of /* @__PURE__ */ new Set([...Object.keys(fromTypes), ...Object.keys(toTypes)])) { + const src = asRecord(fromTypes[typeId]) ?? {}; + const dst = asRecord(toTypes[typeId]) ?? {}; + for (const key of CANDLE_OVERRIDE_KEYS) { + const value = src[key] ?? null; + if (value !== (dst[key] ?? null)) (types[typeId] ?? (types[typeId] = {}))[key] = value; + } + } + if (Object.keys(types).length > 0) patch.chartTypes = types; + return Object.keys(patch).length > 0 ? patch : null; +} +function asRecord(v) { + return v != null && typeof v === "object" ? v : null; } // src/workspace/persist.ts @@ -4223,6 +4286,9 @@ var CSS10 = ` .vela-statusline .vela-sl-market { align-self: center; display: inline-flex; } .vela-statusline .vela-sl-market > [hidden] { display: none !important; } .vela-statusline .vela-sl-replay-badge, .vela-statusline .vela-sl-replay-badge svg { display: block; width: 16px; height: 16px; } +/* Tabular figures: every digit has one advance, so a readout whose text changes only in + * its digits keeps its width \u2014 render() skips the ladder for those (see widthKey). */ +.vela-statusline .vela-sl-values { font-variant-numeric: tabular-nums; } .vela-statusline .vela-sl-ohlc { display: flex; gap: var(--vela-space-1); color: var(--vela-fg-muted); } .vela-statusline .vela-sl-ohlc b { color: var(--vela-fg); font-weight: 500; } /* The change value wears the SAME ink as the OHLC values (set inline per render) \u2014 @@ -4340,6 +4406,10 @@ var Statusline = class { this.fitRO = null; /** The ladder rung currently applied — see {@link fit}. */ this.layout = { stacked: false, level: "full" }; + /** The readout {@link widthKey} the applied rung was fitted to. */ + this.fitKey = null; + /** Web fonts landing after the last fit change every width without a resize. */ + this.onFontsLoaded = () => this.fit(); this.onContextMenu = (e) => { if (!this.menu || !this.menuHooks) return; e.preventDefault(); @@ -4403,6 +4473,7 @@ var Statusline = class { this.fitRO = new ResizeObserver(() => this.fit()); this.fitRO.observe(host); } + doc.fonts?.addEventListener("loadingdone", this.onFontsLoaded); this.marketTip = new Tooltip(this.marketEl, { content: MARKET_LABELS.open, placement: "bottom" }); this.eyeTip = new Tooltip(this.eyeEl, { content: "Show chart", placement: "bottom" }); this.setMarketStatus("open"); @@ -4455,6 +4526,7 @@ var Statusline = class { * (detached host, node tests) nothing overflows, so the widest rung stays. */ fit() { + this.fitKey = this.widthKey(); this.syncParts(); const seg = segmentVisibility(this.parts, this.chartHidden); const overflows = () => this.el.scrollWidth > this.el.clientWidth; @@ -4611,6 +4683,7 @@ var Statusline = class { this.detach(); this.fitRO?.disconnect(); this.fitRO = null; + this.el.ownerDocument.fonts?.removeEventListener("loadingdone", this.onFontsLoaded); this.el.removeEventListener("contextmenu", this.onContextMenu); this.menu?.destroy(); this.menu = null; @@ -4626,7 +4699,22 @@ var Statusline = class { } render() { if (this.menuHooks) this.setChartHidden(!this.menuHooks.chartVisible()); - this.fit(); + if (this.widthKey() === this.fitKey) this.renderValues(); + else this.fit(); + } + /** Everything the readout's width depends on, at every rung: its shape, and each + * value's sign, digit count and decimals (the digits themselves are tabular — see + * the CSS; the grouping commas follow from the digit count). `toFixed` carries all + * three at a fraction of the locale formatter's cost — this runs per pointer move. + * The parts, the host's size and the fonts re-fit through their own paths. */ + widthKey() { + const bar = this.hoverBar ?? this.lastBar; + if (!bar) return this.readout; + const dp = decimalsFor(bar.close); + const diff = bar.close - bar.open; + const text = [bar.open, bar.high, bar.low, bar.close, diff].map((v) => v.toFixed(dp)); + text.push((diff / bar.open * 100).toFixed(2)); + return `${this.readout} ${text.join(" ")}`.replace(/\d/g, "0"); } /** Write the value readout for the current bar at the current ladder level. */ renderValues() { @@ -4772,113 +4860,28 @@ var Watermark = class { } }; -// src/widget/context-menu-model.ts -var SETTINGS_SECTION = { - body: "Canvas", - "price-axis": "Scales and lines", - "time-axis": "Scales and lines" -}; -function settingsItem(zone, label) { - return { id: `settings:${SETTINGS_SECTION[zone]}`, label, separatorBefore: true }; -} -function settingsSectionOf(id) { - return id.slice("settings:".length) || void 0; -} -var SCALE_CHOICES = [ - ["regular", "Regular"], - ["percent", "Percent"], - ["indexed", "Indexed to 100"], - ["log", "Logarithmic"] -]; -function paneScaleAt(panes, y) { - return panes.find((p) => y >= p.top && y < p.top + p.height) ?? panes[0] ?? null; -} -function scaleChoiceOf(scale) { - if (scale.log) return "log"; - if (scale.mode === "percent") return "percent"; - if (scale.mode === "indexed") return "indexed"; - return "regular"; -} -function mainScale(pane) { - return pane === null || pane.kind === "price"; -} -function scaleWrites(choice, pane) { - const mode = choice === "percent" ? "percent" : choice === "indexed" ? "indexed" : "price"; - const log = choice === "log"; - if (mainScale(pane)) { - return [ - ["scaleMode", mode], - ["logScale", log] - ]; - } - return [ - ["scaleMode", { pane: pane.id, mode }], - ["logScale", { pane: pane.id, value: log }] - ]; -} -function invertWrite(next, pane) { - return mainScale(pane) ? ["invertScale", next] : ["invertScale", { pane: pane.id, value: next }]; -} -function priceAxisItems(s) { - return [ - { id: "auto", label: "Auto (fits data to screen)", checked: s.auto }, - { id: "invert", label: "Invert scale", checked: s.invert }, - ...SCALE_CHOICES.map(([choice, label], i) => ({ - id: `scale:${choice}`, - label, - checked: s.choice === choice, - separatorBefore: i === 0 - })), - { - id: "labels", - label: "Labels", - separatorBefore: true, - submenu: [ - { id: "toggle:axisLabels", label: "Price axis labels", checked: s.axisLabels }, - { id: "toggle:priceLabel", label: "Last price label", checked: s.priceLabel }, - { id: "toggle:countdown", label: "Countdown to bar close", checked: s.countdown } - ] - }, - { - id: "levels", - label: "Levels", - submenu: [{ id: "toggle:currentPriceLine", label: "Last Price Line", checked: s.priceLine }] - }, - settingsItem("price-axis", "More settings\u2026") - ]; -} -function timeAxisItems(timezone) { - return [ - { - id: "timezone", - label: "Time zone", - submenu: timezoneMenuRows(timezone).map((r) => ({ id: `tz:${r.value}`, label: r.label, checked: r.checked })) - }, - settingsItem("time-axis", "More settings\u2026") - ]; -} -function bodyItems(counts) { - return [ - { id: "reset-view", label: "Reset chart view" }, - { id: "remove-drawings", label: "Remove drawings", disabled: counts.drawings === 0, separatorBefore: true }, - { id: "remove-indicators", label: "Remove indicators", disabled: counts.indicators === 0 }, - settingsItem("body", "Settings\u2026") - ]; -} - // src/widget/context-menu.ts var PRICE_AXIS_W = 60; var TIME_AXIS_H = 26; +var OFF_PLOT = { price: null, time: null, paneKind: null }; var ChartContextMenu = class { constructor(host, cbs) { this.cbs = cbs; this.chart = null; + this.offCrosshair = null; + /** The bound chart's latest crosshair report — a right-click always follows a pointer + * move to its spot, so this is where it landed. */ + this.crosshair = OFF_PLOT; + /** {@link crosshair} as it stood when the menu opened: the pointer moves on through the + * menu before a row is picked, and `run` must see the right-clicked spot. */ + this.pointer = OFF_PLOT; this.lastZone = "body"; /** The pane whose scale the open price-axis menu targets (null ⇒ the main scale). */ this.lastPane = null; this.onContextMenu = (e) => { e.preventDefault(); if (!this.chart) return; + this.pointer = this.crosshair; this.lastZone = this.zoneOf(e); this.lastPane = this.lastZone === "price-axis" ? this.paneAt(e) : null; this.menu.setItems(this.itemsFor(this.lastZone)); @@ -4892,15 +4895,23 @@ var ChartContextMenu = class { // Pointer-anchored action menu: checked state reads as a leading ✓, not a // washed row (which would read as hover in a menu with no trigger button). checkmarks: true, + iconBadges: true, onSelect: (id) => this.run(id) }); host.addEventListener("contextmenu", this.onContextMenu); } /** (Re)bind to a chart instance — called after every widget rebuild. */ onChart(chart) { + this.offCrosshair?.(); this.chart = chart; + this.crosshair = OFF_PLOT; + this.offCrosshair = chart.renderer.onCrosshairMove((e) => { + this.crosshair = { price: e.price, time: e.time, paneKind: e.paneKind ?? null }; + }); } destroy() { + this.offCrosshair?.(); + this.offCrosshair = null; this.host.removeEventListener("contextmenu", this.onContextMenu); this.menu.destroy(); } @@ -4919,49 +4930,52 @@ var ChartContextMenu = class { flag(feature) { return Boolean(this.chart?.renderer.get(feature)); } - contributed(zone) { + /** A fresh widget context carrying the pointer captured at open. Copied by property + * descriptor: the context's getters must stay LIVE, and a spread would freeze them. */ + context() { const ctx = this.cbs.getContext?.(); - return widgetActions(`context:${zone}`, ctx).map((a, i) => ({ - id: `action:${a.id}`, - label: a.label, - icon: a.icon, - separatorBefore: i === 0 + if (!ctx) return void 0; + return Object.create(Object.getPrototypeOf(ctx), { + ...Object.getOwnPropertyDescriptors(ctx), + pointer: { value: this.pointer, enumerable: true } + }); + } + contributed(zone) { + return widgetActions(`context:${zone}`, this.context()).map((a) => ({ + item: { id: `action:${a.id}`, label: a.label, icon: a.icon }, + order: a.order })); } itemsFor(zone) { + return composeMenu(zone, this.builtinItems(zone), this.contributed(zone)); + } + builtinItems(zone) { if (zone === "price-axis") { const pane = this.lastPane; - return [ - ...priceAxisItems({ - auto: this.chart?.renderer.get("autoScale") !== false, - invert: pane ? pane.invert : this.flag("invertScale"), - choice: scaleChoiceOf(pane ?? { mode: String(this.chart?.renderer.get("scaleMode") ?? "price"), log: this.flag("logScale") }), - axisLabels: this.flag("axisLabels"), - priceLabel: this.flag("priceLabel"), - countdown: this.flag("countdown"), - priceLine: this.flag("currentPriceLine") - }), - ...this.contributed(zone) - ]; + return priceAxisItems({ + auto: this.chart?.renderer.get("autoScale") !== false, + invert: pane ? pane.invert : this.flag("invertScale"), + choice: scaleChoiceOf(pane ?? { mode: String(this.chart?.renderer.get("scaleMode") ?? "price"), log: this.flag("logScale") }), + axisLabels: this.flag("axisLabels"), + priceLabel: this.flag("priceLabel"), + countdown: this.flag("countdown"), + priceLine: this.flag("currentPriceLine") + }); } if (zone === "time-axis") { - const tz = this.cbs.timezone?.() ?? String(this.chart?.renderer.get("timezone") ?? "Etc/UTC"); - return [...timeAxisItems(tz), ...this.contributed("time-axis")]; + return timeAxisItems(this.cbs.timezone?.() ?? String(this.chart?.renderer.get("timezone") ?? "Etc/UTC")); } const chart = this.chart; - return [ - ...bodyItems({ - drawings: chart?.drawings.supported ? chart.drawings.all().length : 0, - indicators: chart?.indicators().length ?? 0 - }), - ...this.contributed("body") - ]; + return bodyItems({ + drawings: chart?.drawings.supported ? chart.drawings.all().length : 0, + indicators: chart?.indicators().length ?? 0 + }); } run(id) { const chart = this.chart; if (!chart) return; if (id.startsWith("action:")) { - const ctx = this.cbs.getContext?.(); + const ctx = this.context(); if (ctx) widgetActions(`context:${this.lastZone}`, ctx).find((a) => a.id === id.slice("action:".length))?.run(ctx); return; } @@ -5611,8 +5625,8 @@ function seedDefaults(opts) { }; } function cellChartDefaults(opts) { - const { renderer, defaultLanguage, currentPriceLine, logScale, animations, glow, upColor, downColor, drawings, settings } = opts; - return { renderer, defaultLanguage, currentPriceLine, logScale, animations, glow, upColor, downColor, drawings, settings }; + const { renderer, defaultLanguage, currentPriceLine, logScale, animations, glow, upColor, downColor, drawings, settings, priceAxis } = opts; + return { renderer, defaultLanguage, currentPriceLine, logScale, animations, glow, upColor, downColor, drawings, settings, priceAxis }; } function cellDrawings(opt) { if (opt === false) return false; @@ -6182,12 +6196,14 @@ var ChartCell = class { this.watermarkOn = visible; this.watermark?.setVisible(visible); this.deps.onStateDirty(); + this.deps.onStatusPrefsChanged(this.id); } /** Show/hide the "Replay" line under this cell's watermark while it replays (persisted per cell). */ setReplayWatermarkVisible(visible) { this.replayWatermarkOn = visible; this.watermark?.setReplayVisible(visible); this.deps.onStateDirty(); + this.deps.onStatusPrefsChanged(this.id); } /** Show/hide this cell's indicator titles — the in-chart legend rows (persisted per cell). */ setIndicatorTitlesVisible(visible) { @@ -6208,18 +6224,20 @@ var ChartCell = class { this.statusline?.setPartVisible(part, visible); this.deps.onStatusPrefsChanged(this.id); } - /** This cell's Status line tab prefs as one bundle (see {@link CellStatusPrefs}). */ + /** This cell's Status line tab and watermark prefs as one bundle (see {@link CellStatusPrefs}). */ statusPrefs() { const sl = this.statusline; return { parts: sl ? { logo: sl.partVisible("logo"), name: sl.partVisible("name"), market: sl.partVisible("market"), ohlc: sl.partVisible("ohlc"), change: sl.partVisible("change") } : null, indicatorTitles: this.indicatorTitlesOn, - indicatorValues: this.indicatorValuesOn + indicatorValues: this.indicatorValuesOn, + watermark: this.watermarkOn, + replayWatermark: this.replayWatermarkOn }; } - /** Converge this cell's Status line tab prefs to `prefs` — the follower half of - * the workspace's style link. Idempotent: matching values change nothing, so a - * propagated echo dies on its own. */ + /** Converge this cell's Status line tab and watermark prefs to `prefs` — the + * follower half of the workspace's style link. Idempotent: matching values change + * nothing, so a propagated echo dies on its own. */ applyStatusPrefs(prefs) { if (prefs.parts && this.statusline) { for (const part of Object.keys(prefs.parts)) { @@ -6228,6 +6246,8 @@ var ChartCell = class { } if (prefs.indicatorTitles !== this.indicatorTitlesOn) this.setIndicatorTitlesVisible(prefs.indicatorTitles); if (prefs.indicatorValues !== this.indicatorValuesOn) this.setIndicatorValuesVisible(prefs.indicatorValues); + if (prefs.watermark !== this.watermarkOn) this.setWatermarkVisible(prefs.watermark); + if (prefs.replayWatermark !== this.replayWatermarkOn) this.setReplayWatermarkVisible(prefs.replayWatermark); } /** The LIVE chart of this cell — never cache it across a layout change (the cell's * identity is what endures; the chart dies with the cell). */ @@ -7099,6 +7119,55 @@ function occupancyGrid(def) { const cols = def.cols.length; return def.rows.map((_, r) => def.cols.map((_2, c) => def.cells[r * cols + c]?.id ?? `\xB7${r}x${c}`)); } +var GLYPH_MIN = 1.5; +var GLYPH_SPAN = 13; +function glyphStops(weights, n) { + const w = Array.from({ length: n }, (_, i) => { + const v = weights[i]; + return v !== void 0 && Number.isFinite(v) && v > 0 ? v : 1; + }); + const total = w.reduce((a, b) => a + b, 0); + const stops = [GLYPH_MIN]; + let acc = 0; + for (const v of w) { + acc += v; + stops.push(Math.round((GLYPH_MIN + GLYPH_SPAN * acc / total) * 100) / 100); + } + return stops; +} +function layoutGlyph(def) { + const grid = occupancyGrid(def); + const rows = grid.length; + const cols = grid.reduce((n, row) => Math.max(n, row.length), 0); + const xs = glyphStops(def.cols, cols); + const ys = glyphStops(def.rows, rows); + const at = (r, c) => grid[r]?.[c]; + const seams = []; + for (let c = 1; c < cols; c += 1) { + let start = -1; + for (let r = 0; r <= rows; r += 1) { + const split = r < rows && at(r, c - 1) !== at(r, c); + if (split && start < 0) start = r; + if (!split && start >= 0) { + seams.push(`M${xs[c]} ${ys[start]}V${ys[r]}`); + start = -1; + } + } + } + for (let r = 1; r < rows; r += 1) { + let start = -1; + for (let c = 0; c <= cols; c += 1) { + const split = c < cols && at(r - 1, c) !== at(r, c); + if (split && start < 0) start = c; + if (!split && start >= 0) { + seams.push(`M${xs[start]} ${ys[r]}H${xs[c]}`); + start = -1; + } + } + } + const frame = ``; + return svg16(seams.length > 0 ? `${frame}` : frame); +} function gridStyles(def, trackSizes) { const cols = trackSizes?.cols?.length === def.cols.length ? trackSizes.cols : def.cols; const rows = trackSizes?.rows?.length === def.rows.length ? trackSizes.rows : def.rows; @@ -8009,7 +8078,11 @@ var MoreDrawer = class { row(doc, label, opts) { const el = doc.createElement("div"); el.className = "vela-md-row"; - if (opts.icon) el.appendChild(iconEl(opts.icon, doc)); + if (opts.icon) { + const icon2 = iconEl(opts.icon, doc); + if (opts.glyph) icon2.innerHTML = opts.glyph; + el.appendChild(icon2); + } const text = doc.createElement("span"); text.className = "vela-md-row-label"; text.textContent = label; @@ -8051,7 +8124,7 @@ var MoreDrawer = class { if (this.opts.layout) { const shape = this.opts.layout.shape(); const value = shape ? `${shape.cols} \xD7 ${shape.rows}` : this.opts.layout.presets().find((p) => p.checked)?.label; - list.appendChild(this.row(doc, "Layout", { icon: "layout", value, chevron: true, onClick: () => this.show("layout") })); + list.appendChild(this.row(doc, "Layout", { icon: "layout", glyph: this.opts.layout.glyph?.(), value, chevron: true, onClick: () => this.show("layout") })); } for (const act of this.opts.primaryActions?.() ?? []) list.appendChild(this.actionRow(doc, act)); for (const panel of this.opts.panels()) { @@ -8915,7 +8988,8 @@ var VelaWorkspace = class { onToggleSync: (id) => { const kind = id; this.sync.set(kind, this.syncOpts[kind] ? false : true); - } + }, + glyph: () => layoutGlyph(this.def) }, getContext: () => this.context() }); @@ -9414,6 +9488,7 @@ var VelaWorkspace = class { this.applyGrid(); this.buildCells(); this.alignNewCellStyles(preexisting); + this.alignNewCellDrawings(preexisting); this.syncCellPresentation(); this.refreshCellControls(); this.topbar.setLayout(next.id); @@ -9830,6 +9905,7 @@ var VelaWorkspace = class { const chart = cell.chart; chart.on("indicator:error", ({ error }) => this.toastHost.show(`[${cell.id}] ${error.message}`, "error", 5e3)); chart.on("script:run", (run) => this.events.emit("script:run", { ...run, cell: cell.id })); + chart.on("priceStyle:change", ({ from, to }) => this.events.emit("cell:priceStyle", { id: cell.id, from, to })); chart.on("alert", (alert) => { const source = [parseSymbol(cell.symbol).ticker || cell.symbol, timeframeLabel(cell.timeframe), alert.indicator].filter(Boolean).join(" "); this.alerts.unshift({ cellId: cell.id, source, title: alert.title ?? "Alert", message: alert.message, time: alert.time }); @@ -9947,12 +10023,66 @@ var VelaWorkspace = class { } } /** - * Mirror an origin cell's presentation — the Canvas + Scales-and-lines slice of - * its renderer config plus its Status line tab prefs — onto its same-group - * followers (the style link). Loop-safe two ways: the busy guard eats the - * followers' SYNCHRONOUS echoes (their `applyConfig` re-fires `onConfigChanged` - * in the same tick), and the equality short-circuits leave already-converged - * followers untouched, so nothing re-emits once the group agrees. + * Bring cells minted by a layout change into their drawings group: with the link + * on, a NEW cell (fresh slot, or one returning from the pool that missed edits + * while dormant) receives the drawings of a pre-existing group peer — the active + * cell when it is one. A drawing the arriving cell already holds a linked copy of + * is refreshed in place; any other is copied and linked like a freshly synced + * drawing, so later edits and removals follow both ways. The arrival is the cell's + * starting state, not an edit: it stays out of the cell's undo timeline, and the + * busy guard keeps the copies' own events from fanning back out. + */ + alignNewCellDrawings(preexisting) { + const setting = this.syncOpts.drawings; + if (!setting) return; + const ids = [...this.cellsById.keys()]; + for (const id of ids) { + if (preexisting.has(id)) continue; + const cell = this.cellsById.get(id); + if (!cell?.chart.drawings.supported) continue; + const peers = syncTargets(id, setting, ids).filter((p) => preexisting.has(p)); + if (peers.length === 0) continue; + const sourceId = this.activeId && peers.includes(this.activeId) ? this.activeId : peers[0]; + const source = this.cellsById.get(sourceId); + if (!source) continue; + const drawings = cell.chart.drawings; + this.drawingSyncBusy = true; + try { + cell.history.silently(() => { + const held = new Set(drawings.all().map((d) => d.id)); + for (const doc of source.chart.drawings.all()) { + const group = this.drawingLinks.get(`${sourceId}\0${doc.id}`) ?? /* @__PURE__ */ new Map([[sourceId, doc.id]]); + const peerId = group.get(id); + if (peerId != null && held.has(peerId)) { + drawings.update(peerId, { anchors: doc.anchors, style: doc.style, text: doc.text, props: doc.props }); + continue; + } + const copy = drawings.add(doc.type, { + paneId: doc.paneId, + anchors: doc.anchors, + style: doc.style, + text: doc.text, + props: doc.props, + zIndex: doc.zIndex + }); + if (!copy) continue; + if (peerId != null) this.drawingLinks.delete(`${id}\0${peerId}`); + group.set(id, copy.id); + for (const [cellId, dId] of group) this.drawingLinks.set(`${cellId}\0${dId}`, group); + } + }); + } finally { + this.drawingSyncBusy = false; + } + } + } + /** + * Mirror an origin cell's presentation — the style-link slice of its renderer + * config ({@link styleConfigPatch}) plus its Status line and watermark prefs — + * onto its same-group followers (the style link). Loop-safe two ways: the busy + * guard eats the followers' SYNCHRONOUS echoes (their `applyConfig` re-fires + * `onConfigChanged` in the same tick), and the equality short-circuits leave + * already-converged followers untouched, so nothing re-emits once the group agrees. */ propagateStylePrefs(originId) { if (this.styleSyncBusy || this.destroyed) return; @@ -9960,17 +10090,15 @@ var VelaWorkspace = class { if (targets.length === 0) return; const origin = this.cellsById.get(originId); if (!origin) return; - const slice = styleConfigSlice(origin.chart.renderer.getConfig()); - const sliceJson = slice ? JSON.stringify(slice) : null; + const config = origin.chart.renderer.getConfig(); const prefs = origin.statusPrefs(); this.styleSyncBusy = true; try { for (const id of targets) { const cell = this.cellsById.get(id); if (!cell) continue; - if (slice && sliceJson !== JSON.stringify(styleConfigSlice(cell.chart.renderer.getConfig()))) { - cell.chart.renderer.applyConfig(slice); - } + const patch = styleConfigPatch(config, cell.chart.renderer.getConfig()); + if (patch) cell.chart.renderer.applyConfig(patch); cell.applyStatusPrefs(prefs); } } finally { @@ -10291,7 +10419,8 @@ var VelaWorkspace = class { onToggleSync: (id) => { const kind = id; this.sync.set(kind, this.syncOpts[kind] ? false : true); - } + }, + glyph: () => layoutGlyph(this.def) }, onOpenChange: (open) => this.trackDialog(open) })); diff --git a/console/frontend/vendor/vela/dist/chunk-NELQJCGK.js b/console/frontend/vendor/vela/dist/chunk-G7B7ZCBF.js similarity index 94% rename from console/frontend/vendor/vela/dist/chunk-NELQJCGK.js rename to console/frontend/vendor/vela/dist/chunk-G7B7ZCBF.js index 4491bec..4adc62c 100644 --- a/console/frontend/vendor/vela/dist/chunk-NELQJCGK.js +++ b/console/frontend/vendor/vela/dist/chunk-G7B7ZCBF.js @@ -1,4 +1,4 @@ -import { overlayScrollbarCss, isDarkColor, mix, HIGHLIGHT, ACCENT_BRIGHT, ACCENT, withAlpha, injectStyles, iconAt, iconEl, BULLISH, BEARISH, WARNING, NEUTRAL } from './chunk-BZQM2XO7.js'; +import { overlayScrollbarCss, isDarkColor, mix, HIGHLIGHT, ACCENT_BRIGHT, ACCENT, withAlpha, injectStyles, announceSurface, holdForExit, iconAt, iconEl, BULLISH, BEARISH, WARNING, NEUTRAL } from './chunk-VHGACEHO.js'; import { VanillaMachine, normalizeProps, spreadProps } from '@zag-js/vanilla'; export { normalizeProps, spreadProps } from '@zag-js/vanilla'; import * as menu from '@zag-js/menu'; @@ -226,6 +226,35 @@ var MENU_CSS = ` color: var(--vela-fg-bright); } .vela-menu-item[data-checkmark] { color: var(--vela-fg-bright); } +/* Badge mode (iconBadges): the row icon sits in a rounded tile and the row grows to fit + it. An icon-less row of the same level keeps an invisible slot, so labels align. */ +.vela-menu[data-badges] > .vela-menu-item { padding: 5px 10px 5px 6px; } +.vela-menu-item .vela-menu-badge { + width: 24px; + height: 24px; + padding: 3px; + flex: none; + box-sizing: border-box; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: var(--vela-radius-md); + background: var(--vela-hover); + border: 1px solid var(--vela-border); + color: var(--vela-fg-muted); + transition: background var(--vela-dur-fast) var(--vela-ease), border-color var(--vela-dur-fast) var(--vela-ease), color var(--vela-dur-fast) var(--vela-ease); +} +.vela-menu-item .vela-menu-badge:empty { background: transparent; border-color: transparent; } +.vela-menu-item .vela-menu-badge .vela-icon { color: inherit; } +.vela-menu-item[data-highlighted] .vela-menu-badge:not(:empty) { color: var(--vela-fg-bright); } +/* The selected tile inverts: a bright fill under the surface-colored glyph. After the + hover rule, so a selected row keeps its tile while highlighted. */ +.vela-menu-item[data-checked] .vela-menu-badge:not(:empty), +.vela-menu-item[data-checkmark] .vela-menu-badge:not(:empty) { + background: color-mix(in srgb, var(--vela-fg-bright) 83%, var(--vela-surface)); + border-color: color-mix(in srgb, var(--vela-fg-bright) 40%, transparent); + color: var(--vela-surface); +} /* Switch rows (boolean settings in a dropdown): a right-aligned toggle pill \u2014 the same control language as the settings dialog's toggles. */ .vela-menu-switch { @@ -290,11 +319,16 @@ var Surface = class _Surface { /** Trigger rect captured when this level opened — the list stays put if the * trigger then moves (favorite chips shifting the caret). */ this.pinnedAnchor = null; + /** The open state last announced — see {@link announce}. */ + this.shown = false; + /** The list's exit animation after a close; a reopen cancels it. */ + this.exit = null; this.doc = doc; this.host = opts.host; this.onSelect = opts.onSelect; this.onFavorite = opts.onFavorite; this.checkmarks = opts.checkmarks === true; + this.iconBadges = opts.iconBadges === true; this.positioner = doc.createElement("div"); this.positioner.className = "vela-ui-layer"; this.list = doc.createElement("ul"); @@ -303,6 +337,7 @@ var Surface = class _Surface { this.positioner.appendChild(this.list); this.host.appendChild(this.positioner); const trigger = opts.trigger; + this.opener = trigger ?? opts.opener ?? null; this.ctrl = menuController({ items: [], id: opts.id, @@ -324,15 +359,37 @@ var Surface = class _Surface { if (opts.triggerId && trigger) trigger.id = opts.triggerId; this.handle = runMachine(this.ctrl.machine, this.ctrl.props, (service) => { const api = this.ctrl.connect(service); + const closing = this.shown && !api.open; + if (closing) this.announce(false); + if (api.open && this.exit) { + this.exit.cancel(); + this.exit = null; + } if (trigger) spreadProps(trigger, api.getTriggerProps(), this.mid); spreadProps(this.positioner, api.getPositionerProps(), this.mid); spreadProps(this.list, api.getContentProps(), this.mid); this.project(api); + if (closing) this.holdExit(); + if (api.open && !this.shown) this.announce(true); + }); + } + /** Keep the just-closed list up through its exit animation. `spreadProps` re-applies + * `hidden` only when the machine's value for it changes, so the list stays shown until + * the exit ends — or until a reopen, which projects `hidden: false` itself. */ + holdExit() { + this.list.hidden = false; + this.exit = holdForExit(this.list, () => { + this.exit = null; + if (!this.shown) this.list.hidden = true; }); } get api() { return this.ctrl.connect(this.handle.service); } + announce(open2) { + this.shown = open2; + announceSurface(this.list, open2, "menu", this.opener); + } setItems(items) { this.items = items; for (const sub of this.subs.values()) sub.destroy(); @@ -349,7 +406,9 @@ var Surface = class _Surface { destroy() { for (const sub of this.subs.values()) sub.destroy(); this.subs.clear(); + this.exit?.finish(); this.handle.stop(); + if (this.shown) this.announce(false); this.positioner.remove(); } byId(id) { @@ -374,6 +433,10 @@ var Surface = class _Surface { const doc = this.doc; this.list.replaceChildren(); const markable = this.checkmarks && this.items.some((i) => !(i.submenu && i.submenu.length > 0) && !i.toggle && i.checked !== void 0); + const iconic = this.items.some((i) => !!i.icon); + const badged = this.iconBadges && iconic; + if (badged) this.list.dataset.badges = "1"; + else delete this.list.dataset.badges; for (const item of this.items) { if (item.separatorBefore) { const sep = doc.createElement("li"); @@ -399,7 +462,16 @@ var Surface = class _Surface { } else if (!branch && !item.toggle && item.checked) { li.dataset.checked = "1"; } - if (item.icon) li.appendChild(iconEl(item.icon, doc)); + if (badged) { + const badge = doc.createElement("span"); + badge.className = "vela-menu-badge"; + if (item.icon) badge.appendChild(iconEl(item.icon, doc)); + li.appendChild(badge); + } else if (item.icon) { + li.appendChild(iconEl(item.icon, doc)); + } else if (iconic) { + li.appendChild(iconEl("", doc)); + } const label = doc.createElement("span"); label.className = "vela-menu-label"; label.textContent = item.label; @@ -443,9 +515,11 @@ var Surface = class _Surface { const sub = new _Surface(doc, { host: this.host, placement: "right-start", + opener: li, onSelect: this.onSelect, onFavorite: this.onFavorite, checkmarks: this.checkmarks, + iconBadges: this.iconBadges, id: `${this.mid}--${item.id}` }); sub.setItems(item.submenu ?? []); @@ -471,7 +545,8 @@ var Menu = class { id: opts.id, minWidth: opts.minWidth, onFavorite: opts.onFavorite, - checkmarks: opts.checkmarks + checkmarks: opts.checkmarks, + iconBadges: opts.iconBadges }); this.root.setItems(opts.items); } @@ -575,6 +650,7 @@ var POPOVER_CSS = ` // src/ui/components/popover/view.ts var open = null; +var leaving = /* @__PURE__ */ new Set(); function closeOpenPopovers() { open?.hide(); } @@ -602,6 +678,8 @@ var Popover = class { this.shown = false; /** The pending removal of a fading-out shell; a show() that reuses the shell cancels it. */ this.leaveTimer = null; + /** The shell's exit animation before it leaves the DOM; a show() that reuses the shell cancels it. */ + this.exit = null; const doc = opts.trigger.ownerDocument; injectStyles(POPOVER_STYLE_ID, POPOVER_CSS, doc); this.trigger = opts.trigger; @@ -638,6 +716,10 @@ var Popover = class { clearTimeout(this.leaveTimer); this.leaveTimer = null; } + this.exit?.cancel(); + this.exit = null; + leaving.delete(this); + for (const p of [...leaving]) if (p.trigger === this.trigger) p.exit?.finish(); ensureUIHost(this.el, this.inheritsTokens ? void 0 : this.theme); if (this.fadeMs > 0) { this.el.style.transition = `opacity ${this.fadeMs}ms ease`; @@ -662,16 +744,21 @@ var Popover = class { this.hide(); }; const onReflow = () => this.place(); - setTimeout(() => document.addEventListener("pointerdown", onOutside, true), 0); + setTimeout(() => { + if (this.onOutside === onOutside) document.addEventListener("pointerdown", onOutside, true); + }, 0); document.addEventListener("keydown", onKey, true); window.addEventListener("resize", onReflow, true); document.addEventListener("scroll", onReflow, true); this.onOutside = onOutside; this.onKey = onKey; this.onReflow = onReflow; + announceSurface(this.el, true, "popover", this.trigger); } hide() { if (!this.shown) return; + this.shown = false; + announceSurface(this.el, false, "popover", this.trigger); if (this.onOutside) document.removeEventListener("pointerdown", this.onOutside, true); if (this.onKey) document.removeEventListener("keydown", this.onKey, true); if (this.onReflow) { @@ -689,9 +776,13 @@ var Popover = class { this.el.remove(); }, this.fadeMs); } else { - this.el.remove(); + this.exit = holdForExit(this.el, () => { + this.exit = null; + leaving.delete(this); + this.el.remove(); + }); + if (this.exit) leaving.add(this); } - this.shown = false; if (open === this) open = null; this.ctrl.onClose?.(); } @@ -702,6 +793,7 @@ var Popover = class { } destroy() { this.hide(); + this.exit?.finish(); } reposition() { if (this.shown) this.place(); @@ -1377,6 +1469,11 @@ ${overlayScrollbarCss(".vela-dialog *")} `; var Dialog = class { constructor(opts = {}) { + this.opener = null; + this.wasOpen = false; + /** The panel and scrim's exit animation after a close; a reopen cancels it. */ + this.exit = null; + this.destroyed = false; const doc = (opts.host ?? document.body).ownerDocument; injectStyles(DIALOG_STYLE_ID, DIALOG_CSS, doc); const host = opts.host ?? doc.body; @@ -1473,19 +1570,73 @@ var Dialog = class { const mid = String(this.ctrl.props.id); this.handle = runMachine(this.ctrl.machine, this.ctrl.props, (service) => { const api = this.ctrl.connect(service); + const closing = this.wasOpen && !api.open; + if (closing) this.announce(false); spreadProps(this.backdrop, api.getBackdropProps(), mid); spreadProps(this.positioner, api.getPositionerProps(), mid); spreadProps(this.panel, api.getContentProps(), mid); spreadProps(title, api.getTitleProps(), mid); spreadProps(close, api.getCloseTriggerProps(), mid); - this.backdrop.style.display = api.open ? "" : "none"; - this.positioner.style.display = api.open ? "" : "none"; + if (api.open) { + this.exit?.cancel(); + this.exit = null; + this.setShown(true); + } else if (closing) { + this.holdExit(); + } else if (!this.exit) { + this.setShown(false); + } + if (api.open && !this.wasOpen) this.announce(true); + if (this.wasOpen && !api.open) this.restoreOpener(); + this.wasOpen = api.open; }); } + setShown(shown) { + this.backdrop.style.display = shown ? "" : "none"; + this.positioner.style.display = shown ? "" : "none"; + } + /** Keep the just-closed dialog up through its exit animation, then hide it — or + * remove it, when it was destroyed meanwhile. `spreadProps` re-applies the close + * props' `hidden` only when its value changes, so lifting it keeps the panel and + * scrim up until the exit ends. The positioner spans the viewport: inert, it lets + * clicks through to the page while the panel animates out. */ + holdExit() { + const held = [this.panel, this.backdrop]; + for (const el of held) el.hidden = false; + this.exit = holdForExit( + held, + () => { + this.exit = null; + if (this.destroyed) { + this.detach(); + } else if (!this.open) { + for (const el of held) el.hidden = true; + this.setShown(false); + } + }, + { inert: [this.positioner] } + ); + } + detach() { + this.backdrop.remove(); + this.positioner.remove(); + } + /** Closing hands focus back to whatever opened it (Escape, the ✕, hide(), or a + * teardown that outruns the machine's close notification). */ + restoreOpener() { + const opener = this.opener; + this.opener = null; + if (opener?.isConnected) opener.focus({ preventScroll: true }); + } + announce(open2) { + const opener = this.opener === this.panel.ownerDocument.body ? null : this.opener; + announceSurface(this.panel, open2, "dialog", opener); + } get open() { return this.ctrl.connect(this.handle.service).open; } show() { + this.opener = this.panel.ownerDocument.activeElement; this.ctrl.connect(this.handle.service).setOpen(true); } hide() { @@ -1498,10 +1649,16 @@ var Dialog = class { return el?.closest(".vela-popover, .vela-menu") != null; } destroy() { + if (this.wasOpen && !this.open) this.handle.flush(); if (this.open) this.hide(); this.handle.stop(); - this.backdrop.remove(); - this.positioner.remove(); + this.destroyed = true; + if (this.wasOpen) { + this.wasOpen = false; + this.announce(false); + } + this.restoreOpener(); + if (!this.exit) this.detach(); } }; diff --git a/console/frontend/vendor/vela/dist/chunk-ATGTCWHJ.js b/console/frontend/vendor/vela/dist/chunk-HMHA733L.js similarity index 97% rename from console/frontend/vendor/vela/dist/chunk-ATGTCWHJ.js rename to console/frontend/vendor/vela/dist/chunk-HMHA733L.js index ef79e83..8873cc4 100644 --- a/console/frontend/vendor/vela/dist/chunk-ATGTCWHJ.js +++ b/console/frontend/vendor/vela/dist/chunk-HMHA733L.js @@ -1,6 +1,6 @@ -import { deserializeDrawing, chartTypes, rendererLayers, isLineLikeSeries, seriesShownOn, foldBaseModulation, registerChartType, rendererDefaults, getDrawingType, settingsRowVisible, normalizeSettingsRow, Magnifier, TextLabel, Callout, resetDrawingSettings, registerNativeIndicator, chartType, getNativeIndicator, nativeIndicatorDescriptors, nativeInstanceChannel, drawingTypes, settingsRowValueKeys, formatDuration, RegressionChannel, FixedRangeVolumeProfile, DEFAULT_DRAWING_COLOR, SegmentDrawing, ArrowMark, GlyphStamp, RadialFib, FibSpiral, DedekindTessellation, MachFigure, GannSquare, FibRatios, MeasureBox, PositionTool, AnchoredVwap, PatternDrawing, Comment, PriceNote, Signpost, Note, PriceLabel, GANN_SQUARE_ARCS, magnifierTimeframeLabel, lineSegmentIntersection, MAGNIFIER_TIMEFRAME_OPTIONS, GLYPH_OPTIONS, STAMP_SIZE_OPTIONS, LINE_STYLE_OPTIONS, DEDEKIND_CURVATURE_OPTIONS, MACH_NUMBER_OPTIONS, MACH_WAVE_COUNT_OPTIONS, TEXT_SIZE_OPTIONS, createDrawing, inputVisible, seriesInScale, tickerModifierIds, CalloutBase, DIRECTION_OPTIONS, stableSeriesId } from './chunk-EZ5FWVLA.js'; -import { themeTokens, Dialog, closeOpenPopovers, closeWidthPopover, fieldSection, buildFieldControl, fieldSeparator, fieldGrid, fieldRow, CALLOUT_STYLE_ID, CALLOUT_CSS, Popover, blendOver, splitColor, CalloutBubble, Menu, TextArea, NumberInput, buildColorPicker, isPopoverOpen, DatePicker, eventDismissedPopover, toggleSelectList, normalizeDateInput, openPopoverTrigger, fieldGridColumns, FIELD_GAP_PX, STATIC_TOKENS } from './chunk-NELQJCGK.js'; -import { icon, iconAt, withAlpha, WARNING, ACCENT, NEUTRAL, INFO, BULLISH, BEARISH, isDarkColor, injectStyles, SERIES_LINE, CHIP_PLATE, CROSSHAIR, TRADE_EXIT, TRADE_SHORT, TRADE_LONG, iconMarkup, overlayScrollbarCss, SLATE_DEEP, VALID, INVALID, SLATE, FIELD_FOCUS_CSS, FIELD_FOCUS_RING, svg24, svg24Solid } from './chunk-BZQM2XO7.js'; +import { deserializeDrawing, chartTypes, rendererLayers, isLineLikeSeries, seriesShownOn, foldBaseModulation, registerChartType, rendererDefaults, getDrawingType, normalizeTimezone, settingsRowVisible, normalizeSettingsRow, Magnifier, TextLabel, Callout, resetDrawingSettings, registerNativeIndicator, chartType, getNativeIndicator, nativeIndicatorDescriptors, nativeInstanceChannel, drawingTypes, settingsRowValueKeys, TIMEZONES, tzMenuLabel, formatDuration, RegressionChannel, FixedRangeVolumeProfile, DEFAULT_DRAWING_COLOR, SegmentDrawing, ArrowMark, GlyphStamp, RadialFib, FibSpiral, DedekindTessellation, MachFigure, GannSquare, FibRatios, MeasureBox, PositionTool, AnchoredVwap, PatternDrawing, Comment, PriceNote, Signpost, Note, PriceLabel, GANN_SQUARE_ARCS, magnifierTimeframeLabel, lineSegmentIntersection, MAGNIFIER_TIMEFRAME_OPTIONS, GLYPH_OPTIONS, STAMP_SIZE_OPTIONS, LINE_STYLE_OPTIONS, DEDEKIND_CURVATURE_OPTIONS, MACH_NUMBER_OPTIONS, MACH_WAVE_COUNT_OPTIONS, TEXT_SIZE_OPTIONS, createDrawing, inputVisible, seriesInScale, tickerModifierIds, CalloutBase, DIRECTION_OPTIONS, FibRetracement, stableSeriesId } from './chunk-KWI3YDBW.js'; +import { themeTokens, Dialog, closeOpenPopovers, closeWidthPopover, fieldSection, buildFieldControl, fieldSeparator, fieldGrid, fieldRow, CALLOUT_STYLE_ID, CALLOUT_CSS, Popover, blendOver, splitColor, CalloutBubble, Menu, TextArea, NumberInput, buildColorPicker, isPopoverOpen, DatePicker, eventDismissedPopover, toggleSelectList, normalizeDateInput, openPopoverTrigger, fieldGridColumns, FIELD_GAP_PX, STATIC_TOKENS } from './chunk-G7B7ZCBF.js'; +import { icon, iconAt, withAlpha, WARNING, ACCENT, NEUTRAL, INFO, BULLISH, BEARISH, announceSurface, holdForExit, isDarkColor, injectStyles, SERIES_LINE, CHIP_PLATE, CROSSHAIR, TRADE_EXIT, TRADE_SHORT, TRADE_LONG, iconMarkup, overlayScrollbarCss, SLATE_DEEP, VALID, INVALID, SLATE, FIELD_FOCUS_CSS, FIELD_FOCUS_RING, svg24, svg24Solid } from './chunk-VHGACEHO.js'; // src/core/events/EventBus.ts var TypedEventBus = class { @@ -1885,100 +1885,6 @@ var SecondClock = class _SecondClock { } }; -// src/core/timezones.ts -var TIMEZONES = [ - { value: "Etc/UTC", label: "UTC" }, - { value: "Etc/GMT+12", label: "International Date Line West" }, - { value: "Pacific/Pago_Pago", label: "Pago Pago" }, - { value: "Pacific/Honolulu", label: "Honolulu" }, - { value: "Pacific/Marquesas", label: "Marquesas Islands" }, - { value: "America/Anchorage", label: "Anchorage" }, - { value: "America/Los_Angeles", label: "Los Angeles" }, - { value: "America/Phoenix", label: "Phoenix" }, - { value: "America/Denver", label: "Denver" }, - { value: "America/Chicago", label: "Chicago" }, - { value: "America/Mexico_City", label: "Mexico City" }, - { value: "America/New_York", label: "New York" }, - { value: "America/Bogota", label: "Bogot\xE1" }, - { value: "America/Caracas", label: "Caracas" }, - { value: "America/Santiago", label: "Santiago" }, - { value: "America/St_Johns", label: "St. John's" }, - { value: "America/Sao_Paulo", label: "S\xE3o Paulo" }, - { value: "America/Argentina/Buenos_Aires", label: "Buenos Aires" }, - { value: "America/Noronha", label: "Fernando de Noronha" }, - { value: "Atlantic/Azores", label: "Azores" }, - { value: "Atlantic/Reykjavik", label: "Reykjavik" }, - { value: "Europe/London", label: "London" }, - { value: "Europe/Paris", label: "Paris" }, - { value: "Europe/Berlin", label: "Berlin" }, - { value: "Europe/Athens", label: "Athens" }, - { value: "Africa/Cairo", label: "Cairo" }, - { value: "Africa/Johannesburg", label: "Johannesburg" }, - { value: "Europe/Moscow", label: "Moscow" }, - { value: "Europe/Istanbul", label: "Istanbul" }, - { value: "Asia/Tehran", label: "Tehran" }, - { value: "Asia/Dubai", label: "Dubai" }, - { value: "Asia/Kabul", label: "Kabul" }, - { value: "Asia/Karachi", label: "Karachi" }, - { value: "Asia/Kolkata", label: "Mumbai" }, - { value: "Asia/Kathmandu", label: "Kathmandu" }, - { value: "Asia/Dhaka", label: "Dhaka" }, - { value: "Asia/Yangon", label: "Yangon" }, - { value: "Asia/Bangkok", label: "Bangkok" }, - { value: "Asia/Shanghai", label: "Shanghai" }, - { value: "Asia/Hong_Kong", label: "Hong Kong" }, - { value: "Asia/Singapore", label: "Singapore" }, - { value: "Australia/Eucla", label: "Eucla" }, - { value: "Asia/Tokyo", label: "Tokyo" }, - { value: "Asia/Seoul", label: "Seoul" }, - { value: "Australia/Adelaide", label: "Adelaide" }, - { value: "Australia/Sydney", label: "Sydney" }, - { value: "Australia/Lord_Howe", label: "Lord Howe Island" }, - { value: "Pacific/Noumea", label: "Noum\xE9a" }, - { value: "Pacific/Auckland", label: "Auckland" }, - { value: "Pacific/Chatham", label: "Chatham Islands" }, - { value: "Pacific/Apia", label: "Apia" }, - { value: "Pacific/Kiritimati", label: "Kiritimati" } -]; -var EXCHANGE_TIMEZONE = "exchange"; -function isExchangeTimezone(zone) { - return zone === EXCHANGE_TIMEZONE; -} -function resolveTimezone(zone, exchangeZone) { - if (!isExchangeTimezone(zone)) return zone; - return exchangeZone && exchangeZone !== "" ? exchangeZone : "Etc/UTC"; -} -function normalizeTimezone(zone) { - return zone === "UTC" || zone === "Etc/UTC" || zone === "Etc/GMT" ? "Etc/UTC" : zone; -} -function timezoneMenuRows(current) { - const active = normalizeTimezone(current); - const [utc, ...zones] = TIMEZONES.map((t) => ({ value: t.value, label: tzMenuLabel(t.value, t.label), checked: t.value === active })); - return [utc, { value: EXCHANGE_TIMEZONE, label: "Exchange", checked: isExchangeTimezone(current) }, ...zones]; -} -function tzOffset(zone, date = /* @__PURE__ */ new Date()) { - try { - const parts = new Intl.DateTimeFormat("en-US", { timeZone: zone, timeZoneName: "shortOffset" }).formatToParts(date); - const raw = parts.find((p) => p.type === "timeZoneName")?.value ?? ""; - const m = raw.match(/GMT(?:(\+|-)(\d{1,2})(?::(\d{2}))?)?/); - if (!m || !m[1]) return "UTC"; - const sign = m[1] === "-" ? "-" : "+"; - const hrs = m[2] ?? "0"; - const mins = m[3] ?? ""; - return mins ? `UTC${sign}${hrs}:${mins}` : `UTC${sign}${hrs}`; - } catch { - return "UTC"; - } -} -function tzMenuLabel(zone, location) { - if (normalizeTimezone(zone) === "Etc/UTC") return location; - return `(${tzOffset(zone)}) ${location}`; -} -function tzButtonLabel(zone) { - if (normalizeTimezone(zone) === "Etc/UTC") return "UTC"; - return tzOffset(zone); -} - // src/core/drawings/effectiveColor.ts var VALID_FILL = VALID; var INVALID_FILL = INVALID; @@ -2602,6 +2508,7 @@ function chromeHint(text, opts) { // src/renderers/native/drawings/DrawingToolbar.ts var TOOLBAR_WIDTH = 44; var TOOLBAR_COLLAPSED_WIDTH = 16; +var FLYOUT_GAP = 3; var DrawingToolbar = class { constructor(host, theme, onArm, onMagnet = () => { }, onMeasure = () => { @@ -2631,6 +2538,9 @@ var DrawingToolbar = class { // group id (or MAGNET_ID) whose flyout is open this.flyoutCell = null; // the cell the open flyout is anchored to + /** Closed flyouts still playing their exit animation, by owner id — reopening the same + * owner takes its element back instead of stacking a second one on it. */ + this.exitingFlyouts = /* @__PURE__ */ new Map(); this.groupCells = /* @__PURE__ */ new Map(); // the composite cell (hover/active bg + flyout anchor) this.groupIcons = /* @__PURE__ */ new Map(); @@ -2739,6 +2649,7 @@ var DrawingToolbar = class { } destroy() { this.closeFlyout(); + for (const { exit } of [...this.exitingFlyouts.values()]) exit.finish(); for (const dispose of this.tipDisposers.splice(0)) dispose(); this.root.remove(); } @@ -2966,16 +2877,22 @@ var DrawingToolbar = class { * outside-dismiss. Callers fill it with items. */ beginFlyout(ownerId, cell) { const t = this.theme; - const fly = document.createElement("div"); + const back = this.exitingFlyouts.get(ownerId); + if (back) { + this.exitingFlyouts.delete(ownerId); + back.exit.cancel(); + back.fly.replaceChildren(); + } + const fly = back?.fly ?? document.createElement("div"); fly.className = "vela-dtb-flyout"; - fly.style.cssText = `position:absolute;z-index:23;display:flex;flex-direction:column;gap:2px;padding:4px;border-radius:0 8px 8px 0;background:var(--vela-surface-elev);border:1px solid ${this.borderColor};border-left:none;box-shadow:var(--vela-shadow);pointer-events:auto;overflow-y:auto;overscroll-behavior:contain;`; + fly.style.cssText = `position:absolute;z-index:23;display:flex;flex-direction:column;gap:2px;padding:4px;border-radius:var(--vela-radius-md);background:var(--vela-surface);border:1px solid ${this.borderOverride ?? "var(--vela-border-strong)"};box-shadow:var(--vela-shadow);pointer-events:auto;overflow-y:auto;overscroll-behavior:contain;`; applyChromeTokens(fly, t); this.host.appendChild(fly); const r = cell.getBoundingClientRect(); const rootR = this.root.getBoundingClientRect(); const hostR = this.host.getBoundingClientRect(); const top = r.top - hostR.top; - fly.style.left = `${rootR.right - hostR.left - 1}px`; + fly.style.left = `${rootR.right - hostR.left + FLYOUT_GAP}px`; fly.style.top = `${top}px`; fly.style.maxHeight = `${Math.max(120, hostR.height - top - 8)}px`; this.flyout = fly; @@ -2991,6 +2908,7 @@ var DrawingToolbar = class { if (!cell) return; const fly = this.beginFlyout(group.id, cell); const sections = group.sections ?? [{ label: "", tools: group.tools }]; + const badge = sections.some((s) => s.tools.some((tool) => !!tool.icon)); for (let si = 0; si < sections.length; si++) { const section = sections[si]; if (section.label) { @@ -3001,6 +2919,7 @@ var DrawingToolbar = class { fly.appendChild( this.makeFlyoutItem({ icon: tool.icon, + badge, label: tool.label, selected: tool.type === this.active, shortcut: this.shortcuts.get(tool.type), @@ -3013,6 +2932,7 @@ var DrawingToolbar = class { ); } } + announceSurface(fly, true, "menu", cell); } openMagnetFlyout() { const cell = this.magnetCell; @@ -3036,6 +2956,7 @@ var DrawingToolbar = class { }) ); } + announceSurface(fly, true, "menu", cell); } flyoutHeader(text) { const t = this.theme; @@ -3049,21 +2970,24 @@ var DrawingToolbar = class { div.style.cssText = `height:1px;margin:4px 8px;background:${this.borderColor};`; return div; } - /** A flyout row, left to right: optional leading icon, label, a check when it's the selected - * entry, an optional shortcut hint, and — at the far right — the favorite star (tool rows). - * Hover tint is CSS (`.vela-dtb-item:hover`), so navigating the menu stays smooth. */ + /** A flyout row, left to right: optional leading icon badge, label, a check when it's the + * selected entry, an optional shortcut hint, and — at the far right — the favorite star (tool + * rows). Hover tint is CSS (`.vela-dtb-item:hover`), so navigating the menu stays smooth. */ makeFlyoutItem(opts) { const t = this.theme; const item = document.createElement("button"); item.type = "button"; item.className = "vela-dtb-item"; item.setAttribute("aria-label", opts.label); - item.style.cssText = `display:flex;align-items:center;gap:8px;padding:5px 10px 5px 8px;cursor:pointer;color:${t.textColor};border-radius:var(--vela-radius-sm);font:13px ${t.fontFamily};white-space:nowrap;min-width:148px;`; - if (opts.icon) { - const icon2 = document.createElement("span"); - icon2.style.cssText = "width:18px;height:18px;display:flex;align-items:center;justify-content:center;flex:none;"; - icon2.innerHTML = sizedIcon(opts.icon); - item.appendChild(icon2); + const badged = opts.badge === true || !!opts.icon; + const box = badged ? "gap:10px;padding:4px 10px 4px 6px;" : "gap:8px;padding:5px 10px 5px 8px;"; + item.style.cssText = `display:flex;align-items:center;${box}cursor:pointer;color:${t.textColor};border-radius:var(--vela-radius-sm);font:13px ${t.fontFamily};white-space:nowrap;min-width:148px;`; + if (opts.selected) item.dataset.selected = "1"; + if (badged) { + const badge = document.createElement("span"); + badge.className = "vela-dtb-badge"; + if (opts.icon) badge.innerHTML = opts.icon; + item.appendChild(badge); } const label = document.createElement("span"); label.textContent = opts.label; @@ -3104,9 +3028,16 @@ var DrawingToolbar = class { } closeFlyout() { this.starEls.clear(); - if (this.flyout) { - this.flyout.remove(); + const fly = this.flyout; + if (fly) { this.flyout = null; + announceSurface(fly, false, "menu", this.flyoutCell); + const owner = this.flyoutOwnerId ?? ""; + const exit = holdForExit(fly, () => { + if (this.exitingFlyouts.get(owner)?.fly === fly) this.exitingFlyouts.delete(owner); + fly.remove(); + }); + if (exit) this.exitingFlyouts.set(owner, { fly, exit }); this.flyoutCell?.classList.remove("vela-open"); this.flyoutCell = null; this.flyoutOwnerId = null; @@ -3190,6 +3121,11 @@ function ensureStyles() { .vela-dtb[data-collapsed='1'] .vela-dtb-collapse .vela-dtb-hit{width:14px;} .vela-dtb-item{background:transparent;border:none;transition:background var(--vela-dur-fast) ease;} .vela-dtb-item:hover{background:var(--vela-hover-strong);} +.vela-dtb-badge{width:24px;height:24px;padding:3px;box-sizing:border-box;display:flex;align-items:center;justify-content:center;flex:none;border-radius:var(--vela-radius-md);background:var(--vela-hover);border:1px solid var(--vela-border);color:var(--vela-fg-muted);transition:background var(--vela-dur-fast) ease,border-color var(--vela-dur-fast) ease,color var(--vela-dur-fast) ease;} +.vela-dtb-badge:empty{background:transparent;border-color:transparent;} +.vela-dtb-badge svg{width:100%;height:100%;} +.vela-dtb-item:hover .vela-dtb-badge:not(:empty){background:var(--vela-active);color:var(--vela-fg-bright);} +.vela-dtb-item[data-selected='1'] .vela-dtb-badge:not(:empty){background:color-mix(in srgb,var(--vela-fg-bright) 83%,var(--vela-surface));border-color:color-mix(in srgb,var(--vela-fg-bright) 40%,transparent);color:var(--vela-surface);} .vela-dtb-star{width:26px;height:22px;margin:-3px -5px -3px 0;padding:3px 5px;box-sizing:border-box;display:flex;align-items:center;justify-content:center;flex:none;opacity:0;color:inherit;border-radius:var(--vela-radius-sm);transition:opacity .1s ease,color .1s ease,background .1s ease;} .vela-dtb-star svg{width:16px;height:16px;} .vela-dtb-item:hover .vela-dtb-star{opacity:.55;} @@ -4075,7 +4011,10 @@ var LEGEND_ICON_PX2 = 16; var LEGEND_CTL_PX = 18; var LEGEND_ROW_PAD_Y = 2; var LEGEND_ROW_PAD_X = 6; +var LEGEND_LEFT_PX = 10; +var LEGEND_SCALE_GAP_PX = 6; var LEGEND_TITLE_VALUES_GAP_PX = 6; +var LEGEND_VALUES_GAP_PX = 5; var LEGEND_TITLE_STATUS_GAP_PX = 8; var LEGEND_ACTION_GAP_PX = 6; var LEGEND_CTL_CSS = `cursor:pointer;display:inline-flex;align-items:center;justify-content:center;border:none;line-height:0;padding:0;width:${LEGEND_CTL_PX}px;height:${LEGEND_CTL_PX}px;border-radius:3px;box-sizing:border-box;flex:none;`; @@ -4361,14 +4300,15 @@ var InputsUI = class { row.valuesEl.replaceChildren(); return; } - row.valuesEl.style.display = "inline-flex"; + row.valuesEl.style.display = "block"; row.valuesEl.replaceChildren(); - for (const v of row.plotValues) { + row.plotValues.forEach((v, i) => { const span = document.createElement("span"); span.textContent = v.value; span.style.color = v.color; + if (i > 0) span.style.marginLeft = `${LEGEND_VALUES_GAP_PX}px`; row.valuesEl.appendChild(span); - } + }); } // ── legend move/merge (menu + drag) ───────────────────────────────────── /** Open the "Move to" menu for a row, anchored under its move button. */ @@ -4469,7 +4409,7 @@ var InputsUI = class { if (!lg) { lg = document.createElement("div"); lg.dataset.velaPane = paneId; - lg.style.cssText = "position:absolute;left:10px;z-index:5;display:flex;flex-direction:column;align-items:flex-start;gap:0;pointer-events:none;font:12px -apple-system,Segoe UI,sans-serif;"; + lg.style.cssText = `position:absolute;left:${LEGEND_LEFT_PX}px;z-index:5;display:flex;flex-direction:column;align-items:flex-start;gap:0;pointer-events:none;font:12px -apple-system,Segoe UI,sans-serif;`; applyChromeTokens(lg, this.theme); this.positionLegend(lg, paneId); this.container.appendChild(lg); @@ -4481,6 +4421,7 @@ var InputsUI = class { const bounds = this.paneBoundsOf ? this.paneBoundsOf(paneId) : { top: 0, height: Infinity }; lg.toggleAttribute(LEGEND_AT_TOP_ATTR, bounds.top === 0); lg.style.display = bounds.height < 4 || !this.titlesVisible ? "none" : "flex"; + lg.style.maxWidth = `calc(100% - ${(bounds.rightAxis ?? 0) + LEGEND_LEFT_PX + LEGEND_SCALE_GAP_PX}px)`; const collapsed = this.paneCollapse.has(paneId); const masterId = this.paneCollapse.get(paneId) ?? null; for (const row of this.rows.values()) { @@ -4572,7 +4513,7 @@ var InputsUI = class { } ensureDialogStyles(); const el = document.createElement("div"); - el.style.cssText = `pointer-events:auto;display:flex;align-items:center;background:${this.idleRowFill()};border-radius:4px;padding:${LEGEND_ROW_PAD_Y}px ${LEGEND_ROW_PAD_X}px;margin-left:-${LEGEND_ROW_PAD_X}px;min-height:${LEGEND_ROW_MIN_H}px;box-sizing:border-box;color:${this.theme.textColor};user-select:none;-webkit-user-select:none;`; + el.style.cssText = `pointer-events:auto;display:flex;align-items:center;background:${this.idleRowFill()};border-radius:4px;padding:${LEGEND_ROW_PAD_Y}px ${LEGEND_ROW_PAD_X}px;margin-left:-${LEGEND_ROW_PAD_X}px;max-width:calc(100% + ${LEGEND_ROW_PAD_X}px);min-height:${LEGEND_ROW_MIN_H}px;box-sizing:border-box;color:${this.theme.textColor};user-select:none;-webkit-user-select:none;`; el.addEventListener("mouseleave", () => { if (this.selectedId !== id) this.setRowHighlighted(id, false); }); @@ -4600,7 +4541,7 @@ var InputsUI = class { const statusEl = document.createElement("span"); statusEl.style.cssText = "display:none;box-sizing:border-box;flex:none;"; const titleWrap = document.createElement("span"); - titleWrap.style.cssText = "white-space:nowrap;"; + titleWrap.style.cssText = "white-space:nowrap;min-width:0;overflow:hidden;text-overflow:ellipsis;"; titleWrap.addEventListener("mouseenter", () => this.setRowHighlighted(id, true)); const titleEl = document.createElement("span"); titleEl.textContent = title; @@ -4618,7 +4559,7 @@ var InputsUI = class { el.appendChild(calloutsEl); el.appendChild(statusEl); const valuesEl = document.createElement("span"); - valuesEl.style.cssText = `display:none;align-items:center;gap:5px;margin-left:${LEGEND_TITLE_VALUES_GAP_PX}px;white-space:nowrap;font-variant-numeric:tabular-nums;`; + valuesEl.style.cssText = `display:none;flex:1 1 0%;min-width:0;overflow:hidden;text-overflow:ellipsis;margin-left:${LEGEND_TITLE_VALUES_GAP_PX}px;white-space:nowrap;font-variant-numeric:tabular-nums;`; el.appendChild(valuesEl); const controlsEl = document.createElement("span"); controlsEl.style.cssText = `display:none;align-items:center;gap:${LEGEND_ACTION_GAP_PX}px;flex:none;margin-left:${LEGEND_ACTION_GAP_PX}px;`; @@ -5791,15 +5732,23 @@ var Batch = class { this.seg(x + w, y + h, x, y + h, lineWidth, c); this.seg(x, y + h, x, y, lineWidth, c); } - /** Filled circle (triangle fan). */ + /** + * Filled circle (triangle fan), feathered like a line: the rim is padded by {@link AA_PAD} and + * edgeDist runs from 0 at the center to the padded radius at the rim, with edgeHalf = r. The + * distance grows linearly along each spoke, so the shader's line feather gives a round soft edge. + */ circle(cx, cy, r, c, segments = 16) { - let px = cx + r; + const ext = r + AA_PAD; + let px = cx + ext; let py = cy; + this.ensure(segments * 3); for (let i = 1; i <= segments; i += 1) { const a = i / segments * Math.PI * 2; - const nx = cx + Math.cos(a) * r; - const ny = cy + Math.sin(a) * r; - this.tri(cx, cy, c, px, py, c, nx, ny, c); + const nx = cx + Math.cos(a) * ext; + const ny = cy + Math.sin(a) * ext; + this.v(cx, cy, c, 0, r); + this.v(px, py, c, ext, r); + this.v(nx, ny, c, ext, r); px = nx; py = ny; } @@ -5980,7 +5929,7 @@ var WebGL2Backend = class { } mount(canvas) { this.canvas = canvas; - this.gl = canvas.getContext("webgl2", { alpha: true, antialias: true, depth: false, stencil: false, premultipliedAlpha: true }); + this.gl = canvas.getContext("webgl2", { alpha: true, antialias: false, depth: false, stencil: false, premultipliedAlpha: true }); if (!this.gl) return; if (!this.initGL()) { this.gl = null; @@ -7205,6 +7154,11 @@ var InputController = class { /** When true (the default), the separators between stacked panes are draggable to * resize the panes above/below. When false, a press there is a normal data-area pan. */ this.paneResize = true; + /** When true (the default), the user drawings take part in pointer input: they claim a + * press over a drawing or with a tool armed, and see hover moves. When false, every press + * is a plain pan/click and hover leaves them alone; a drawing gesture already under way + * still finishes. */ + this.drawings = true; this.el = null; this.dragging = false; this.moved = false; @@ -7268,18 +7222,18 @@ var InputController = class { this.onModifier = (e) => { if (e.repeat || e.key !== "Shift" && e.key !== "Control" && e.key !== "Meta") return; if (Number.isNaN(this.cursorX)) return; - if (this.dragging && this.region !== "drawing") return; + if (this.dragging ? this.region !== "drawing" : !this.drawings) return; this.deps.drawingsPointerMove?.(this.cursorX, this.cursorY, this.snapMode(e), e.shiftKey, e.ctrlKey || e.metaKey); }; this.onDown = (e) => { if (e.button === 1) { const { x: x2, y: y2 } = this.local(e); - this.middleDeleted = this.deps.drawingsDeleteAt?.(x2, y2) ?? false; + this.middleDeleted = this.drawings && (this.deps.drawingsDeleteAt?.(x2, y2) ?? false); if (this.middleDeleted) e.preventDefault(); return; } if (e.button === 2) { - this.rightCancelled = this.deps.drawingsCancelPlacement?.() ?? false; + this.rightCancelled = this.drawings && (this.deps.drawingsCancelPlacement?.() ?? false); if (this.rightCancelled) e.preventDefault(); return; } @@ -7301,20 +7255,20 @@ var InputController = class { this.startY = y; this.prevPressDrawing = this.lastPressDrawing; this.lastPressDrawing = false; - if (this.deps.drawingsClaim?.(x, y)) { + if (this.drawings && this.deps.drawingsClaim?.(x, y)) { this.region = "drawing"; this.lastPressDrawing = true; this.deps.drawingsPointerDown?.(x, y, this.snapMode(e), e.shiftKey, e.ctrlKey || e.metaKey); this.capture(e.pointerId); return; } - if (e.shiftKey && this.regionAt(x, y) === "data" && this.deps.drawingsMeasureStart?.(x, y, this.snapMode(e))) { + if (this.drawings && e.shiftKey && this.regionAt(x, y) === "data" && this.deps.drawingsMeasureStart?.(x, y, this.snapMode(e))) { this.region = "drawing"; this.lastPressDrawing = true; this.capture(e.pointerId); return; } - if ((e.ctrlKey || e.metaKey) && this.regionAt(x, y) === "data" && this.deps.drawingsMarqueeStart?.(x, y)) { + if (this.drawings && (e.ctrlKey || e.metaKey) && this.regionAt(x, y) === "data" && this.deps.drawingsMarqueeStart?.(x, y)) { this.region = "drawing"; this.lastPressDrawing = true; this.capture(e.pointerId); @@ -7391,7 +7345,7 @@ var InputController = class { const drawCursor = this.deps.drawingsCursor?.(x, y); const r = this.regionAt(x, y); this.el.style.cursor = drawCursor ?? (r === "price" ? "ns-resize" : r === "time" ? "ew-resize" : r === "separator" ? "row-resize" : ""); - this.deps.drawingsPointerMove?.(x, y, this.snapMode(e), e.shiftKey, e.ctrlKey || e.metaKey); + if (this.drawings) this.deps.drawingsPointerMove?.(x, y, this.snapMode(e), e.shiftKey, e.ctrlKey || e.metaKey); } if (e.pointerType !== "touch") this.deps.onPointerMove(x, y); }; @@ -7432,7 +7386,7 @@ var InputController = class { this.deps.drawingsPointerUp?.(x, y, this.snapMode(e)); } else if (tapRelease && this.region === "data") { this.deps.onClick(x, y); - } else if (this.dragging && this.region === "data") { + } else if (this.dragging && this.region === "data" && wasTouch) { const stale = e.timeStamp - this.lastT > FLING_STALE_MS; if (!stale && Math.abs(this.vx) > FLING_MIN_SPEED) { const pitch = this.deps.getCoords().pxPerBar(); @@ -7633,7 +7587,7 @@ var InputController = class { } /** Shared double-click / double-tap routing, by the region under the point. */ doubleActivate(x, y) { - if (this.deps.drawingsDblClick?.(x, y)) return; + if (this.drawings && this.deps.drawingsDblClick?.(x, y)) return; const region = this.regionAt(x, y); if (region === "price") this.deps.resetPriceScale(x, y); else if (region === "separator") this.deps.resetPaneSize(y); @@ -9683,10 +9637,13 @@ function priceTicks(min, max, target = 6) { const norm = raw / mag; const step = (norm < 1.5 ? 1 : norm < 3 ? 2 : norm < 7 ? 5 : 10) * mag; const decimals = Math.max(0, -Math.floor(Math.log10(step)) + 1); - const out = []; const start = Math.ceil(min / step) * step; - for (let v = start; v <= max + step * 1e-6; v += step) { - out.push(Number(v.toFixed(decimals))); + if (!(step > 0) || start + step === start) return []; + const count = Math.floor((max - start) / step + 1e-6) + 1; + if (!(count > 0) || count > 1e3) return []; + const out = []; + for (let i = 0; i < count; i += 1) { + out.push(Number((start + i * step).toFixed(decimals))); } return out; } @@ -9884,6 +9841,100 @@ function calendarTicks(zFrom, zTo, months, offsetMs) { return out; } +// src/renderers/native/chrome/priceAxisTicks.ts +var PriceAxisTickSource = class { + constructor() { + this.fn = null; + this.memo = /* @__PURE__ */ new WeakMap(); + this.warned = false; + } + /** The host function, or null for the built-in ticks. */ + get hook() { + return this.fn; + } + /** Set (or clear) the host function. Drops every memoized result, so setting the same + * function again recomputes — how a host refreshes ticks that depend on its own state. */ + setHook(fn) { + this.fn = fn; + this.memo = /* @__PURE__ */ new WeakMap(); + } + /** The pane's master-scale ticks for this frame. An unscaled pane (`axisFormat: 'none'`) + * gets none, and the host is never asked for it. */ + ticksFor(scene, pane, coords) { + const format = pane.axisFormat; + if (format === "none") return []; + const pct = percentScaleFor(scene, pane); + const height = pane.bounds.height; + const fn = this.fn; + if (!fn || !(height > 0)) return paneAxisTicks(pane.scale, height, pct, scene.priceMintick, format); + const s = pane.scale; + const m = this.memo.get(pane); + const fontSize = scene.style.fontSize; + if (m && m.kind === pane.kind && m.min === s.min && m.max === s.max && m.log === !!s.log && m.invert === !!s.invert && m.height === height && m.baseline === pct?.baseline && m.indexed === !!pct?.indexed && m.mintick === scene.priceMintick && m.format === format && m.fontSize === fontSize) { + return m.ticks; + } + const defaults = paneAxisTicks(s, height, pct, scene.priceMintick, format); + const ticks = this.callHook(fn, scene, pane, coords, defaults, pct?.baseline, pct ? pct.indexed ? "indexed" : "percent" : "price"); + this.memo.set(pane, { + kind: pane.kind, + min: s.min, + max: s.max, + log: !!s.log, + invert: !!s.invert, + height, + baseline: pct?.baseline, + indexed: !!pct?.indexed, + mintick: scene.priceMintick, + format, + fontSize, + ticks + }); + return ticks; + } + callHook(fn, scene, pane, coords, defaults, baseline, mode) { + const scale = { min: pane.scale.min, max: pane.scale.max, log: !!pane.scale.log, invert: !!pane.scale.invert }; + const bounds = { top: 0, height: pane.bounds.height }; + const ctx = { + pane: { id: pane.id, kind: pane.kind }, + min: Math.min(scale.min, scale.max), + max: Math.max(scale.min, scale.max), + log: !!scale.log, + height: bounds.height, + mode, + baseline, + mintick: scene.priceMintick, + fontSize: scene.style.fontSize, + priceToY: (price) => coords.priceToY(price, scale, bounds), + defaults + }; + let out; + try { + out = fn(ctx); + } catch (err) { + this.warnOnce("threw", err); + return defaults; + } + if (out == null) return defaults; + if (!Array.isArray(out)) { + this.warnOnce("returned a non-array", out); + return defaults; + } + const ticks = []; + for (const t of out) { + if (!t || typeof t !== "object") continue; + const { price, label, major } = t; + if (typeof price !== "number" || !Number.isFinite(price) || typeof label !== "string") continue; + ticks.push(typeof major === "boolean" ? { price, label, major } : { price, label }); + } + return ticks; + } + warnOnce(what, detail) { + if (this.warned) return; + this.warned = true; + console.warn(`[vela] the priceAxisTicks function ${what} \u2014 the default ticks are used instead.`, detail); + } +}; + // src/renderers/native/chrome/countdown.ts function countdownText(barOpen, barMs, now2) { if (!(barMs > 0)) return null; @@ -10236,8 +10287,11 @@ function standaloneSvg(markup, ink, px) { } // src/renderers/native/chrome/ChromeRenderer.ts +var MINOR_LABEL_ALPHA = 0.5; var ChromeRenderer = class { - constructor() { + /** `axisTicks` is shared with the backdrop layer, so price labels and gridlines agree. */ + constructor(axisTicks = new PriceAxisTickSource()) { + this.axisTicks = axisTicks; this.canvas = null; this.ctx = null; // The color for axis tick labels — the host-passed surface text, set each frame in render(). @@ -10342,7 +10396,8 @@ var ChromeRenderer = class { this.drawTimeAxis(ctx, scene, coords, theme, dataW, dataH, fullH); this.drawMarkLane(ctx, scene, coords, theme, dataW, dataH); } - /** The timeline-mark lane — after the axis, so the tokens read over the plot's bottom edge. */ + /** The timeline-mark lane — after the axis, so the tokens read over the plot's bottom edge, + * but clipped to the data area so a glyph on the edge bar never paints over the price scale. */ drawMarkLane(ctx, scene, coords, theme, dataW, dataH) { if (!scene.marks.visible || scene.timelineMarks.length === 0) { this.markLayout = { glyphs: [], stacks: /* @__PURE__ */ new Map() }; @@ -10360,6 +10415,10 @@ var ChromeRenderer = class { expanded: scene.marksExpandedStack }); const nowMs = typeof performance !== "undefined" ? performance.now() : Date.now(); + ctx.save(); + ctx.beginPath(); + ctx.rect(0, 0, dataW, dataH); + ctx.clip(); paintMarkLane(ctx, this.markLayout, { axisY: dataH, background: theme.background, @@ -10373,6 +10432,7 @@ var ChromeRenderer = class { flashKey: scene.marksFlash && scene.marksFlash.until > nowMs ? scene.marksFlash.key : null, nowMs }); + ctx.restore(); } barTimes(scene) { if (this.barTimesSrc !== scene.bars || this.barTimesCache.length !== scene.bars.length) { @@ -10429,13 +10489,19 @@ var ChromeRenderer = class { if (!scene.showAxisLabels) return; ctx.fillStyle = this.axisTextColor; ctx.textAlign = "left"; + const font = `${scene.style.fontSize}px ${theme.fontFamily}`; + const majorFont = `600 ${font}`; + const alpha = ctx.globalAlpha; for (const pane of panes) { if (pane.collapsed) continue; - const pct = percentScaleFor(scene, pane); - for (const t of paneAxisTicks(pane.scale, pane.bounds.height, pct, scene.priceMintick, pane.axisFormat)) { + for (const t of this.axisTicks.ticksFor(scene, pane, coords)) { const y = coords.priceToY(t.price, pane.scale, pane.bounds); if (y < pane.bounds.top + 6 || y > pane.bounds.top + pane.bounds.height - 4) continue; + if (t.major === true) ctx.font = majorFont; + else if (t.major === false) ctx.globalAlpha = alpha * MINOR_LABEL_ALPHA; ctx.fillText(t.label, dataW + 6, y); + if (t.major === true) ctx.font = font; + else if (t.major === false) ctx.globalAlpha = alpha; } if (pane.axisBands) { for (const b of pane.axisBands) { @@ -10677,15 +10743,23 @@ var CrosshairRenderer = class { constructor() { this.canvas = null; this.ctx = null; + this.shade = null; } mount(canvas) { this.canvas = canvas; this.ctx = canvas.getContext("2d"); } + /** The plot area the last frame veiled for `crosshairOverride.shadeRight` — from the + * picked bar's right edge to the price scale, full plot height (the union when both the + * local and a synced crosshair veil) — or null when no veil was painted. */ + get shadeRightArea() { + return this.shade; + } /** Clear the cursor canvas and (re)draw the crosshair lines + axis chips. The optional * `separatorHoverY` highlights the draggable pane separator under the cursor; * `external` is a SYNCED ghost crosshair (another chart's pointer, pixel-resolved). */ render(scene, coords, theme, separatorHoverY = null, external = null) { + this.shade = null; const ctx = this.ctx; const canvas = this.canvas; if (!ctx || !canvas) return; @@ -10708,12 +10782,7 @@ var CrosshairRenderer = class { const x = crisp(coords.logicalToX(logical), ov?.width ?? cs.width); if (vertical && ov?.shadeRight) { const from = Math.max(0, Math.round(coords.logicalToX(logical + 0.5))); - if (from < dataW) { - ctx.fillStyle = ov.shadeRight.color; - ctx.globalAlpha = ov.shadeRight.opacity ?? 1; - ctx.fillRect(from, 0, dataW - from, dataH); - ctx.globalAlpha = 1; - } + if (from < dataW) this.paintShade(ctx, ov.shadeRight, from, dataW, dataH); } ctx.strokeStyle = ov?.color ?? cs.color ?? theme.textColor; ctx.lineWidth = ov?.width ?? cs.width; @@ -10749,6 +10818,7 @@ var CrosshairRenderer = class { destroy() { this.canvas = null; this.ctx = null; + this.shade = null; } /** The synced ghost: a dimmed vertical line at the bar the renderer resolved as * CONTAINING the foreign time (+ horizontal line when a comparable price came @@ -10768,12 +10838,7 @@ var CrosshairRenderer = class { if (ov?.vertical === false) return; if (ov?.shadeRight) { const from = Math.max(0, Math.round(coords.logicalToX(Math.round(coords.xToLogical(ext.x)) + 0.5))); - if (from < dataW) { - ctx.fillStyle = ov.shadeRight.color; - ctx.globalAlpha = ov.shadeRight.opacity ?? 1; - ctx.fillRect(from, 0, dataW - from, dataH); - ctx.globalAlpha = 1; - } + if (from < dataW) this.paintShade(ctx, ov.shadeRight, from, dataW, dataH); } if (ext.line === false || x < 0 || x > dataW) return; ctx.font = `${scene.style.fontSize}px ${theme.fontFamily}`; @@ -10809,6 +10874,15 @@ var CrosshairRenderer = class { this.chip(ctx, x, dataH + 1, formatTimeStamp(ext.time, scene.timezone, coords.barInterval), chipBg, "center", true, theme.background); ctx.globalAlpha = 1; } + /** Paint the `shadeRight` veil from `from` to the price scale and record the veiled area. */ + paintShade(ctx, shade, from, dataW, dataH) { + ctx.fillStyle = shade.color; + ctx.globalAlpha = shade.opacity ?? 1; + ctx.fillRect(from, 0, dataW - from, dataH); + ctx.globalAlpha = 1; + const x = this.shade ? Math.min(this.shade.x, from) : from; + this.shade = { x, width: dataW - x, height: dataH }; + } /** A soft band + a brighter crisp center line over the hovered separator, so it reads as * a draggable handle (the cursor is already `row-resize`). Spans the full width (data + * scale gutter) to match the separator itself. Theme-derived (textColor). */ @@ -13846,6 +13920,12 @@ var DrawingInteraction = class { activeDragId() { return this.state.kind === "pressed" && this.state.moved ? this.state.id : null; } + /** The store drawings a live drag is moving — the pressed one and its riders — or none + * before the drag passes the slop. A Ctrl-drag moves copies, so its sources stay put. */ + movingIds() { + if (this.state.kind !== "pressed" || !this.state.moved || this.state.clones) return /* @__PURE__ */ new Set(); + return /* @__PURE__ */ new Set([this.state.id, ...this.state.riders.map((r) => r.id)]); + } /** The drawing under a press that has not been released yet (drag or click undecided), or null. */ pressedId() { return this.state.kind === "pressed" ? this.state.id : null; @@ -14220,15 +14300,16 @@ var DrawingSettingsDialog = class { } open(drawing, actions, kind) { this.close(); - const snapshot = clonePlain(drawing.serialize()); + const live = actions.resolve() ?? drawing; + const snapshot = clonePlain(live.serialize()); const grid = fieldGrid({ variant: "inputs" }); grid.style.padding = "16px 20px"; grid.style.overflowY = "auto"; grid.style.overflowX = "hidden"; grid.style.flex = "1 1 auto"; - if (kind === "position" && drawing instanceof PositionTool) this.buildPosition(grid, drawing, actions); - else if (kind === "frvp" && drawing instanceof FixedRangeVolumeProfile) this.buildFrvp(grid, drawing, actions); - else if (kind === "levels") this.buildLevels(grid, drawing, actions); + if (kind === "position" && live instanceof PositionTool) this.buildPosition(grid, live, actions); + else if (kind === "frvp" && live instanceof FixedRangeVolumeProfile) this.buildFrvp(grid, live, actions); + else if (kind === "levels") this.buildLevels(grid, live, actions); else return; const ui = new Dialog({ host: this.host, @@ -14504,6 +14585,17 @@ var DrawingSettingsDialog = class { } })); } + if (drawing instanceof FibRetracement) { + const fib = drawing; + grid.appendChild(fieldRow({ + label: "Reverse", + bool: true, + toggle: { + checked: fib.reverse, + onChange: (v) => actions.patch({ reverse: v }) + } + })); + } levels.forEach((lv, i) => { const row = document.createElement("div"); row.className = "vela-field-span"; @@ -14864,7 +14956,7 @@ var DrawingSettingsPopup = class { this.reposition(); return; } - const text = drawing.text; + const text = (actions.resolve() ?? drawing).text; const panel = document.createElement("div"); panel.style.cssText = `padding:6px;border-top:1px solid var(--vela-border);display:flex;flex-direction:column;gap:4px;`; const ta = new TextArea({ @@ -15657,6 +15749,8 @@ var UserDrawingController = class { this.drawings = []; /** Ids painted on an interleave layer this frame — the top canvas paints only their handles. */ this.sliced = /* @__PURE__ */ new Set(); + /** Interleaved drawings mid-drag: painted on the top canvas, left out of their slice. */ + this.lifted = /* @__PURE__ */ new Set(); /** Cached slice canvases, keyed `paneId|beforeZ`, reused across frames to avoid churn. */ this.sliceCache = /* @__PURE__ */ new Map(); /** Series boundaries per pane as of the last `prepareSlices` — lets a repaint between data @@ -15744,7 +15838,7 @@ var UserDrawingController = class { selectedIds: () => this.selectedIds, emit: (i) => this.emit(i), changed: () => { - this.invalidateSlices(); + this.syncLift(); this.render(); }, openSettings: (id, x, y) => this.openSettingsById(id, x, y), @@ -16033,6 +16127,12 @@ var UserDrawingController = class { this.render(); } } + /** Drop the hover (its handles) — the pointer no longer reaches the drawings. */ + clearHover() { + if (this.hoveredId == null) return; + this.hoveredId = null; + this.render(); + } pointerUp(x, y, snap = "off") { if (this.eraserMode) { this.erasing = false; @@ -16370,6 +16470,20 @@ var UserDrawingController = class { /** A drawing that paints inside the series stack changed (content, not hover): its pixels * live in the backend composite, so this layer alone can't show the change — ask for a * data frame, which re-runs `prepareSlices` before the backend composites. */ + /** A drawing being dragged leaves its interleave slice for the top canvas, so each pointer + * move repaints one 2D layer instead of re-rasterizing and re-uploading a plot-sized slice + * texture through the data frame. The slices rebuild once as the drag starts and once as it + * ends (release, cancel), when the lifted set changes. */ + syncLift() { + const moving = this.interaction.movingIds(); + let same = moving.size === this.lifted.size; + if (same) { + for (const id of moving) if (!this.lifted.has(id)) same = false; + } + if (same) return; + this.lifted = new Set(moving); + this.invalidateSlices(); + } invalidateSlices() { if (this.sliced.size > 0 || this.drawings.some((d) => this.isInterleaved(d))) this.deps.requestDataPaint(); } @@ -16388,7 +16502,7 @@ var UserDrawingController = class { const theme = this.deps.theme(); const buckets = /* @__PURE__ */ new Map(); for (const d of this.drawings) { - if (!d.visible) continue; + if (!d.visible || this.lifted.has(d.id)) continue; const beforeZ = sliceKeyFor(d.zIndex, this.lastBounds.get(d.paneId) ?? []); if (beforeZ === null) continue; const key = `${d.paneId}|${beforeZ}`; @@ -16440,8 +16554,9 @@ var UserDrawingController = class { mutedLabel: edited instanceof TextLabel ? edited.id : null }; this.painter.seriesLook = this.deps.seriesLook(); - this.painter.paintAll(ctx, this.drawings.filter((d) => !this.isInterleaved(d)), proj, this.deps.theme(), targets); - this.painter.paintHighlights(ctx, this.drawings.filter((d) => this.isInterleaved(d)), proj, handleIdsFor(targets)); + const onTop = (d) => !this.isInterleaved(d) || this.lifted.has(d.id); + this.painter.paintAll(ctx, this.drawings.filter(onTop), proj, this.deps.theme(), targets); + this.painter.paintHighlights(ctx, this.drawings.filter((d) => !onTop(d)), proj, handleIdsFor(targets)); const clones = this.interaction.dragClones(); if (clones) this.painter.paintAll(ctx, clones, proj, this.deps.theme(), { selected: new Set(clones.map((c) => c.id)) }); this.layoutTextEditor(); @@ -17008,9 +17123,10 @@ function computePaneScale(models, bars, includeCandles, i0, i1, drawings, log = consider(drawings.max); } if (min === Infinity || max === -Infinity) return { min: 0, max: 1 }; - if (min === max) { - const pad = Math.abs(min) * 0.1 || 1; - return { min: min - pad, max: max + pad, log: log && min - pad > 0 }; + if (max - min <= Math.max(Math.abs(min), Math.abs(max)) * 1e-12) { + const mid = (min + max) / 2; + const pad = Math.abs(mid) * 0.1 || 1; + return { min: mid - pad, max: mid + pad, log: log && mid - pad > 0 }; } const content = Math.max(0.1, 1 - (margins.top + margins.bottom) / 100); const above = margins.top / 100 / content; @@ -17514,7 +17630,9 @@ function bandEdgeSlot(logical) { return Math.ceil(logical) - 0.5; } var BackdropRenderer = class { - constructor() { + /** `axisTicks` is shared with the chrome layer, so gridlines and price labels agree. */ + constructor(axisTicks = new PriceAxisTickSource()) { + this.axisTicks = axisTicks; this.canvas = null; this.ctx = null; } @@ -17591,9 +17709,8 @@ var BackdropRenderer = class { if (scene.showGrid && gridHorz.visible && !pane.collapsed) { ctx.globalAlpha = gridAlpha; ctx.strokeStyle = horzColor; - const pct = percentScaleFor(scene, pane); ctx.beginPath(); - for (const t of paneAxisTicks(pane.scale, pane.bounds.height, pct, void 0, pane.axisFormat)) { + for (const t of this.axisTicks.ticksFor(scene, pane, coords)) { const y = Math.round(coords.priceToY(t.price, pane.scale, pane.bounds)) + 0.5; if (y < pane.bounds.top || y > pane.bounds.top + pane.bounds.height) continue; ctx.moveTo(0, y); @@ -18183,8 +18300,16 @@ var NativeRenderer = class { this.toolbarGutter = 0; // px reserved on the left for the docked drawings toolbar (0 when hidden) this.mountContainer = null; + /** The host-styleable twin of the `shadeRight` veil (`.vela-shade-right`), directly under + * the cursor canvas; hidden whenever the crosshair layer paints no veil. */ + this.shadeRightEl = null; + /** The veil geometry last written to {@link shadeRightEl} ('' = hidden) — the DOM is + * touched only when it changes, never on a plain pointer move. */ + this.shadeRightSig = ""; this.userDrawings = null; - this.backdropRenderer = new BackdropRenderer(); + /** One price-axis tick source for the gridlines (backdrop) and the labels (chrome). */ + this.priceAxisTicks = new PriceAxisTickSource(); + this.backdropRenderer = new BackdropRenderer(this.priceAxisTicks); this.volumeRenderer = new VolumeRenderer(); /** SDK renderer layers instantiated at mount ({@link registerRendererLayer}). */ /** @@ -18217,7 +18342,7 @@ var NativeRenderer = class { this.backendMode = "auto"; this.glowAmount = 0; // WebGL2 neon-glow intensity (canvas2d ignores it) - this.chrome = new ChromeRenderer(); + this.chrome = new ChromeRenderer(this.priceAxisTicks); /** Prepaints each indicator's Pine drawings into interleave slices at the model's z. */ this.indicatorSlices = new IndicatorDrawingSlices(); /** Hover tooltips for Pine labels (canvas hit-rects collected by the chrome layer). */ @@ -18334,6 +18459,8 @@ var NativeRenderer = class { // pane just below it this.resizeSplitStart = null; // the two panes' shared span when the drag began + /** The user drawings take part in pointer input (the runtime `drawingsInteractive` feature). */ + this.drawingsInteractive = true; this.hoverSeparatorY = null; // pixel y of the separator under the cursor (drives its hover highlight) // ── pane management (merge / reorder / collapse / maximize) ── @@ -18389,8 +18516,9 @@ var NativeRenderer = class { this.toggleVisibleCbs = /* @__PURE__ */ new Set(); this.moveIndicatorCbs = /* @__PURE__ */ new Set(); this.priceStyleCbs = /* @__PURE__ */ new Set(); + this.priceStyleWillChangeCbs = /* @__PURE__ */ new Set(); this.name = "native"; - this.features = ["logScale", "currentPriceLine", "priceLabel", "countdown", "upColor", "downColor", "glow", "animZoom", "animPan", "animScroll", "animAutoscale", "animLiveBar", "intro", "zoomAnchor", "axisDrag", "paneResize", "candleZOrder", "candleVisible", "seriesOrder", "highlights", "sessionZones", "gridlines", "axisLabels", "scaleMode", "invertScale", "paneScales", "autoScale", "timezone", "keyboard", "historyChords", "priceStyle", "priceBaseline", "baselinePrice", "settings", "attribution", "dialogHost", "tradeMarkers", "marks", "indicatorTitles", "indicatorValues", "crosshairOverride"]; + this.features = ["logScale", "currentPriceLine", "priceLabel", "countdown", "upColor", "downColor", "glow", "animZoom", "animPan", "animScroll", "animAutoscale", "animLiveBar", "intro", "zoomAnchor", "axisDrag", "paneResize", "candleZOrder", "candleVisible", "seriesOrder", "highlights", "sessionZones", "gridlines", "axisLabels", "scaleMode", "invertScale", "paneScales", "autoScale", "timezone", "keyboard", "historyChords", "priceStyle", "priceBaseline", "baselinePrice", "settings", "attribution", "dialogHost", "tradeMarkers", "marks", "indicatorTitles", "indicatorValues", "crosshairOverride", "drawingsInteractive", "priceAxisTicks"]; /** Track cursor proximity to the scroll button on the plot (bubbles from the button too, * so moving onto the button doesn't count as leaving). */ this.onScrollProximityMove = (e) => { @@ -18434,6 +18562,7 @@ var NativeRenderer = class { this.scene.priceStyle = opts.priceStyle; this.scene.basePainting = basePaintingOf(opts.priceStyle); this.scene.candleOverride = candleOverrideFor(opts.priceStyle, this.scene.style.chartTypes); + if (typeof opts.priceAxisTicks === "function") this.priceAxisTicks.setHook(opts.priceAxisTicks); } this.theme = this.deriveTheme(DARK_THEME); } @@ -18572,6 +18701,15 @@ var NativeRenderer = class { case "crosshairOverride": this.scene.crosshairOverride = sanitizeCrosshairOverride(value); break; + case "drawingsInteractive": + this.drawingsInteractive = value !== false; + if (this.input) this.input.drawings = this.drawingsInteractive; + if (!this.drawingsInteractive) this.userDrawings?.clearHover(); + return; + // affects the next gesture only — clearHover repaints what it drops + case "priceAxisTicks": + this.priceAxisTicks.setHook(typeof value === "function" ? value : null); + break; case "keyboard": this.setKeyboardEnabled(Boolean(value)); return; @@ -18687,6 +18825,10 @@ var NativeRenderer = class { return { visible: this.scene.marks.visible, groups: { ...this.scene.marks.groups } }; case "crosshairOverride": return this.scene.crosshairOverride ? { ...this.scene.crosshairOverride } : null; + case "drawingsInteractive": + return this.drawingsInteractive; + case "priceAxisTicks": + return this.priceAxisTicks.hook; case "keyboard": return this.keyboardEnabled; case "historyChords": @@ -19360,6 +19502,12 @@ var NativeRenderer = class { Object.assign(this.drawingsCanvas.style, { position: "absolute", inset: "0", width: "100%", height: "100%", pointerEvents: "none" }); this.cursorCanvas = document.createElement("canvas"); Object.assign(this.cursorCanvas.style, { position: "absolute", inset: "0", width: "100%", height: "100%", pointerEvents: "none" }); + this.shadeRightEl = document.createElement("div"); + this.shadeRightEl.className = "vela-shade-right"; + this.shadeRightEl.setAttribute("aria-hidden", "true"); + this.shadeRightEl.hidden = true; + Object.assign(this.shadeRightEl.style, { position: "absolute", top: "0", left: "0", width: "0", height: "0", pointerEvents: "none", display: "none" }); + this.shadeRightSig = ""; this.overlayRoot = document.createElement("div"); Object.assign(this.overlayRoot.style, { position: "absolute", inset: "0", pointerEvents: "none" }); this.plot = document.createElement("div"); @@ -19367,7 +19515,7 @@ var NativeRenderer = class { this.extLayers = rendererLayers().map((def) => ({ def, instance: def.create(), canvas: this.createLayerCanvas(), channel: def.id, owner: null })); const below = this.extLayers.filter((l) => l.def.placement === "below-data").map((l) => l.canvas); const above = this.extLayers.filter((l) => l.def.placement !== "below-data").map((l) => l.canvas); - this.plot.append(this.backdropCanvas, ...below, this.dataCanvas, this.volumeCanvas, this.vpvrCanvas, ...above, this.chromeCanvas, this.drawingsCanvas, this.cursorCanvas, this.overlayRoot); + this.plot.append(this.backdropCanvas, ...below, this.dataCanvas, this.volumeCanvas, this.vpvrCanvas, ...above, this.chromeCanvas, this.drawingsCanvas, this.shadeRightEl, this.cursorCanvas, this.overlayRoot); this.layerOrderSig = ""; this.wrapper.appendChild(this.plot); this.factoryConfig = this.getConfig(); @@ -19425,13 +19573,14 @@ var NativeRenderer = class { drawingsPointerDown: (x, y, snap, shift2, mod) => this.userDrawings?.pointerDown(x, y, snap, shift2, mod), drawingsPointerMove: (x, y, snap, shift2, mod) => this.userDrawings?.pointerMove(x, y, snap, shift2, mod), drawingsPointerUp: (x, y, snap) => this.userDrawings?.pointerUp(x, y, snap), - drawingsCursor: (x, y) => this.userDrawings?.cursorAt(x, y) ?? (this.chrome.markGlyphAt(x, y) ? "pointer" : null), + drawingsCursor: (x, y) => (this.drawingsInteractive ? this.userDrawings?.cursorAt(x, y) : null) ?? (this.chrome.markGlyphAt(x, y) ? "pointer" : null), drawingsDblClick: (x, y) => this.userDrawings?.dblClick(x, y) ?? false, drawingsClearTransient: () => this.userDrawings?.clearTransient() }); this.input.rightEdgeZoom = this.zoomAnchorMode === "right"; this.input.axisDrag = this.axisDragEnabled; this.input.paneResize = this.paneResizeEnabled; + this.input.drawings = this.drawingsInteractive; this.input.attach(this.dataCanvas); if (this.settingsEnabled) this.setSettingsEnabled(true); this.syncCountdownTimer(); @@ -19740,6 +19889,8 @@ var NativeRenderer = class { this.backend.destroy(); this.chrome.destroy(); this.crosshairLayer.destroy(); + this.shadeRightEl?.remove(); + this.shadeRightEl = null; this.attributionEl?.remove(); this.attributionEl = null; this.mountContainer?.style.removeProperty("--vela-toolbar-gutter"); @@ -20086,14 +20237,21 @@ var NativeRenderer = class { this.priceStyleCbs.add(cb); return () => this.priceStyleCbs.delete(cb); } + onPriceStyleWillChange(cb) { + this.priceStyleWillChangeCbs.add(cb); + return () => this.priceStyleWillChangeCbs.delete(cb); + } /** * THE single write path for the base price style at runtime (feature set / settings dialog / - * config template — the constructor seeds the field directly, pre-listeners). Updates the - * scene, eases any reveal layer toward the new style's target, and notifies the core — - * which owns the DATA side of styles that need one (a chart type's SeriesDataEngine). + * config template — the constructor seeds the field directly, pre-listeners). Announces the + * switch while the scene still holds the old style (a listener may paint/capture that frame), + * then updates the scene, eases any reveal layer toward the new style's target, and notifies + * the core — which owns the DATA side of styles that need one (a chart type's SeriesDataEngine). */ setPriceStyle(style) { if (style === this.scene.priceStyle) return; + const from = this.scene.priceStyle; + for (const cb of this.priceStyleWillChangeCbs) cb(from, style); this.scene.priceStyle = style; this.scene.basePainting = basePaintingOf(style); this.scene.candleOverride = candleOverrideFor(style, this.scene.style.chartTypes); @@ -20323,7 +20481,7 @@ var NativeRenderer = class { if (this.easeLiveBar(dtMs)) active = true; this.skeletonClockMs += dtMs; this.paintData(); - this.crosshairLayer.render(this.scene, this.coords, this.theme, this.hoverSeparatorY, this.externalCrossPx()); + this.renderCrosshairLayer(); this.updateLegendValues(); this.emitViewportChange(); return active; @@ -20898,10 +21056,31 @@ var NativeRenderer = class { this.chrome.render(this.scene, this.coords, this.theme, this.axisSurface()); this.trackMarkPopover(); } - this.crosshairLayer.render(this.scene, this.coords, this.theme, this.hoverSeparatorY, this.externalCrossPx()); + this.renderCrosshairLayer(); if (!repaintsData(level) && this.paintedData) this.repaintCursorLayers(); this.updateLegendValues(); } + /** Repaint the L2 crosshair canvas and keep the `.vela-shade-right` element on the veil it painted. */ + renderCrosshairLayer() { + this.crosshairLayer.render(this.scene, this.coords, this.theme, this.hoverSeparatorY, this.externalCrossPx()); + this.syncShadeRight(); + } + /** Position (or hide) the `.vela-shade-right` element over the veil of the last crosshair frame. */ + syncShadeRight() { + const el = this.shadeRightEl; + if (!el) return; + const area = this.crosshairLayer.shadeRightArea; + const sig = area ? `${area.x},${area.width},${area.height}` : ""; + if (sig === this.shadeRightSig) return; + this.shadeRightSig = sig; + if (!area) { + el.hidden = true; + el.style.display = "none"; + return; + } + Object.assign(el.style, { left: `${area.x}px`, width: `${area.width}px`, height: `${area.height}px`, display: "" }); + el.hidden = false; + } /** Repaint the SDK layers that opted into cursor tracking (their own canvas only). */ repaintCursorLayers() { const pane = this.scene.panes.get(PRICE_PANE_ID); @@ -21695,7 +21874,7 @@ var NativeRenderer = class { if (this.animator.active) { this.computeScales(); this.paintData(); - this.crosshairLayer.render(this.scene, this.coords, this.theme, this.hoverSeparatorY, this.externalCrossPx()); + this.renderCrosshairLayer(); } else { this.scheduler.flushNow(4 /* Full */); } @@ -21904,7 +22083,7 @@ var IndicatorHandleImpl = class { this.controller.applyProps(this.id, values); } updateCode(source) { - this.controller.updateCode(this.id, source); + return this.controller.updateCode(this.id, source); } setVisible(visible) { this.controller.setVisible(this.id, visible); @@ -22335,6 +22514,7 @@ var EngineOrchestrator = class _EngineOrchestrator { this.activeEngineStyle = null; /** The chart's current price style (tracked from the renderer's change events + initial read). */ this.priceStyle = "candles"; + this.priceStyleWillChangeUnsub = null; this.unresolvedUnsub = null; /** Latest chart visible range (left/right bar times), fed to viewport-dependent scripts. */ this.visibleRange = null; @@ -22433,6 +22613,7 @@ var EngineOrchestrator = class _EngineOrchestrator { this.renderer.onThemeSelect?.((name) => this.setTheme(resolveTheme(name))); this.viewportUnsub = this.renderer.onViewportChange((range) => this.onViewportChange(range)); this.renderer.onPriceStyleChange?.((style) => this.syncPriceStyle(style)); + this.priceStyleWillChangeUnsub = this.renderer.onPriceStyleWillChange?.((from, to) => this.events.emit("priceStyle:change", { from, to })) ?? null; const initialStyle = this.renderer.readFeature("priceStyle"); if (typeof initialStyle === "string") this.priceStyle = initialStyle; this.barTransform = barTransformFor(initialStyle); @@ -23719,20 +23900,26 @@ var EngineOrchestrator = class _EngineOrchestrator { /** * IndicatorController: replace a SCRIPT indicator's source in place (see * {@link IndicatorHandle.updateCode}). Prepare-first: the running session keeps - * computing until the new source has compiled, so a broken edit costs the user - * nothing but an `error` event. Natives have no script — warn and leave them alone. + * computing until the new source has compiled; then the new code runs on TRIAL until + * its first model lands, and a failure before that puts the previous code back. + * Natives have no script — warn and leave them alone. */ updateCode(id, source) { const record = this.registry.get(id); const handle = this.handles.get(id); - if (!record || !handle) return; + if (!record || !handle) return Promise.resolve({ ok: false, error: new Error(`[vela] updateCode("${id}") \u2014 the indicator is no longer on the chart.`) }); if (record.native) { console.warn(`[vela] updateCode("${id}") \u2014 a native indicator has no script to update.`); - return; + return Promise.resolve({ ok: false, error: new Error(`[vela] updateCode("${id}") \u2014 a native indicator has no script to update.`) }); } - if (source === record.source && record.pendingSource === void 0) return; - record.pendingSource = source; - void this.swapSource(id, source, handle); + const busy = record.pendingSource !== void 0 || record.codeTrial !== void 0; + if (!busy && source === record.source) return Promise.resolve({ ok: true, error: null }); + return new Promise((resolve) => { + (record.codeWaiters ?? (record.codeWaiters = [])).push(resolve); + if (record.pendingSource === source || record.pendingSource === void 0 && record.codeTrial && record.source === source) return; + record.pendingSource = source; + void this.swapSource(id, source, handle); + }); } async swapSource(id, source, handle) { const engine = this.registry.get(id)?.engine ?? this.engineFor(this.registry.get(id)?.options?.language); @@ -23743,26 +23930,41 @@ var EngineOrchestrator = class _EngineOrchestrator { const record2 = this.registry.get(id); if (record2?.pendingSource === source) { record2.pendingSource = void 0; - this.fail(id, handle, err); + this.rejectCode(id, record2, handle, err); } return; } const record = this.registry.get(id); if (!record || record.pendingSource !== source) return; record.pendingSource = void 0; + const previous = record.codeTrial?.previous ?? { + source: record.source, + engine: record.engine, + prepared: record.prepared, + inputValues: record.inputValues, + propValues: record.propValues, + inputs: [...handle.inputs], + props: [...handle.props] + }; + record.inputValues = valuesOnSchema(prepared.inputs, record.inputValues, record.prepared?.inputs); + record.propValues = valuesOnSchema(prepared.props ?? [], record.propValues, record.prepared?.props); record.source = source; record.engine = engine; record.prepared = prepared; handle.setSource(source); - record.inputValues = valuesOnSchema(prepared.inputs, record.inputValues); - record.propValues = valuesOnSchema(prepared.props ?? [], record.propValues); handle.setSchema(prepared.inputs); handle.setPropsSchema(prepared.props ?? []); record.session?.stop(); record.session = void 0; record.pendingStructural = true; record.pendingCause = "code"; - if (record.hidden) return; + if (record.hidden) { + record.codeTrial = void 0; + if (record.renderHandle) this.renderer.setIndicatorInputs(record.renderHandle, record.inputValues, record.propValues); + this.settleCode(record, { ok: true, error: null }); + return; + } + record.codeTrial = { previous }; if (record.renderHandle) { this.renderer.setIndicatorInputs(record.renderHandle, record.inputValues, record.propValues); this.setLoading(record, true); @@ -23770,6 +23972,46 @@ var EngineOrchestrator = class _EngineOrchestrator { this.mountLoadingPlaceholder(id, record); } this.executeIndicator(id, handle); + if (this.bars.length === 0 && record.codeTrial) { + record.codeTrial = void 0; + this.settleCode(record, { ok: true, error: null }); + } + } + /** Resolve every `updateCode` caller waiting on this record's chain of edits. */ + settleCode(record, result) { + const waiters = record.codeWaiters; + record.codeWaiters = void 0; + if (waiters) for (const resolve of waiters) resolve(result); + } + /** + * An update failed — at prepare, or on trial before its first model. A trial puts the + * previous code back (source, engine, prepared script, values, schema) and restarts it; + * its visuals were never dropped, so the chart keeps painting throughout. Then the + * failure reports the usual way and every waiting caller learns it. + */ + rejectCode(id, record, handle, err) { + const trial = record.codeTrial; + record.codeTrial = void 0; + this.fail(id, handle, err); + if (trial) { + const p = trial.previous; + record.session?.stop(); + record.session = void 0; + record.source = p.source; + record.engine = p.engine; + record.prepared = p.prepared; + record.inputValues = p.inputValues; + record.propValues = p.propValues; + handle.setSource(p.source); + handle.setSchema(p.inputs); + handle.setPropsSchema(p.props); + record.pendingStructural = true; + record.pendingCause = void 0; + if (record.renderHandle) this.renderer.setIndicatorInputs(record.renderHandle, record.inputValues, record.propValues); + if (!record.hidden) this.executeIndicator(id, handle); + } + const error = err instanceof Error ? err : new Error(String(err)); + this.settleCode(record, { ok: false, error }); } /** IndicatorController: tear down an indicator and (if now empty) its pane. */ /** Live handles of every indicator on the chart (script + native), insertion order. */ @@ -23784,6 +24026,7 @@ var EngineOrchestrator = class _EngineOrchestrator { removeIndicator(id) { const record = this.registry.remove(id); if (record?.native?.type === "volume") this.volumeOptedOut = true; + if (record) this.settleCode(record, { ok: false, error: new Error(`[vela] updateCode("${id}") \u2014 the indicator was removed.`) }); record?.session?.stop(); if (record?.native?.started) record.native.instance.stop(); this.handles.delete(id); @@ -23811,6 +24054,10 @@ var EngineOrchestrator = class _EngineOrchestrator { if (!visible) { record.session?.stop(); record.session = void 0; + if (record.codeTrial) { + record.codeTrial = void 0; + this.settleCode(record, { ok: true, error: null }); + } if (record.native?.started) record.native.instance.suspend(); if (record.renderHandle) this.renderer.setIndicatorVisible?.(record.renderHandle, false); else if (record.native) this.mountHiddenNativeRow(id, record); @@ -23897,7 +24144,10 @@ var EngineOrchestrator = class _EngineOrchestrator { if (this.viewportTimer != null) clearTimeout(this.viewportTimer); this.viewportUnsub?.(); this.paneActionUnsub?.(); + this.priceStyleWillChangeUnsub?.(); + this.priceStyleWillChangeUnsub = null; for (const record of this.registry.all()) { + this.settleCode(record, { ok: false, error: new Error("[vela] updateCode \u2014 the chart was destroyed.") }); record.session?.stop(); if (record.native?.started) record.native.instance.stop(); } @@ -23966,7 +24216,8 @@ var EngineOrchestrator = class _EngineOrchestrator { const record = this.registry.get(id); if (!record || !record.engine || !record.prepared || record.hidden) return; const mode = this.config.live && !record.prepared.reactsToViewport && record.engine.capabilities.streaming ? "live" : "static"; - record.session = record.engine.execute( + const prepared = record.prepared; + const session = record.engine.execute( { prepared: record.prepared, market: this.market(), @@ -23987,6 +24238,10 @@ var EngineOrchestrator = class _EngineOrchestrator { const cause = record.pendingCause ?? "history"; if (!this.applyModel(id, model)) return; record.pendingCause = void 0; + if (record.codeTrial) { + record.codeTrial = void 0; + this.settleCode(record, { ok: true, error: null }); + } this.emitContextChanged(id); this.emitScriptRun(id, cause, first); }, @@ -23997,9 +24252,17 @@ var EngineOrchestrator = class _EngineOrchestrator { handle.emit("alert", { id: a.id, message: a.message, title: a.title, time: a.time }); }, onWarning: (w) => this.events.emit("warning", w), - onError: (err) => this.fail(id, handle, err) + onError: (err) => { + if (record.codeTrial) this.rejectCode(id, record, handle, err); + else this.fail(id, handle, err); + } } ); + if (record.prepared !== prepared) { + session.stop(); + return; + } + record.session = session; this.emitContextChanged(id); } /** @@ -24500,7 +24763,7 @@ function yieldToPaint() { } return new Promise((resolve) => setTimeout(resolve, 0)); } -function valuesOnSchema(schema, previous) { +function valuesOnSchema(schema, previous, oldSchema = []) { const out = {}; const declared = /* @__PURE__ */ new Set(); for (const s of schema) { @@ -24508,9 +24771,22 @@ function valuesOnSchema(schema, previous) { declared.add(s.key); declared.add(s.title); } - for (const [k, v] of Object.entries(previous)) if (declared.has(k)) out[k] = v; + const oldDefaults = /* @__PURE__ */ new Map(); + for (const s of oldSchema) { + oldDefaults.set(s.key, s.defval); + if (!oldDefaults.has(s.title)) oldDefaults.set(s.title, s.defval); + } + for (const [k, v] of Object.entries(previous)) { + if (!declared.has(k)) continue; + if (oldDefaults.has(k) && sameInputValue(oldDefaults.get(k), v)) continue; + out[k] = v; + } return out; } +function sameInputValue(a, b) { + if (a === b) return true; + return typeof a === "object" && a !== null && typeof b === "object" && b !== null && JSON.stringify(a) === JSON.stringify(b); +} function blankedModel(model) { return { ...model, @@ -28533,7 +28809,8 @@ var Vela = class { glow: options.glow ?? 0, upColor: options.upColor ?? BULLISH, downColor: options.downColor ?? BEARISH, - priceStyle: options.priceStyle ?? "candles" + priceStyle: options.priceStyle ?? "candles", + priceAxisTicks: options.priceAxis?.ticks ?? null }; const RendererClass = options.renderer ?? NativeRenderer; if (typeof RendererClass !== "function") { @@ -28877,4 +29154,4 @@ function resolveElement(container) { return element; } -export { BUILTIN_PRICE_STYLES, BarStore, CachingDataFeed, DARK_THEME, DataControl, DrawingStore, DrawingToolbar, DrawingsControl, LEGEND_AT_TOP_ATTR, LIGHT_THEME, MarksControl, MultiProviderFeed, NativeRenderer, RendererControl, ReplayControl, SecondClock, TIMEZONES, TypedEventBus, Vela, applyAttributionMarkTheme, buildToolbar, createAttributionMark, createCustomMark, defaultMemberOf, defaultToolbar, groupKeyOf, groupMembers, isExchangeTimezone, isGroupRow, normalizeSession, normalizeTimezone, parseSymbol, priceStyleIds, registerBuiltinChartTypes, resolveTheme, resolveTimezone, sharedBarStore, timeframeToMs, timezoneMenuRows, tzButtonLabel, tzMenuLabel, tzOffset }; +export { BUILTIN_PRICE_STYLES, BarStore, CANDLE_OVERRIDE_KEYS, CachingDataFeed, DARK_THEME, DataControl, DrawingStore, DrawingToolbar, DrawingsControl, LEGEND_AT_TOP_ATTR, LIGHT_THEME, MarksControl, MultiProviderFeed, NativeRenderer, RendererControl, ReplayControl, SecondClock, TypedEventBus, Vela, applyAttributionMarkTheme, buildToolbar, createAttributionMark, createCustomMark, defaultMemberOf, defaultToolbar, groupKeyOf, groupMembers, isGroupRow, normalizeSession, parseSymbol, priceStyleIds, registerBuiltinChartTypes, resolveTheme, sharedBarStore, timeframeToMs }; diff --git a/console/frontend/vendor/vela/dist/chunk-EZ5FWVLA.js b/console/frontend/vendor/vela/dist/chunk-KWI3YDBW.js similarity index 93% rename from console/frontend/vendor/vela/dist/chunk-EZ5FWVLA.js rename to console/frontend/vendor/vela/dist/chunk-KWI3YDBW.js index 5988e16..0359801 100644 --- a/console/frontend/vendor/vela/dist/chunk-EZ5FWVLA.js +++ b/console/frontend/vendor/vela/dist/chunk-KWI3YDBW.js @@ -1,4 +1,4 @@ -import { svg24, NEUTRAL, BEARISH, WARNING, BULLISH, INFO, ACCENT_BRIGHT, VALID, INVALID, MARKER, ACCENT, injectStyles, iconEl } from './chunk-BZQM2XO7.js'; +import { svg24, NEUTRAL, BEARISH, WARNING, BULLISH, INFO, ACCENT_BRIGHT, VALID, INVALID, MARKER, ACCENT, injectStyles, iconEl, announceSurface, holdForExit } from './chunk-VHGACEHO.js'; // src/core/model/series.ts function isLineLikeSeries(spec) { @@ -2778,6 +2778,10 @@ var FibRatios = class extends Drawing { // src/core/drawings/types/FibLevels.ts var FibLevels = class extends FibRatios { + /** Price of a level for the two anchor prices; subclasses override to change which anchor ratio 0 sits on. */ + levelPrice(ratio, p1, p2) { + return p1 + ratio * (p2 - p1); + } /** Per-level pixel line + price for the ENABLED levels, spanning the anchors' time range. */ levelLines(proj) { const a = this.anchors[0]; @@ -2787,11 +2791,10 @@ var FibLevels = class extends FibRatios { const xb = proj.xOf(b.time); const x1 = Math.min(xa, xb); const x2 = Math.max(xa, xb); - const delta = b.price - a.price; const out = []; for (const lv of this.levels) { if (!lv.enabled) continue; - const price = a.price + lv.ratio * delta; + const price = this.levelPrice(lv.ratio, a.price, b.price); const y = proj.yOf(price, this.paneId); if (y == null) continue; out.push({ ratio: lv.ratio, color: lv.color, label: lv.label, price, x1, x2, y }); @@ -2831,8 +2834,7 @@ var FibLevels = class extends FibRatios { const a = this.anchors[0]; const b = this.anchors[1]; if (!a || !b) return null; - const delta = b.price - a.price; - const prices = this.levels.filter((l) => l.enabled).map((l) => a.price + l.ratio * delta); + const prices = this.levels.filter((l) => l.enabled).map((l) => this.levelPrice(l.ratio, a.price, b.price)); if (prices.length === 0) return null; return { min: Math.min(...prices), max: Math.max(...prices) }; } @@ -2918,13 +2920,24 @@ function cycleLevels(count, enabledCount = count) { // src/core/drawings/types/FibRetracement.ts var LEVELS = fibLevels([0, 0.236, 0.382, 0.5, 0.618, 0.786, 1]); var FibRetracement = class extends FibLevels { - constructor() { - super(...arguments); + constructor(init) { + super(init); this.type = "fibretracement"; + if (this.reverse === void 0) this.reverse = false; } defaultLevels() { return LEVELS; } + levelPrice(ratio, p1, p2) { + return this.reverse ? p1 + ratio * (p2 - p1) : p2 + ratio * (p1 - p2); + } + writeProps() { + return { ...super.writeProps(), reverse: this.reverse }; + } + readProps(props) { + super.readProps(props); + this.reverse = typeof props.reverse === "boolean" ? props.reverse : true; + } }; // src/core/drawings/types/FibExtension.ts @@ -5892,6 +5905,100 @@ function inputDeltas(schema, values) { return Object.keys(out).length > 0 ? out : void 0; } +// src/core/timezones.ts +var TIMEZONES = [ + { value: "Etc/UTC", label: "UTC" }, + { value: "Etc/GMT+12", label: "International Date Line West" }, + { value: "Pacific/Pago_Pago", label: "Pago Pago" }, + { value: "Pacific/Honolulu", label: "Honolulu" }, + { value: "Pacific/Marquesas", label: "Marquesas Islands" }, + { value: "America/Anchorage", label: "Anchorage" }, + { value: "America/Los_Angeles", label: "Los Angeles" }, + { value: "America/Phoenix", label: "Phoenix" }, + { value: "America/Denver", label: "Denver" }, + { value: "America/Chicago", label: "Chicago" }, + { value: "America/Mexico_City", label: "Mexico City" }, + { value: "America/New_York", label: "New York" }, + { value: "America/Bogota", label: "Bogot\xE1" }, + { value: "America/Caracas", label: "Caracas" }, + { value: "America/Santiago", label: "Santiago" }, + { value: "America/St_Johns", label: "St. John's" }, + { value: "America/Sao_Paulo", label: "S\xE3o Paulo" }, + { value: "America/Argentina/Buenos_Aires", label: "Buenos Aires" }, + { value: "America/Noronha", label: "Fernando de Noronha" }, + { value: "Atlantic/Azores", label: "Azores" }, + { value: "Atlantic/Reykjavik", label: "Reykjavik" }, + { value: "Europe/London", label: "London" }, + { value: "Europe/Paris", label: "Paris" }, + { value: "Europe/Berlin", label: "Berlin" }, + { value: "Europe/Athens", label: "Athens" }, + { value: "Africa/Cairo", label: "Cairo" }, + { value: "Africa/Johannesburg", label: "Johannesburg" }, + { value: "Europe/Moscow", label: "Moscow" }, + { value: "Europe/Istanbul", label: "Istanbul" }, + { value: "Asia/Tehran", label: "Tehran" }, + { value: "Asia/Dubai", label: "Dubai" }, + { value: "Asia/Kabul", label: "Kabul" }, + { value: "Asia/Karachi", label: "Karachi" }, + { value: "Asia/Kolkata", label: "Mumbai" }, + { value: "Asia/Kathmandu", label: "Kathmandu" }, + { value: "Asia/Dhaka", label: "Dhaka" }, + { value: "Asia/Yangon", label: "Yangon" }, + { value: "Asia/Bangkok", label: "Bangkok" }, + { value: "Asia/Shanghai", label: "Shanghai" }, + { value: "Asia/Hong_Kong", label: "Hong Kong" }, + { value: "Asia/Singapore", label: "Singapore" }, + { value: "Australia/Eucla", label: "Eucla" }, + { value: "Asia/Tokyo", label: "Tokyo" }, + { value: "Asia/Seoul", label: "Seoul" }, + { value: "Australia/Adelaide", label: "Adelaide" }, + { value: "Australia/Sydney", label: "Sydney" }, + { value: "Australia/Lord_Howe", label: "Lord Howe Island" }, + { value: "Pacific/Noumea", label: "Noum\xE9a" }, + { value: "Pacific/Auckland", label: "Auckland" }, + { value: "Pacific/Chatham", label: "Chatham Islands" }, + { value: "Pacific/Apia", label: "Apia" }, + { value: "Pacific/Kiritimati", label: "Kiritimati" } +]; +var EXCHANGE_TIMEZONE = "exchange"; +function isExchangeTimezone(zone) { + return zone === EXCHANGE_TIMEZONE; +} +function resolveTimezone(zone, exchangeZone) { + if (!isExchangeTimezone(zone)) return zone; + return exchangeZone && exchangeZone !== "" ? exchangeZone : "Etc/UTC"; +} +function normalizeTimezone(zone) { + return zone === "UTC" || zone === "Etc/UTC" || zone === "Etc/GMT" ? "Etc/UTC" : zone; +} +function timezoneMenuRows(current) { + const active = normalizeTimezone(current); + const [utc, ...zones] = TIMEZONES.map((t) => ({ value: t.value, label: tzMenuLabel(t.value, t.label), checked: t.value === active })); + return [utc, { value: EXCHANGE_TIMEZONE, label: "Exchange", checked: isExchangeTimezone(current) }, ...zones]; +} +function tzOffset(zone, date = /* @__PURE__ */ new Date()) { + try { + const parts = new Intl.DateTimeFormat("en-US", { timeZone: zone, timeZoneName: "shortOffset" }).formatToParts(date); + const raw = parts.find((p) => p.type === "timeZoneName")?.value ?? ""; + const m = raw.match(/GMT(?:(\+|-)(\d{1,2})(?::(\d{2}))?)?/); + if (!m || !m[1]) return "UTC"; + const sign = m[1] === "-" ? "-" : "+"; + const hrs = m[2] ?? "0"; + const mins = m[3] ?? ""; + return mins ? `UTC${sign}${hrs}:${mins}` : `UTC${sign}${hrs}`; + } catch { + return "UTC"; + } +} +function tzMenuLabel(zone, location) { + if (normalizeTimezone(zone) === "Etc/UTC") return location; + return `(${tzOffset(zone)}) ${location}`; +} +function tzButtonLabel(zone) { + if (normalizeTimezone(zone) === "Etc/UTC") return "UTC"; + return tzOffset(zone); +} + // src/renderers/native/layers.ts function foldBaseModulation(acc, next) { if (next == null) return acc; @@ -6023,10 +6130,12 @@ function legendActions() { } function legendActionsProviderFor(chart, context) { return (indicatorId) => { - const handle = chart.indicators().find((h) => h.id === indicatorId); + const find = () => chart.indicators().find((h) => h.id === indicatorId); + const infoOf = (h) => ({ id: h.id, title: h.title, ...h.source !== void 0 ? { source: h.source } : {} }); + const handle = find(); if (!handle) return []; - const info = { id: handle.id, title: handle.title, ...handle.source !== void 0 ? { source: handle.source } : {} }; - return legendActions().filter((d) => !d.when || d.when(info)).map((d) => ({ id: d.id, icon: d.icon, tooltip: d.tooltip, run: () => d.run(context(), info) })); + const info = infoOf(handle); + return legendActions().filter((d) => !d.when || d.when(info)).map((d) => ({ id: d.id, icon: d.icon, tooltip: d.tooltip, run: () => d.run(context(), infoOf(find() ?? handle)) })); }; } var calloutRegistry = /* @__PURE__ */ new Map(); @@ -6113,6 +6222,127 @@ function resolveEngines(overrides) { return { ...Object.fromEntries(defaultEngines), ...overrides }; } +// src/widget/context-menu-model.ts +var SETTINGS_SECTION = { + body: "Canvas", + "price-axis": "Scales and lines", + "time-axis": "Scales and lines" +}; +function settingsItem(zone, label, icon) { + return { id: `settings:${SETTINGS_SECTION[zone]}`, label, ...icon ? { icon } : {}, separatorBefore: true }; +} +function settingsSectionOf(id) { + return id.slice("settings:".length) || void 0; +} +var SCALE_CHOICES = [ + ["regular", "Regular"], + ["percent", "Percent"], + ["indexed", "Indexed to 100"], + ["log", "Logarithmic"] +]; +function paneScaleAt(panes, y) { + return panes.find((p) => y >= p.top && y < p.top + p.height) ?? panes[0] ?? null; +} +function scaleChoiceOf(scale) { + if (scale.log) return "log"; + if (scale.mode === "percent") return "percent"; + if (scale.mode === "indexed") return "indexed"; + return "regular"; +} +function mainScale(pane) { + return pane === null || pane.kind === "price"; +} +function scaleWrites(choice, pane) { + const mode = choice === "percent" ? "percent" : choice === "indexed" ? "indexed" : "price"; + const log = choice === "log"; + if (mainScale(pane)) { + return [ + ["scaleMode", mode], + ["logScale", log] + ]; + } + return [ + ["scaleMode", { pane: pane.id, mode }], + ["logScale", { pane: pane.id, value: log }] + ]; +} +function invertWrite(next, pane) { + return mainScale(pane) ? ["invertScale", next] : ["invertScale", { pane: pane.id, value: next }]; +} +function priceAxisItems(s) { + return [ + { id: "auto", label: "Auto (fits data to screen)", checked: s.auto }, + { id: "invert", label: "Invert scale", checked: s.invert }, + ...SCALE_CHOICES.map(([choice, label], i) => ({ + id: `scale:${choice}`, + label, + checked: s.choice === choice, + separatorBefore: i === 0 + })), + { + id: "labels", + label: "Labels", + separatorBefore: true, + submenu: [ + { id: "toggle:axisLabels", label: "Price axis labels", checked: s.axisLabels }, + { id: "toggle:priceLabel", label: "Last price label", checked: s.priceLabel }, + { id: "toggle:countdown", label: "Countdown to bar close", checked: s.countdown } + ] + }, + { + id: "levels", + label: "Levels", + submenu: [{ id: "toggle:currentPriceLine", label: "Last Price Line", checked: s.priceLine }] + }, + settingsItem("price-axis", "More settings\u2026") + ]; +} +function timeAxisItems(timezone) { + return [ + { + id: "timezone", + label: "Time zone", + submenu: timezoneMenuRows(timezone).map((r) => ({ id: `tz:${r.value}`, label: r.label, checked: r.checked })) + }, + settingsItem("time-axis", "More settings\u2026") + ]; +} +function bodyItems(counts) { + return [ + { id: "reset-view", label: "Reset chart view", icon: "reset" }, + { id: "remove-drawings", label: "Remove drawings", icon: "eraser", disabled: counts.drawings === 0, separatorBefore: true }, + { id: "remove-indicators", label: "Remove indicators", icon: "indicators", disabled: counts.indicators === 0 }, + settingsItem("body", "Settings\u2026", "gear") + ]; +} +var CONTEXT_MENU_BUILTIN_ORDER = { + body: { "reset-view": -30, "remove-drawings": -20, "remove-indicators": -10, settings: 1e3 }, + "price-axis": { + auto: -80, + invert: -70, + "scale:regular": -60, + "scale:percent": -50, + "scale:indexed": -40, + "scale:log": -30, + labels: -20, + levels: -10, + settings: 1e3 + }, + "time-axis": { timezone: -10, settings: 1e3 } +}; +function composeMenu(zone, builtin, contributed) { + const ranks = CONTEXT_MENU_BUILTIN_ORDER[zone]; + const rows = []; + let group = 0; + for (const item of builtin) { + if (item.separatorBefore) group += 1; + rows.push({ item, rank: ranks[item.id.startsWith("settings") ? "settings" : item.id] ?? 0, group }); + } + for (const { item, order } of contributed) rows.push({ item, rank: order ?? 0, group: -1 }); + rows.sort((a, b) => a.rank - b.rank); + return rows.map(({ item, group: g }, i) => ({ ...item, separatorBefore: i > 0 && rows[i - 1].group !== g })); +} + // src/widget/side-panel.ts var STYLE_ID = "vela-widget-sidepanel"; var DEFAULT_PANEL_WIDTH = 280; @@ -6177,6 +6407,32 @@ var CSS = ` .vela-panel-pin .vela-icon { width: 15px; height: 15px; } .vela-panel-pin:hover { background: var(--vela-hover); color: var(--vela-fg-bright); } .vela-panel-pin[data-on='1'] { color: var(--vela-fg-bright); } +.vela-panel-max { + all: unset; + cursor: pointer; + width: 26px; + height: 26px; + flex: none; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 4px; + color: var(--vela-fg-muted); +} +.vela-panel-max .vela-icon { width: 15px; height: 15px; } +.vela-panel-max:hover { background: var(--vela-hover); color: var(--vela-fg-bright); } +/* MAXIMIZED: the panel covers the whole dock host \u2014 every chart of the shell \u2014 whatever + its placement; the width handle and the pin have nothing to do meanwhile. */ +.vela-panel[data-maximized] { + position: absolute; + inset: 0; + width: auto; + max-width: none; + z-index: 26; + border-left: none; +} +.vela-panel[data-maximized] .vela-panel-resizer, +.vela-panel[data-maximized] .vela-panel-pin { display: none; } .vela-panel-body { flex: 1; overflow: auto; padding: 8px; } .vela-panel-body::-webkit-scrollbar { width: 8px; } .vela-panel-body::-webkit-scrollbar-thumb { background: var(--vela-scroll); border-radius: 4px; border: 2px solid transparent; background-clip: padding-box; } @@ -6229,6 +6485,7 @@ var CSS = ` border-left: none; } [data-layout='mobile'] .vela-panel-resizer { display: none; } +[data-layout='mobile'] .vela-panel-max { display: none; } `; function clampPanelWidth(px, min = DEFAULT_PANEL_MIN_WIDTH, max = DEFAULT_PANEL_MAX_WIDTH) { const lo = Number.isFinite(min) && min > 0 ? min : DEFAULT_PANEL_MIN_WIDTH; @@ -6252,6 +6509,15 @@ var SidePanel = class { * never on a programmatic {@link setOverlay}, for the same reason as widths. */ this.onPlacementChange = null; this.pin = null; + this.maxButton = null; + this.maximizedOn = false; + /** Set while the close is announced, so a listener's own close does not re-enter. */ + this.closing = false; + /** Open as far as the dock and the host are concerned — a closed panel can still be on + * screen while its exit animation runs. */ + this.isOpen = false; + /** The exit animation of a close; a reopen cancels it. */ + this.exit = null; const doc = host.ownerDocument; injectStyles(STYLE_ID, CSS, doc); this.minWidth = opts.resizable ? opts.minWidth ?? DEFAULT_PANEL_MIN_WIDTH : 1; @@ -6286,7 +6552,13 @@ var SidePanel = class { }); this.refreshPin(); } - header.append(this.heading, this.slot, ...this.pin ? [this.pin] : [], close); + if (opts.maximizable) { + this.maxButton = doc.createElement("button"); + this.maxButton.className = "vela-panel-max"; + this.maxButton.addEventListener("click", () => this.setMaximized(!this.maximizedOn)); + this.refreshMaxButton(); + } + header.append(this.heading, this.slot, ...this.pin ? [this.pin] : [], ...this.maxButton ? [this.maxButton] : [], close); this.body = doc.createElement("div"); this.body.className = "vela-panel-body"; this.el.append(header, this.body); @@ -6294,13 +6566,65 @@ var SidePanel = class { host.appendChild(this.el); } get open() { - return !this.el.hidden; + return this.isOpen; } - /** Open/close the panel — a bare call flips it. */ - toggle(open = this.el.hidden) { - if (open === !this.el.hidden) return; - this.el.hidden = !open; + /** + * Open/close the panel — a bare call flips it. The panel reports closed at once, but a + * close keeps it on screen, marked `data-closing`, while a host exit animation runs. + * `instant` skips that, and also cuts short the exit of a panel already closing: a panel + * handing the dock to another leaves at once. + */ + toggle(open = !this.isOpen, instant = false) { + if (open === this.isOpen) { + if (!open && instant) this.exit?.finish(); + return; + } + if (!open && this.closing) return; + if (!open) { + this.closing = true; + announceSurface(this.el, false, "panel"); + this.closing = false; + } + this.isOpen = open; + if (open) { + if (this.exit) { + this.exit.cancel(); + this.exit = null; + this.setMaximized(false); + } + this.el.hidden = false; + } else { + const hide = () => { + this.exit = null; + this.el.hidden = true; + this.setMaximized(false); + }; + if (instant) hide(); + else this.exit = holdForExit(this.el, hide); + } this.onOpenChange?.(open); + if (open && this.isOpen) announceSurface(this.el, true, "panel"); + } + /** Whether the panel covers every chart right now. */ + get maximized() { + return this.maximizedOn; + } + /** Maximize the panel over the shell's charts, or restore it. A no-op on a panel not + * declared `maximizable`. */ + setMaximized(maximized) { + if (!this.maxButton || maximized === this.maximizedOn) return; + this.maximizedOn = maximized; + if (maximized) this.el.dataset.maximized = "1"; + else delete this.el.dataset.maximized; + this.refreshMaxButton(); + } + refreshMaxButton() { + if (!this.maxButton) return; + const doc = this.maxButton.ownerDocument; + this.maxButton.replaceChildren(iconEl(this.maximizedOn ? "restore" : "maximize", doc)); + this.maxButton.title = this.maximizedOn ? "Restore" : "Maximize"; + this.maxButton.setAttribute("aria-label", this.maxButton.title); + this.maxButton.setAttribute("aria-pressed", this.maximizedOn ? "true" : "false"); } /** The scrolling body, for a panel filled from OUTSIDE the class — a contributed panel's * `mount` receives exactly this element. Subclasses use the protected `body`. */ @@ -6352,6 +6676,8 @@ var SidePanel = class { this.pin.setAttribute("aria-pressed", pinned ? "true" : "false"); } destroy() { + if (this.open) announceSurface(this.el, false, "panel"); + this.exit?.finish(); this.el.remove(); } /** The drag handle on the panel's inner (left) edge — the panel is docked right, so dragging @@ -6396,4 +6722,4 @@ var SidePanel = class { } }; -export { AnchoredVwap, ArrowMark, Callout, CalloutBase, Comment, DEDEKIND_CURVATURE_OPTIONS, DEFAULT_DRAWING_COLOR, DEFAULT_PANEL_MAX_WIDTH, DEFAULT_PANEL_MIN_WIDTH, DEFAULT_PANEL_ORDER, DEFAULT_PANEL_WIDTH, DIRECTION_OPTIONS, DedekindTessellation, Drawing, FibRatios, FibSpiral, FixedRangeVolumeProfile, GANN_SQUARE_ARCS, GLYPH_OPTIONS, GannSquare, GlyphStamp, LINE_STYLE_OPTIONS, MACH_NUMBER_OPTIONS, MACH_WAVE_COUNT_OPTIONS, MAGNIFIER_TIMEFRAME_OPTIONS, MachFigure, Magnifier, MeasureBox, Note, OVERRIDABLE_TOPBAR_IDS, PatternDrawing, PositionTool, PriceLabel, PriceNote, RadialFib, RegressionChannel, STAMP_SIZE_OPTIONS, SegmentDrawing, SidePanel, Signpost, TEXT_SIZE_OPTIONS, TOPBAR_BUILTIN_IDS, TOPBAR_DEFAULT_LEFT, TOPBAR_DEFAULT_RIGHT, TextLabel, chartType, chartTypes, clampPanelWidth, createDrawing, deserializeDrawing, drawingTypes, foldBaseModulation, formatDuration, getDrawingType, getNativeIndicator, inputDeltas, inputVisible, isLineLikeSeries, legendActions, legendActionsProviderFor, legendCallouts, legendCalloutsProviderFor, lineSegmentIntersection, magnifierTimeframeLabel, mobilePlacement, nativeIndicatorDescriptors, nativeIndicatorTypes, nativeInstanceChannel, normalizeSettingsRow, pinnedTopbarActionIds, registerChartType, registerDefaultEngine, registerDrawingType, registerLegendAction, registerLegendCallout, registerNativeIndicator, registerRendererDefaults, registerRendererLayer, registerSidePanel, registerStatePersistence, registerSymbolRanking, registerWidgetAction, registerWidgetAttachment, rendererDefaults, rendererLayers, resetDrawingSettings, resolveEngines, resolveTopbarComposition, seriesInScale, seriesShownOn, settingsRowValueKeys, settingsRowVisible, sidePanels, stableSeriesId, statePersistenceHandlers, symbolRanking, tickerModifierIds, topbarActionOverride, topbarHas, unregisterChartType, unregisterDefaultEngine, unregisterLegendAction, unregisterLegendCallout, unregisterNativeIndicator, unregisterRendererDefaults, unregisterRendererLayer, unregisterSidePanel, unregisterStatePersistence, unregisterWidgetAction, unregisterWidgetAttachment, widgetActions, widgetAttachments }; +export { AnchoredVwap, ArrowMark, CONTEXT_MENU_BUILTIN_ORDER, Callout, CalloutBase, Comment, DEDEKIND_CURVATURE_OPTIONS, DEFAULT_DRAWING_COLOR, DEFAULT_PANEL_MAX_WIDTH, DEFAULT_PANEL_MIN_WIDTH, DEFAULT_PANEL_ORDER, DEFAULT_PANEL_WIDTH, DIRECTION_OPTIONS, DedekindTessellation, Drawing, FibRatios, FibRetracement, FibSpiral, FixedRangeVolumeProfile, GANN_SQUARE_ARCS, GLYPH_OPTIONS, GannSquare, GlyphStamp, LINE_STYLE_OPTIONS, MACH_NUMBER_OPTIONS, MACH_WAVE_COUNT_OPTIONS, MAGNIFIER_TIMEFRAME_OPTIONS, MachFigure, Magnifier, MeasureBox, Note, OVERRIDABLE_TOPBAR_IDS, PatternDrawing, PositionTool, PriceLabel, PriceNote, RadialFib, RegressionChannel, STAMP_SIZE_OPTIONS, SegmentDrawing, SidePanel, Signpost, TEXT_SIZE_OPTIONS, TIMEZONES, TOPBAR_BUILTIN_IDS, TOPBAR_DEFAULT_LEFT, TOPBAR_DEFAULT_RIGHT, TextLabel, bodyItems, chartType, chartTypes, clampPanelWidth, composeMenu, createDrawing, deserializeDrawing, drawingTypes, foldBaseModulation, formatDuration, getDrawingType, getNativeIndicator, inputDeltas, inputVisible, invertWrite, isExchangeTimezone, isLineLikeSeries, legendActions, legendActionsProviderFor, legendCallouts, legendCalloutsProviderFor, lineSegmentIntersection, magnifierTimeframeLabel, mobilePlacement, nativeIndicatorDescriptors, nativeIndicatorTypes, nativeInstanceChannel, normalizeSettingsRow, normalizeTimezone, paneScaleAt, pinnedTopbarActionIds, priceAxisItems, registerChartType, registerDefaultEngine, registerDrawingType, registerLegendAction, registerLegendCallout, registerNativeIndicator, registerRendererDefaults, registerRendererLayer, registerSidePanel, registerStatePersistence, registerSymbolRanking, registerWidgetAction, registerWidgetAttachment, rendererDefaults, rendererLayers, resetDrawingSettings, resolveEngines, resolveTimezone, resolveTopbarComposition, scaleChoiceOf, scaleWrites, seriesInScale, seriesShownOn, settingsRowValueKeys, settingsRowVisible, settingsSectionOf, sidePanels, stableSeriesId, statePersistenceHandlers, symbolRanking, tickerModifierIds, timeAxisItems, timezoneMenuRows, topbarActionOverride, topbarHas, tzButtonLabel, tzMenuLabel, tzOffset, unregisterChartType, unregisterDefaultEngine, unregisterLegendAction, unregisterLegendCallout, unregisterNativeIndicator, unregisterRendererDefaults, unregisterRendererLayer, unregisterSidePanel, unregisterStatePersistence, unregisterWidgetAction, unregisterWidgetAttachment, widgetActions, widgetAttachments }; diff --git a/console/frontend/vendor/vela/dist/chunk-LMBYEGUR.js b/console/frontend/vendor/vela/dist/chunk-TO3GIK7Z.js similarity index 87% rename from console/frontend/vendor/vela/dist/chunk-LMBYEGUR.js rename to console/frontend/vendor/vela/dist/chunk-TO3GIK7Z.js index 4498df3..0b99973 100644 --- a/console/frontend/vendor/vela/dist/chunk-LMBYEGUR.js +++ b/console/frontend/vendor/vela/dist/chunk-TO3GIK7Z.js @@ -1,5 +1,5 @@ -import { normalizeProps, nextUid, runMachine, spreadProps } from './chunk-NELQJCGK.js'; -import { injectStyles } from './chunk-BZQM2XO7.js'; +import { normalizeProps, nextUid, runMachine, spreadProps } from './chunk-G7B7ZCBF.js'; +import { injectStyles, holdForExit, announceSurface } from './chunk-VHGACEHO.js'; import * as tooltip from '@zag-js/tooltip'; import * as dialog from '@zag-js/dialog'; @@ -343,6 +343,11 @@ function swipeDirection(dx, dy) { } var Drawer = class { constructor(opts = {}) { + this.opener = null; + this.wasOpen = false; + /** The sheet and scrim's exit animation after a close; a reopen cancels it. */ + this.exit = null; + this.destroyed = false; const doc = (opts.host ?? document.body).ownerDocument; injectStyles(DRAWER_STYLE_ID, DRAWER_CSS, doc); const host = opts.host ?? doc.body; @@ -370,12 +375,24 @@ var Drawer = class { const mid = String(this.ctrl.props.id); this.handle = runMachine(this.ctrl.machine, this.ctrl.props, (service) => { const api = this.ctrl.connect(service); + const closing = this.wasOpen && !api.open; + if (closing) this.announce(false); spreadProps(this.backdrop, api.getBackdropProps(), mid); spreadProps(this.positioner, api.getPositionerProps(), mid); spreadProps(this.panel, api.getContentProps(), mid); spreadProps(this.titleEl, api.getTitleProps(), mid); - this.backdrop.style.display = api.open ? "" : "none"; - this.positioner.style.display = api.open ? "" : "none"; + if (api.open) { + this.exit?.cancel(); + this.exit = null; + this.setShown(true); + } else if (closing) { + this.holdExit(); + } else if (!this.exit) { + this.setShown(false); + } + if (api.open && !this.wasOpen) this.announce(true); + if (this.wasOpen && !api.open) this.restoreOpener(); + this.wasOpen = api.open; }); } /** Any element between `from` and the panel that has already been scrolled down — @@ -484,19 +501,67 @@ var Drawer = class { setTitle(title) { this.titleEl.textContent = title; } + setShown(shown) { + this.backdrop.style.display = shown ? "" : "none"; + this.positioner.style.display = shown ? "" : "none"; + } + /** Keep the just-closed sheet up through its exit animation, then hide it — or + * remove it, when it was destroyed meanwhile. `spreadProps` re-applies the close + * props' `hidden` only when its value changes, so lifting it keeps the sheet and + * scrim up until the exit ends. The positioner spans the host: inert, it lets + * clicks through to the page while the sheet animates out. */ + holdExit() { + const held = [this.panel, this.backdrop]; + for (const el of held) el.hidden = false; + this.exit = holdForExit( + held, + () => { + this.exit = null; + if (this.destroyed) { + this.detach(); + } else if (!this.open) { + for (const el of held) el.hidden = true; + this.setShown(false); + } + }, + { inert: [this.positioner] } + ); + } + detach() { + this.backdrop.remove(); + this.positioner.remove(); + } + /** Closing hands focus back to whatever opened it (Escape, the ✕, hide(), or a + * teardown that outruns the machine's close notification). */ + restoreOpener() { + const opener = this.opener; + this.opener = null; + if (opener?.isConnected) opener.focus({ preventScroll: true }); + } + announce(open) { + const opener = this.opener === this.panel.ownerDocument.body ? null : this.opener; + announceSurface(this.panel, open, "drawer", opener); + } get open() { return this.ctrl.connect(this.handle.service).open; } show() { + this.opener = this.panel.ownerDocument.activeElement; this.ctrl.connect(this.handle.service).setOpen(true); } hide() { this.ctrl.connect(this.handle.service).setOpen(false); } destroy() { + if (this.wasOpen && !this.open) this.handle.flush(); this.handle.stop(); - this.backdrop.remove(); - this.positioner.remove(); + this.destroyed = true; + if (this.wasOpen) { + this.wasOpen = false; + this.announce(false); + } + this.restoreOpener(); + if (!this.exit) this.detach(); } }; diff --git a/console/frontend/vendor/vela/dist/chunk-BZQM2XO7.js b/console/frontend/vendor/vela/dist/chunk-VHGACEHO.js similarity index 87% rename from console/frontend/vendor/vela/dist/chunk-BZQM2XO7.js rename to console/frontend/vendor/vela/dist/chunk-VHGACEHO.js index 92db1b9..63663dc 100644 --- a/console/frontend/vendor/vela/dist/chunk-BZQM2XO7.js +++ b/console/frontend/vendor/vela/dist/chunk-VHGACEHO.js @@ -146,6 +146,7 @@ registerIcon("expand", S('')); registerIcon("minus", S('')); registerIcon("maximize", S('')); +registerIcon("restore", S('')); registerIcon("restore", S('')); registerIcon("star", S('')); registerIcon("star-filled", S('', 'fill="currentColor"')); @@ -270,4 +271,64 @@ function iconEl(id, doc = document) { return span; } -export { ACCENT, ACCENT_BRIGHT, BEARISH, BULLISH, CATEGORICAL, CHIP_PLATE, CROSSHAIR, FIELD_FOCUS_CSS, FIELD_FOCUS_RING, HIGHLIGHT, INFO, INVALID, MARKER, NEUTRAL, SERIES_LINE, SESSION_OFF, SESSION_POST, SESSION_PRE, SLATE, SLATE_DEEP, TRADE_EXIT, TRADE_LONG, TRADE_SHORT, VALID, WARNING, categoricalColor, icon, iconAt, iconEl, iconMarkup, injectStyles, isDarkColor, mix, overlayScrollbarCss, registerIcon, svg16, svg24, svg24Solid, withAlpha }; +// src/ui/surface-events.ts +var SURFACE_OPEN_EVENT = "vela:surface-open"; +var SURFACE_CLOSE_EVENT = "vela:surface-close"; +function announceSurface(el, open, kind, trigger = null) { + const View = el.ownerDocument.defaultView; + if (!View) return; + el.dispatchEvent( + new View.CustomEvent(open ? SURFACE_OPEN_EVENT : SURFACE_CLOSE_EVENT, { bubbles: true, composed: true, detail: { kind, trigger } }) + ); +} + +// src/ui/surface-exit.ts +var CLOSING_ATTR = "data-closing"; +var SURFACE_EXIT_CAP_MS = 1e3; +function animationsOf(els) { + return els.flatMap((el) => el.getAnimations({ subtree: true })); +} +function ends(a) { + return Number.isFinite(a.effect?.getComputedTiming().endTime ?? Number.POSITIVE_INFINITY); +} +function holdForExit(els, done, opts = {}) { + const list = Array.isArray(els) ? els : [els]; + if (list.length === 0 || !list.every((el) => typeof el.getAnimations === "function")) { + done(); + return null; + } + const before = new Set(animationsOf(list)); + for (const el of list) el.setAttribute(CLOSING_ATTR, ""); + const exit = animationsOf(list).filter((a) => !before.has(a) && ends(a)); + if (exit.length === 0) { + for (const el of list) el.removeAttribute(CLOSING_ATTR); + done(); + return null; + } + const frozen = [...list, ...opts.inert ?? []]; + const wasInert = frozen.map((el) => el.inert); + for (const el of frozen) el.inert = true; + let settled = false; + const settle = (complete) => { + if (settled) return; + settled = true; + clearTimeout(cap); + for (const el of list) el.removeAttribute(CLOSING_ATTR); + frozen.forEach((el, i) => { + el.inert = wasInert[i]; + }); + if (complete) done(); + }; + const cap = setTimeout(() => settle(true), SURFACE_EXIT_CAP_MS); + let pending = exit.length; + const one = () => { + if (--pending === 0) settle(true); + }; + for (const a of exit) a.finished.then(one, one); + return { + cancel: () => settle(false), + finish: () => settle(true) + }; +} + +export { ACCENT, ACCENT_BRIGHT, BEARISH, BULLISH, CATEGORICAL, CHIP_PLATE, CROSSHAIR, FIELD_FOCUS_CSS, FIELD_FOCUS_RING, HIGHLIGHT, INFO, INVALID, MARKER, NEUTRAL, SERIES_LINE, SESSION_OFF, SESSION_POST, SESSION_PRE, SLATE, SLATE_DEEP, SURFACE_CLOSE_EVENT, SURFACE_OPEN_EVENT, TRADE_EXIT, TRADE_LONG, TRADE_SHORT, VALID, WARNING, announceSurface, categoricalColor, holdForExit, icon, iconAt, iconEl, iconMarkup, injectStyles, isDarkColor, mix, overlayScrollbarCss, registerIcon, svg16, svg24, svg24Solid, withAlpha }; diff --git a/console/frontend/vendor/vela/dist/chunk-JU4CWEBF.js b/console/frontend/vendor/vela/dist/chunk-W5YPYZ2P.js similarity index 100% rename from console/frontend/vendor/vela/dist/chunk-JU4CWEBF.js rename to console/frontend/vendor/vela/dist/chunk-W5YPYZ2P.js diff --git a/console/frontend/vendor/vela/dist/index.js b/console/frontend/vendor/vela/dist/index.js index e38cc54..3ba6343 100644 --- a/console/frontend/vendor/vela/dist/index.js +++ b/console/frontend/vendor/vela/dist/index.js @@ -1,8 +1,8 @@ -import './chunk-JU4CWEBF.js'; -export { BarStore, CachingDataFeed, DARK_THEME, DataControl, DrawingStore, DrawingToolbar, DrawingsControl, LIGHT_THEME, MarksControl, MultiProviderFeed, NativeRenderer, RendererControl, ReplayControl, SecondClock, TypedEventBus, Vela, buildToolbar, defaultToolbar, resolveTheme, sharedBarStore, timeframeToMs } from './chunk-ATGTCWHJ.js'; -export { DEFAULT_PANEL_MAX_WIDTH, DEFAULT_PANEL_MIN_WIDTH, DEFAULT_PANEL_WIDTH, Drawing, OVERRIDABLE_TOPBAR_IDS, chartType, chartTypes, clampPanelWidth, createDrawing, deserializeDrawing, drawingTypes, getDrawingType, getNativeIndicator, inputDeltas, inputVisible, legendActions, legendCallouts, nativeIndicatorDescriptors, nativeIndicatorTypes, normalizeSettingsRow, registerChartType, registerDefaultEngine, registerDrawingType, registerLegendAction, registerLegendCallout, registerNativeIndicator, registerRendererDefaults, registerRendererLayer, registerSidePanel, registerStatePersistence, registerSymbolRanking, registerWidgetAction, registerWidgetAttachment, rendererDefaults, rendererLayers, resolveEngines, seriesInScale, seriesShownOn, settingsRowValueKeys, sidePanels, stableSeriesId, statePersistenceHandlers, symbolRanking, tickerModifierIds, topbarActionOverride, unregisterChartType, unregisterDefaultEngine, unregisterLegendAction, unregisterLegendCallout, unregisterNativeIndicator, unregisterRendererDefaults, unregisterRendererLayer, unregisterSidePanel, unregisterStatePersistence, unregisterWidgetAction, unregisterWidgetAttachment, widgetActions, widgetAttachments } from './chunk-EZ5FWVLA.js'; -import './chunk-NELQJCGK.js'; -export { ACCENT, ACCENT_BRIGHT, BEARISH, BULLISH, CATEGORICAL, CHIP_PLATE, CROSSHAIR, HIGHLIGHT, INFO, INVALID, MARKER, NEUTRAL, SERIES_LINE, SESSION_OFF, SESSION_POST, SESSION_PRE, SLATE, SLATE_DEEP, TRADE_EXIT, TRADE_LONG, TRADE_SHORT, VALID, WARNING, categoricalColor, iconMarkup, registerIcon } from './chunk-BZQM2XO7.js'; +import './chunk-W5YPYZ2P.js'; +export { BarStore, CachingDataFeed, DARK_THEME, DataControl, DrawingStore, DrawingToolbar, DrawingsControl, LIGHT_THEME, MarksControl, MultiProviderFeed, NativeRenderer, RendererControl, ReplayControl, SecondClock, TypedEventBus, Vela, buildToolbar, defaultToolbar, resolveTheme, sharedBarStore, timeframeToMs } from './chunk-HMHA733L.js'; +export { CONTEXT_MENU_BUILTIN_ORDER, DEFAULT_PANEL_MAX_WIDTH, DEFAULT_PANEL_MIN_WIDTH, DEFAULT_PANEL_WIDTH, Drawing, OVERRIDABLE_TOPBAR_IDS, chartType, chartTypes, clampPanelWidth, createDrawing, deserializeDrawing, drawingTypes, getDrawingType, getNativeIndicator, inputDeltas, inputVisible, legendActions, legendCallouts, nativeIndicatorDescriptors, nativeIndicatorTypes, normalizeSettingsRow, registerChartType, registerDefaultEngine, registerDrawingType, registerLegendAction, registerLegendCallout, registerNativeIndicator, registerRendererDefaults, registerRendererLayer, registerSidePanel, registerStatePersistence, registerSymbolRanking, registerWidgetAction, registerWidgetAttachment, rendererDefaults, rendererLayers, resolveEngines, seriesInScale, seriesShownOn, settingsRowValueKeys, sidePanels, stableSeriesId, statePersistenceHandlers, symbolRanking, tickerModifierIds, topbarActionOverride, unregisterChartType, unregisterDefaultEngine, unregisterLegendAction, unregisterLegendCallout, unregisterNativeIndicator, unregisterRendererDefaults, unregisterRendererLayer, unregisterSidePanel, unregisterStatePersistence, unregisterWidgetAction, unregisterWidgetAttachment, widgetActions, widgetAttachments } from './chunk-KWI3YDBW.js'; +import './chunk-G7B7ZCBF.js'; +export { ACCENT, ACCENT_BRIGHT, BEARISH, BULLISH, CATEGORICAL, CHIP_PLATE, CROSSHAIR, HIGHLIGHT, INFO, INVALID, MARKER, NEUTRAL, SERIES_LINE, SESSION_OFF, SESSION_POST, SESSION_PRE, SLATE, SLATE_DEEP, TRADE_EXIT, TRADE_LONG, TRADE_SHORT, VALID, WARNING, categoricalColor, iconMarkup, registerIcon } from './chunk-VHGACEHO.js'; // src/core/replayTicks.ts function lowerTimeframeTicks(chart, timeframe) { diff --git a/console/frontend/vendor/vela/dist/plugin.js b/console/frontend/vendor/vela/dist/plugin.js index aefb355..41d7960 100644 --- a/console/frontend/vendor/vela/dist/plugin.js +++ b/console/frontend/vendor/vela/dist/plugin.js @@ -1,3 +1,3 @@ -import './chunk-JU4CWEBF.js'; -export { DEFAULT_PANEL_MAX_WIDTH, DEFAULT_PANEL_MIN_WIDTH, DEFAULT_PANEL_WIDTH, OVERRIDABLE_TOPBAR_IDS, chartType, chartTypes, clampPanelWidth, drawingTypes, getDrawingType, getNativeIndicator, inputDeltas, inputVisible, legendActions, legendCallouts, nativeIndicatorTypes, normalizeSettingsRow, registerChartType, registerDefaultEngine, registerLegendAction, registerLegendCallout, registerNativeIndicator, registerRendererDefaults, registerRendererLayer, registerSidePanel, registerStatePersistence, registerSymbolRanking, registerWidgetAction, registerWidgetAttachment, rendererDefaults, rendererLayers, resolveEngines, seriesInScale, seriesShownOn, settingsRowValueKeys, sidePanels, stableSeriesId, statePersistenceHandlers, symbolRanking, tickerModifierIds, topbarActionOverride, unregisterChartType, unregisterDefaultEngine, unregisterLegendAction, unregisterLegendCallout, unregisterNativeIndicator, unregisterRendererDefaults, unregisterRendererLayer, unregisterSidePanel, unregisterStatePersistence, unregisterWidgetAction, unregisterWidgetAttachment, widgetActions, widgetAttachments } from './chunk-EZ5FWVLA.js'; -export { ACCENT, ACCENT_BRIGHT, BEARISH, BULLISH, CATEGORICAL, CHIP_PLATE, CROSSHAIR, HIGHLIGHT, INFO, INVALID, MARKER, NEUTRAL, SERIES_LINE, SESSION_OFF, SESSION_POST, SESSION_PRE, SLATE, SLATE_DEEP, TRADE_EXIT, TRADE_LONG, TRADE_SHORT, VALID, WARNING, categoricalColor, iconMarkup, registerIcon } from './chunk-BZQM2XO7.js'; +import './chunk-W5YPYZ2P.js'; +export { CONTEXT_MENU_BUILTIN_ORDER, DEFAULT_PANEL_MAX_WIDTH, DEFAULT_PANEL_MIN_WIDTH, DEFAULT_PANEL_WIDTH, OVERRIDABLE_TOPBAR_IDS, chartType, chartTypes, clampPanelWidth, drawingTypes, getDrawingType, getNativeIndicator, inputDeltas, inputVisible, legendActions, legendCallouts, nativeIndicatorTypes, normalizeSettingsRow, registerChartType, registerDefaultEngine, registerLegendAction, registerLegendCallout, registerNativeIndicator, registerRendererDefaults, registerRendererLayer, registerSidePanel, registerStatePersistence, registerSymbolRanking, registerWidgetAction, registerWidgetAttachment, rendererDefaults, rendererLayers, resolveEngines, seriesInScale, seriesShownOn, settingsRowValueKeys, sidePanels, stableSeriesId, statePersistenceHandlers, symbolRanking, tickerModifierIds, topbarActionOverride, unregisterChartType, unregisterDefaultEngine, unregisterLegendAction, unregisterLegendCallout, unregisterNativeIndicator, unregisterRendererDefaults, unregisterRendererLayer, unregisterSidePanel, unregisterStatePersistence, unregisterWidgetAction, unregisterWidgetAttachment, widgetActions, widgetAttachments } from './chunk-KWI3YDBW.js'; +export { ACCENT, ACCENT_BRIGHT, BEARISH, BULLISH, CATEGORICAL, CHIP_PLATE, CROSSHAIR, HIGHLIGHT, INFO, INVALID, MARKER, NEUTRAL, SERIES_LINE, SESSION_OFF, SESSION_POST, SESSION_PRE, SLATE, SLATE_DEEP, TRADE_EXIT, TRADE_LONG, TRADE_SHORT, VALID, WARNING, categoricalColor, iconMarkup, registerIcon } from './chunk-VHGACEHO.js'; diff --git a/console/frontend/vendor/vela/dist/ui.js b/console/frontend/vendor/vela/dist/ui.js index 503c050..f215e86 100644 --- a/console/frontend/vendor/vela/dist/ui.js +++ b/console/frontend/vendor/vela/dist/ui.js @@ -1,3 +1,3 @@ -export { Drawer, KeymapManager, Tooltip, drawerController, tooltipController } from './chunk-LMBYEGUR.js'; -export { CALLOUT_CSS, CALLOUT_STYLE_ID, CalloutBubble, ColorField, DatePicker, Dialog, FIELD_GAP_PX, GlyphSelect, Menu, NumberInput, Popover, Select, Switch, TextArea, TextField, WIDTH_FIELD_OPTIONS, applyPlotOverlayTokens, applyThemeTokens, blendOver, buildColorPicker, buildFieldControl, buildPalette, calloutPanelRows, clampNumber, closeColorPopover, closeOpenPopovers, closeWidthPopover, closesPanel, colorField, colorPickerController, combineColor, datePickerController, decorateSelectScroll, dialogController, ensureUIHost, eventDismissedPopover, fieldGrid, fieldGridColumns, fieldRow, fieldSection, fieldSeparator, fillSelectList, glyphSelectController, hslHex, insetRect, intersectRects, isPopoverOpen, isoDate, lineWidthGlyph, menuController, nextUid, normalizeDateInput, normalizeProps, numberInputController, openPopoverTrigger, openSelectList, placePopover, popoverController, runMachine, selectController, snapToStep, splitColor, spreadProps, switchController, textAreaController, textFieldController, toggleSelectList, transparencyChecker, viewportRect, widthField, widthFieldOptions } from './chunk-NELQJCGK.js'; -export { FIELD_FOCUS_CSS, FIELD_FOCUS_RING, iconEl, iconMarkup, injectStyles, overlayScrollbarCss, registerIcon, svg16, svg24, withAlpha } from './chunk-BZQM2XO7.js'; +export { Drawer, KeymapManager, Tooltip, drawerController, tooltipController } from './chunk-TO3GIK7Z.js'; +export { CALLOUT_CSS, CALLOUT_STYLE_ID, CalloutBubble, ColorField, DatePicker, Dialog, FIELD_GAP_PX, GlyphSelect, Menu, NumberInput, Popover, Select, Switch, TextArea, TextField, WIDTH_FIELD_OPTIONS, applyPlotOverlayTokens, applyThemeTokens, blendOver, buildColorPicker, buildFieldControl, buildPalette, calloutPanelRows, clampNumber, closeColorPopover, closeOpenPopovers, closeWidthPopover, closesPanel, colorField, colorPickerController, combineColor, datePickerController, decorateSelectScroll, dialogController, ensureUIHost, eventDismissedPopover, fieldGrid, fieldGridColumns, fieldRow, fieldSection, fieldSeparator, fillSelectList, glyphSelectController, hslHex, insetRect, intersectRects, isPopoverOpen, isoDate, lineWidthGlyph, menuController, nextUid, normalizeDateInput, normalizeProps, numberInputController, openPopoverTrigger, openSelectList, placePopover, popoverController, runMachine, selectController, snapToStep, splitColor, spreadProps, switchController, textAreaController, textFieldController, toggleSelectList, transparencyChecker, viewportRect, widthField, widthFieldOptions } from './chunk-G7B7ZCBF.js'; +export { FIELD_FOCUS_CSS, FIELD_FOCUS_RING, SURFACE_CLOSE_EVENT, SURFACE_OPEN_EVENT, iconEl, iconMarkup, injectStyles, overlayScrollbarCss, registerIcon, svg16, svg24, withAlpha } from './chunk-VHGACEHO.js'; diff --git a/console/frontend/vendor/vela/dist/vela.global.min.js b/console/frontend/vendor/vela/dist/vela.global.min.js index 1f760da..87162aa 100644 --- a/console/frontend/vendor/vela/dist/vela.global.min.js +++ b/console/frontend/vendor/vela/dist/vela.global.min.js @@ -1,9 +1,9 @@ -var Vela=(function(exports){'use strict';function Yt(r,e,t=1e3){return r===true?e:typeof r!="number"||!Number.isFinite(r)||r<=0?0:Math.min(r,t)}function Ud(r){return Yt(r,90,1e3)}function Yd(r){let e={style:false,duration:0};if(r===true)return {style:"settle",duration:650};if(r==="settle"||r==="grow")return {style:r,duration:650};if(r&&typeof r=="object"){let t=r,n=t.duration;return {style:t.style==="grow"?"grow":"settle",duration:typeof n=="number"&&Number.isFinite(n)&&n>0?Math.min(n,5e3):650}}return e}function Im(r){if(r===false)return {animZoom:0,animPan:0,animScroll:0,animAutoscale:0,animLiveBar:0,animIntro:{style:false,duration:0}};let e=r===true||r==null?{}:r,t=Yt(e.pan??true,110);return {animZoom:Yt(e.zoom??true,70),animPan:t,animScroll:e.scroll===void 0?t>0?130:0:Yt(e.scroll,130),animAutoscale:Yt(e.autoscale??true,80),animLiveBar:Ud(e.liveBar),animIntro:Yd(e.intro??true)}}function Ge(r){return r.kind!=="candle"&&r.kind!=="bar"&&r.kind!=="markers"}function Rt(r,e){return r.display?r.display[e]!==false:r.visible!==false}function ta(r){return Rt(r,"pane")||Rt(r,"priceScale")}var lr=class{constructor(){this.handlers=new Map;}on(e,t){let n=this.handlers.get(e);n||(n=new Set,this.handlers.set(e,n));let o=n;return o.add(t),()=>{o.delete(t);}}off(e,t){this.handlers.get(e)?.delete(t);}hasListeners(e){return (this.handlers.get(e)?.size??0)>0}emit(e,t){let n=this.handlers.get(e);if(n)for(let o of n)try{o(t);}catch(i){console.error(`[vela] event handler error for "${String(e)}"`,i);}}clear(){this.handlers.clear();}};var na=class{constructor(){this.records=new Map;this.counter=0;}nextId(e="ind",t=()=>false){let n;do this.counter+=1,n=`${e}-${this.counter}`;while(this.records.has(n)||t(n));return n}add(e){this.records.set(e.id,e);}get(e){return this.records.get(e)}remove(e){let t=this.records.get(e);return this.records.delete(e),t}all(){return [...this.records.values()]}};function Am(r,e){return `${r}#${e}`}var ci=new Map;function Vn(r){ci.set(r.type,r);}function Rm(r){ci.delete(r);}function di(r){return ci.get(r)}function Dm(){return [...ci.keys()]}function ra(){return [...ci.values()]}var oa=class{constructor(e,t,n){this.feed=e;this.market=t;this.onBar=n;this.unsubscribe=null;}start(){this.unsubscribe||(this.unsubscribe=this.feed.subscribe(this.market,this.onBar));}stop(){this.unsubscribe?.(),this.unsubscribe=null;}};var Jr=class{constructor(e,t,n,o,i){this.controller=n;this.schema=[];this.propsSchema=[];this.visibleState=true;this.bus=new lr;this.id=e,this.title=t,o!==void 0&&(this.source=o),i!==void 0&&(this.nativeType=i);}get inputs(){return this.schema}get props(){return this.propsSchema}get visible(){return this.visibleState}inputValues(){return this.controller.inputValuesOf(this.id)}propValues(){return this.controller.propValuesOf(this.id)}setInput(e,t){this.controller.applyInputs(this.id,{[e]:t});}setInputs(e){this.controller.applyInputs(this.id,e);}setProp(e,t){this.controller.applyProps(this.id,{[e]:t});}setProps(e){this.controller.applyProps(this.id,e);}updateCode(e){this.controller.updateCode(this.id,e);}setVisible(e){this.controller.setVisible(this.id,e);}moveTo(e){this.controller.moveIndicator(this.id,e);}on(e,t){return this.bus.on(e,t)}context(e){return this.controller.getIndicatorContext(this.id,e)}remove(){this.controller.removeIndicator(this.id);}setSchema(e){this.schema=e;}setPropsSchema(e){this.propsSchema=e;}setSource(e){this.source=e;}setVisibleState(e){this.visibleState=e;}emit(e,t){this.bus.emit(e,t);}};function oS(r){let e={};for(let o of r.series)e[o.kind]=(e[o.kind]??0)+1;let t=o=>o?.filter(i=>i.overlay===true).length??0,n=t(r.series)+t(r.fills)+t(r.backgrounds)+t(r.lines)+t(r.boxes)+t(r.labels)+t(r.polylines)+t(r.linefills)+t(r.tables);return {id:r.id,title:r.title,overlay:r.overlay,paneId:r.paneId,native:!!r.native,nativeType:r.native?.type,series:e,fills:r.fills.length,backgrounds:r.backgrounds.length,priceLines:r.priceLines.length,lines:r.lines?.length??0,boxes:r.boxes?.length??0,labels:r.labels?.length??0,polylines:r.polylines?.length??0,linefills:r.linefills?.length??0,tables:r.tables?.length??0,barColors:r.barColors?.length??0,trades:r.trades?.length??0,inputs:r.inputs.length,forcedOverlay:n}}function Om(r){let e=r.map(oS),t=n=>e.reduce((o,i)=>o+n(i),0);return {indicators:e,totals:{panes:new Set(e.map(n=>n.paneId??"price")).size,series:t(n=>Object.values(n.series).reduce((o,i)=>o+i,0)),fills:t(n=>n.fills),backgrounds:t(n=>n.backgrounds),priceLines:t(n=>n.priceLines),lines:t(n=>n.lines),boxes:t(n=>n.boxes),labels:t(n=>n.labels),polylines:t(n=>n.polylines),linefills:t(n=>n.linefills),tables:t(n=>n.tables),barColors:t(n=>n.barColors),trades:t(n=>n.trades),forcedOverlay:t(n=>n.forcedOverlay)}}}var iS={"1D":864e5,"1W":6048e5,"1M":2592e6,"3M":7776e6,"6M":15552e6,"1Y":31536e6,"5Y":15768e7};function Nm(r,e){if(e.length===0)return null;let t=e[0].time,n=e[e.length-1].time;if(r==="ALL")return {from:t,to:n};let o;return r==="YTD"?o=Date.UTC(new Date(n).getUTCFullYear(),0,1):o=n-iS[r],{from:Math.max(t,o),to:n}}var nt="#2962ff",eo="#38c0fd",O="#089981",D="#f23645",A="#787b86",Vm="#e0b400",U="#ff9800",ce="#5b9cf6",Bm="#ff5d00",ia="#0ecb81",sa="#f6465d",cO="#f97316",dO="#0ea5e9",uO="#9ca3af",ui="#3b82f6",_m="#9aa0ad",Hm="#1e293b",zm="#475569",Wm="#595959",Gm=nt,$m=D,Um="#d500f9",Fm=[nt,O,D,U,"#7e57c2","#26a69a",ce,"#e573b5"];function hO(r){let e=0;for(let t=0;t>>0;return Fm[e%Fm.length]}var _=eo;function Kd(){return {lineColor:_,lineWidth:2,lineStyle:"solid"}}function gn(r=""){return {value:r,size:"normal",hAlign:"left",vAlign:"top"}}var aa=class aa{constructor(e){this.locked=false;this.visible=true;this.zIndex=0;this.id=e.id??`dw-${aa.seq+=1}`,this.paneId=e.paneId,this.anchors=(e.anchors??[]).map(t=>({time:t.time,price:t.price})),this.style=e.style?{...e.style}:Kd(),this.text=e.text?{...e.text}:void 0,this.locked=e.locked??false,this.visible=e.visible??true,this.zIndex=e.zIndex??0,this.createdAt=e.createdAt??Date.now(),e.props&&this.readProps(e.props);}isComplete(){return this.anchors.length>=this.anchorSchema().min}placementMode(){return "click"}onPlaced(e){}constrainHandleDrag(e){}translateBody(e,t,n){return n.map(o=>({time:o.time+e,price:o.price+t}))}timeExtent(){if(this.anchors.length===0)return null;let e=1/0,t=-1/0;for(let n of this.anchors)n.timet&&(t=n.time);return {min:e,max:t}}editableLevels(){return null}applySettings(e){for(let[t,n]of Object.entries(e))t.startsWith("text.")&&!this.text&&(this.text=gn()),Ym(this,t,n);}applyProps(e){this.readProps(e);}serialize(){return {id:this.id,type:this.type,paneId:this.paneId,anchors:this.anchors.map(e=>({time:e.time,price:e.price})),style:{...this.style},text:this.text?{...this.text}:void 0,locked:this.locked,visible:this.visible,zIndex:this.zIndex,createdAt:this.createdAt,props:this.writeProps()}}writeProps(){}readProps(e){}};aa.seq=0;var K=aa;function Ym(r,e,t){let n=e.split("."),o=r;for(let i=0;i${r}`}function B(r,e=""){return `${r}`}function jd(r){return `${r}`}var Y=Km;H("style-candles",Y(''));H("style-bars",Y(''));H("style-line",Y(''));H("style-area",Y(''));H("style-baseline",Y(''));H("style-heikinashi",Y(''));H("indicators",Y(''));H("undo",Y(''));H("redo",Y(''));H("objects",Y(''));H("clock",Y(''));H("calendar",Y(''));H("datawindow",Y(''));H("camera",Y(''));H("gear",Y(''));H("search",Y(''));H("bell",Y(''));H("market-open",B(''));H("market-pre",B(''));H("market-post",B(''));H("market-extended",B(''));H("market-closed",B(''));H("market-holiday",B(''));H("chevron-right",Y(''));H("chevron-left",Y(''));H("chevron-down",Y(''));H("chevron-up",Y(''));H("chevrons-right",Y(''));H("chevrons-left",Y(''));H("replay",Y(''));H("check",Y(''));H("close",Y(''));H("pin",Y(''));H("pin-filled",Y(''));H("eye",Y(''));H("eye-off",Y(''));H("lock",Y(''));H("unlock",Y(''));H("trash",Y(''));H("group",Y(''));H("ungroup",Y(''));H("clone",Y(''));H("arrow-up",Y(''));H("arrow-down",Y(''));H("move-vertical",Y(''));H("move",Y(''));H("pen",Y(''));H("wave",Y(''));H("folder-plus",Y(''));H("folder-minus",Y(''));H("collapse",Y(''));H("expand",Y(''));H("plus",Y(''));H("minus",Y(''));H("maximize",Y(''));H("restore",Y(''));H("star",Y(''));H("star-filled",Y('','fill="currentColor"'));H("grip",Y('','fill="currentColor" stroke="none"'));H("kebab",Y('','fill="currentColor" stroke="none"'));H("burger",Y(''));H("info",Y(''));H("reset",Y(''));H("pane-collapse",Y(''));H("pane-expand",Y(''));H("cursor",B('','fill="currentColor" stroke="none"'));H("ruler",B(''));H("magnet",B(''));H("eraser",B(''));H("pen-lock",B(''));H("pen-sync",B(''));H("brush",B(''));H("bucket",B(''));H("type",B(''));H("bold",B('','stroke-width="2.4"'));H("italic",B('','stroke-width="2.2"'));H("price-delta",B(''));H("date-delta",B(''));H("bring-front",B(''));H("send-back",B(''));H("r-squared",'R\xB2');H("bands",B(''));H("dedekind",B(''));H("sonic",B(''));H("supersonic",B(''));var rt=[{value:"solid",label:"Solid"},{value:"dashed",label:"Dashed"},{value:"dotted",label:"Dotted"}],G=[{path:"style.lineColor",label:"Line color",kind:"color",group:"line"},{path:"style.lineWidth",label:"Line width",kind:"number",min:1,max:10,step:1,group:"line"},{path:"style.lineStyle",label:"Line style",kind:"lineStyle",options:rt,group:"line"}],fe=[{path:"style.fillColor",label:"Fill color",kind:"color",group:"fill"}],Dt=[{value:"small",label:"Small"},{value:"normal",label:"Normal"},{value:"large",label:"Large"},{value:"huge",label:"Huge"}],$=[{path:"text.value",label:"Text",kind:"text",group:"text"},{path:"text.color",label:"Text color",kind:"color",group:"text"},{path:"text.size",label:"Text size",kind:"select",options:Dt,group:"text"},{path:"text.bold",label:"Bold",kind:"boolean",group:"text"},{path:"text.italic",label:"Italic",kind:"boolean",group:"text"}];function ae(r,e,t,n,o,i){let s=o-t,a=i-n,l=s*s+a*a;if(l<=1e-9)return Math.hypot(r-t,e-n);let c=((r-t)*s+(e-n)*a)/l;return c=c<0?0:c>1?1:c,Math.hypot(r-(t+c*s),e-(n+c*a))}function no(r,e,t){let n=1/0;for(let o=1;o=a&&r<=l&&e>=c&&e<=d}function Kt(r,e,t){let n=false;for(let o=0,i=t.length-1;oe!=a[1]>e&&r<(a[0]-s[0])*(e-s[1])/(a[1]-s[1])+s[0]&&(n=!n);}return n}function qd(r,e,t,n,o,i,s,a){let l=t-r,c=n-e,d=s-o,u=a-i,h=d*c-u*l;if(Math.abs(h)<1e-9)return null;let p=((i-e)*l-(o-r)*c)/h;return p<0||p>1?null:[o+p*d,i+p*u]}function j(r,e,t,n=6){for(let o=0;o=e;return c?m?[r,e,t,s]:[r,e,t,0]:m?[r,0,t,n]:[r,s,t,n]}let d=(n-e)/a,u=m=>e+d*(m-r),h=l?-2:Math.min(r,t),p=c?i+2:Math.max(r,t);return [h,u(h),p,u(p)]}var la=class extends K{constructor(){super(...arguments);this.type="trendline";}anchorSchema(){return {min:2,max:2,slots:[{role:"p1",free:"both"},{role:"p2",free:"both"}]}}pixels(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);return i==null||s==null?null:[t.xOf(n.time),i,t.xOf(o.time),s]}hitTest(t,n,o,i){let s=this.pixels(o);return s!=null&&ae(t,n,s[0],s[1],s[2],s[3])<=i}handlePoints(t){let n=this.pixels(t);return n?[[n[0],n[1]],[n[2],n[3]]]:[]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.pixels(t);if(!n)return null;let o=Math.min(n[0],n[2]),i=Math.min(n[1],n[3]);return {x:o,y:i,w:Math.abs(n[2]-n[0]),h:Math.abs(n[3]-n[1])}}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}schema(){return {fields:[...G,{path:"style.arrowRight",label:"Arrow",kind:"boolean",group:"line"},...$]}}};var ca=class extends K{constructor(){super(...arguments);this.type="hline";}anchorSchema(){return {min:1,max:1,slots:[{role:"p",free:"y"}]}}y(t){let n=this.anchors[0];return n?t.yOf(n.price,this.paneId):null}hitTest(t,n,o,i){let s=this.y(o);return s!=null&&Math.abs(n-s)<=i}handlePoints(t){let n=this.anchors[0],o=this.y(t);return !n||o==null?[]:[[t.xOf(n.time),o]]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.y(t);return n==null?null:{x:0,y:n-1,w:t.width,h:2}}priceRange(){let t=this.anchors[0];return t?{min:t.price,max:t.price}:null}timeExtent(){return null}schema(){return {fields:[...G,...$]}}};var da=class extends K{constructor(){super(...arguments);this.type="ray";}anchorSchema(){return {min:2,max:2,slots:[{role:"p1",free:"both"},{role:"p2",free:"both"}]}}pixels(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);return i==null||s==null?null:[t.xOf(n.time),i,t.xOf(o.time),s]}hitTest(t,n,o,i){let s=this.pixels(o);if(!s)return false;let[a,l,c,d]=Pe(s[0],s[1],s[2],s[3],"right",o.width,o.height);return ae(t,n,a,l,c,d)<=i}handlePoints(t){let n=this.pixels(t);return n?[[n[0],n[1]],[n[2],n[3]]]:[]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.pixels(t);return n?{x:Math.min(n[0],n[2]),y:Math.min(n[1],n[3]),w:Math.abs(n[2]-n[0]),h:Math.abs(n[3]-n[1])}:null}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}schema(){return {fields:[...G,...$]}}};var Bn=class extends K{anchorSchema(){return {min:2,max:2,slots:[{role:"p1",free:"both"},{role:"p2",free:"both"}]}}pixels(e){let t=this.anchors[0],n=this.anchors[1];if(!t||!n)return null;let o=e.yOf(t.price,this.paneId),i=e.yOf(n.price,this.paneId);return o==null||i==null?null:[e.xOf(t.time),o,e.xOf(n.time),i]}hitTest(e,t,n,o){let i=this.pixels(n);return i!=null&&ae(e,t,i[0],i[1],i[2],i[3])<=o}handlePoints(e){let t=this.pixels(e);return t?[[t[0],t[1]],[t[2],t[3]]]:[]}hitHandle(e,t,n,o){return j(e,t,this.handlePoints(n),o+3)}bounds(e){let t=this.pixels(e);return t?{x:Math.min(t[0],t[2]),y:Math.min(t[1],t[3]),w:Math.abs(t[2]-t[0]),h:Math.abs(t[3]-t[1])}:null}priceRange(){let e=this.anchors[0],t=this.anchors[1];return !e||!t?null:{min:Math.min(e.price,t.price),max:Math.max(e.price,t.price)}}schema(){return {fields:[...G,...$]}}};var ua=class extends Bn{constructor(){super(...arguments);this.type="extendedline";}hitTest(t,n,o,i){let s=this.pixels(o);if(!s)return false;let[a,l,c,d]=Pe(s[0],s[1],s[2],s[3],"both",o.width,o.height);return ae(t,n,a,l,c,d)<=i}timeExtent(){return null}};var ha=class extends K{constructor(){super(...arguments);this.type="vline";}anchorSchema(){return {min:1,max:1,slots:[{role:"p",free:"x"}]}}x(t){let n=this.anchors[0];return n?t.xOf(n.time):null}hitTest(t,n,o,i){let s=this.x(o);return s!=null&&Math.abs(t-s)<=i}handlePoints(t){let n=this.anchors[0],o=this.x(t);if(!n||o==null)return [];let i=t.yOf(n.price,this.paneId);return i==null?[]:[[o,i]]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.x(t);return n==null?null:{x:n-1,y:0,w:2,h:t.height}}priceRange(){return null}schema(){return {fields:[...G,...$]}}};var pa=class extends K{constructor(){super(...arguments);this.type="hray";}anchorSchema(){return {min:1,max:1,slots:[{role:"p",free:"both"}]}}pt(t){let n=this.anchors[0];if(!n)return null;let o=t.yOf(n.price,this.paneId);return o==null?null:[t.xOf(n.time),o]}hitTest(t,n,o,i){let s=this.pt(o);return s!=null&&ae(t,n,s[0],s[1],o.width,s[1])<=i}handlePoints(t){let n=this.pt(t);return n?[n]:[]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.pt(t);return n?{x:n[0],y:n[1]-1,w:Math.max(0,t.width-n[0]),h:2}:null}priceRange(){let t=this.anchors[0];return t?{min:t.price,max:t.price}:null}timeExtent(){let t=this.anchors[0];return t?{min:t.time,max:Number.POSITIVE_INFINITY}:null}schema(){return {fields:[...G,...$]}}};var ma=class extends K{constructor(){super(...arguments);this.type="crossline";}anchorSchema(){return {min:1,max:1,slots:[{role:"p",free:"both"}]}}pt(t){let n=this.anchors[0];if(!n)return null;let o=t.yOf(n.price,this.paneId);return o==null?null:[t.xOf(n.time),o]}hitTest(t,n,o,i){let s=this.pt(o);return s!=null&&(Math.abs(n-s[1])<=i||Math.abs(t-s[0])<=i)}handlePoints(t){let n=this.pt(t);return n?[n]:[]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.pt(t);return n?{x:n[0]-1,y:n[1]-1,w:2,h:2}:null}priceRange(){let t=this.anchors[0];return t?{min:t.price,max:t.price}:null}timeExtent(){return null}schema(){return {fields:[...G,...$]}}};var fa=class extends Bn{constructor(){super(...arguments);this.type="infoline";}};var ga=class extends Bn{constructor(){super(...arguments);this.type="trendangle";}};var ba=class extends K{constructor(){super(...arguments);this.type="box";}anchorSchema(){return {min:2,max:2,slots:[{role:"c1",free:"both"},{role:"c2",free:"both"}]}}rect(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);return i==null||s==null?null:{x1:t.xOf(n.time),y1:i,x2:t.xOf(o.time),y2:s}}hitTest(t,n,o,i){let s=this.rect(o);return s?this.style.fillColor&&$e(t,n,s.x1,s.y1,s.x2,s.y2)?true:[[s.x1,s.y1,s.x2,s.y1],[s.x2,s.y1,s.x2,s.y2],[s.x2,s.y2,s.x1,s.y2],[s.x1,s.y2,s.x1,s.y1]].some(l=>ae(t,n,l[0],l[1],l[2],l[3])<=i):false}handlePoints(t){let n=this.rect(t);return n?[[n.x1,n.y1],[n.x2,n.y2]]:[]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.rect(t);return n?{x:Math.min(n.x1,n.x2),y:Math.min(n.y1,n.y2),w:Math.abs(n.x2-n.x1),h:Math.abs(n.y2-n.y1)}:null}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}schema(){return {fields:[...G.map(t=>({...t,label:t.label.replace("Line","Border")})),{path:"style.fillColor",label:"Fill color",kind:"color",group:"fill"},...$]}}};var sS={tiny:10,small:12,normal:14,large:18,huge:24,auto:14},_n=class extends K{defaultLabel(){return "Text"}labelText(){return this.text?.value??this.defaultLabel()}anchorSchema(){return {min:1,max:1,slots:[{role:"p",free:"both"}]}}box(e){let t=this.anchors[0];if(!t)return null;let n=e.yOf(t.price,this.paneId);if(n==null)return null;let o=sS[this.text?.size??"normal"]??14,i=this.labelText().split(` -`),s=Math.max(1,...i.map(a=>a.length));return {x:e.xOf(t.time),y:n,w:Math.max(12,s*o*.6)+8,h:i.length*o*1.4+4}}hitTest(e,t,n,o){let i=this.box(n);return i!=null&&$e(e,t,i.x,i.y,i.x+i.w,i.y+i.h)}handlePoints(e){let t=this.anchors[0],n=t?e.yOf(t.price,this.paneId):null;return t&&n!=null?[[e.xOf(t.time),n]]:[]}hitHandle(e,t,n,o){return j(e,t,this.handlePoints(n),o+3)}bounds(e){return this.box(e)}priceRange(){let e=this.anchors[0];return e?{min:e.price,max:e.price}:null}};var bn=class extends _n{constructor(t){super(t);this.type="text";this.text||(this.text={...gn(),size:"large"});}schema(){return {fields:[...$],textIsContent:true}}};var cr=class extends _n{constructor(t){super(t);this.type="note";this.text||(this.text=gn("Note"));}defaultLabel(){return "Note"}schema(){return {fields:[...G,...fe,...$],textIsContent:true}}};var dr=class extends _n{constructor(){super(...arguments);this.type="pricelabel";}labelText(){let t=this.anchors[0]?.price;return t==null?"0.00":t.toFixed(2)}schema(){return {fields:[...G,...fe,...$.filter(t=>t.path!=="text.value")]}}};var aS={tiny:10,small:12,normal:14,large:18,huge:24,auto:14},vt=class extends K{constructor(e){super(e),this.text||(this.text=gn(this.defaultLabel()));}defaultLabel(){return "Callout"}labelText(){return this.text?.value??this.defaultLabel()}anchorSchema(){return {min:2,max:2,slots:[{role:"target",free:"both"},{role:"box",free:"both"}]}}box(e){let t=this.anchors[1];if(!t)return null;let n=e.yOf(t.price,this.paneId);if(n==null)return null;let o=aS[this.text?.size??"normal"]??14,i=this.labelText().split(` -`),s=Math.max(1,...i.map(c=>c.length)),a=Math.max(20,s*o*.6)+16,l=i.length*o*1.4+12;return {x:e.xOf(t.time)-a/2,y:n-l/2,w:a,h:l}}points(e){let t=this.anchors[0],n=this.anchors[1];if(!t||!n)return null;let o=e.yOf(t.price,this.paneId),i=e.yOf(n.price,this.paneId);return o==null||i==null?null:[[e.xOf(t.time),o],[e.xOf(n.time),i]]}hitTest(e,t,n,o){let i=this.box(n);if(i&&$e(e,t,i.x,i.y,i.x+i.w,i.y+i.h,o))return true;let s=this.points(n);return s!=null&&ae(e,t,s[0][0],s[0][1],s[1][0],s[1][1])<=o}handlePoints(e){let t=this.points(e);return t?[t[0]]:[]}hitHandle(e,t,n,o){return j(e,t,this.handlePoints(n),o+3)}translateBody(e,t,n){let o=n[0],i=n[1];return !o||!i?n.map(s=>({time:s.time+e,price:s.price+t})):[{time:o.time,price:o.price},{time:i.time+e,price:i.price+t}]}bounds(e){return this.box(e)}priceRange(){let e=this.anchors[0],t=this.anchors[1];return !e||!t?null:{min:Math.min(e.price,t.price),max:Math.max(e.price,t.price)}}schema(){return {fields:[...G,...fe,...$],textIsContent:true}}};var Xt=class extends vt{constructor(){super(...arguments);this.type="callout";}};var ur=class extends vt{constructor(){super(...arguments);this.type="pricenote";}defaultLabel(){return ""}labelText(){let t=this.anchors[0]?.price;return t==null?"0.00":t.toFixed(2)}schema(){return {fields:[...G,...fe,...$.filter(t=>t.path!=="text.value")]}}};var hr=class extends vt{constructor(){super(...arguments);this.type="comment";}defaultLabel(){return "Comment"}};var pr=class extends vt{constructor(){super(...arguments);this.type="signpost";}defaultLabel(){return "Signpost"}};var ve=class extends K{hitTest(e,t,n,o){let i=this.geometry(n);return i?this.style.fillColor&&i.fill&&Kt(e,t,i.fill)?true:i.segments.some(s=>ae(e,t,s[0],s[1],s[2],s[3])<=o):false}handlePoints(e){let t=[];for(let n of this.anchors){let o=e.yOf(n.price,this.paneId);if(o==null)return [];t.push([e.xOf(n.time),o]);}return t}hitHandle(e,t,n,o){return j(e,t,this.handlePoints(n),o+3)}bounds(e){let t=this.handlePoints(e);if(t.length===0)return null;let n=t.map(a=>a[0]),o=t.map(a=>a[1]),i=Math.min(...n),s=Math.min(...o);return {x:i,y:s,w:Math.max(...n)-i,h:Math.max(...o)-s}}};var va=class extends ve{constructor(){super(...arguments);this.type="parallelchannel";}anchorSchema(){return {min:3,max:3,slots:[{role:"p1",free:"both"},{role:"p2",free:"both"},{role:"offset",free:"y"}]}}offset(){let t=this.anchors[0],n=this.anchors[1],o=this.anchors[2];return !t||!n||!o?0:o.price-(t.price+n.price)/2}handlePoints(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return [];let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);if(i==null||s==null)return [];let a=[[t.xOf(n.time),i],[t.xOf(o.time),s]],l=this.anchors[2];if(l){let c=t.yOf(l.price,this.paneId);c!=null&&a.push([t.xOf((n.time+o.time)/2),c]);}return a}timeExtent(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.time,n.time),max:Math.max(t.time,n.time)}}geometry(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=this.offset(),s=t.xOf(n.time),a=t.xOf(o.time),l=t.yOf(n.price,this.paneId),c=t.yOf(o.price,this.paneId),d=t.yOf(n.price+i,this.paneId),u=t.yOf(o.price+i,this.paneId);return l==null||c==null||d==null||u==null?null:{segments:[[s,l,a,c],[s,d,a,u]],fill:[[s,l],[a,c],[a,u],[s,d]]}}priceRange(){let t=this.anchors[0],n=this.anchors[1];if(!t||!n)return null;let o=this.offset(),i=[t.price,n.price,t.price+o,n.price+o],s=this.anchors[2];return s&&i.push(s.price),{min:Math.min(...i),max:Math.max(...i)}}schema(){return {fields:[...G,...fe,...$]}}};var ya=class extends ve{constructor(){super(...arguments);this.type="disjointchannel";}anchorSchema(){return {min:4,max:4,slots:[{role:"top1",free:"both"},{role:"top2",free:"both"},{role:"bot1",free:"both"},{role:"bot2",free:"both"}]}}seg(t,n,o){let i=this.anchors[t],s=this.anchors[n];if(!i||!s)return null;let a=o.yOf(i.price,this.paneId),l=o.yOf(s.price,this.paneId);return a==null||l==null?null:[o.xOf(i.time),a,o.xOf(s.time),l]}geometry(t){let n=this.seg(0,1,t),o=this.seg(2,3,t),i=[n,o].filter(a=>a!=null);if(i.length===0)return null;let s=n&&o?[[n[0],n[1]],[n[2],n[3]],[o[2],o[3]],[o[0],o[1]]]:null;return {segments:i,fill:s}}priceRange(){if(this.anchors.length===0)return null;let t=this.anchors.map(n=>n.price);return {min:Math.min(...t),max:Math.max(...t)}}schema(){return {fields:[...G,...fe,...$]}}};var wa=class extends ve{constructor(){super(...arguments);this.type="flattopbottom";}anchorSchema(){return {min:3,max:3,slots:[{role:"p1",free:"both"},{role:"p2",free:"both"},{role:"flat",free:"y"}]}}handlePoints(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return [];let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);if(i==null||s==null)return [];let a=[[t.xOf(n.time),i],[t.xOf(o.time),s]],l=this.anchors[2];if(l){let c=t.yOf(l.price,this.paneId);c!=null&&a.push([t.xOf((n.time+o.time)/2),c]);}return a}timeExtent(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.time,n.time),max:Math.max(t.time,n.time)}}geometry(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.xOf(n.time),s=t.xOf(o.time),a=t.yOf(n.price,this.paneId),l=t.yOf(o.price,this.paneId);if(a==null||l==null)return null;let c=this.anchors[2];if(!c)return {segments:[[i,a,s,l]],fill:null};let d=t.yOf(c.price,this.paneId);return d==null?null:{segments:[[i,a,s,l],[i,d,s,d]],fill:[[i,a],[s,l],[s,d],[i,d]]}}priceRange(){let t=this.anchors[0],n=this.anchors[1];if(!t||!n)return null;let o=[t.price,n.price],i=this.anchors[2];return i&&o.push(i.price),{min:Math.min(...o),max:Math.max(...o)}}schema(){return {fields:[...G,...fe,...$]}}};var lS=2;function Xm(){return {midColor:A,midStyle:"solid",upperColor:O,upperStyle:"solid",lowerColor:D,lowerStyle:"solid",upperFill:`${O}26`,lowerFill:`${D}26`,showR2:true}}function jm(r){let e=r.length;if(e<2)return null;let t=0,n=0,o=0,i=0,s=0;for(let m=0;mae(t,n,c[0],c[1],c[2],c[3])<=i)}handlePoints(t){let n=this.layout(t);if(n)return [[n.x0,n.midY0],[n.x1,n.midY1]];let o=[];for(let i of this.anchors){let s=t.yOf(i.price,this.paneId);if(s==null)return [];o.push([t.xOf(i.time),s]);}return o}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.band(t);if(!n)return null;let o=n.map(l=>l[0]),i=n.map(l=>l[1]),s=Math.min(...o),a=Math.min(...i);return {x:s,y:a,w:Math.max(...o)-s,h:Math.max(...i)-a}}priceRange(){if(this.cachedRange)return this.cachedRange;let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}schema(){return {fields:[{path:"reg.midColor",label:"Midline color",kind:"color",group:"line"},{path:"reg.midStyle",label:"Midline style",kind:"lineStyle",group:"line"},{path:"reg.upperColor",label:"Upper line color",kind:"color",group:"line"},{path:"reg.upperStyle",label:"Upper line style",kind:"lineStyle",group:"line"},{path:"reg.lowerColor",label:"Lower line color",kind:"color",group:"line"},{path:"reg.lowerStyle",label:"Lower line style",kind:"lineStyle",group:"line"},{path:"reg.upperFill",label:"Upper fill",kind:"color",group:"fill"},{path:"reg.lowerFill",label:"Lower fill",kind:"color",group:"fill"},{path:"reg.showR2",label:"Show R\xB2",kind:"boolean",group:"behavior"}]}}writeProps(){return {...this.reg}}readProps(t){this.reg={...Xm(),...t};}};var qm=`${ce}00`;function Zm(){return {midColor:ce,midStyle:"solid",multiplier:1,upperColor:qm,upperStyle:"solid",lowerColor:qm,lowerStyle:"solid",bandFill:`${ce}33`}}function Qm(r,e){let t=r.length;if(t<1)return null;let n=0;for(let c of r)n+=c.volume>0?c.volume:0;let o=n>0,i=0,s=0,a=0,l=[];for(let c=0;c0?s/i:u,m=i>0?Math.max(0,a/i-p*p):0,f=Math.sqrt(m)*e;l.push({time:d.time,mid:p,upper:p+f,lower:p-f});}return l}var mr=class extends K{constructor(t){super(t);this.type="anchoredvwap";this.cachedRange=null;this.cachedExtent=null;this.vwap||(this.vwap=Zm());}anchorSchema(){return {min:1,max:1,slots:[{role:"anchor",free:"x"}]}}series(t){let n=this.anchors[0];if(!n)return null;let o=t.barsInRange?.(n.time,Number.POSITIVE_INFINITY)??null;if(!o||o.length<1)return null;let i=Qm(o.map(s=>({time:s.time,high:s.high,low:s.low,close:s.close,volume:s.volume??0})),this.vwap.multiplier);if(i&&i.length>0){let s=1/0,a=-1/0;for(let l of i)l.lowera&&(a=l.upper);this.cachedRange={min:s,max:a},this.cachedExtent={min:i[0].time,max:i[i.length-1].time};}return i}layout(t){let n=this.series(t);if(!n)return null;let o=[],i=[],s=[];for(let a of n){let l=t.xOf(a.time),c=t.yOf(a.mid,this.paneId),d=t.yOf(a.upper,this.paneId),u=t.yOf(a.lower,this.paneId);c==null||d==null||u==null||(o.push([l,c]),i.push([l,d]),s.push([l,u]));}return o.length>0?{mid:o,upper:i,lower:s}:null}bandPolygon(t){return [...t.upper,...[...t.lower].reverse()]}hitTest(t,n,o,i){let s=this.layout(o);return s?Kt(t,n,this.bandPolygon(s))?true:Zd(t,n,s.mid,i)||Zd(t,n,s.upper,i)||Zd(t,n,s.lower,i):false}handlePoints(t){let n=this.layout(t);if(n&&n.mid.length>0)return [n.mid[0]];let o=this.anchors[0];if(!o)return [];let i=t.yOf(o.price,this.paneId);return i==null?[]:[[t.xOf(o.time),i]]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.layout(t);if(!n)return null;let o=[...n.upper,...n.lower],i=o.map(c=>c[0]),s=o.map(c=>c[1]),a=Math.min(...i),l=Math.min(...s);return {x:a,y:l,w:Math.max(...i)-a,h:Math.max(...s)-l}}priceRange(){return this.cachedRange}timeExtent(){return this.cachedExtent}schema(){return {fields:[{path:"vwap.midColor",label:"VWAP color",kind:"color",group:"line"},{path:"vwap.midStyle",label:"VWAP style",kind:"lineStyle",group:"line"},{path:"vwap.multiplier",label:"Band multiplier",kind:"number",min:.5,max:5,step:.5,group:"behavior"},{path:"vwap.upperColor",label:"Upper band color",kind:"color",group:"line"},{path:"vwap.lowerColor",label:"Lower band color",kind:"color",group:"line"},{path:"vwap.bandFill",label:"Band fill",kind:"color",group:"fill"}]}}writeProps(){return {...this.vwap}}readProps(t){this.vwap={...Zm(),...t};}};function Zd(r,e,t,n){for(let o=1;o=e?e-1:r}function ef(r,e,t){let n=r.length,o=0,i=0;for(let d=0;di&&(i=u);}let s=o*Math.min(1,Math.max(0,t)),a=e,l=e,c=i;for(;c0||l0?r[a-1].up+r[a-1].down:-1,u=ld?(l+=1,c+=u):(a-=1,c+=d);}return {vaFrom:a,vaTo:l}}function tf(r,e,t,n){let o=n.volume;if(!(o>0))return;let i=r.length,s=n.close>=n.open?"up":"down",a=new Set;for(let l of [n.open,n.high,n.low,n.close])a.add(pS(Math.floor((l-e)/t),i));for(let l of a)r[l][s]+=o;}function nf(r){let e=0,t=0;for(let n=0;ne&&(e=o,t=n);}return e>0?{poc:t,maxTotal:e}:null}function rf(r,e,t){let n=1/0,o=-1/0;for(let p of r)p.volume>0&&(p.lowo&&(o=p.high));if(!Number.isFinite(n))return null;let i=o>n?Math.max(1,Math.round(e)):1,s=o>n?(o-n)/i:1,a=Array.from({length:i},(p,m)=>({price:n+m*s,up:0,down:0}));for(let p of r)tf(a,n,s,p);let l=nf(a);if(!l)return null;let{poc:c,maxTotal:d}=l,{vaFrom:u,vaTo:h}=ef(a,c,t);return {rows:a,rowH:s,min:n,maxTotal:d,poc:c,vaFrom:u,vaTo:h}}function of(r,e,t,n){let o=rf(r,e,t);if(!o)return null;if(!n||r.length<1)return {profile:o,developingPoc:[],developingVaHigh:[],developingVaLow:[]};let{min:i,rowH:s}=o,a=o.rows.length,l=Array.from({length:a},(h,p)=>({price:i+p*s,up:0,down:0})),c=[],d=[],u=[];for(let h of r){tf(l,i,s,h);let p=nf(l);if(!p)continue;let{poc:m}=p,{vaFrom:f,vaTo:g}=ef(l,m,t);c.push({time:h.time,price:l[m].price+s/2}),d.push({time:h.time,price:l[g].price+s}),u.push({time:h.time,price:l[f].price});}return {profile:o,developingPoc:c,developingVaHigh:d,developingVaLow:u}}var gt=class extends K{constructor(t){super(t);this.type="fixedrangevp";this.cachedRange=null;this.frvp||(this.frvp=Jm());}anchorSchema(){return {min:2,max:2,slots:[{role:"start",free:"x"},{role:"end",free:"x"}]}}barsInSpan(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=Math.min(n.time,o.time),s=Math.max(n.time,o.time),a=t.barsInRange?.(i,s)??null;return !a||a.length<1?null:a.map(l=>({time:l.time,open:l.open,high:l.high,low:l.low,close:l.close,volume:l.volume??0}))}compute(t){let n=this.barsInSpan(t);if(!n)return null;let o=this.frvp,i=o.showDevelopingPoc||o.showDevelopingVa,s=of(n,o.rows,o.valueAreaPct/100,i);if(s){let{profile:a}=s;this.cachedRange={min:a.min,max:a.min+a.rowH*a.rows.length};}return s}layout(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=this.compute(t);if(!i)return null;let{profile:s}=i,a=Math.min(n.time,o.time),l=Math.max(n.time,o.time),c=t.xOf(a),d=t.xOf(l),u=Math.abs(d-c),h=Math.max(1,Math.min(100,Math.max(0,this.frvp.widthPct))/100*u),p=this.frvp.anchor==="left",m=p?Math.min(c,d):Math.max(c,d),f=p?1:-1,g=[];for(let S=0;S<=s.rows.length;S+=1){let L=t.yOf(s.min+S*s.rowH,this.paneId);if(L==null)return null;g.push(L);}let b=S=>t.yOf(S,this.paneId),y=s.rows[s.vaTo].price+s.rowH,w=s.rows[s.vaFrom].price,C=s.rows[s.poc].price+s.rowH/2,M=S=>{let L=[];for(let v of S){let k=b(v.price);k!=null&&L.push([t.xOf(v.time),k]);}return L};return {x0:Math.min(c,d),x1:Math.max(c,d),anchorX:m,maxW:h,grow:f,profile:s,yEdges:g,vahY:b(y),valY:b(w),pocY:b(C),developingPoc:M(i.developingPoc),developingVaHigh:M(i.developingVaHigh),developingVaLow:M(i.developingVaLow)}}hitTest(t,n,o,i){let s=this.layout(o);if(!s)return false;let a=s.grow===1?s.anchorX:s.anchorX-s.maxW,l=s.grow===1?s.anchorX+s.maxW:s.anchorX,c=Math.min(s.yEdges[0],s.yEdges[s.yEdges.length-1]),d=Math.max(s.yEdges[0],s.yEdges[s.yEdges.length-1]);if(Kt(t,n,[[a,c],[l,c],[l,d],[a,d]]))return true;let u=[[s.x0,s.vahY],[s.x0,s.valY],[s.x0,s.pocY]];for(let[,h]of u)if(h!=null&&ae(t,n,s.x0,h,s.x1,h)<=i)return true;for(let h of [s.developingPoc,s.developingVaHigh,s.developingVaLow])for(let p=1;p{let b=t.yOf(g.price,this.paneId);return b==null?null:[t.xOf(g.time),b]},s=i(n),a=i(o);if(!s||!a)return null;let l=this.anchors[2];if(!l)return {segments:[[s[0],s[1],a[0],a[1]]],fill:null};let c=i(l);if(!c)return null;let d=(a[0]+c[0])/2,u=(a[1]+c[1])/2,h=d-s[0],p=u-s[1],m=t.width,f=t.height;return {segments:[Pe(s[0],s[1],d,u,"right",m,f),Pe(a[0],a[1],a[0]+h,a[1]+p,"right",m,f),Pe(c[0],c[1],c[0]+h,c[1]+p,"right",m,f),[a[0],a[1],c[0],c[1]]],fill:null}}priceRange(){if(this.anchors.length===0)return null;let t=this.anchors.map(n=>n.price);return {min:Math.min(...t),max:Math.max(...t)}}schema(){return {fields:[...G,...$]}}};var ro=class extends ve{anchorSchema(){return {min:3,max:3,slots:[{role:"pivot",free:"both"},{role:"upper",free:"both"},{role:"lower",free:"both"}]}}geometry(e){let t=this.anchors[0],n=this.anchors[1];if(!t||!n)return null;let o=g=>{let b=e.yOf(g.price,this.paneId);return b==null?null:[e.xOf(g.time),b]},i=o(t),s=o(n);if(!i||!s)return null;let a=this.anchors[2];if(!a)return {segments:[[i[0],i[1],s[0],s[1]]],fill:null};let l=o(this.medianStart(t,n,a)),c=o(a);if(!l||!c)return null;let d=(s[0]+c[0])/2,u=(s[1]+c[1])/2,h=d-l[0],p=u-l[1],m=e.width,f=e.height;return {segments:[Pe(l[0],l[1],d,u,"right",m,f),Pe(s[0],s[1],s[0]+h,s[1]+p,"right",m,f),Pe(c[0],c[1],c[0]+h,c[1]+p,"right",m,f),[s[0],s[1],c[0],c[1]],[i[0],i[1],s[0],s[1]]],fill:null}}priceRange(){if(this.anchors.length===0)return null;let e=this.anchors.map(t=>t.price);return {min:Math.min(...e),max:Math.max(...e)}}schema(){return {fields:[...G,...$]}}};var Ca=class extends ro{constructor(){super(...arguments);this.type="schiffpitchfork";}medianStart(t,n){return {time:t.time,price:(t.price+n.price)/2}}};var Sa=class extends ro{constructor(){super(...arguments);this.type="modifiedschiffpitchfork";}medianStart(t,n){return {time:(t.time+n.time)/2,price:(t.price+n.price)/2}}};var Ta=class extends ve{constructor(){super(...arguments);this.type="insidepitchfork";}anchorSchema(){return {min:3,max:3,slots:[{role:"pivot",free:"both"},{role:"upper",free:"both"},{role:"lower",free:"both"}]}}geometry(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=b=>{let y=t.yOf(b.price,this.paneId);return y==null?null:[t.xOf(b.time),y]},s=i(n),a=i(o);if(!s||!a)return null;let l=this.anchors[2];if(!l)return {segments:[[s[0],s[1],a[0],a[1]]],fill:null};let c=i({time:(n.time+o.time)/2,price:(n.price+o.price)/2}),d=i(l);if(!c||!d)return null;let u=(a[0]+d[0])/2,h=(a[1]+d[1])/2,p=d[0]-c[0],m=d[1]-c[1],f=t.width,g=t.height;return {segments:[Pe(u,h,u+p,h+m,"right",f,g),Pe(a[0],a[1],a[0]+p,a[1]+m,"right",f,g),Pe(d[0],d[1],d[0]+p,d[1]+m,"right",f,g),[a[0],a[1],d[0],d[1]],[c[0],c[1],d[0],d[1]],[s[0],s[1],a[0],a[1]]],fill:null}}priceRange(){if(this.anchors.length===0)return null;let t=this.anchors.map(n=>n.price);return {min:Math.min(...t),max:Math.max(...t)}}schema(){return {fields:[...G,...$]}}};var ka=class extends K{constructor(){super(...arguments);this.type="arrow";}anchorSchema(){return {min:2,max:2,slots:[{role:"p1",free:"both"},{role:"p2",free:"both"}]}}pixels(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);return i==null||s==null?null:[t.xOf(n.time),i,t.xOf(o.time),s]}hitTest(t,n,o,i){let s=this.pixels(o);return s!=null&&ae(t,n,s[0],s[1],s[2],s[3])<=i}handlePoints(t){let n=this.pixels(t);return n?[[n[0],n[1]],[n[2],n[3]]]:[]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.pixels(t);return n?{x:Math.min(n[0],n[2]),y:Math.min(n[1],n[3]),w:Math.abs(n[2]-n[0]),h:Math.abs(n[3]-n[1])}:null}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}schema(){return {fields:[...G,{path:"style.arrowRight",label:"Head (end)",kind:"boolean",group:"line"},{path:"style.arrowLeft",label:"Head (start)",kind:"boolean",group:"line"},...$]}}};var sf=48,La=class extends K{constructor(){super(...arguments);this.type="ellipse";}anchorSchema(){return {min:2,max:2,slots:[{role:"c1",free:"both"},{role:"c2",free:"both"}]}}oval(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);if(i==null||s==null)return null;let a=t.xOf(n.time),l=t.xOf(o.time);return {cx:(a+l)/2,cy:(i+s)/2,rx:Math.abs(l-a)/2,ry:Math.abs(s-i)/2}}perimeter(t){let n=[];for(let o=0;o<=sf;o+=1){let i=o/sf*Math.PI*2;n.push([t.cx+t.rx*Math.cos(i),t.cy+t.ry*Math.sin(i)]);}return n}hitTest(t,n,o,i){let s=this.oval(o);if(!s||s.rx<1||s.ry<1)return false;let a=((t-s.cx)/s.rx)**2+((n-s.cy)/s.ry)**2;return this.style.fillColor&&a<=1?true:no(t,n,this.perimeter(s))<=i}handlePoints(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return [];let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);return i==null||s==null?[]:[[t.xOf(n.time),i],[t.xOf(o.time),s]]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.oval(t);return n?{x:n.cx-n.rx,y:n.cy-n.ry,w:n.rx*2,h:n.ry*2}:null}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}schema(){return {fields:[...G,...fe,...$]}}};var Ma=class extends ve{constructor(){super(...arguments);this.type="triangle";}anchorSchema(){return {min:3,max:3,slots:[{role:"v1",free:"both"},{role:"v2",free:"both"},{role:"v3",free:"both"}]}}geometry(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=d=>{let u=t.yOf(d.price,this.paneId);return u==null?null:[t.xOf(d.time),u]},s=i(n),a=i(o);if(!s||!a)return null;let l=this.anchors[2];if(!l)return {segments:[[s[0],s[1],a[0],a[1]]],fill:null};let c=i(l);return c?{segments:[[s[0],s[1],a[0],a[1]],[a[0],a[1],c[0],c[1]],[c[0],c[1],s[0],s[1]]],fill:[s,a,c]}:null}priceRange(){if(this.anchors.length===0)return null;let t=this.anchors.map(n=>n.price);return {min:Math.min(...t),max:Math.max(...t)}}schema(){return {fields:[...G,...fe,...$]}}};var mS=512,Hn=class extends ve{anchorSchema(){return {min:2,max:mS,slots:[]}}geometry(e){let t=[];for(let o of this.anchors){let i=e.yOf(o.price,this.paneId);if(i==null)return null;t.push([e.xOf(o.time),i]);}if(t.length<2)return null;let n=[];for(let o=1;ot.price);return {min:Math.min(...e),max:Math.max(...e)}}schema(){return {fields:[...G,...$]}}};var Ea=class extends Hn{constructor(){super(...arguments);this.type="polyline";}};var hi=class extends Hn{placementMode(){return "freehand"}handlePoints(e){return []}bounds(e){let t=[],n=[];for(let s of this.anchors){let a=e.yOf(s.price,this.paneId);a!=null&&(t.push(e.xOf(s.time)),n.push(a));}if(t.length===0)return null;let o=Math.min(...t),i=Math.min(...n);return {x:o,y:i,w:Math.max(...t)-o,h:Math.max(...n)-i}}},Pa=class extends hi{constructor(){super(...arguments);this.type="freehand";}};var fS=[{path:"style.lineColor",label:"Color",kind:"color",group:"line"},{path:"style.lineWidth",label:"Width",kind:"number",min:4,max:60,step:1,group:"line"}],Ia=class extends hi{constructor(){super(...arguments);this.type="highlighter";}schema(){return {fields:fS}}};var Aa=class extends K{constructor(){super(...arguments);this.type="circle";}anchorSchema(){return {min:2,max:2,slots:[{role:"center",free:"both"},{role:"edge",free:"both"}]}}geom(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);if(i==null||s==null)return null;let a=t.xOf(n.time),l=t.xOf(o.time);return {cx:a,cy:i,r:Math.hypot(l-a,s-i)}}hitTest(t,n,o,i){let s=this.geom(o);if(!s||s.r<1)return false;let a=Math.hypot(t-s.cx,n-s.cy);return this.style.fillColor&&a<=s.r?true:Math.abs(a-s.r)<=i}handlePoints(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return [];let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);return i==null||s==null?[]:[[t.xOf(n.time),i],[t.xOf(o.time),s]]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.geom(t);return n?{x:n.cx-n.r,y:n.cy-n.r,w:n.r*2,h:n.r*2}:null}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}schema(){return {fields:[...G,...fe,...$]}}};var Ra=class extends ve{constructor(){super(...arguments);this.type="rotatedrect";}anchorSchema(){return {min:3,max:3,slots:[{role:"p1",free:"both"},{role:"p2",free:"both"},{role:"w",free:"both"}]}}px(t,n){let o=this.anchors[n];if(!o)return null;let i=t.yOf(o.price,this.paneId);return i==null?null:[t.xOf(o.time),i]}geometry(t){let n=this.px(t,0),o=this.px(t,1);if(!n||!o)return null;let i=this.px(t,2);if(!i||this.anchors.length<3)return {segments:[[n[0],n[1],o[0],o[1]]],fill:null};let s=o[0]-n[0],a=o[1]-n[1],l=Math.hypot(s,a);if(l<1e-6)return {segments:[[n[0],n[1],o[0],o[1]]],fill:null};let c=-a/l,d=s/l,u=(i[0]-n[0])*c+(i[1]-n[1])*d,h=c*u,p=d*u,m=n,f=o,g=[o[0]+h,o[1]+p],b=[n[0]+h,n[1]+p];return {segments:[[m[0],m[1],f[0],f[1]],[f[0],f[1],g[0],g[1]],[g[0],g[1],b[0],b[1]],[b[0],b[1],m[0],m[1]]],fill:[m,f,g,b]}}priceRange(){if(this.anchors.length===0)return null;let t=this.anchors.map(n=>n.price);return {min:Math.min(...t),max:Math.max(...t)}}schema(){return {fields:[...G.map(t=>({...t,label:t.label.replace("Line","Border")})),...fe,...$]}}};var Da=class extends Hn{constructor(){super(...arguments);this.type="path";}};var af=40,Oa=class extends ve{constructor(){super(...arguments);this.type="arc";}anchorSchema(){return {min:3,max:3,slots:[{role:"p1",free:"both"},{role:"p2",free:"both"},{role:"apex",free:"both"}]}}pinApex(){let t=this.anchors[0],n=this.anchors[1],o=this.anchors[2];t&&n&&o&&(o.time=(t.time+n.time)/2);}onPlaced(){this.pinApex();}constrainHandleDrag(){this.pinApex();}px(t,n){let o=this.anchors[n];if(!o)return null;let i=t.yOf(o.price,this.paneId);return i==null?null:[t.xOf(o.time),i]}geometry(t){let n=this.px(t,0),o=this.px(t,1);if(!n||!o)return null;let i=this.anchors[2];if(!i||this.anchors.length<3)return {segments:[[n[0],n[1],o[0],o[1]]],fill:null};let s=t.yOf(i.price,this.paneId);if(s==null)return null;let a=(n[0]+o[0])/2,l=(n[1]+o[1])/2,c=(o[0]-n[0])/2,d=(o[1]-n[1])/2,u=Math.hypot(c,d);if(u<1e-6)return {segments:[[n[0],n[1],o[0],o[1]]],fill:null};let h=-d/u,p=c/u,m=(s-l)*p;m<0&&(h=-h,p=-p);let f=Math.abs(m),g=[];for(let y=0;y<=af;y+=1){let w=y/af*Math.PI,C=Math.cos(w),M=Math.sin(w);g.push([a+C*c+M*f*h,l+C*d+M*f*p]);}let b=[];for(let y=1;yn.price);return {min:Math.min(...t),max:Math.max(...t)}}schema(){return {fields:[...G.map(t=>({...t,label:t.label.replace("Line","Border")})),...fe,...$]}}};var lf=40,Na=class extends ve{constructor(){super(...arguments);this.type="curve";}anchorSchema(){return {min:3,max:3,slots:[{role:"p1",free:"both"},{role:"p2",free:"both"},{role:"control",free:"both"}]}}px(t,n){let o=this.anchors[n];if(!o)return null;let i=t.yOf(o.price,this.paneId);return i==null?null:[t.xOf(o.time),i]}geometry(t){let n=this.px(t,0),o=this.px(t,1);if(!n||!o)return null;let i=this.px(t,2);if(!i||this.anchors.length<3)return {segments:[[n[0],n[1],o[0],o[1]]],fill:null};let s=[];for(let l=0;l<=lf;l+=1){let c=l/lf,d=1-c;s.push([d*d*n[0]+2*d*c*i[0]+c*c*o[0],d*d*n[1]+2*d*c*i[1]+c*c*o[1]]);}let a=[];for(let l=1;ln.price);return {min:Math.min(...t),max:Math.max(...t)}}schema(){return {fields:[...G,...fe,...$]}}};var gS={head:11,headW:9,stemW:3.5,len:22},fr=class extends K{anchorSchema(){return {min:1,max:1,slots:[{role:"p",free:"both"}]}}glyphPoints(e){let t=this.anchors[0];if(!t)return null;let n=e.yOf(t.price,this.paneId);if(n==null)return null;let o=e.xOf(t.time),{head:i,headW:s,stemW:a,len:l}=gS,c=[[0,0],[-s,i],[-a,i],[-a,l],[a,l],[a,i],[s,i]],d=this.dir(),u=([h,p])=>{switch(d){case "up":return [h,p];case "down":return [h,-p];case "left":return [p,h];default:return [-p,h]}};return c.map(h=>{let[p,m]=u(h);return [o+p,n+m]})}hitTest(e,t,n,o){let i=this.glyphPoints(n);return i!=null&&Kt(e,t,i)}handlePoints(e){let t=this.anchors[0];if(!t)return [];let n=e.yOf(t.price,this.paneId);return n==null?[]:[[e.xOf(t.time),n]]}hitHandle(e,t,n,o){return j(e,t,this.handlePoints(n),o+3)}bounds(e){let t=this.glyphPoints(e);if(!t)return null;let n=t.map(a=>a[0]),o=t.map(a=>a[1]),i=Math.min(...n),s=Math.min(...o);return {x:i,y:s,w:Math.max(...n)-i,h:Math.max(...o)-s}}priceRange(){let e=this.anchors[0];return e?{min:e.price,max:e.price}:null}schema(){return {fields:[{path:"style.lineColor",label:"Color",kind:"color",group:"line"},...$]}}},pi=class extends fr{constructor(){super(...arguments);this.type="arrowmarkup";}dir(){return "up"}},mi=class extends fr{constructor(){super(...arguments);this.type="arrowmarkdown";}dir(){return "down"}};var bi=["\u2605","\u2606","\u25CF","\u25C6","\u25B2","\u25BC","\u27A4","\u2691","\u271A","\u2715","\u2764","\u2666"],Fa=["small","normal","large","huge"],cf={small:16,normal:22,large:32,huge:44},gr=class extends K{constructor(e){super(e),this.glyph||(this.glyph=this.defaultGlyph()),this.size||(this.size="normal");}sizePx(){return cf[this.size]??cf.normal}anchorSchema(){return {min:1,max:1,slots:[{role:"p",free:"both"}]}}center(e){let t=this.anchors[0];if(!t)return null;let n=e.yOf(t.price,this.paneId);return n==null?null:[e.xOf(t.time),n]}hitTest(e,t,n,o){let i=this.center(n);if(!i)return false;let s=this.sizePx()/2+o;return Math.abs(e-i[0])<=s&&Math.abs(t-i[1])<=s}handlePoints(e){let t=this.center(e);return t?[t]:[]}hitHandle(e,t,n,o){return j(e,t,this.handlePoints(n),o+3)}bounds(e){let t=this.center(e);if(!t)return null;let n=this.sizePx();return {x:t[0]-n/2,y:t[1]-n/2,w:n,h:n}}priceRange(){let e=this.anchors[0];return e?{min:e.price,max:e.price}:null}schema(){return {fields:[{path:"glyph",label:"Icon",kind:"select",options:bi.map(e=>({value:e,label:e})),group:"line"},{path:"size",label:"Size",kind:"select",options:Fa.map(e=>({value:e,label:e})),group:"line"},{path:"style.lineColor",label:"Color",kind:"color",group:"line"},...$]}}writeProps(){return {glyph:this.glyph,size:this.size}}readProps(e){typeof e.glyph=="string"&&(this.glyph=e.glyph),typeof e.size=="string"&&(this.size=e.size);}},fi=class extends gr{constructor(){super(...arguments);this.type="flagmark";}defaultGlyph(){return "\u2691"}},gi=class extends gr{constructor(){super(...arguments);this.type="iconstamp";}defaultGlyph(){return "\u2605"}};var df=r=>r==="small"||r==="normal"||r==="large"||r==="huge";function bS(r){if(!r||typeof r!="object")return null;let e=r;return typeof e.ratio!="number"||typeof e.color!="string"?null:{ratio:e.ratio,color:e.color,enabled:e.enabled!==false,...typeof e.label=="string"&&e.label?{label:e.label}:{}}}var Ce=class extends K{constructor(e){super(e),this.levels||(this.levels=this.defaultLevels().map(t=>({...t}))),this.numbersSize||(this.numbersSize="small"),this.labelsSize||(this.labelsSize="normal");}fillBands(e){return []}editableLevels(){return this.levels}anchorSchema(){return {min:2,max:2,slots:[{role:"p1",free:"both"},{role:"p2",free:"both"}]}}hitTest(e,t,n,o){let i=this.entryLines(n);return i!=null&&i.some(s=>ae(e,t,s.x1,s.y1,s.x2,s.y2)<=o)}handlePoints(e){let t=[];for(let n of this.anchors){let o=e.yOf(n.price,this.paneId);if(o==null)return [];t.push([e.xOf(n.time),o]);}return t}hitHandle(e,t,n,o){return j(e,t,this.handlePoints(n),o+3)}bounds(e){let t=this.handlePoints(e);if(t.length===0)return null;let n=t.map(a=>a[0]),o=t.map(a=>a[1]),i=Math.min(...n),s=Math.min(...o);return {x:i,y:s,w:Math.max(...n)-i,h:Math.max(...o)-s}}schema(){return {fields:G.filter(e=>e.path!=="style.lineColor")}}writeProps(){return {levels:this.levels.map(e=>({...e})),numbersSize:this.numbersSize,labelsSize:this.labelsSize}}readProps(e){if(Array.isArray(e.levels)){let t=e.levels.map(bS).filter(n=>n!=null);t.length&&(this.levels=t);}df(e.numbersSize)&&(this.numbersSize=e.numbersSize),df(e.labelsSize)&&(this.labelsSize=e.labelsSize);}};var oo=class extends Ce{levelLines(e){let t=this.anchors[0],n=this.anchors[1];if(!t||!n)return null;let o=e.xOf(t.time),i=e.xOf(n.time),s=Math.min(o,i),a=Math.max(o,i),l=n.price-t.price,c=[];for(let d of this.levels){if(!d.enabled)continue;let u=t.price+d.ratio*l,h=e.yOf(u,this.paneId);h!=null&&c.push({ratio:d.ratio,color:d.color,label:d.label,price:u,x1:s,x2:a,y:h});}return c}entryLines(e){let t=this.levelLines(e);return t?t.map(n=>({color:n.color,label:n.label,x1:n.x1,y1:n.y,x2:n.x2,y2:n.y,numberText:`${n.ratio} (${n.price.toFixed(2)})`,numberX:n.x1+4,numberY:n.y-7,numberAlign:"left",labelX:(n.x1+n.x2)/2,labelY:n.y-7})):null}fillBands(e){let t=this.levelLines(e);if(!t)return [];let n=[];for(let o=1;oi.enabled).map(i=>e.price+i.ratio*n);return o.length===0?null:{min:Math.min(...o),max:Math.max(...o)}}};var br=A,jt=D,qt=U,vr="#4caf50",zn=O,yn=ce,yr="#9c27b0",vS="#e91e63",Qd="#26a69a",yS="#ab47bc",wS="#ef5350",uf="#ffb74d",xS="#38c0fd",Va="#b2b5be",io=[xS,yn,zn,vr,qt,jt,vS,yr,br,Qd,yS,wS];function hf(r){return io[(r%io.length+io.length)%io.length]}var CS=[[0,br],[.125,jt],[.236,jt],[.25,jt],[.382,qt],[.5,vr],[.618,zn],[.75,yn],[.786,yn],[1,br],[1.272,yn],[1.382,qt],[1.618,jt],[2,br],[2.382,qt],[2.618,qt],[3,br],[4.236,vr],[6.854,zn],[11.09,yn]];function SS(r,e=0){return CS.find(([t])=>t===r)?.[1]??hf(e)}function ye(r){return r.map((e,t)=>{let n=typeof e=="number"?{ratio:e}:e;return {ratio:n.ratio,color:n.color??SS(n.ratio,t),enabled:n.enabled!==false,...n.label?{label:n.label}:{}}})}function pf(r,e=r){return Array.from({length:r},(t,n)=>({ratio:n+1,color:hf(n),enabled:na.enabled).map(a=>o.price+a.ratio*i);return s.push(t.price,n.price,o.price),{min:Math.min(...s),max:Math.max(...s)}}};var MS=ye([.236,.382,.5,.618,.786,1]),za=class extends Ce{constructor(){super(...arguments);this.type="fibfan";}defaultLevels(){return MS}fanLines(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.xOf(n.time),s=t.yOf(n.price,this.paneId);if(s==null)return null;let a=t.xOf(o.time),l=o.price-n.price,c=[];for(let d of this.levels){if(!d.enabled)continue;let u=t.yOf(n.price+d.ratio*l,this.paneId);if(u==null)continue;let[h,p,m,f]=Pe(i,s,a,u,"right",t.width,t.height);c.push({ratio:d.ratio,color:d.color,label:d.label,x1:h,y1:p,x2:m,y2:f,labelX:a+5,labelY:u});}return c}entryLines(t){let n=this.fanLines(t);return n?n.map(o=>({color:o.color,label:o.label,x1:o.x1,y1:o.y1,x2:o.x2,y2:o.y2,numberText:String(o.ratio),numberX:o.labelX,numberY:o.labelY,numberAlign:"left",labelX:o.labelX,labelY:o.labelY+13})):null}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}};var ES=[0,1,2,3,5,8,13,21,34].map(r=>({ratio:r,color:_,enabled:true})),Wa=class extends Ce{constructor(){super(...arguments);this.type="fibtimezones";}defaultLevels(){return ES}zoneLines(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=o.time-n.time;if(Math.abs(i)<1e-9)return null;let s=[];for(let a of this.levels)a.enabled&&s.push({n:a.ratio,color:a.color,label:a.label,x:t.xOf(n.time+a.ratio*i)});return s}entryLines(t){let n=this.zoneLines(t);if(!n)return null;let o=t.height;return n.map(i=>({color:i.color,label:i.label,x1:i.x,y1:0,x2:i.x,y2:o,numberText:String(i.n),numberX:i.x,numberY:9,numberAlign:"center",labelX:i.x,labelY:24}))}priceRange(){return null}timeExtent(){return null}};var PS=ye([0,.236,.382,.5,.618,.786,1,1.618,2.618]),Ga=class extends Ce{constructor(){super(...arguments);this.type="fibchannel";}defaultLevels(){return PS}anchorSchema(){return {min:3,max:3,slots:[{role:"p1",free:"both"},{role:"p2",free:"both"},{role:"offset",free:"both"}]}}entryLines(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);if(i==null||s==null)return null;let a=t.xOf(n.time),l=t.xOf(o.time),c=0,d=0,u=this.anchors[2];if(u){let p=t.yOf(u.price,this.paneId);if(p==null)return null;c=t.xOf(u.time)-a,d=p-i;}let h=[];for(let p of this.levels){if(!p.enabled)continue;let m=p.ratio*c,f=p.ratio*d,g=l+m,b=s+f;h.push({color:p.color,label:p.label,x1:a+m,y1:i+f,x2:g,y2:b,numberText:String(p.ratio),numberX:g+5,numberY:b,numberAlign:"left",labelX:g+5,labelY:b+13});}return h}priceRange(){let t=this.anchors[0],n=this.anchors[1],o=this.anchors[2];if(!t||!n)return null;let i=o?o.price-t.price:0,s=1/0,a=-1/0;for(let l of this.levels)if(l.enabled)for(let c of [t.price,n.price]){let d=c+l.ratio*i;da&&(a=d);}return s<=a?{min:s,max:a}:null}};var IS=ye([0,.236,.382,.5,.618,.786,1]),$a=class extends Ce{constructor(){super(...arguments);this.type="fibspeedfan";}defaultLevels(){return IS}entryLines(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);if(i==null||s==null)return null;let a=t.xOf(n.time),c=t.xOf(o.time)-a,d=s-i,u=c>=0?"right":"left",h=t.width,p=t.height,m=[];for(let f of this.levels){if(!f.enabled)continue;let g=a+c,b=i+d*f.ratio,y=Pe(a,i,g,b,u,h,p);if(m.push({color:f.color,label:f.label,x1:y[0],y1:y[1],x2:y[2],y2:y[3],numberText:String(f.ratio),numberX:u==="right"?g+5:g-5,numberY:b,numberAlign:u==="right"?"left":"right",labelX:g,labelY:b}),f.ratio===1)continue;let w=a+c*f.ratio,C=i+d,M=Pe(a,i,w,C,u,h,p);m.push({color:f.color,label:f.label,x1:M[0],y1:M[1],x2:M[2],y2:M[3],numberText:String(f.ratio),numberX:w,numberY:C+(d>=0?12:-12),numberAlign:"center",labelX:w,labelY:C+12});}return m}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}};var AS=ye([0,.382,{ratio:.5,enabled:false},.618,1,1.382,1.618,2,2.382,2.618,3]),Ua=class extends Ce{constructor(){super(...arguments);this.type="trendfibtime";}defaultLevels(){return AS}anchorSchema(){return {min:3,max:3,slots:[{role:"p1",free:"both"},{role:"p2",free:"both"},{role:"p3",free:"both"}]}}entryLines(t){let n=this.anchors[0],o=this.anchors[1],i=this.anchors[2];if(!n||!o||!i)return null;let s=o.time-n.time;if(Math.abs(s)<1e-9)return null;let a=t.height,l=[];for(let c of this.levels){if(!c.enabled)continue;let d=t.xOf(i.time+c.ratio*s);l.push({color:c.color,label:c.label,x1:d,y1:0,x2:d,y2:a,numberText:String(c.ratio),numberX:d,numberY:9,numberAlign:"center",labelX:d,labelY:24});}return l}priceRange(){return null}timeExtent(){return null}};function RS(r,e,t){if(t-e>=Math.PI*2-.001)return true;let n=r-e,o=Math.PI*2;for(;n<0;)n+=o;for(;n>=o;)n-=o;return n<=t-e+1e-6}var Ot=class extends Ce{boundingLines(e){return []}entryLines(e){return []}hitTest(e,t,n,o){let i=this.radial(n);if(i){let s=Math.hypot(e-i.cx,t-i.cy),a=Math.atan2(t-i.cy,e-i.cx);if(RS(a,i.a0,i.a1)){for(let l of this.levels)if(l.enabled&&Math.abs(s-i.R0*l.ratio)<=o)return true}}return this.boundingLines(n).some(s=>ae(e,t,s[0],s[1],s[2],s[3])<=o)}priceRange(){if(this.anchors.length===0)return null;let e=this.anchors.map(t=>t.price);return {min:Math.min(...e),max:Math.max(...e)}}};var DS=ye([.236,.382,.5,.618,.786,1,1.618,2.618]),Ya=class extends Ot{constructor(){super(...arguments);this.type="fibcircles";}defaultLevels(){return DS}radial(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);if(i==null||s==null)return null;let a=t.xOf(n.time),l=t.xOf(o.time);return {cx:a,cy:i,R0:Math.hypot(l-a,s-i),a0:0,a1:Math.PI*2}}};var OS=ye([.236,.382,.5,.618,.786,1,1.618,2.618]),Ka=class extends Ot{constructor(){super(...arguments);this.type="fibarcs";}defaultLevels(){return OS}pts(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);return i==null||s==null?null:{cx:t.xOf(n.time),cy:i,ex:t.xOf(o.time),ey:s}}radial(t){let n=this.pts(t);if(!n)return null;let o=Math.hypot(n.ex-n.cx,n.ey-n.cy),i=Math.atan2(n.ey-n.cy,n.ex-n.cx);return {cx:n.cx,cy:n.cy,R0:o,a0:i-Math.PI/2,a1:i+Math.PI/2}}boundingLines(t){let n=this.pts(t);return n?[[n.cx,n.cy,n.ex,n.ey]]:[]}};var NS=ye([.236,.382,.5,.618,.786,1]),Xa=class extends Ot{constructor(){super(...arguments);this.type="fibwedge";}defaultLevels(){return NS}anchorSchema(){return {min:3,max:3,slots:[{role:"apex",free:"both"},{role:"radius",free:"both"},{role:"angle",free:"both"}]}}px(t,n){let o=this.anchors[n];if(!o)return null;let i=t.yOf(o.price,this.paneId);return i==null?null:[t.xOf(o.time),i]}radial(t){let n=this.px(t,0),o=this.px(t,1),i=this.px(t,2);if(!n||!o||!i)return null;let s=Math.hypot(o[0]-n[0],o[1]-n[1]);if(s<1)return null;let a=Math.atan2(o[1]-n[1],o[0]-n[0]),l=Math.atan2(i[1]-n[1],i[0]-n[0]),c=Math.min(a,l),d=Math.max(a,l);return d-c>Math.PI&&([c,d]=[d,c+Math.PI*2]),{cx:n[0],cy:n[1],R0:s,a0:c,a1:d}}boundingLines(t){let n=this.px(t,0),o=this.px(t,1);if(!n||!o)return [];let i=[[n[0],n[1],o[0],o[1]]],s=this.px(t,2);if(s){let a=Math.hypot(o[0]-n[0],o[1]-n[1]),l=Math.hypot(s[0]-n[0],s[1]-n[1]);l>1e-6&&i.push([n[0],n[1],n[0]+(s[0]-n[0])/l*a,n[1]+(s[1]-n[1])/l*a]);}return i}};var FS=1.6180339887,mf=Math.log(FS)/(Math.PI/2),VS=Math.PI/64,BS=Math.PI,_S=.5,wr=class extends K{constructor(){super(...arguments);this.type="fibspiral";}anchorSchema(){return {min:2,max:2,slots:[{role:"center",free:"both"},{role:"edge",free:"both"}]}}spiralPoints(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);if(i==null||s==null)return null;let a=t.xOf(n.time),l=t.xOf(o.time),c=Math.hypot(l-a,s-i);if(c<1)return null;let d=Math.atan2(s-i,l-a),u=Math.max(Math.log(_S/c)/mf,-8*Math.PI*2),h=[];for(let p=u;p<=BS;p+=VS){let m=c*Math.exp(mf*p),f=d+p;h.push([a+m*Math.cos(f),i+m*Math.sin(f)]);}return h}hitTest(t,n,o,i){let s=this.spiralPoints(o);return s!=null&&s.length>=2&&no(t,n,s)<=i}handlePoints(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return [];let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);return i==null||s==null?[]:[[t.xOf(n.time),i],[t.xOf(o.time),s]]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.handlePoints(t);if(n.length<2)return null;let o=n.map(l=>l[0]),i=n.map(l=>l[1]),s=Math.min(...o),a=Math.min(...i);return {x:s,y:a,w:Math.max(...o)-s,h:Math.max(...i)-a}}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}schema(){return {fields:[...G,...$]}}};var HS=ye([{ratio:.125,color:jt,label:"1/8"},{ratio:.25,color:qt,label:"1/4"},{ratio:.333,color:uf,label:"1/3"},{ratio:.5,color:vr,label:"1/2"},{ratio:1,color:Va,label:"1/1"},{ratio:2,color:zn,label:"2/1"},{ratio:3,color:yn,label:"3/1"},{ratio:4,color:Qd,label:"4/1"},{ratio:8,color:yr,label:"8/1"}]),ja=class extends Ce{constructor(){super(...arguments);this.type="gannfan";}defaultLevels(){return HS}entryLines(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.xOf(n.time),s=t.yOf(n.price,this.paneId);if(s==null)return null;let a=t.xOf(o.time),l=o.price-n.price,c=[];for(let d of this.levels){if(!d.enabled)continue;let u=t.yOf(n.price+l*d.ratio,this.paneId);if(u==null)continue;let[h,p,m,f]=Pe(i,s,a,u,"right",t.width,t.height);c.push({color:d.color,x1:h,y1:p,x2:m,y2:f,numberText:d.label??String(d.ratio),numberX:a+5,numberY:u,numberAlign:"left",labelX:a+5,labelY:u});}return c}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}};var zS=ye([0,.25,.382,.5,.618,.75,1].map(r=>({ratio:r,label:String(r)}))),qa=class extends Ce{constructor(){super(...arguments);this.type="gannbox";}defaultLevels(){return zS}corners(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.xOf(n.time),s=t.xOf(o.time),a=t.yOf(n.price,this.paneId),l=t.yOf(o.price,this.paneId);return a==null||l==null?null:{c1:n,c2:o,left:Math.min(i,s),right:Math.max(i,s),top:Math.min(a,l),bot:Math.max(a,l)}}entryLines(t){let n=this.corners(t);if(!n)return null;let{c1:o,c2:i,left:s,right:a,top:l,bot:c}=n,d=[];for(let h of this.levels){if(!h.enabled)continue;let p=t.yOf(o.price+h.ratio*(i.price-o.price),this.paneId);p!=null&&d.push({color:h.color,x1:s,y1:p,x2:a,y2:p,numberText:h.label??String(h.ratio),numberX:s-5,numberY:p,numberAlign:"right",labelX:s,labelY:p});let m=t.xOf(o.time+h.ratio*(i.time-o.time));d.push({color:h.color,x1:m,y1:l,x2:m,y2:c,numberText:"",numberX:m,numberY:l,numberAlign:"center",labelX:m,labelY:l});}let u=this.levels.find(h=>h.ratio===1)?.color??br;return d.push({color:u,x1:s,y1:l,x2:a,y2:c,numberText:"",numberX:0,numberY:0,numberAlign:"left",labelX:0,labelY:0}),d.push({color:u,x1:s,y1:c,x2:a,y2:l,numberText:"",numberX:0,numberY:0,numberAlign:"left",labelX:0,labelY:0}),d}hitTest(t,n,o,i){let s=this.corners(o);return s!=null&&$e(t,n,s.left,s.top,s.right,s.bot,i)}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}};var WS=ye([0,.25,.382,.5,.618,.75,1].map(r=>({ratio:r,label:String(r)}))),GS=[{label:"3x1",x:3,y:1,color:jt},{label:"2x1",x:2,y:1,color:qt},{label:"1x1",x:1,y:1,color:Va},{label:"1x2",x:1,y:2,color:zn},{label:"1x3",x:1,y:3,color:yn}],Jd=[{k:.25,color:jt},{k:.5,color:qt},{k:.75,color:vr},{k:1,color:zn}],xr=class extends Ce{constructor(){super(...arguments);this.type="gannsquare";}defaultLevels(){return WS}box(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);if(i==null||s==null)return null;let a=t.xOf(n.time),l=t.xOf(o.time);return {ox:a,oy:i,bx:l-a,py:s-i,left:Math.min(a,l),top:Math.min(i,s),right:Math.max(a,l),bot:Math.max(i,s)}}arcGeom(t){let n=this.box(t);return n?{ox:n.ox,oy:n.oy,bx:n.bx,py:n.py}:null}entryLines(t){let n=this.box(t);if(!n)return null;let o=this.anchors[0],i=this.anchors[1],s=[];for(let a of this.levels){if(!a.enabled)continue;let l=t.yOf(o.price+a.ratio*(i.price-o.price),this.paneId);l!=null&&s.push({color:a.color,x1:n.left,y1:l,x2:n.right,y2:l,numberText:a.label??String(a.ratio),numberX:n.left-5,numberY:l,numberAlign:"right",labelX:n.left,labelY:l});let c=t.xOf(o.time+a.ratio*(i.time-o.time));s.push({color:a.color,x1:c,y1:n.top,x2:c,y2:n.bot,numberText:"",numberX:c,numberY:n.top,numberAlign:"center",labelX:c,labelY:n.top});}for(let a of GS){let l,c;a.x>a.y?(l=n.ox+n.bx,c=n.oy+a.y/a.x*n.py):(c=n.oy+n.py,l=n.ox+a.x/a.y*n.bx),s.push({color:a.color,x1:n.ox,y1:n.oy,x2:l,y2:c,numberText:a.label,numberX:l+4,numberY:c,numberAlign:"left",labelX:l+4,labelY:c});}return s}hitTest(t,n,o,i){let s=this.box(o);return s!=null&&$e(t,n,s.left,s.top,s.right,s.bot,i)}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}};var eu=[4,8,12,16,24,32,48,64],$S=24,US=.75;function ff(r,e){if(!Number.isInteger(r)||!Number.isInteger(e)||e<=0)return false;let t=r*r-1;return e%2===1?t%e===0:e%8===0?t%e!==0?false:t/e%2!==0:false}function gf(r){let e=[];for(let t=0;tp+.5||m.push({kind:"vline",x:y,y0:s,y1:i});}for(let b=1;b<=d;b+=1){let y=1/b,w=y*a;if(wh)continue;let x=o+(k-l)*a;x+wp+1||m.push({kind:"arc",cx:x,cy:s,r:w});}}return m}hitTest(t,n,o,i){let s=this.box(o);return s!=null&&$e(t,n,s.left,s.top,s.right,s.bot,i)}handlePoints(t){let n=this.box(t);return n?[[n.left,n.top],[n.right,n.bot]]:[]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.box(t);return n?{x:n.left,y:n.top,w:n.right-n.left,h:n.bot-n.top}:null}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}schema(){return {fields:[...G,{path:"maxCurvature",label:"Max curvature",kind:"number",min:4,max:64,step:4,group:"behavior"},...$]}}writeProps(){return {maxCurvature:this.maxCurvature}}readProps(t){typeof t.maxCurvature=="number"&&Number.isFinite(t.maxCurvature)&&(this.maxCurvature=Math.max(1,Math.min(64,Math.round(t.maxCurvature))));}};var tu=[3,4,5,6,8,10,12],nu=[1.5,2,2.5,3,4,5],Za=6,YS=2;function ru(r=Za){return [...pf(io.length,r)]}function KS(r){if(!r||typeof r!="object")return null;let e=r;return typeof e.ratio!="number"||typeof e.color!="string"?null:{ratio:e.ratio,color:e.color,enabled:e.enabled!==false,...typeof e.label=="string"&&e.label?{label:e.label}:{}}}var so={path:"showRatios",label:"Show ratios",kind:"boolean",group:"behavior"},dt=class extends K{constructor(e){super(e),this.waveCount===void 0&&(this.waveCount=Za),this.showRatios===void 0&&(this.showRatios=true);let t=Array.isArray(e.props?.levels);this.levels||(this.levels=this.defaultLevels().map(n=>({...n}))),!t&&this.shouldSyncWaveCount()&&this.syncLevelsToWaveCount();}shouldSyncWaveCount(){return true}syncLevelsToWaveCount(){let e=Math.max(1,Math.min(this.levels.length,Math.round(this.waveCount)));this.waveCount=e;for(let t=0;tS.enabled&&S.ratio>0).slice().sort((S,L)=>S.ratio-L.ratio);if(m.length===0)return null;let f=Math.max(1,this.machNumber()),g=[];for(let S of m){let L=S.ratio*d;g.push({cx:l+f*(L-d)*u,cy:c+f*(L-d)*h,r:L,color:S.color,ratio:S.ratio});}let b=l-f*d*u,y=c-f*d*h,w=g[g.length-1].r,C=f*w+2*d,M=[];if(f<=1+1e-9){let S=-h,L=u;M.push([b-S*C,y-L*C,b+S*C,y+L*C]);}else {let S=Math.asin(1/f),L=Math.cos(S),v=Math.sin(S),k=(V,Z,be)=>[V*L-Z*be*v,V*be*v+Z*L],[x,E]=k(u,h,1),[I,N]=k(u,h,-1);M.push([b,y,b+x*C,y+E*C]),M.push([b,y,b+I*C,y+N*C]);}return {c0x:l,c0y:c,R:d,fx:u,fy:h,noseX:b,noseY:y,circles:g,rays:M}}hitTest(e,t,n,o){let i=this.geom(n);if(!i)return false;for(let s of i.circles)if(Math.abs(Math.hypot(e-s.cx,t-s.cy)-s.r)<=o)return true;return i.rays.some(s=>ae(e,t,s[0],s[1],s[2],s[3])<=o)}handlePoints(e){let t=this.anchors[0],n=this.anchors[1];if(!t||!n)return [];let o=e.yOf(t.price,this.paneId),i=e.yOf(n.price,this.paneId);return o==null||i==null?[]:[[e.xOf(t.time),o],[e.xOf(n.time),i]]}hitHandle(e,t,n,o){return j(e,t,this.handlePoints(n),o+3)}bounds(e){let t=this.geom(e);if(!t)return null;let n=t.noseX,o=t.noseX,i=t.noseY,s=t.noseY;for(let a of t.circles)n=Math.min(n,a.cx-a.r),o=Math.max(o,a.cx+a.r),i=Math.min(i,a.cy-a.r),s=Math.max(s,a.cy+a.r);for(let a of t.rays)n=Math.min(n,a[0],a[2]),o=Math.max(o,a[0],a[2]),i=Math.min(i,a[1],a[3]),s=Math.max(s,a[1],a[3]);return {x:n,y:i,w:o-n,h:s-i}}priceRange(){let e=this.anchors[0],t=this.anchors[1];return !e||!t?null:{min:Math.min(e.price,t.price),max:Math.max(e.price,t.price)}}applySettings(e){if(super.applySettings(e),Object.prototype.hasOwnProperty.call(e,"waveCount")&&typeof this.waveCount=="number"){let t=Math.max(1,Math.min(this.levels.length,Math.round(this.waveCount)));this.waveCount=t;for(let n=0;n({...e}))}}readProps(e){if(typeof e.waveCount=="number"&&Number.isFinite(e.waveCount)&&(this.waveCount=Math.max(2,Math.min(12,Math.round(e.waveCount)))),typeof e.showRatios=="boolean"&&(this.showRatios=e.showRatios),Array.isArray(e.levels)){let t=e.levels.map(KS).filter(n=>n!=null);t.length&&(this.levels=t);}}},vi=class extends dt{constructor(){super(...arguments);this.type="sonic";}defaultLevels(){return ru(Za)}machNumber(){return 1}},yi=class extends dt{constructor(t){super(t);this.type="supersonic";this.mach===void 0&&(this.mach=YS);}defaultLevels(){return ru(Za)}machNumber(){return Math.max(1.01,this.mach)}schema(){return {fields:[...G,{path:"mach",label:"Mach number",kind:"number",min:1.5,max:5,step:.5,group:"behavior"},{path:"waveCount",label:"Waves",kind:"number",min:3,max:12,step:1,group:"behavior"},so,...$]}}writeProps(){return {...super.writeProps(),mach:this.mach}}readProps(t){super.readProps(t),typeof t.mach=="number"&&Number.isFinite(t.mach)&&(this.mach=Math.max(1.01,Math.min(20,t.mach)));}};var bf=ye([.236,.382,.5,.618,.786,1,1.618,2.618,4.236,6.854,11.09]),XS=2,Qa=class extends dt{constructor(){super(...arguments);this.type="goldensonic";}shouldSyncWaveCount(){return false}defaultLevels(){return bf}machNumber(){return 1}schema(){return {fields:[...G,so,...$]}}},Ja=class extends dt{constructor(t){super(t);this.type="goldensupersonic";this.mach===void 0&&(this.mach=XS);}shouldSyncWaveCount(){return false}defaultLevels(){return bf}machNumber(){return Math.max(1.01,this.mach)}schema(){return {fields:[...G,{path:"mach",label:"Mach number",kind:"number",min:1.5,max:5,step:.5,group:"behavior"},so,...$]}}writeProps(){return {...super.writeProps(),mach:this.mach}}readProps(t){super.readProps(t),typeof t.mach=="number"&&Number.isFinite(t.mach)&&(this.mach=Math.max(1.01,Math.min(20,t.mach)));}};var We=class extends K{legRatios(){return false}fillTriangles(){return []}necklineIndices(){return null}anchorSchema(){let e=this.vertexLabels().length,t=[];for(let n=0;n=2&&no(e,t,i)<=o}hitHandle(e,t,n,o){return j(e,t,this.handlePoints(n),o+3)}bounds(e){let t=this.handlePoints(e);if(t.length===0)return null;let n=t.map(a=>a[0]),o=t.map(a=>a[1]),i=Math.min(...n),s=Math.min(...o);return {x:i,y:s,w:Math.max(...n)-i,h:Math.max(...o)-s}}priceRange(){if(this.anchors.length===0)return null;let e=this.anchors.map(t=>t.price);return {min:Math.min(...e),max:Math.max(...e)}}patternName(){return null}ratioOk(e){return null}valid(){return null}ratioAt(e){let t=this.anchors[e-2],n=this.anchors[e-1],o=this.anchors[e];if(!t||!n||!o)return null;let i=Math.abs(n.price-t.price);return i<1e-9?null:Math.abs(o.price-n.price)/i}schema(){return {fields:[...G,...this.fillTriangles().length?fe:[]]}}};var el=class extends We{constructor(){super(...arguments);this.type="xabcd";}vertexLabels(){return ["X","A","B","C","D"]}legRatios(){return true}fillTriangles(){return [[0,1,2],[2,3,4]]}};var tl=class extends We{constructor(){super(...arguments);this.type="abcd";}vertexLabels(){return ["A","B","C","D"]}legRatios(){return true}};var nl=class extends We{constructor(){super(...arguments);this.type="elliottimpulse";}vertexLabels(){return ["1","2","3","4","5"]}};var rl=class extends We{constructor(){super(...arguments);this.type="elliottcorrection";}vertexLabels(){return ["A","B","C"]}};var ol=class extends We{constructor(){super(...arguments);this.type="headshoulders";}vertexLabels(){return ["","LS","","H","","RS",""]}necklineIndices(){return [2,4]}};var ut=class extends We{vertexLabels(){return ["X","A","B","C","D"]}legRatios(){return true}fillTriangles(){return [[0,1,2],[2,3,4]]}legValue(e){let[t,n,o,i,s]=this.anchors;if(!t||!n||!o||!i||!s)return null;let a=(u,h)=>Math.abs(h.price-u.price),l=a(t,n),c=a(n,o),d=a(o,i);switch(e){case "ab":return l<1e-9?null:c/l;case "bc":return c<1e-9?null:d/c;case "cd":return d<1e-9?null:a(i,s)/d;default:return l<1e-9?null:a(n,s)/l}}inBand(e,t){return e!=null&&e>=t.min&&e<=t.max}ratioOk(e){let t=this.ranges();return e===2?this.inBand(this.legValue("ab"),t.ab):e===3?this.inBand(this.legValue("bc"),t.bc):e===4?this.inBand(this.legValue("cd"),t.cd):null}valid(){if(this.anchors.length<5)return null;let e=this.ranges();return this.inBand(this.legValue("ab"),e.ab)&&this.inBand(this.legValue("bc"),e.bc)&&this.inBand(this.legValue("cd"),e.cd)&&this.inBand(this.legValue("ad"),e.ad)}};var il=class extends ut{constructor(){super(...arguments);this.type="gartley";}patternName(){return "Gartley"}ranges(){return {ab:{min:.55,max:.68},bc:{min:.382,max:.886},cd:{min:1.13,max:1.618},ad:{min:.74,max:.83}}}};var sl=class extends ut{constructor(){super(...arguments);this.type="bat";}patternName(){return "Bat"}ranges(){return {ab:{min:.382,max:.5},bc:{min:.382,max:.886},cd:{min:1.618,max:2.618},ad:{min:.84,max:.92}}}};var al=class extends ut{constructor(){super(...arguments);this.type="butterfly";}patternName(){return "Butterfly"}ranges(){return {ab:{min:.74,max:.83},bc:{min:.382,max:.886},cd:{min:1.618,max:2.618},ad:{min:1.272,max:1.618}}}};var ll=class extends ut{constructor(){super(...arguments);this.type="crab";}patternName(){return "Crab"}ranges(){return {ab:{min:.382,max:.618},bc:{min:.382,max:.886},cd:{min:2.618,max:3.618},ad:{min:1.55,max:1.69}}}};var cl=class extends ut{constructor(){super(...arguments);this.type="shark";}patternName(){return "Shark"}ranges(){return {ab:{min:.382,max:.618},bc:{min:1.13,max:1.618},cd:{min:1.618,max:2.24},ad:{min:.886,max:1.13}}}};var jS={min:1.272,max:1.414},qS={min:.74,max:.83},dl=class extends ut{constructor(){super(...arguments);this.type="cypher";}patternName(){return "Cypher"}ranges(){return {ab:{min:.382,max:.618},bc:{min:0,max:1/0},cd:{min:0,max:1/0},ad:{min:0,max:1/0}}}xcOverXa(){let t=this.anchors[0],n=this.anchors[1],o=this.anchors[3];if(!t||!n||!o)return null;let i=Math.abs(n.price-t.price);return i<1e-9?null:Math.abs(o.price-t.price)/i}cdOverXc(){let t=this.anchors[0],n=this.anchors[3],o=this.anchors[4];if(!t||!n||!o)return null;let i=Math.abs(n.price-t.price);return i<1e-9?null:Math.abs(o.price-n.price)/i}ratioOk(t){return t===2?this.inBand(this.legValue("ab"),this.ranges().ab):null}valid(){return this.anchors.length<5?null:this.inBand(this.legValue("ab"),this.ranges().ab)&&this.inBand(this.xcOverXa(),jS)&&this.inBand(this.cdOverXc(),qS)}};function vf(r){return `${r>=0?"+":""}${r.toFixed(2)}`}function wi(r){let e=Math.abs(r),t=864e5,n=36e5,o=6e4;if(e>=t){let i=Math.floor(e/t),s=Math.round(e%t/n);return s?`${i}d ${s}h`:`${i}d`}if(e>=n){let i=Math.floor(e/n),s=Math.round(e%n/o);return s?`${i}h ${s}m`:`${i}h`}return e>=o?`${Math.round(e/o)}m`:`${Math.round(e/1e3)}s`}var Sr=class extends K{constructor(e){super(e),this.showPrice===void 0&&(this.showPrice=true),this.showDate===void 0&&(this.showDate=true);}anchorSchema(){return {min:2,max:2,slots:[{role:"c1",free:"both"},{role:"c2",free:"both"}]}}measureLabel(e){let t=[];return this.showPrice&&t.push(this.priceLabel()),this.showDate&&t.push(this.timeLabel(e)),t}isUp(){let e=this.anchors[0],t=this.anchors[1];return e!=null&&t!=null&&t.price>=e.price}priceLabel(){let e=this.anchors[0],t=this.anchors[1];if(!e||!t)return "";let n=t.price-e.price,o=e.price!==0?n/e.price*100:0;return `${vf(n)} (${vf(o)}%)`}timeLabel(e){let t=this.anchors[0],n=this.anchors[1];if(!t||!n)return "";let o=wi(n.time-t.time),i=e.barsBetween?Math.round(e.barsBetween(t.time,n.time)):null;return i!=null?`${i} bars, ${o}`:o}rect(e){let t=this.anchors[0],n=this.anchors[1];if(!t||!n)return null;let o=e.yOf(t.price,this.paneId),i=e.yOf(n.price,this.paneId);return o==null||i==null?null:{x1:e.xOf(t.time),y1:o,x2:e.xOf(n.time),y2:i}}hitTest(e,t,n,o){let i=this.rect(n);return i!=null&&$e(e,t,i.x1,i.y1,i.x2,i.y2,o)}handlePoints(e){let t=this.rect(e);return t?[[t.x1,t.y1],[t.x2,t.y2]]:[]}hitHandle(e,t,n,o){return j(e,t,this.handlePoints(n),o+3)}bounds(e){let t=this.rect(e);return t?{x:Math.min(t.x1,t.x2),y:Math.min(t.y1,t.y2),w:Math.abs(t.x2-t.x1),h:Math.abs(t.y2-t.y1)}:null}priceRange(){let e=this.anchors[0],t=this.anchors[1];return !e||!t?null:{min:Math.min(e.price,t.price),max:Math.max(e.price,t.price)}}schema(){return {fields:[{path:"showPrice",label:"Show price",kind:"boolean",group:"behavior"},{path:"showDate",label:"Show date",kind:"boolean",group:"behavior"},...G.filter(e=>e.path!=="style.lineColor"),{path:"text.color",label:"Text color",kind:"color",group:"text"},{path:"text.size",label:"Text size",kind:"select",options:Dt,group:"text"}]}}writeProps(){return {showPrice:this.showPrice,showDate:this.showDate}}readProps(e){typeof e.showPrice=="boolean"&&(this.showPrice=e.showPrice),typeof e.showDate=="boolean"&&(this.showDate=e.showDate);}};var ul=class extends Sr{constructor(){super(...arguments);this.type="datepricerange";}};var hl=[{value:"long",label:"Long"},{value:"short",label:"Short"}],De=class De extends K{constructor(t){super(t);this.type="position";this.riskPercent===void 0&&(this.riskPercent=De.DEFAULT_RISK_PERCENT),this.accountBalance===void 0&&(this.accountBalance=De.DEFAULT_ACCOUNT_BALANCE),this.showText===void 0&&(this.showText=true),this.showHeader===void 0&&(this.showHeader=true),this.showPrices===void 0&&(this.showPrices=false),this.showLossSize===void 0&&(this.showLossSize=true),this.showTargetLabel===void 0&&(this.showTargetLabel=true),this.showStopLabel===void 0&&(this.showStopLabel=true),this.profitColor===void 0&&(this.profitColor=De.DEFAULT_PROFIT_COLOR),this.lossColor===void 0&&(this.lossColor=De.DEFAULT_LOSS_COLOR);}directionLabel(){let t=this.prices();return t&&t.target>=t.entry?"LONG":"SHORT"}get direction(){return this.directionLabel()==="LONG"?"long":"short"}set direction(t){let n=this.anchors[0],o=this.anchors[1],i=this.anchors[2];!n||!o||!i||(t==="long"||t==="short")&&t!==this.direction&&(o.price=2*n.price-o.price,i.price=2*n.price-i.price);}get quantity(){return this.positionSize()}set quantity(t){let n=this.prices();if(!n||!Number.isFinite(t)||t<0)return;let o=Math.abs(n.entry-n.stop);o<1e-9||this.accountBalance<=0||(this.riskPercent=t*o/this.accountBalance*100);}get entryPrice(){return this.anchors[0]?.price??0}set entryPrice(t){let n=this.anchors[0];n&&Number.isFinite(t)&&(n.price=t,this.constrainHandleDrag(0));}get stopPrice(){return this.anchors[1]?.price??0}set stopPrice(t){let n=this.anchors[1];n&&Number.isFinite(t)&&(n.price=t,this.constrainHandleDrag(1));}get targetPrice(){return this.anchors[2]?.price??0}set targetPrice(t){let n=this.anchors[2];n&&Number.isFinite(t)&&(n.price=t,this.constrainHandleDrag(2));}anchorSchema(){return {min:2,max:2,slots:[{role:"entry",free:"both"},{role:"stop",free:"both"},{role:"target",free:"both"}]}}onPlaced(t){let n=this.anchors[0];if(!n)return;let o=t.xOf(n.time),i=t.yOf(n.price,this.paneId);if(i==null)return;let s=this.anchors[1],a=s?t.yOf(s.price,this.paneId):null,l,c;s&&a!=null&&Math.abs(a-i)>=De.MIN_DRAG_PX?(l=a,c=o+Math.max(Math.abs(t.xOf(s.time)-o),De.MIN_WIDTH_PX)):(l=i-De.DEFAULT_RISK_PX*De.DEFAULT_RR,c=o+De.DEFAULT_WIDTH_PX);let d=i-(l-i)/De.DEFAULT_RR,u=t.pxToPoint(c,i,this.paneId).time;this.anchors=[{time:n.time,price:n.price},{time:u,price:t.pxToPoint(o,d,this.paneId).price},{time:u,price:t.pxToPoint(o,l,this.paneId).price}];}constrainHandleDrag(t){let n=this.anchors[0],o=this.anchors[1],i=this.anchors[2];if(!n||!o||!i)return;let s=Math.sign(o.price-n.price),a=Math.sign(i.price-n.price);s===0||a===0||s!==a||(t===2?o.price=2*n.price-o.price:i.price=2*n.price-i.price);}resolved(){let t=this.anchors[0],n=this.anchors[1];if(!t||!n)return null;if(this.anchors[2])return [t,n,this.anchors[2]];let o={time:n.time,price:t.price-(n.price-t.price)/De.DEFAULT_RR};return [t,o,n]}prices(){let t=this.resolved();return t?{entry:t[0].price,stop:t[1].price,target:t[2].price}:null}rr(){let t=this.prices();if(!t)return 0;let n=Math.abs(t.entry-t.stop);return n<1e-9?0:Math.abs(t.target-t.entry)/n}rewardPct(){let t=this.prices();return t&&t.entry!==0?Math.abs(t.target-t.entry)/t.entry*100:0}riskPct(){let t=this.prices();return t&&t.entry!==0?Math.abs(t.entry-t.stop)/t.entry*100:0}dollarLoss(){return Math.max(0,this.accountBalance)*(Math.max(0,this.riskPercent)/100)}positionSize(){let t=this.prices();if(!t)return 0;let n=Math.abs(t.entry-t.stop);return n<1e-9?0:this.dollarLoss()/n}headerLabel(){return `${this.directionLabel()} \xB7 R:R ${this.rr().toFixed(2)}`}lossSizeLabel(){return `Loss $${ZS(this.dollarLoss())} \xB7 Size ${QS(this.positionSize())}`}targetLabel(){let t=this.prices(),n=this.showPrices&&t?` @ ${yf(t.target)}`:"";return `Target +${this.rewardPct().toFixed(2)}%${n}`}stopLabel(){let t=this.prices(),n=this.showPrices&&t?` @ ${yf(t.stop)}`:"";return `Stop \u2212${this.riskPct().toFixed(2)}%${n}`}levelDisplayValue(t,n){let o=this.prices();if(!o)return 0;let i=t==="stop"?o.stop:o.target;return wf(n==="price"?i:Math.abs(i-o.entry))}levelPriceFromDisplay(t,n,o){let i=this.prices();if(!i||n==="price")return o;let s=t==="stop"?i.stop:i.target,a=Math.sign(s-i.entry);return a===0&&(a=(t==="target"?1:-1)*(this.direction==="long"?1:-1)),i.entry+a*Math.abs(o)}box(t){let n=this.handlePoints(t);if(n.length<3)return null;let o=n.map(i=>i[0]);return {x1:Math.min(...o),x2:Math.max(...o),ey:n[0][1],sy:n[1][1],ty:n[2][1]}}layout(t){return this.box(t)}hitTest(t,n,o,i){let s=this.box(o);if(!s)return false;let a=Math.min(s.ey,s.sy,s.ty),l=Math.max(s.ey,s.sy,s.ty);return $e(t,n,s.x1,a,s.x2,l,i)}handlePoints(t){let n=this.resolved();if(!n)return [];let o=[];for(let i of n){let s=t.yOf(i.price,this.paneId);if(s==null)return [];o.push([t.xOf(i.time),s]);}return o}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.box(t);if(!n)return null;let o=Math.min(n.ey,n.sy,n.ty);return {x:n.x1,y:o,w:n.x2-n.x1,h:Math.max(n.ey,n.sy,n.ty)-o}}priceRange(){let t=this.resolved();if(!t)return null;let n=t.map(o=>o.price);return {min:Math.min(...n),max:Math.max(...n)}}schema(){return {fields:[{path:"riskPercent",label:"Risk %",kind:"number",min:0,max:100,step:.1,group:"behavior"},{path:"accountBalance",label:"Account balance",kind:"number",min:0,max:1e12,step:1,group:"behavior"},{path:"quantity",label:"Position size",kind:"number",group:"behavior"},{path:"direction",label:"Direction",kind:"select",options:hl,group:"behavior"},{path:"entryPrice",label:"Entry price",kind:"number",group:"behavior"},{path:"stopPrice",label:"Stop price",kind:"number",group:"behavior"},{path:"targetPrice",label:"Target price",kind:"number",group:"behavior"},{path:"showText",label:"Show text",kind:"boolean",group:"behavior"},{path:"showHeader",label:"Show direction & ratio",kind:"boolean",group:"behavior"},{path:"showLossSize",label:"Show loss & size",kind:"boolean",group:"behavior"},{path:"showTargetLabel",label:"Show target label",kind:"boolean",group:"behavior"},{path:"showStopLabel",label:"Show stop label",kind:"boolean",group:"behavior"},{path:"showPrices",label:"Show level prices",kind:"boolean",group:"behavior"},{path:"profitColor",label:"Profit zone",kind:"color",group:"fill"},{path:"lossColor",label:"Loss zone",kind:"color",group:"fill"},...G.filter(t=>t.path!=="style.lineColor"),{path:"text.color",label:"Text color",kind:"color",group:"text"},{path:"text.size",label:"Text size",kind:"select",options:Dt,group:"text"}]}}writeProps(){return {riskPercent:this.riskPercent,accountBalance:this.accountBalance,showText:this.showText,showHeader:this.showHeader,showPrices:this.showPrices,showLossSize:this.showLossSize,showTargetLabel:this.showTargetLabel,showStopLabel:this.showStopLabel,profitColor:this.profitColor,lossColor:this.lossColor}}readProps(t){typeof t.riskPercent=="number"&&Number.isFinite(t.riskPercent)&&(this.riskPercent=t.riskPercent),typeof t.accountBalance=="number"&&Number.isFinite(t.accountBalance)&&(this.accountBalance=t.accountBalance),typeof t.showText=="boolean"&&(this.showText=t.showText),typeof t.showHeader=="boolean"&&(this.showHeader=t.showHeader),typeof t.showPrices=="boolean"&&(this.showPrices=t.showPrices),typeof t.showLossSize=="boolean"&&(this.showLossSize=t.showLossSize),typeof t.showTargetLabel=="boolean"&&(this.showTargetLabel=t.showTargetLabel),typeof t.showStopLabel=="boolean"&&(this.showStopLabel=t.showStopLabel),typeof t.profitColor=="string"&&(this.profitColor=t.profitColor),typeof t.lossColor=="string"&&(this.lossColor=t.lossColor);}};De.DEFAULT_RR=2,De.MIN_DRAG_PX=6,De.DEFAULT_RISK_PX=64,De.DEFAULT_WIDTH_PX=150,De.MIN_WIDTH_PX=48,De.DEFAULT_RISK_PERCENT=1,De.DEFAULT_ACCOUNT_BALANCE=1e4,De.DEFAULT_PROFIT_COLOR=ia,De.DEFAULT_LOSS_COLOR=sa;var yt=De;function ZS(r){if(!Number.isFinite(r))return "0";let e=Math.round(r*100)/100;return Number.isInteger(e)?String(e):e.toFixed(2)}function QS(r){return !Number.isFinite(r)||r===0?"0":r>=100?r.toFixed(2):r>=1?r.toFixed(4).replace(/\.?0+$/,""):r.toPrecision(4).replace(/\.?0+$/,"")}function yf(r){return Number.isFinite(r)?Math.abs(r)>=1?r.toFixed(2):r.toPrecision(4).replace(/\.?0+$/,""):"0"}function wf(r){return Math.round(r*1e8)/1e8}var Tr=[{value:"auto",label:"Auto",ms:0},{value:"1",label:"1m",ms:6e4},{value:"5",label:"5m",ms:3e5},{value:"15",label:"15m",ms:9e5},{value:"30",label:"30m",ms:18e5},{value:"60",label:"1h",ms:36e5},{value:"240",label:"4h",ms:144e5},{value:"D",label:"1D",ms:864e5}];function xi(r){let e=Tr.find(n=>n.value===r);if(e)return e.label;let t=Number(r);return Number.isFinite(t)&&t>0?t%1440===0?`${t/1440}D`:t%60===0?`${t/60}h`:`${t}m`:r}function xf(){return {timeframe:"auto",upColor:"",downColor:""}}var ht=class extends K{constructor(t){super(t);this.type="magnifier";this.chipRect=null;this.magnifier||(this.magnifier=xf());}anchorSchema(){return {min:2,max:2,slots:[{role:"c1",free:"both"},{role:"c2",free:"both"}]}}placementMode(){return "drag"}rect(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);return i==null||s==null?null:{x1:t.xOf(n.time),y1:i,x2:t.xOf(o.time),y2:s}}hitTest(t,n,o,i){let s=this.rect(o);return s?$e(t,n,s.x1,s.y1,s.x2,s.y2)?true:[[s.x1,s.y1,s.x2,s.y1],[s.x2,s.y1,s.x2,s.y2],[s.x2,s.y2,s.x1,s.y2],[s.x1,s.y2,s.x1,s.y1]].some(l=>ae(t,n,l[0],l[1],l[2],l[3])<=i):false}handlePoints(t){let n=this.rect(t);return n?[[n.x1,n.y1],[n.x2,n.y2]]:[]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.rect(t);return n?{x:Math.min(n.x1,n.x2),y:Math.min(n.y1,n.y2),w:Math.abs(n.x2-n.x1),h:Math.abs(n.y2-n.y1)}:null}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}schema(){return {fields:[{path:"magnifier.timeframe",label:"Timeframe",kind:"select",options:Tr,group:"behavior"},...G.map(t=>({...t,label:t.label.replace("Line","Border")})),{path:"magnifier.upColor",label:"Up candles",kind:"color",group:"fill"},{path:"magnifier.downColor",label:"Down candles",kind:"color",group:"fill"}]}}writeProps(){return {...this.magnifier}}readProps(t){this.magnifier={...xf(),...t};}};var Ci=new Map;function W(r){Ci.set(r.type,r);}function Nt(r){return Ci.get(r)}function pl(){return [...Ci.values()]}function Wn(r,e){let t=Ci.get(r);if(!t)return null;let n={...t.defaultStyle,...e.style??{}};return t.create({...e,style:n})}function ml(r){let e=Wn(r.type,{paneId:r.paneId});if(!e)return;r.style={...e.style};let t=r.text?.value;e.text?(r.text={...e.text},t!==void 0&&(r.text.value=t)):r.text=void 0;let n=e.serialize().props;n!==void 0&&r.applyProps(n);}function wt(r){let e=Ci.get(r.type);return e?e.create(r):null}var JS=B(''),eT=B('');W({type:"trendline",group:"lines",label:"Trend Line",icon:JS,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new la(r)});W({type:"hline",group:"lines",label:"Horizontal Line",icon:eT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"dashed"},create:r=>new ca(r)});var tT=B(''),nT=B(''),rT=B('');W({type:"ray",group:"lines",label:"Ray",icon:tT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new da(r)});var oT=B(''),iT=B(''),sT=B(''),aT=B(''),lT=B(''),cT=B('');W({type:"extendedline",group:"lines",label:"Extended Line",icon:oT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new ua(r)});W({type:"vline",group:"lines",label:"Vertical Line",icon:iT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new ha(r)});W({type:"hray",group:"lines",label:"Horizontal Ray",icon:sT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new pa(r)});W({type:"crossline",group:"lines",label:"Cross Line",icon:aT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new ma(r)});W({type:"infoline",group:"lines",label:"Info Line",icon:lT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new fa(r)});W({type:"trendangle",group:"lines",label:"Trend Angle",icon:cT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new ga(r)});W({type:"box",group:"shapes",label:"Rectangle",icon:nT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid",fillColor:`${_}26`},create:r=>new ba(r)});W({type:"text",group:"annotations",label:"Text",icon:rT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new bn(r)});var dT=B('');W({type:"callout",group:"annotations",label:"Callout",icon:dT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid",fillColor:`${_}d9`},create:r=>new Xt(r)});var uT=B(''),hT=B(''),pT=B(''),mT=B(''),fT=B('');W({type:"note",group:"annotations",label:"Note",icon:uT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid",fillColor:`${_}d9`},create:r=>new cr(r)});W({type:"pricenote",group:"annotations",label:"Price Note",icon:hT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid",fillColor:`${_}d9`},create:r=>new ur(r)});W({type:"comment",group:"annotations",label:"Comment",icon:pT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid",fillColor:`${_}d9`},create:r=>new hr(r)});W({type:"pricelabel",group:"annotations",label:"Price Label",icon:mT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid",fillColor:`${_}d9`},create:r=>new dr(r)});W({type:"signpost",group:"annotations",label:"Signpost",icon:fT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid",fillColor:`${_}d9`},create:r=>new pr(r)});var gT=B(''),bT=B(''),vT=B('');W({type:"parallelchannel",group:"channels",label:"Parallel Channel",icon:gT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid",fillColor:`${_}1a`},create:r=>new va(r)});W({type:"disjointchannel",group:"channels",label:"Disjoint Channel",icon:bT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid",fillColor:`${_}1a`},create:r=>new ya(r)});var yT=B('');W({type:"flattopbottom",group:"channels",label:"Flat Top/Bottom",icon:yT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid",fillColor:`${_}1a`},create:r=>new wa(r)});var wT=B('');W({type:"regressionchannel",group:"channels",label:"Linear Regression",icon:wT,defaultStyle:{lineColor:A,lineWidth:1,lineStyle:"solid"},create:r=>new vn(r)});W({type:"pitchfork",group:"pitchforks",label:"Pitchfork",icon:vT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new xa(r)});var xT=B(''),CT=B(''),ST=B('');W({type:"schiffpitchfork",group:"pitchforks",label:"Schiff Pitchfork",icon:xT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new Ca(r)});W({type:"modifiedschiffpitchfork",group:"pitchforks",label:"Modified Schiff Pitchfork",icon:CT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new Sa(r)});W({type:"insidepitchfork",group:"pitchforks",label:"Inside Pitchfork",icon:ST,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new Ta(r)});var TT=B(''),kT=B(''),LT=B('');W({type:"arrow",group:"shapes",label:"Arrow",icon:TT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid",arrowRight:true},create:r=>new ka(r)});W({type:"ellipse",group:"shapes",label:"Ellipse",icon:kT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid",fillColor:`${_}1a`},create:r=>new La(r)});W({type:"triangle",group:"shapes",label:"Triangle",icon:LT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid",fillColor:`${_}1a`},create:r=>new Ma(r)});var MT=B(''),ET=B(''),PT=B('');W({type:"polyline",group:"shapes",label:"Polyline",icon:MT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new Ea(r)});W({type:"freehand",group:"shapes",label:"Brush",icon:ET,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new Pa(r)});W({type:"highlighter",group:"shapes",label:"Highlighter",icon:PT,defaultStyle:{lineColor:`${Bm}59`,lineWidth:14,lineStyle:"solid"},create:r=>new Ia(r)});var IT=B(''),AT=B(''),RT=B(''),DT=B(''),OT=B(''),NT=B(''),FT=B('');W({type:"circle",group:"shapes",label:"Circle",icon:IT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid",fillColor:`${_}1a`},create:r=>new Aa(r)});W({type:"rotatedrect",group:"shapes",label:"Rotated Rectangle",icon:AT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid",fillColor:`${_}26`},create:r=>new Ra(r)});W({type:"path",group:"shapes",label:"Path",icon:RT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new Da(r)});W({type:"arc",group:"shapes",label:"Arc",icon:DT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid",fillColor:`${_}26`},create:r=>new Oa(r)});W({type:"curve",group:"shapes",label:"Curve",icon:OT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new Na(r)});W({type:"arrowmarkup",group:"shapes",label:"Arrow Mark Up",icon:NT,defaultStyle:{lineColor:O,lineWidth:1,lineStyle:"solid"},create:r=>new pi(r)});W({type:"arrowmarkdown",group:"shapes",label:"Arrow Mark Down",icon:FT,defaultStyle:{lineColor:D,lineWidth:1,lineStyle:"solid"},create:r=>new mi(r)});var VT=B(''),BT=B('');W({type:"flagmark",group:"stamps",label:"Flag",icon:VT,defaultStyle:{lineColor:nt,lineWidth:1,lineStyle:"solid"},create:r=>new fi(r)});W({type:"iconstamp",group:"stamps",label:"Icon",icon:BT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new gi(r)});var _T=B(''),HT=B('');W({type:"fibretracement",group:"fibonacci",label:"Fib Retracement",icon:_T,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new Ba(r)});W({type:"fibextension",group:"fibonacci",label:"Fib Extension",icon:HT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new _a(r)});var zT=B('');W({type:"fibextensiontrend",group:"fibonacci",label:"Trend-Based Fib Extension",icon:zT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new Ha(r)});var WT=B(''),GT=B('');W({type:"fibfan",group:"fibonacci",label:"Fib Fan",icon:WT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new za(r)});W({type:"fibtimezones",group:"fibonacci",label:"Fib Time Zones",icon:GT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"dashed"},create:r=>new Wa(r)});var $T=B(''),UT=B(''),YT=B('');W({type:"fibchannel",group:"fibonacci",label:"Fib Channel",icon:$T,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new Ga(r)});W({type:"fibspeedfan",group:"fibonacci",label:"Fib Speed Resistance Fan",icon:UT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new $a(r)});W({type:"trendfibtime",group:"fibonacci",label:"Trend-Based Fib Time",icon:YT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"dashed"},create:r=>new Ua(r)});var KT=B(''),XT=B(''),jT=B(''),qT=B('');W({type:"fibcircles",group:"fibonacci",label:"Fib Circles",icon:KT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new Ya(r)});W({type:"fibarcs",group:"fibonacci",label:"Fib Speed Resistance Arcs",icon:XT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new Ka(r)});W({type:"fibwedge",group:"fibonacci",label:"Fib Wedge",icon:jT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new Xa(r)});W({type:"fibspiral",group:"fibonacci",label:"Fib Spiral",icon:qT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new wr(r)});var ZT=B(''),QT=B('');W({type:"gannfan",group:"fibonacci",label:"Gann Fan",icon:ZT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new ja(r)});W({type:"gannbox",group:"fibonacci",label:"Gann Box",icon:QT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new qa(r)});var JT=B('');W({type:"gannsquare",group:"fibonacci",label:"Gann Square",icon:JT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new xr(r)});var e1=B('');W({type:"dedekind",group:"geometry",label:"Dedekind Tessellation",icon:e1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new Cr(r)});var t1=B(''),n1=B('');W({type:"sonic",group:"geometry",label:"Sonic",icon:t1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new vi(r)});W({type:"supersonic",group:"geometry",label:"Supersonic",icon:n1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new yi(r)});var r1=B(''),o1=B('');W({type:"goldensonic",group:"geometry",label:"Golden Sonic",icon:r1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new Qa(r)});W({type:"goldensupersonic",group:"geometry",label:"Golden Supersonic",icon:o1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new Ja(r)});var i1=B(''),s1=B(''),a1=B(''),l1=B(''),c1=B('');W({type:"xabcd",group:"patterns",label:"XABCD Pattern",icon:i1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new el(r)});W({type:"abcd",group:"patterns",label:"ABCD Pattern",icon:s1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new tl(r)});W({type:"elliottimpulse",group:"patterns",label:"Elliott Impulse Wave (1-5)",icon:a1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new nl(r)});W({type:"elliottcorrection",group:"patterns",label:"Elliott Correction Wave (ABC)",icon:l1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new rl(r)});W({type:"headshoulders",group:"patterns",label:"Head & Shoulders",icon:c1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new ol(r)});var d1=B(''),ao={group:"patterns",icon:d1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"}};W({type:"gartley",label:"Gartley",...ao,create:r=>new il(r)});W({type:"bat",label:"Bat",...ao,create:r=>new sl(r)});W({type:"butterfly",label:"Butterfly",...ao,create:r=>new al(r)});W({type:"crab",label:"Crab",...ao,create:r=>new ll(r)});W({type:"shark",label:"Shark",...ao,create:r=>new cl(r)});W({type:"cypher",label:"Cypher",...ao,create:r=>new dl(r)});var u1=B('');W({type:"datepricerange",group:"measure",label:"Date & Price Range",icon:u1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new ul(r)});var h1=B('');W({type:"position",group:"measure",label:"Long/Short Position",icon:h1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new yt(r)});var p1=B('');W({type:"magnifier",group:"measure",label:"Magnifier",icon:p1,defaultStyle:{lineColor:"",lineWidth:1,lineStyle:"solid"},coversSeries:true,placementHint:"Drag an area on the chart to view it at a lower timeframe",create:r=>new ht(r)});var m1=B('');W({type:"anchoredvwap",group:"measure",label:"Anchored VWAP",icon:m1,defaultStyle:{lineColor:ce,lineWidth:2,lineStyle:"solid"},create:r=>new mr(r)});var f1=B('');W({type:"fixedrangevp",group:"measure",label:"Fixed Range Volume Profile",icon:f1,defaultStyle:{lineColor:O,lineWidth:1,lineStyle:"solid"},create:r=>new gt(r)});var g1=["fibretracement","fibextension","fibextensiontrend","fibfan","fibtimezones","fibchannel","fibspeedfan","trendfibtime","fibcircles","fibarcs","fibwedge","fibspiral"],b1=["gannfan","gannbox","gannsquare"],v1=["dedekind","sonic","supersonic","goldensonic","goldensupersonic"],y1=["xabcd","abcd","headshoulders"],w1=["elliottimpulse","elliottcorrection"],x1=["gartley","bat","butterfly","crab","shark","cypher"],C1=["position","datepricerange","magnifier"],S1=["anchoredvwap","fixedrangevp"],T1=["freehand","highlighter"],k1=["arrow","arrowmarkup","arrowmarkdown"],L1=["box","ellipse","triangle","polyline","circle","rotatedrect","path","arc","curve"],M1=["text","callout","note","pricenote","comment","pricelabel","signpost"],E1=["flagmark","iconstamp"],P1=[{id:"lines-channels-pitchforks",label:"Lines",sections:[{label:"Lines",registryGroup:"lines"},{label:"Channels",registryGroup:"channels"},{label:"Pitchforks",registryGroup:"pitchforks"}]},{id:"fibonacci-gann",label:"Fibonacci",sections:[{label:"Fibonacci",types:g1},{label:"Gann",types:b1},{label:"Geometry",types:v1}]},{id:"patterns-waves-harmonics",label:"Patterns",sections:[{label:"Patterns",types:y1},{label:"Elliott Waves",types:w1},{label:"Harmonics",types:x1}]},{id:"measurements",label:"Measurements",sections:[{label:"Measurements",types:C1},{label:"Volume",types:S1}]},{id:"brushes-arrows-shapes",label:"Shapes",sections:[{label:"Brushes",types:T1},{label:"Arrows",types:k1},{label:"Shapes",types:L1}]},{id:"text",label:"Text",sections:[{label:"Text",types:M1}]},{id:"icons",label:"Icons",sections:[{label:"Icons",types:E1}]}];function I1(r){let e=Nt(r);return e?{type:e.type,label:e.label,icon:e.icon}:null}function A1(r){let e=new Map;for(let t of pl()){if(r&&!r.has(t.type))continue;let n={type:t.type,label:t.label,icon:t.icon};e.has(t.group)||e.set(t.group,[]),e.get(t.group).push(n);}return e}function R1(r,e,t){return "registryGroup"in r?e.get(r.registryGroup)??[]:r.types.map(n=>t.get(n)).filter(n=>n!=null)}function Cf(r){let e=A1(r),t=new Map;for(let o of e.values())for(let i of o)t.set(i.type,i);let n=[];for(let o of P1){let i=[],s=[];for(let a of o.sections){let l=R1(a,e,t);l.length!==0&&(i.push({label:a.label,tools:l}),s.push(...l));}s.length!==0&&n.push({id:o.id,label:o.label,tools:s,sections:i.length>0?i:void 0});}return {groups:n}}function D1(r){let e=new Set;for(let t of r)Nt(t)&&e.add(t);return Cf(e)}function O1(r){let e=[];for(let t of r){let n=t.tools.map(I1).filter(o=>o!=null);n.length>0&&e.push({id:t.id,label:t.label,tools:n});}return {groups:e}}function Si(){return Cf()}function Ti(r){if(r===false)return {definition:Si(),visible:false};if(r===void 0||r===true)return {definition:Si(),visible:true};let e=r.toolbar??true;return r.groups?{definition:O1(r.groups),visible:e}:r.tools?{definition:D1(r.tools),visible:e}:{definition:Si(),visible:e}}function Zt(r){let e=globalThis.structuredClone;return e?e(r):JSON.parse(JSON.stringify(r))}function Sf(r){if(!r||typeof r!="object")return false;let e=r;return typeof e.id=="string"&&typeof e.type=="string"&&typeof e.paneId=="string"&&Array.isArray(e.anchors)&&e.anchors.every(t=>t&&typeof t.time=="number"&&typeof t.price=="number")&&!!e.style&&typeof e.style=="object"}function ou(r){let e=r;return !e||typeof e!="object"||e.version!==1||!Array.isArray(e.drawings)?{version:1,drawings:[]}:{version:1,drawings:e.drawings.filter(Sf)}}var lo=class{constructor(){this.byId=new Map;this.seq=0;this.zCounter=1;this.listeners=new Set;}nextId(){return this.seq+=1,`dw-${this.seq}`}add(e){return e.zIndex||(e.zIndex=this.zCounter),this.zCounter=Math.max(this.zCounter,Math.ceil(e.zIndex))+1,this.byId.set(e.id,e),this.emit(),e}remove(e){let t=this.byId.delete(e);return t&&this.emit(),t}get(e){return this.byId.get(e)}has(e){return this.byId.has(e)}update(e,t){let n=this.byId.get(e);return n?(t.anchors&&(n.anchors=t.anchors.map(o=>({time:o.time,price:o.price}))),t.style&&(n.style={...t.style}),t.text!==void 0&&(n.text=t.text?{...t.text}:void 0),t.paneId!==void 0&&(n.paneId=t.paneId),t.locked!==void 0&&(n.locked=t.locked),t.visible!==void 0&&(n.visible=t.visible),t.zIndex!==void 0&&(n.zIndex=t.zIndex),t.props!==void 0&&n.applyProps(t.props),this.emit(),n):null}all(){return [...this.byId.values()].sort((e,t)=>e.zIndex-t.zIndex)}byPane(e){return this.all().filter(t=>t.paneId===e)}bringToFront(e,t=0){let n=this.byId.get(e);n&&(n.zIndex=Math.max(this.zCounter,Math.floor(t)+1),this.zCounter=n.zIndex+1,this.emit());}sendToBack(e,t=1){let n=this.byId.get(e);if(!n)return;let o=Math.min(...[...this.byId.values()].map(i=>i.zIndex),Math.ceil(t));n.zIndex=o-1,this.emit();}setLocked(e,t){let n=this.byId.get(e);n&&(n.locked=t,this.emit());}setVisible(e,t){let n=this.byId.get(e);n&&(n.visible=t,this.emit());}clear(){this.byId.size!==0&&(this.byId.clear(),this.emit());}serialize(){return {version:1,drawings:this.all().map(e=>e.serialize())}}load(e){let t=ou(e);this.byId.clear(),this.seq=0,this.zCounter=1;for(let n of t.drawings){let o=wt(n);o&&(this.byId.set(o.id,o),this.zCounter=Math.max(this.zCounter,o.zIndex)+1,this.bumpSeqPast(o.id));}this.emit();}onChange(e){return this.listeners.add(e),()=>this.listeners.delete(e)}bumpSeqPast(e){let t=/^dw-(\d+)$/.exec(e);t&&(this.seq=Math.max(this.seq,Number(t[1])));}emit(){for(let e of this.listeners)e();}};var fl=class{constructor(e=100){this.cap=e;this.undoStack=[];this.redoStack=[];this.pending=null;this.dirtied=false;this.depth=0;}begin(e){this.depth+=1,this.depth===1&&(this.pending=Zt(e),this.dirtied=false);}markDirty(){this.depth===0||this.dirtied||!this.pending||(this.push(this.pending),this.dirtied=true);}commit(){this.depth!==0&&(this.depth-=1,this.depth===0&&(this.pending=null,this.dirtied=false));}abort(){this.commit();}record(e){if(this.depth>0){this.markDirty();return}this.push(Zt(e));}undo(e){let t=this.undoStack.pop();return t?(this.redoStack.push(Zt(e)),t):null}redo(e){let t=this.redoStack.pop();return t?(this.undoStack.push(Zt(e)),t):null}canUndo(){return this.undoStack.length>0}canRedo(){return this.redoStack.length>0}clear(){this.undoStack=[],this.redoStack=[],this.pending=null,this.dirtied=false,this.depth=0;}push(e){this.undoStack.push(e),this.undoStack.length>this.cap&&this.undoStack.shift(),this.redoStack=[];}};var gl=class{constructor(e,t,n,o){this.events=t;this.store=new lo;this.history=new fl;this.activeTool=null;this.snapMode="off";this.stayInDrawingMode=false;this.mode=null;this.favs=new Set;this.selectedIds=[];this.clipboard=[];this.lastStyle=new Map;this.subs=[];if(this.enabled=!!e.capabilities.userDrawings&&!!e.userDrawingsPort,this.port=this.enabled?e.userDrawingsPort:null,this.port){let{definition:i,visible:s}=Ti(n);this.port.setToolbar(i),this.port.showToolbar(s),o&&this.port.setSeriesGateway?.(o),this.subs.push(this.port.onDrawingIntent(a=>this.onIntent(a))),this.subs.push(this.store.onChange(()=>this.sync()));}}get supported(){return this.enabled}setTool(e){if(!this.port)return;let t=e!==this.activeTool;this.activeTool=e,this.port.setActiveTool(e,e?this.lastStyle.get(e):void 0),t&&this.events.emit("drawing:tool",{type:e});}getTool(){return this.activeTool}getSnapMode(){return this.snapMode}setSnapMode(e){!this.port||e===this.snapMode||(this.snapMode=e,this.port.setSnapMode?.(e),this.events.emit("drawing:snap",{mode:e}));}getStayMode(){return this.stayInDrawingMode}setStayMode(e){!this.port||e===this.stayInDrawingMode||(this.stayInDrawingMode=e,this.port.setStayMode?.(e),this.events.emit("drawing:stay",{on:e}));}getMode(){return this.mode}setMode(e){!this.port||e===this.mode||(this.mode=e,this.port.setMode?.(e),this.events.emit("drawing:mode",{mode:e}));}showToolbar(e){this.port?.showToolbar(e);}favorites(){return [...this.favs]}isFavorite(e){return this.favs.has(e)}setFavorite(e,t){Nt(e)&&t!==this.favs.has(e)&&(t?this.favs.add(e):this.favs.delete(e),this.pushFavorites());}setFavorites(e){let t=e.filter(n=>Nt(n)!=null);t.length===this.favs.size&&t.every(n=>this.favs.has(n))||(this.favs=new Set(t),this.pushFavorites());}pushFavorites(){let e=[...this.favs];this.port?.setFavorites?.(e),this.events.emit("drawing:favorites",{favorites:e});}setToolbar(e){this.port?.setToolbar(Ti(e).definition);}setExternalGhost(e){this.port?.setExternalGhost?.(e);}setToolShortcuts(e){this.port?.setToolShortcuts?.(e);}add(e,t={}){if(!this.enabled)return null;let o={...this.lastStyle.get(e)??{},...t.style??{}},i=Wn(e,{id:this.store.nextId(),paneId:t.paneId??"price",anchors:t.anchors,style:o,text:t.text,props:t.props,zIndex:t.zIndex??this.startZ(e,t.paneId??"price")});return i?(this.history.record(this.store.serialize()),this.store.add(i),this.captureStyle(i.id),this.events.emit("drawing:created",{id:i.id}),i):null}remove(e){this.deleteMany([e]);}update(e,t){let n=this.store.serialize(),o=t.style?this.store.get(e):void 0,i=t.style&&o?{...t,style:{...o.style,...t.style}}:t;this.store.update(e,i)&&(this.history.record(n),this.captureStyle(e),this.events.emit("drawing:edited",{id:e}));}updateMany(e){this.history.begin(this.store.serialize());for(let{id:t,patch:n}of e)this.store.update(t,n)&&(this.history.markDirty(),this.events.emit("drawing:edited",{id:t}));this.history.commit();}removeMany(e){this.deleteMany(e);}setLocked(e,t){let n=this.store.serialize();this.history.record(n),this.store.setLocked(e,t),this.events.emit("drawing:edited",{id:e});}setVisible(e,t){let n=this.store.serialize();this.history.record(n),this.store.setVisible(e,t),this.events.emit("drawing:edited",{id:e});}bringToFront(e){let t=this.store.serialize();this.history.record(t),this.store.bringToFront(e,this.seriesTopZ(this.store.get(e)?.paneId)),this.events.emit("drawing:edited",{id:e});}sendToBack(e){let t=this.store.serialize();this.history.record(t),this.store.sendToBack(e,this.seriesBottomZ(this.store.get(e)?.paneId)),this.events.emit("drawing:edited",{id:e});}seriesTopZ(e){return e!==void 0?this.port?.stackRange?.(e)?.front??0:0}seriesBottomZ(e){return e!==void 0?this.port?.stackRange?.(e)?.back??1:1}startZ(e,t){let n=this.port?.stackRange?.(t);if(n)return Nt(e)?.coversSeries?n.front+.5:(n.price??n.front)-.5}select(e,t=false){this.setSelection(e,t);}openSettings(e){this.port?.openSettings(e);}undo(){let e=this.history.undo(this.store.serialize());e&&this.restoreSnapshot(e);}redo(){let e=this.history.redo(this.store.serialize());e&&this.restoreSnapshot(e);}canUndo(){return this.history.canUndo()}canRedo(){return this.history.canRedo()}duplicate(e){if(!this.enabled)return [];let t=this.resolve(e);return t.length===0?[]:this.insertClones(t.map(n=>n.serialize()))}clone(e){return this.duplicate([e])[0]??null}copy(e){let t=this.resolve(e).map(n=>Zt(n.serialize()));t.length&&(this.clipboard=t);}paste(){return !this.enabled||this.clipboard.length===0?[]:this.insertClones(this.clipboard)}all(){return this.store.serialize().drawings}toJSON(){return this.store.serialize()}fromJSON(e){this.history.clear(),this.selectedIds=[],this.store.load(e);}destroy(){for(let e of this.subs)e();this.subs.length=0;}setSelection(e,t=false){let n;if(t){n=[...this.selectedIds];for(let o of e){let i=n.indexOf(o);i>=0?n.splice(i,1):n.push(o);}}else n=[...e];this.selectedIds=n.filter(o=>this.store.has(o)),this.announceSelection();}announceSelection(){this.port?.setSelection(this.selectedIds),this.events.emit("drawing:selected",{id:this.selectedIds[0]??null,ids:[...this.selectedIds]});}restoreSnapshot(e){this.store.load(e),this.selectedIds=this.selectedIds.filter(t=>this.store.has(t)),this.announceSelection();}deleteMany(e){this.history.begin(this.store.serialize());let t=[];for(let o of e)this.store.remove(o)&&t.push(o),this.history.markDirty();if(this.history.commit(),t.length===0)return;let n=this.selectedIds.filter(o=>this.store.has(o));n.length!==this.selectedIds.length&&this.setSelection(n);for(let o of t)this.events.emit("drawing:removed",{id:o});}insertClones(e){this.history.begin(this.store.serialize());let t=[];for(let n of e){let o=wt({...n,id:this.store.nextId()});o&&(this.store.add(o),this.history.markDirty(),t.push(o));}if(this.history.commit(),t.length){this.setSelection(t.map(n=>n.id));for(let n of t)this.events.emit("drawing:created",{id:n.id});}return t}resolve(e){return e.map(t=>this.store.get(t)).filter(t=>t!=null)}captureStyle(e){let t=this.store.get(e);t&&this.lastStyle.set(t.type,{...t.style});}sync(){this.port?.syncDrawings(this.store.serialize().drawings);}onIntent(e){switch(e.kind){case "arm":this.setTool(e.type);break;case "draft":this.events.emit("drawing:draft",{doc:e.doc});break;case "create":{let t=this.store.serialize(),n=this.lastStyle.get(e.doc.type),o=n?{...e.doc.style,...n}:e.doc.style,i=wt({...e.doc,id:this.store.nextId(),style:o});if(!i)return;i.zIndex||(i.zIndex=this.startZ(i.type,i.paneId)??0),this.history.record(t),this.store.add(i),this.captureStyle(i.id),this.events.emit("drawing:created",{id:i.id});break}case "edit":{let t=this.store.serialize();this.store.update(e.doc.id,e.doc)&&(this.history.record(t),this.captureStyle(e.doc.id),this.events.emit("drawing:edited",{id:e.doc.id}));break}case "edit-many":{this.history.begin(this.store.serialize());for(let t of e.docs)this.store.update(t.id,t)&&(this.history.markDirty(),this.events.emit("drawing:edited",{id:t.id}));this.history.commit();break}case "select":this.setSelection(e.ids,e.additive);break;case "delete":this.deleteMany(e.ids);break;case "reorder":e.to==="front"?this.bringToFront(e.id):this.sendToBack(e.id);break;case "settings":this.events.emit("drawing:settings",{id:e.id});break;case "favorite":this.setFavorite(e.type,e.on);break;case "snap-mode":e.mode!==this.snapMode&&(this.snapMode=e.mode,this.events.emit("drawing:snap",{mode:e.mode}));break;case "stay-mode":e.on!==this.stayInDrawingMode&&(this.stayInDrawingMode=e.on,this.events.emit("drawing:stay",{on:e.on}));break;case "mode":e.mode!==this.mode&&(this.mode=e.mode,this.events.emit("drawing:mode",{mode:e.mode}));break;case "tool-finished":!this.stayInDrawingMode&&e.type!=="freehand"&&e.type!=="highlighter"&&this.setTool(null);break;case "undo":this.undo();break;case "redo":this.redo();break;case "duplicate":this.duplicate(e.ids);break;case "clone":this.enabled&&e.docs.length&&this.insertClones(e.docs);break;case "copy":this.copy(e.ids);break;case "paste":this.paste();break}}};function bl(r,e,t){let n=r[e];return typeof n=="boolean"?n:t.find(o=>o.id===e)?.visible!==false}function vl(r,e,t){if(e===void 0)return true;let n=new Set,o=e;for(;o!==void 0&&!n.has(o);){if(n.add(o),!bl(r,o,t))return false;let i=t.find(s=>s.id===o)?.parent;o=i!==void 0&&t.some(s=>s.id===i)?i:void 0;}return true}function iu(r){let e=new Set(r.map(i=>i.id)),t=[],n=new Set,o=(i,s)=>{if(!n.has(i.id)){n.add(i.id),t.push({group:i,depth:s});for(let a of r)a.parent===i.id&&a.id!==i.id&&o(a,s+1);}};for(let i of r)i.parent!==void 0&&e.has(i.parent)&&i.parent!==i.id||o(i,0);for(let i of r)o(i,0);return t}var yl=class{constructor(e,t){this.renderer=e;this.marks=new Map;this.groups=new Map;this.subs=[];this.enabled=!!e.capabilities.timelineMarks&&typeof e.setTimelineMarks=="function",this.enabled&&e.onMarkClick&&this.subs.push(e.onMarkClick(n=>t.emit("mark:click",n)));}get supported(){return this.enabled}add(e){this.marks.set(e.id,kf(e)),this.sync();}set(e){this.marks.clear();for(let t of e)this.marks.set(t.id,kf(t));this.sync();}remove(e){let t=this.marks.delete(e);return t&&this.sync(),t}clear(){this.marks.size!==0&&(this.marks.clear(),this.sync());}all(){return [...this.marks.values()].map(e=>({...e,glyph:{...e.glyph}}))}defineGroup(e){if(!e||typeof e.id!="string"||e.id.length===0)throw new Error("[vela] marks.defineGroup: `id` must be a non-empty string");if(typeof e.label!="string")throw new Error(`[vela] marks.defineGroup: group "${e.id}" needs a string \`label\``);if(e.parent!==void 0&&(typeof e.parent!="string"||e.parent.length===0))throw new Error(`[vela] marks.defineGroup: group "${e.id}" has a \`parent\` that is not a group id`);this.groups.set(e.id,{...e}),this.sync();}groupDefinitions(){return [...this.groups.values()].map(e=>({...e}))}setGroupVisible(e,t){if(!this.renderer.features.includes("marks")){console.warn(`[vela] renderer "${this.renderer.name}" does not paint timeline marks \u2014 setGroupVisible ignored.`);return}this.renderer.applyFeature("marks",{groups:{[e]:t}});}isGroupVisible(e){let t=this.renderer.readFeature("marks"),n={};for(let[o,i]of Object.entries(t?.groups??{}))typeof i=="boolean"&&(n[o]=i);return vl(n,e,[...this.groups.values()])}destroy(){for(let e of this.subs)e();this.subs.length=0;}sync(){this.enabled&&this.renderer.setTimelineMarks([...this.marks.values()],[...this.groups.values()]);}};function kf(r){if(!r||typeof r!="object")throw new Error("[vela] marks: a mark must be an object");if(typeof r.id!="string"||r.id.length===0)throw new Error("[vela] marks: `id` must be a non-empty string");if(typeof r.time!="number"||!Number.isFinite(r.time))throw new Error(`[vela] marks: mark "${r.id}" needs a finite epoch-ms \`time\``);if(!r.glyph||typeof r.glyph!="object"||typeof r.glyph.color!="string")throw new Error(`[vela] marks: mark "${r.id}" needs a glyph with a \`color\``);return {...r,glyph:{...r.glyph}}}var Lf={D:864e5,W:6048e5,M:2592e6};function Ft(r){let e=r.trim();if(Lf[e])return Lf[e];let t=/^(\d+)\s*(m|h|d|w)?$/i.exec(e);if(t){let n=parseInt(t[1],10),o=(t[2]??"m").toLowerCase();return n*(o==="m"?6e4:o==="h"?36e5:o==="d"?864e5:6048e5)}return 36e5}var N1=5e3,F1=.25,V1=16,B1=15e3,su=["240","60","30","15","5","1"],wl=class{constructor(e){this.deps=e;this.cache=new Map;this.listeners=new Set;}seriesInRange(e,t,n){if(!this.deps.canFetch())return {state:"unavailable",reason:"no-source"};let o=this.resolveTimeframe(e);if(typeof o!="string")return {state:"unavailable",reason:o.reason};let i=Ft(o),s=Math.min(t,n),a=Math.max(t,n);if(!(a>s)||!(i>0))return {state:"unavailable",reason:"not-lower"};if((a-s)/i>N1)return {state:"unavailable",reason:"too-wide"};let l=`${this.deps.marketKey()}|${o}`,c=this.cache.get(l)??[],d=c.find(u=>u.from<=s&&u.to>=a);if(d){if(d.pending)return this.loading(c,o,i,s,a);if(d.failedAt>0){if(Date.now()-d.failedAtthis.listeners.delete(e)}resolveTimeframe(e){let t=Ft(this.deps.chartTimeframe()),n=su[su.length-1];if(Ft(n)>=t)return {reason:"none-lower"};let o=e.trim()||"auto";if(o==="auto"){for(let i of su)if(Ft(i)<=t/4)return i;return n}return Ft(o)0)&&!(l.toi))for(let c of this.slice(l.bars,o,i))s.set(c.time,c);if(s.size===0)return {state:"loading",timeframe:t,barMs:n};let a=[...s.values()].sort((l,c)=>l.time-c.time);return {state:"loading",timeframe:t,barMs:n,bars:a}}fetchWindow(e,t,n,o,i){if(t.some(l=>l.pending&&l.to>=o&&l.from<=i))return;let s=(i-o)*F1,a={from:o-s,to:i+s,bars:[],fetchedAt:0,pending:true,failedAt:0};t.push(a),this.cache.set(e,t),this.evict(),this.deps.fetchBars(n,{from:a.from,to:a.to}).then(l=>{a.bars=l,a.fetchedAt=Date.now(),a.pending=false,this.absorbOverlaps(e,a),this.fire();}).catch(()=>{a.pending=false,a.failedAt=Date.now(),this.fire();});}maybeRefresh(e,t,n,o,i){if(t.pending)return;let s=t.bars.length>0?t.bars[t.bars.length-1].time:t.from;i{t.bars=a,t.fetchedAt=Date.now(),t.pending=false,this.fire();}).catch(()=>{t.pending=false,t.fetchedAt=Date.now();}));}absorbOverlaps(e,t){let n=this.cache.get(e);if(n)for(let o=n.length-1;o>=0;o-=1){let i=n[o];if(i===t||i.pending||i.failedAt>0||i.tot.to)continue;let s=new Map;for(let a of i.bars)s.set(a.time,a);for(let a of t.bars)s.set(a.time,a);t.bars=[...s.values()].sort((a,l)=>a.time-l.time),t.from=Math.min(t.from,i.from),t.to=Math.max(t.to,i.to),t.fetchedAt=Math.min(t.fetchedAt,i.fetchedAt||t.fetchedAt),n.splice(o,1);}}evict(){let e=0;for(let t of this.cache.values())e+=t.length;for(;e>V1;){let t=null,n=-1,o=1/0;for(let[s,a]of this.cache)for(let l=0;ln)break;o.push(i);}return o}fire(){for(let e of [...this.listeners])e();}};function ki(r){return r.group!=null&&r.ticker===r.group}function Mf(r){return `${(r.prefix??r.provider??"").toLowerCase()}:${(r.group??"").toUpperCase()}`}function _1(r,e){let t=Mf(e);return r.filter(n=>n.group!=null&&!ki(n)&&Mf(n)===t)}function Ef(r,e){let t=_1(r,e),n=t.filter(o=>o.default);return (n.length===1?n[0]:t[0])??null}var Qt=r=>r.trim().toLowerCase(),wn=r=>r.trim().toUpperCase();function Jt(r){let e=r.trim(),t=/^(?:([A-Za-z0-9_.]+):)?(.+)$/.exec(e);if(!t)return {provider:null,ticker:e};let n=t[1]?Qt(t[1]):null,o=t[2],i=o.lastIndexOf("."),s=i>0?o.slice(i+1):void 0;return {provider:n,ticker:o,ext:s}}var xl=class{constructor(){this.entries=new Map;this.changeListeners=new Set;this.waits=new Set;this.unresolvedCbs=new Set;}register(e,t){let n=Qt(e),o={name:n,provider:t,index:null,prefixIndex:null,byTicker:null,descriptors:[],settled:false,settle:Promise.resolve()};return this.entries.set(n,o),o.settle=this.buildIndex(o),queueMicrotask(()=>this.notify(false)),o.settle}async buildIndex(e){await Promise.resolve();try{if(e.provider.listSymbols){let t=await e.provider.listSymbols();e.descriptors=t,e.index=new Set(t.map(n=>wn(n.ticker))),e.byTicker=new Map(t.map(n=>[wn(n.ticker),n])),e.prefixIndex=new Map;for(let n of t)n.prefix&&e.prefixIndex.set(`${Qt(n.prefix)}:${wn(n.ticker)}`,n);}}catch{e.index=null;}finally{e.settled=true,this.notify(true);}}notify(e){for(let t of [...this.changeListeners])t(e);}onChange(e){return this.changeListeners.add(e),()=>this.changeListeners.delete(e)}unregister(e){this.entries.delete(Qt(e)),this.notify(false);}has(e){return this.entries.has(Qt(e))}get(e){return this.entries.get(Qt(e))?.provider}names(){return [...this.entries.keys()]}parse(e){return Jt(e)}resolve(e,t={}){let{provider:n,ticker:o}=this.parse(e);if(n){if(this.entries.has(n)){let a=this.entries.get(n).byTicker?.get(wn(o));return {provider:n,ticker:a!=null&&ki(a)?this.loadableTicker(n,a):o}}let s=`${n}:${wn(o)}`;for(let a of this.candidateOrder(t.default)){let l=this.entries.get(a).prefixIndex?.get(s);if(l)return {provider:a,ticker:this.loadableTicker(a,l)}}return null}let i=wn(o);for(let s of this.candidateOrder(t.default)){let a=this.entries.get(s);if(a.index?.has(i)){let l=a.byTicker?.get(i);return {provider:s,ticker:l!=null&&ki(l)?this.loadableTicker(s,l):o}}}if(t.lenient&&this.entries.size===1){let s=this.names()[0],a=this.entries.get(s);if(a.settled&&a.index==null)return {provider:s,ticker:o}}return null}loadableTicker(e,t){return ki(t)?Ef(this.entries.get(e)?.descriptors??[],t)?.ticker??t.ticker:t.ticker}whenResolvable(e,t={}){let n=this.resolve(e,{...t,lenient:true});return n?Promise.resolve(n):new Promise(o=>{let i=this.onChange(a=>{let l=this.resolve(e,{...t,lenient:true});l?(s(),o(l)):a&&this.allSettled()&&this.reportUnresolved(e);}),s=()=>{i(),this.waits.delete(s);};this.waits.add(s);})}allSettled(){for(let e of this.entries.values())if(!e.settled)return false;return true}cancelWaits(){for(let e of [...this.waits])e();}onUnresolved(e){return this.unresolvedCbs.add(e),()=>this.unresolvedCbs.delete(e)}reportUnresolved(e){let t=this.names();console.warn(`[vela] symbol "${e}" not yet resolvable \u2014 registered providers: [${t.join(", ")||"none"}]. Register a provider that serves it.`);for(let n of this.unresolvedCbs)n({symbol:e,providers:t});}candidateOrder(e){let t=this.names();if(e){let n=Qt(e);if(this.entries.has(n))return [n,...t.filter(o=>o!==n)]}return t}displayPrefixOf(e){return this.entries.get(e.provider)?.byTicker?.get(wn(e.ticker))?.prefix??e.provider}canonicalSymbol(e){let t=this.entries.get(e.provider)?.byTicker?.get(wn(e.ticker));return `${t?.prefix??e.provider}:${t?.ticker??e.ticker}`}symbolIconOf(e){let t=e.provider?Qt(e.provider):[...this.entries.keys()][0],n=t!==void 0?this.entries.get(t):void 0;try{return n?.provider.resolveSymbolIcon?.(e)??void 0}catch{return}}symbolIcon(e){if(!e)return;let t=this.entries.get(e.provider)?.byTicker?.get(wn(e.ticker));return this.symbolIconOf({...t??{ticker:e.ticker},provider:t?.provider??e.provider})}symbolsOf(e){return e!=null?this.entries.get(Qt(e))?.descriptors??[]:[...this.entries.entries()].flatMap(([t,n])=>n.descriptors.map(o=>({...o,provider:t})))}infoOf(e){let t=Qt(e),n=this.entries.get(t);if(!n)return {name:t,capabilities:{enumerate:false,stream:false,symbolInfo:false}};let o=n.provider;return o.info?.()??{name:n.name,capabilities:{enumerate:!!o.listSymbols,stream:!!o.subscribe,symbolInfo:!!o.getSymbolInfo}}}indexReady(){return Promise.all([...this.entries.values()].map(e=>e.settle)).then(()=>{})}};function co(r){switch(r.kind){case "row":return {label:r.label,toggle:r.toggle,controls:r.controls,when:r.when};case "toggle":{let e=[];r.number&&e.push({kind:"number",...r.number});for(let t of r.colors??[])e.push({kind:"color",...t});return r.width&&e.push({kind:"width",...r.width}),{label:r.label,toggle:{key:r.key,defval:r.defval},controls:e,when:r.when}}case "number":return {label:r.label,controls:[{kind:"number",key:r.key,label:r.label,defval:r.defval,min:r.min,max:r.max,step:r.step}],when:r.when};case "color":return {label:r.label,controls:[{kind:"color",key:r.key,label:r.label,defval:r.defval}],when:r.when};case "select":return {label:r.label,controls:[{kind:"select",key:r.key,label:r.label,options:r.options,defval:r.defval}],when:r.when};case "range":return {label:r.label,controls:[{kind:"number",key:r.minKey,label:`${r.label} \u2014 min`,defval:r.defval,min:r.min,max:r.max,step:r.step,placeholder:r.placeholder},{kind:"hint",text:"\u2013"},{kind:"number",key:r.maxKey,label:`${r.label} \u2014 max`,defval:r.defval,min:r.min,max:r.max,step:r.step,placeholder:r.placeholder}],when:r.when}}}function Li(r){if(r.kind==="heading"||r.kind==="header")return [];let e=co(r),t=[];e.toggle&&t.push({key:e.toggle.key,type:"boolean",defval:e.toggle.defval});for(let n of e.controls)n.kind!=="hint"&&(n.kind==="color"||n.kind==="select"?t.push({key:n.key,type:"string",defval:n.defval}):t.push({key:n.key,type:"number",defval:n.defval}));return t}function kr(r,e){return r?(Array.isArray(r)?r:[r]).every(n=>n.anyOf?n.anyOf.some(o=>o===e[n.key]):e[n.key]===n.equals):true}var Mi=new Map;function au(r){Mi.set(r.id,r);}function H1(r){Mi.delete(r);}function xn(r){return typeof r=="string"?Mi.get(r):void 0}function xt(){return [...Mi.values()]}function lu(){return [...Mi.values()].filter(r=>r.tickerModifier??r.barTransform!=null).map(r=>r.id)}function uo(r){return xn(r)?.barTransform??null}function Pf(r){let e=r.lastIndexOf(";");if(e<=0||e===r.length-1)return {symbol:r,modifier:null,transform:null};let t=r.slice(e+1).toLowerCase();return t!=="standard"&&!lu().includes(t)?{symbol:r,modifier:null,transform:null}:{symbol:r.slice(0,e),modifier:t,transform:uo(t)}}var en={background:"#151619",textColor:"#b2b5be",gridColor:"#20222c",borderColor:"#2a2b30",upColor:O,downColor:D,fontFamily:"sans-serif"},Ei={background:"#ffffff",textColor:"#1e293b",gridColor:"#cccccc",borderColor:"#d4dae3",upColor:O,downColor:D,fontFamily:"sans-serif"};function ho(r){return !r||r==="dark"?en:r==="light"?Ei:r}var z1=150,W1=1e3,G1=300,$1=5e3,If=1e4,U1=20,Y1=1.5,Af=5e3,K1=16,Cl=class r{constructor(e,t,n,o,i,s){this.renderer=t;this.feed=n;this.config=i;this.dataControl=s;this.events=new lr;this.registry=new na;this.paneOrder=["price"];this.collapsedPanes=new Set;this.maximizedPaneId=null;this.paneActionUnsub=null;this.handles=new Map;this.engines=new Map;this.live=null;this.bars=[];this.rawBars=[];this.barTransform=null;this.typeEngines=new Map;this.typeSettings=new Map;this.activeEngineStyle=null;this.priceStyle="candles";this.unresolvedUnsub=null;this.visibleRange=null;this.viewportUnsub=null;this.viewportTimer=null;this.healing=false;this.healBuffer=[];this.lastHealAt=0;this.onVisible=null;this.replayQueue=null;this.replayTimer=null;this.replayPlaying=false;this.replayIntervalMs=1e3;this.replayDepth=null;this.replayLoading=null;this.replayCarrying=null;this.replayTickSource=null;this.replayForming=null;this.replayTickFetches=new Map;this.replayTickAbort=null;this.barCause="tick";this.historyState="complete";this.generation=0;this.progressiveAbort=null;this.supersedeWaiters=[];this.historyCompleted=false;this.historyCompletePromise=new Promise(e=>{this.resolveHistoryComplete=e;});this.switchingMarket=false;this.loadingUp=false;this.volumeOptedOut=false;this.contextEmitAt=new Map;this.runEmitAt=new Map;for(let c of o)this.registerEngine(c.language,c);this.defaultLanguage=i.defaultLanguage,this.renderer.mount(e,i.theme),this.renderer.onInputChange(c=>c.kind==="prop"?this.applyProps(c.indicatorId,{[c.key]:c.value}):this.applyInputs(c.indicatorId,{[c.key]:c.value})),this.renderer.onRemoveIndicator(c=>this.removeIndicator(c)),this.renderer.onToggleIndicatorVisible?.((c,d)=>this.setVisible(c,d)),this.paneActionUnsub=this.renderer.onPaneAction?.(c=>this.handlePaneAction(c))??null,this.renderer.onChartTypeSettingsChange?.((c,d)=>{this.typeSettings.set(c,d),this.typeEngines.get(c)?.onSettings?.(d);}),this.renderer.onMoveIndicator?.((c,d)=>this.moveIndicator(c,d)),this.renderer.onThemeSelect?.(c=>this.setTheme(ho(c))),this.viewportUnsub=this.renderer.onViewportChange(c=>this.onViewportChange(c)),this.renderer.onPriceStyleChange?.(c=>this.syncPriceStyle(c));let a=this.renderer.readFeature("priceStyle");typeof a=="string"&&(this.priceStyle=a),this.barTransform=uo(a);let l=new wl({fetchBars:(c,d)=>this.fetchSeries(this.config.market.symbol??"",c,d),canFetch:()=>!!this.feed.loadRange&&!this.config.market.data?.length&&!!this.config.market.symbol,chartTimeframe:()=>this.config.market.timeframe??"60",marketKey:()=>`${this.config.market.symbol??""}|${this.config.market.session??""}`});this.drawings=new gl(this.renderer,this.events,i.drawings,l),this.marks=new yl(this.renderer,this.events),this.unresolvedUnsub=this.feed.onUnresolved?.(c=>{this.endLoad(),this.events.emit("data:unresolved",c);})??null,this.readyPromise=this.init(),xn(a)?.dataEngine&&this.syncChartTypeEngine(a);}currentVisibleRange(){if(this.visibleRange)return this.visibleRange;let e=this.renderer.getVisibleRange();return e?{left:e.from,right:e.to}:void 0}engineFor(e){let t=e??this.defaultLanguage,n=this.engines.get(t);if(!n)throw new Error(`[vela] no scripting engine registered for language "${t}". Vela ships none \u2014 install one (Pine Script: @luxalgo/vela-pinets) and register it before addIndicator, e.g. chart.registerEngine('pine', new PineEngine()).`);return n}market(){return {symbol:this.config.market.symbol??"TEST",timeframe:this.config.market.timeframe??"60",symbolInfo:this.feed.symbolInfo?.(this.config.market),chartStyle:this.priceStyle}}async fetchSeries(e,t,n){let o=Pf(e),i={symbol:o.symbol,timeframe:t},s=await(this.feed.loadRange?this.feed.loadRange(i,n):this.feed.load({...i,bars:n.limit}));return o.transform?o.transform.full(s):s}onViewportChange(e){this.visibleRange={left:e.from,right:e.to},this.events.emit("viewport:changed",{from:e.from,to:e.to}),this.viewportTimer!=null&&clearTimeout(this.viewportTimer),this.viewportTimer=setTimeout(()=>{if(this.viewportTimer=null,this.switchingMarket)return;let t=this.visibleRange;if(t){for(let n of this.registry.all())!n.renderHandle||n.hidden||(n.session&&n.prepared?.reactsToViewport?(n.pendingCause="viewport",n.session.setVisibleRange(t)):n.native?.descriptor.reactsToViewport&&n.native.instance.onViewport({from:t.left,to:t.right}));this.activeEngineStyle&&this.typeEngines.get(this.activeEngineStyle)?.onViewport?.({from:t.left,to:t.right});}},z1);}async init(){let e=this.bumpGeneration();this.beginLoad(true),await this.loadMarket(e,{firstLoad:true}),this.generation===e&&(this.startLive(),this.events.emit("ready",void 0));}bumpGeneration(){let e=++this.generation;this.progressiveAbort?.abort(),this.progressiveAbort=null;for(let t of this.supersedeWaiters.splice(0))t();return e}beginLoad(e){if(this.loadingUp)return;this.loadingUp=true,this.renderer.setLoading?.(true);let t=this.config.market;this.events.emit("load:start",{symbol:t.symbol??"TEST",timeframe:t.timeframe??"60",firstLoad:e});}endLoad(){if(!this.loadingUp)return;this.loadingUp=false,this.renderer.setLoading?.(false);let e=this.config.market;this.events.emit("load:end",{symbol:e.symbol??"TEST",timeframe:e.timeframe??"60",bars:this.bars.length});}async loadMarket(e,t){try{await this.loadMarketInner(e,t);}finally{this.generation===e&&this.endLoad();}}async loadMarketInner(e,t){let n=this.config.market,o=n.bars??500,i=n.visibleRange,s=!n.data?.length&&i==null&&o>$1,a=false;if(!n.data?.length&&i==null&&this.feed.loadProgressive){let l=false,c=(u,h)=>{if(!(this.generation!==e||!h&&u.length===0)&&!(!l&&!h&&u.length0&&(l=true,t.firstLoad&&this.activateBarLayers(),h||(this.historyState="backfill"));}},d=new AbortController;this.progressiveAbort=d,a=await new Promise(u=>{let h=false,p=m=>{h||(h=true,u(m));};d.signal.addEventListener("abort",()=>p(true),{once:true}),this.feed.loadProgressive(n,m=>{c(m,false),l&&p(true);},{signal:d.signal}).then(m=>{if(this.progressiveAbort===d&&(this.progressiveAbort=null),m==null)return p(false);if(this.generation!==e)return p(true);c(m,true),this.completeHistory(m.length>=o?"depth":"genesis"),p(true);}).catch(()=>{this.progressiveAbort===d&&(this.progressiveAbort=null),this.generation===e&&this.completeHistory("aborted"),p(true);});});}if(!a)if(s&&this.feed.loadRange){let l=await this.feed.load({...n,bars:Math.min(o,If)});if(this.generation!==e)return;this.setBarSeries(l),t.firstLoad&&this.activateBarLayers(),l.length>0&&o>l.length?(this.historyState="backfill",this.backfillHistory(e,o)):this.completeHistory("depth");}else if(s){let l=await this.feed.load({...n,bars:G1});if(this.generation!==e)return;this.setBarSeries(l),t.firstLoad&&this.activateBarLayers();let c=await this.feed.load(n);if(this.generation!==e)return;this.setBarSeries(c,{preserveView:true}),this.completeHistory("depth");}else {let l=await this.feed.load(n);if(this.generation!==e)return;this.setBarSeries(l),t.firstLoad&&this.activateBarLayers(),this.completeHistory("depth");}i!=null&&(typeof i=="string"?this.setVisibleRangePreset(i):this.renderer.setVisibleRange(i)),this.refreshPriceFormat(),this.ensurePriceFormat();}startLive(){this.config.live&&(this.live=new oa(this.feed,this.config.market,e=>this.onBar(e)),this.live.start(),typeof document<"u"&&(this.onVisible=()=>{if(document.visibilityState!=="visible")return;let e=this.bars[this.bars.length-1];!e||this.healing||!this.canHeal()||Date.now()-this.lastHealAt<=Af||this.healGap(e.time);},document.addEventListener("visibilitychange",this.onVisible)));}stopLive(){this.live?.stop(),this.live=null,this.onVisible&&typeof document<"u"&&document.removeEventListener("visibilitychange",this.onVisible),this.onVisible=null,this.healing=false,this.healBuffer=[],this.lastHealAt=0;}resetHistoryTracking(){this.resolveHistoryComplete(),this.historyCompleted=false,this.historyState="complete",this.historyCompletePromise=new Promise(e=>{this.resolveHistoryComplete=e;});}marketSnapshot(){let e=this.config.market;return {symbol:e.symbol,provider:Jt(e.symbol??"").provider??void 0,timeframe:e.timeframe,bars:e.bars,session:e.session,offline:e.data!==void 0}}async setMarket(e){let t=this.config.market,n=e.symbol!==void 0&&e.symbol!==t.symbol||e.timeframe!==void 0&&e.timeframe!==t.timeframe||e.session!==void 0&&e.session!==t.session||e.data!==void 0,o=e.bars!==void 0&&e.bars!==t.bars,i=n&&e.data===void 0&&(e.symbol===void 0||e.symbol===t.symbol)&&(e.timeframe!==void 0||e.session!==void 0),s=n?this.replayCarrying:null;s&&(this.replayCarrying=null,i||(s.cancelled=true,this.events.emit("replay:end",{reason:"market"})));let a=this.replayQueue&&i&&this.rawBars.length>0?{revealedEnd:this.rawBars[this.rawBars.length-1].time+this.barIntervalMs(),playing:this.replayPlaying,cancelled:false}:s&&i?{revealedEnd:s.revealedEnd,playing:s.playing,cancelled:false}:null;if(s&&(s.cancelled=true),a&&(this.replayCarrying=a),a&&this.replayQueue){this.endReplay(null,{restore:false,resume:false});let y=this.replayDepth;this.replayDepth=null,y&&e.bars===void 0&&(y.bars===void 0?delete t.bars:t.bars=y.bars);}if(this.replayQueue&&(n||o)&&this.endReplay("market",{restore:!n,resume:false}),this.replayLoading&&(n||o)){let y=this.replayDepth;this.abandonReplayLoad("market"),y&&e.bars===void 0&&(y.bars===void 0?delete t.bars:t.bars=y.bars);}let l=o&&!n&&this.rawBars.length>0&&!t.data?.length&&((e.bars??0)<=this.rawBars.length||typeof this.feed.loadRange=="function");if(!n&&!o){typeof e.visibleRange=="string"?this.setVisibleRangePreset(e.visibleRange):e.visibleRange&&this.renderer.setVisibleRange(e.visibleRange);return}let c={symbol:t.symbol??"TEST",timeframe:t.timeframe??"60"},u=n&&e.session!==void 0&&e.data===void 0&&(e.symbol===void 0||e.symbol===t.symbol)&&(e.timeframe===void 0||e.timeframe===t.timeframe)&&e.visibleRange===void 0?this.currentVisibleRange():void 0,h=u?this.rawBars.filter(y=>y.time>=u.left&&y.time<=u.right).length:0,p=this.bumpGeneration();this.switchingMarket=true;try{if(this.stopLive(),this.viewportTimer!=null&&(clearTimeout(this.viewportTimer),this.viewportTimer=null),this.visibleRange=null,this.resetHistoryTracking(),e.symbol!==void 0&&(t.symbol=e.symbol),e.timeframe!==void 0&&(t.timeframe=e.timeframe),e.bars!==void 0&&(t.bars=e.bars),e.session!==void 0&&(t.session=e.session),u){let y=Math.min(Math.ceil((Date.now()-u.left)/this.barIntervalMs())+50,5e3);y>(t.bars??500)&&(t.bars=y);}if(e.data!==void 0?t.data=e.data:e.symbol!==void 0&&delete t.data,t.visibleRange=e.visibleRange??(u?{from:u.left,to:u.right}:void 0),n&&(this.beginLoad(!1),this.setBarSeries([],{clearing:!0}),this.blankIndicatorVisuals(),this.activeEngineStyle&&(this.typeEngines.get(this.activeEngineStyle)?.suspend(),this.renderer.setNativeData?.(this.activeEngineStyle,void 0),this.renderer.setNativeData?.(`${this.activeEngineStyle}-pending`,[]))),l?this.extendDepth(p,t.bars??500):await Promise.race([this.loadMarket(p,{firstLoad:!1}),new Promise(y=>this.supersedeWaiters.push(y))]),this.generation!==p)return}finally{this.generation===p&&(this.switchingMarket=false);}if(u&&h>=2&&this.rawBars.length>0){let y=this.rawBars,w=y.length-1;for(;w>0&&y[w].time>u.right;)w-=1;let C=y[Math.max(0,w-(h-1))].time;this.renderer.setVisibleRange({from:C,to:Math.max(u.right,y[w].time+1)});}let m=a&&!a.cancelled?a:null,f=m?m.revealedEnd-this.barIntervalMs():0,g=m!=null&&this.rawBars.length>0&&f>=this.rawBars[0].time,b=g&&this.resumeCarriedReplay(this.replayStart({from:f}),m);!l&&!b&&(this.restartNativeIndicators(),this.restartChartTypeEngine(),this.reexecuteIndicators()),b||this.startLive(),n&&this.events.emit("market:changed",{symbol:t.symbol??"TEST",timeframe:t.timeframe??"60",prev:c}),m&&!g&&this.resumeCarriedReplay(this.replayStart({from:f}),m);}restartNativeIndicators(){for(let e of this.registry.all())if(e.native)if(e.native.started&&e.native.instance.stop(),e.native.instance=e.native.descriptor.create(),e.native.started=false,e.pendingStructural=true,e.hidden)e.native.stale=true;else {let t=this.handles.get(e.id);t&&this.startNativeIndicator(e.id,t);}}restartChartTypeEngine(){for(let e of this.typeEngines.values())e.stop();this.typeEngines.clear(),this.activeEngineStyle&&this.startChartTypeEngine(this.activeEngineStyle);}activateBarLayers(){this.maybeAutoAddVolume();}extendDepth(e,t){if(this.rawBars.length>t){this.setBarSeries(this.rawBars.slice(this.rawBars.length-t),{preserveView:true}),this.completeHistory("depth");return}if(this.rawBars.length===t){this.completeHistory("depth");return}this.historyState="backfill",this.backfillHistory(e,t);}async backfillHistory(e,t){try{for(;this.generation===e&&this.rawBars.length0;){let n=t-this.rawBars.length,o=If,i=await this.feed.loadRange(this.config.market,{to:this.rawBars[0].time,limit:Math.min(o,n)+1});if(this.generation!==e)return;let s=this.rawBars[0].time,a=i.filter(l=>l.time=o.length){console.warn("[vela] chart.replay.start() ignored \u2014 no bar opens after the requested time");return}let s=this.replayPlaying;this.clearReplayTimer(),this.replayQueue||this.stopLive(),this.replayQueue=o.slice(i),this.setBarSeries(o.slice(0,i)),this.restartBarConsumers({blank:true}),s&&this.events.emit("replay:pause",void 0),this.events.emit("replay:start",{cursorTime:o[i-1].time,remaining:this.replayQueue.length}),this.prefetchTicks();}replayStep(){if(this.replayForming)return this.finishFormingBar(),true;let e=this.replayQueue,t=e?.shift();return !e||!t?false:(this.replayTickFetches.delete(t.time),this.applyBar(t),this.completeReveal(t),this.prefetchTicks(),true)}resumeCarriedReplay(e,t){return this.replayQueue&&this.replayCarrying===t&&(this.replayCarrying=null),e.then(()=>{this.replayCarrying===t&&(this.replayCarrying=null),!t.cancelled&&(this.replayQueue?t.playing&&this.replayPlay():this.events.emit("replay:end",{reason:"market"}));}),this.replayQueue!==null}replayStepUpdate(){if(!this.replayQueue)return false;if(this.replayForming)return this.applyReplayTicks(1),true;let e=this.replayQueue[0];if(!e)return false;let t=this.replayTickSource?this.requestTicks(e):null;if(t&&!t.ticks){let n=this.replayTickAbort;return t.done.then(()=>{!this.replayPlaying&&!this.replayForming&&this.replayTickAbort===n&&this.replayQueue?.[0]===e&&this.replayStepUpdate();}),true}return t?.ticks?.length?(this.openFormingBar(t.ticks,1),true):this.replayStep()}replaySetTicks(e){this.finishFormingBar(),this.dropTickFetches(),this.replayTickSource=e,this.prefetchTicks();}replayPlay(e){if(this.replayQueue){if(e!==void 0){if(!(Number.isFinite(e)&&e>0)){console.warn(`[vela] chart.replay.play(${e}) ignored \u2014 the interval must be a positive number of ms`);return}this.replayIntervalMs=e;}this.clearReplayTimer(),this.replayPlaying=true,this.replayForming&&this.paceFormingBar(this.replayForming),this.scheduleReplayStep(this.replayForming?.delayMs),this.events.emit("replay:play",{intervalMs:this.replayIntervalMs});}}replayPause(){this.replayPlaying&&(this.clearReplayTimer(),this.events.emit("replay:pause",void 0));}replayStop(){let e=this.replayCarrying;if(e&&(e.cancelled=true,this.replayCarrying=null,this.events.emit("replay:end",{reason:"stopped"})),this.replayLoading){let t=this.replayDepth;this.abandonReplayLoad("stopped"),this.setMarket({bars:t?.bars??500});return}this.endReplay("stopped",{restore:true,resume:true});}abandonReplayLoad(e){let t=this.replayLoading;t&&(this.replayLoading=null,this.replayDepth=null,t.seek&&this.events.emit("replay:end",{reason:e}));}replayState(){let e=this.replayQueue!==null;return {active:e||this.replayCarrying!==null,playing:this.replayCarrying?.playing??this.replayPlaying,cursorTime:e?this.rawBars[this.rawBars.length-1]?.time??null:null,remaining:this.replayQueue?.length??0,nextTime:this.replayForming?.bar.time??this.replayQueue?.[0]?.time??null,intervalMs:this.replayIntervalMs}}replayBounds(){let e=this.rawBars[0],t=this.replayQueue?.[this.replayQueue.length-1]??this.rawBars[this.rawBars.length-1];return e&&t?{first:e.time,last:t.time}:null}scheduleReplayStep(e=this.replayIntervalMs){this.replayTimer=setTimeout(()=>{this.replayTimer=null,this.replayAdvance();},e);}replayAdvance(){if(!this.replayPlaying||!this.replayQueue)return;let e=this.replayForming;if(e){let o=Math.floor((Rf()-e.origin)/this.replayIntervalMs)+1;this.applyReplayTicks(Math.max(e.batch,o-e.next)),this.replayPlaying&&this.scheduleReplayStep(e.delayMs);return}let t=this.replayQueue[0];if(!t)return;let n=this.replayTickSource?this.requestTicks(t):null;if(n&&!n.ticks){let o=this.replayTickAbort;n.done.then(()=>{this.replayPlaying&&this.replayTimer==null&&this.replayTickAbort===o&&this.replayQueue?.[0]===t&&this.replayAdvance();});return}if(!n?.ticks?.length){this.replayStep()&&this.replayPlaying&&this.scheduleReplayStep();return}this.openFormingBar(n.ticks),this.replayPlaying&&this.scheduleReplayStep(this.replayForming?.delayMs);}openFormingBar(e,t){let n=this.replayQueue.shift(),o=e.every(s=>s.volume===void 0)?(n.volume??0)/e.length:null,i={bar:n,ticks:e,next:0,candle:null,volumeEach:o,batch:1,delayMs:this.replayIntervalMs,origin:0};this.paceFormingBar(i),this.replayForming=i,this.applyReplayTicks(t??i.batch),this.prefetchTicks();}paceFormingBar(e){e.batch=Math.max(1,Math.ceil(K1/this.replayIntervalMs)),e.delayMs=this.replayIntervalMs*e.batch,e.origin=Rf()-Math.max(0,e.next-1)*this.replayIntervalMs;}applyReplayTicks(e){let t=this.replayForming;if(!t)return;let n=t.candle,o=Math.min(t.ticks.length,t.next+e);for(;t.next=t.ticks.length){this.finishFormingBar();return}this.applyBar(n),this.events.emit("replay:tick",{cursorTime:t.bar.time,index:t.next-1,count:t.ticks.length});}finishFormingBar(){let e=this.replayForming;e&&(this.replayForming=null,this.replayTickFetches.delete(e.bar.time),this.applyBar(e.bar),this.events.emit("replay:tick",{cursorTime:e.bar.time,index:e.ticks.length-1,count:e.ticks.length}),this.completeReveal(e.bar));}settleFormingBar(){let e=this.replayForming;e&&(this.replayForming=null,this.applyBar(e.bar));}mergeHistoryIntoReplay(e){let t=this.replayQueue,n=this.rawBars[0];if(!t||!n)return;let o=t[t.length-1]??this.rawBars[this.rawBars.length-1],i=0;for(;ii&&e[s-1].time>o.time;)s-=1;s0&&(this.setBarSeries([...e.slice(0,i),...this.rawBars],{preserveView:true}),this.notifySessionsBars("backfill"));}completeReveal(e){let t=this.replayQueue;t&&(this.events.emit("replay:step",{cursorTime:e.time,remaining:t.length}),t.length===0&&this.endReplay("finished",{restore:true,resume:true}));}prefetchTicks(){let e=this.replayQueue?.[0];e&&this.replayTickSource&&this.requestTicks(e);}requestTicks(e){let t=this.replayTickFetches.get(e.time);if(t)return t;let n=this.replayTickSource;this.replayTickAbort??(this.replayTickAbort=new AbortController);let o=this.replayTickAbort.signal,i=this.replayQueue??[],s=i[i.indexOf(e)+1]?.time??e.time+this.barIntervalMs(),a={ticks:null,done:Promise.resolve()},l=d=>{a.ticks=X1(d);},c=d=>{o.aborted||console.warn(`[vela] replay tick source failed \u2014 revealing the bar whole (${d instanceof Error?d.message:String(d)})`),l([]);};try{let d=n(e,{end:s,signal:o});Array.isArray(d)?l(d):a.done=Promise.resolve(d).then(l,c);}catch(d){c(d);}return this.replayTickFetches.set(e.time,a),a}dropTickFetches(){this.replayTickAbort?.abort(),this.replayTickAbort=null,this.replayTickFetches.clear();}clearReplayTimer(){this.replayTimer!=null&&clearTimeout(this.replayTimer),this.replayTimer=null,this.replayPlaying=false;}endReplay(e,t){let n=this.replayQueue;if(!n)return;this.clearReplayTimer(),t.restore?this.settleFormingBar():this.replayForming=null,this.dropTickFetches(),this.replayQueue=null;let o=e?this.replayDepth:null;if(e&&(this.replayDepth=null),o&&(o.bars===void 0?delete this.config.market.bars:this.config.market.bars=o.bars),t.restore){let i=o?o.bars??500:1/0;if(n.length>0||this.rawBars.length>i){let s=[...this.rawBars,...n];this.setBarSeries(s.length>i?s.slice(s.length-i):s),this.restartBarConsumers({blank:false});}else this.config.live&&(this.restartNativeIndicators(),this.restartChartTypeEngine());}if(t.resume&&this.config.live){this.startLive();let i=this.rawBars[this.rawBars.length-1];i&&this.canHeal()&&this.healGap(i.time);}e&&this.events.emit("replay:end",{reason:e});}restartBarConsumers(e){e.blank&&this.blankIndicatorVisuals(),this.restartNativeIndicators(),this.restartChartTypeEngine(),this.reexecuteIndicators();}qualifiedSymbol(){let e=this.config.market;return e.symbol?e.symbol:null}refreshPriceFormat(){if(!this.renderer.setPricePrecision)return;let e=this.feed.symbolInfo?.(this.config.market)?.mintick;this.renderer.setPricePrecision(typeof e=="number"&&e>0?e:void 0);}async ensurePriceFormat(){if(!this.renderer.setPricePrecision)return;let e=this.qualifiedSymbol();if(e)try{await this.dataControl.symbolInfo(e),this.refreshPriceFormat();}catch{}}maybeAutoAddVolume(){!this.config.volume||this.volumeOptedOut||!this.renderer.setNativeData||di("volume")&&this.addNativeIndicator("volume");}syncPriceStyle(e){typeof e=="string"&&(this.priceStyle=e),this.syncBarTransform(e),this.syncChartTypeEngine(e);}syncChartTypeEngine(e){let t=typeof e=="string"?e:null,o=xn(t)?.dataEngine?t:null;o!==this.activeEngineStyle&&(this.activeEngineStyle&&this.typeEngines.get(this.activeEngineStyle)?.suspend(),this.activeEngineStyle=o,o&&this.startChartTypeEngine(o));}async startChartTypeEngine(e){if(!this.renderer.setNativeData||(await this.readyPromise,this.activeEngineStyle!==e))return;let t=this.typeEngines.get(e);if(t){t.resume();return}let n=xn(e);if(!n?.dataEngine)return;let o=n.dataEngine();this.typeEngines.set(e,o);let i=this.typeSettings.get(e);i&&o.onSettings?.(i),o.start({symbol:this.config.market.symbol??"TEST",timeframe:this.config.market.timeframe??"60",live:(this.config.live??false)&&this.replayQueue===null,session:this.config.market.session,bars:()=>this.bars,data:this.dataControl,pushData:s=>this.renderer.setNativeData?.(e,s),pushPending:s=>this.renderer.setNativeData?.(`${e}-pending`,s)});}syncBarTransform(e){let t=uo(e);t!==this.barTransform&&(this.barTransform=t,this.rawBars.length!==0&&(this.bars=t?t.full(this.rawBars):this.rawBars,this.renderer.setBars(this.bars,{preserveView:true}),this.reexecuteIndicators()));}blankIndicatorVisuals(){for(let e of this.registry.all())e.hidden||!e.renderHandle||!e.model||(e.model=q1(e.model),e.renderHandle=this.renderer.mountIndicator(e.model),e.pendingStructural=true,this.setLoading(e,true));}reexecuteIndicators(){for(let e of this.registry.all()){if(e.hidden||!e.session)continue;e.session.stop(),e.session=void 0,e.pendingStructural=true,e.pendingCause="market",this.setLoading(e,true);let t=this.handles.get(e.id);t&&this.executeIndicator(e.id,t);}}onBar(e){if(this.healing){this.healBuffer.push(e);return}let t=this.rawBars[this.rawBars.length-1];if(t&&this.canHeal()&&e.time>t.time+this.barIntervalMs()*Y1&&Date.now()-this.lastHealAt>Af){this.healBuffer.push(e),this.healGap(t.time);return}this.applyBar(e);}setBarSeries(e,t){this.rawBars=e,this.bars=this.barTransform?this.barTransform.full(e):e,this.renderer.setBars(this.bars,{preserveView:t?.preserveView}),!t?.clearing&&this.bars.length>0&&this.endLoad();}applyBar(e,t=true){let n=this.rawBars[this.rawBars.length-1],o=e;if(n&&e.time===n.time)this.rawBars[this.rawBars.length-1]=e,this.barCause="tick",this.barTransform&&(o=this.barTransform.next(e,this.bars[this.bars.length-2]),this.bars[this.bars.length-1]=o);else if(!n||e.time>n.time)this.rawBars.push(e),this.barCause="bar",this.barTransform&&(o=this.barTransform.next(e,this.bars[this.bars.length-1]),this.bars.push(o));else return;this.renderer.updateBar(o),this.events.emit("bar",e),t&&this.notifySessionsBars(this.historyState==="backfill"?"backfill":void 0);}notifySessionsBars(e){if(this.switchingMarket)return;let t=e?"history":this.barCause;for(let n of this.registry.all())!n.renderHandle||n.hidden||(n.session?(n.pendingCause=t,n.session.notifyBars(e)):n.native&&n.native.instance.onBars());this.activeEngineStyle&&this.typeEngines.get(this.activeEngineStyle)?.onBars?.();}canHeal(){return !!this.feed.loadRange&&!this.config.market.data?.length}barIntervalMs(){return Ft(this.config.market.timeframe??"60")}async healGap(e){let t=this.generation;this.healing=true,this.lastHealAt=Date.now();try{let n=await this.feed.loadRange(this.config.market,{from:e});if(this.generation!==t||this.replayQueue)return;for(let o of n)this.applyBar(o,!1);}catch{}finally{if(this.generation===t&&!this.replayQueue){this.healing=false;let n=this.healBuffer;this.healBuffer=[];for(let o of n)this.applyBar(o,false);this.notifySessionsBars(this.historyState==="backfill"?"backfill":void 0);}}}registerEngine(e,t){let n=this.engines.get(e);n&&n!==t&&console.warn(`[vela] re-registering scripting engine for language "${e}"; replacing ${n.constructor.name} with ${t.constructor.name}.`),this.engines.set(e,t);}addIndicator(e,t={}){let n=this.claimIndicatorId(t.id),o=t.title??"Indicator",i=new Jr(n,o,this,e);return this.handles.set(n,i),this.registry.add({id:n,title:o,source:e,options:t,inputValues:{...t.inputs??{}},propValues:{...t.props??{}}}),this.startIndicator(n,e,t,i),i}addNativeIndicator(e,t={}){let n=di(e);if(!n?.multiInstance){let l=this.registry.all().find(c=>c.native?.type===e);if(l)return this.handles.get(l.id)??new Jr(l.id,l.title,this,void 0,e)}let o=this.registry.nextId("native",l=>this.handles.has(l)),i=n?.title??e,s=new Jr(o,i,this,void 0,e);if(this.handles.set(o,s),!n)return console.warn(`[vela] addNativeIndicator("${e}") \u2014 no native indicator registered for this type.`),s;let a={...n.defaultInputs(),...t.inputs??{}};return this.registry.add({id:o,title:i,source:e,inputValues:a,propValues:{},native:{type:e,instance:n.create(),descriptor:n}}),s.setSchema(n.inputsSchema()),this.startNativeIndicator(o,s),s}presentNativeIndicators(){return this.registry.all().map(e=>e.native?.type).filter(e=>!!e)}async availableNativeIndicators(){let e=this.qualifiedSymbol(),t=new Set(this.presentNativeIndicators());return Promise.all(ra().map(async n=>({type:n.type,title:n.title,supported:await this.isNativeSupported(n,e),present:t.has(n.type),beta:n.beta,...n.multiInstance?{multiInstance:true}:{}})))}async isNativeSupported(e,t){if(!e.isSupported)return true;if(!t)return false;try{return await e.isSupported(t,this.dataControl)}catch{return false}}applyInputs(e,t){let n=this.registry.get(e);!n||!n.session&&!n.native||(n.inputValues={...n.inputValues,...t},n.renderHandle&&this.renderer.setIndicatorInputs(n.renderHandle,n.inputValues),n.pendingStructural=true,!n.hidden&&!n.native&&this.setLoading(n,true),n.pendingCause="inputs",n.session?n.session.update(n.inputValues):n.native&&!n.hidden&&n.native.instance.setInputs(n.inputValues),this.events.emit("indicator:inputs",{id:e}));}inputValuesOf(e){return {...this.registry.get(e)?.inputValues}}propValuesOf(e){return {...this.registry.get(e)?.propValues}}applyProps(e,t){let n=this.registry.get(e);n?.session&&(n.propValues={...n.propValues,...t},n.renderHandle&&this.renderer.setIndicatorInputs(n.renderHandle,n.inputValues,n.propValues),n.pendingStructural=true,n.hidden||this.setLoading(n,true),n.pendingCause="inputs",n.session.update(n.inputValues,n.propValues),this.events.emit("indicator:inputs",{id:e}));}updateCode(e,t){let n=this.registry.get(e),o=this.handles.get(e);if(!(!n||!o)){if(n.native){console.warn(`[vela] updateCode("${e}") \u2014 a native indicator has no script to update.`);return}t===n.source&&n.pendingSource===void 0||(n.pendingSource=t,this.swapSource(e,t,o));}}async swapSource(e,t,n){let o=this.registry.get(e)?.engine??this.engineFor(this.registry.get(e)?.options?.language),i;try{i=await o.prepare(t,e);}catch(a){let l=this.registry.get(e);l?.pendingSource===t&&(l.pendingSource=void 0,this.fail(e,n,a));return}let s=this.registry.get(e);!s||s.pendingSource!==t||(s.pendingSource=void 0,s.source=t,s.engine=o,s.prepared=i,n.setSource(t),s.inputValues=Df(i.inputs,s.inputValues),s.propValues=Df(i.props??[],s.propValues),n.setSchema(i.inputs),n.setPropsSchema(i.props??[]),s.session?.stop(),s.session=void 0,s.pendingStructural=true,s.pendingCause="code",!s.hidden&&(s.renderHandle?(this.renderer.setIndicatorInputs(s.renderHandle,s.inputValues,s.propValues),this.setLoading(s,true)):this.mountLoadingPlaceholder(e,s),this.executeIndicator(e,n)));}listIndicators(){return [...this.handles.values()]}getIndicatorContext(e,t){return this.registry.get(e)?.session?.getContext?.(t)??Promise.resolve(null)}removeIndicator(e){let t=this.registry.remove(e);t?.native?.type==="volume"&&(this.volumeOptedOut=true),t?.session?.stop(),t?.native?.started&&t.native.instance.stop(),this.handles.delete(e),t?.renderHandle&&this.renderer.removeIndicator(t.renderHandle);let n=t?.model?.paneId;n&&n!=="price"&&!this.paneStillUsed(n)&&(this.renderer.removePane(n),this.forgetPane(n),this.events.emit("pane:changed",void 0)),this.events.emit("indicator:removed",{id:e});}setVisible(e,t){let n=this.registry.get(e);if(!(!n||n.hidden===!t)){if(n.hidden=!t,this.handles.get(e)?.setVisibleState(t),!t)n.session?.stop(),n.session=void 0,n.native?.started&&n.native.instance.suspend(),n.renderHandle?this.renderer.setIndicatorVisible?.(n.renderHandle,false):n.native&&this.mountHiddenNativeRow(e,n);else if(n.renderHandle&&this.renderer.setIndicatorVisible?.(n.renderHandle,true),n.pendingStructural=true,n.native)if(n.native.stale||!n.native.started){n.native.stale=false;let o=this.handles.get(e);o&&this.startNativeIndicator(e,o);}else n.native.instance.resume();else {this.setLoading(n,true);let o=this.handles.get(e);o&&this.executeIndicator(e,o);}this.events.emit("indicator:visibility",{id:e,visible:t});}}ready(){return this.readyPromise}inspect(){let e=[...this.registry.all()].filter(t=>!t.loading).sort((t,n)=>(n.native?1:0)-(t.native?1:0));return Om(e.map(t=>t.model).filter(t=>t!=null))}resize(){this.renderer.resize();}setTheme(e){let t=this.config.theme;Object.keys(e).every(n=>e[n]===t[n])||(this.config.theme=e,this.renderer.setTheme(e),this.events.emit("theme:changed",e));}getVisibleRange(){return this.renderer.getVisibleRange()}setVisibleRange(e){this.renderer.setVisibleRange(e);}panBy(e){if(this.renderer.panBy){this.renderer.panBy(e);return}let t=this.renderer.getVisibleRange();if(!t)return;let n=(t.to-t.from)*e;this.renderer.setVisibleRange({from:t.from+n,to:t.to+n});}setVisibleRangePreset(e){let t=Nm(e,this.bars);t&&this.renderer.setVisibleRange(t);}destroy(){this.bumpGeneration(),this.resolveHistoryComplete(),this.clearReplayTimer(),this.replayQueue=null,this.replayForming=null,this.replayCarrying=null,this.dropTickFetches(),this.replayDepth=null,this.replayLoading=null,this.stopLive(),this.viewportTimer!=null&&clearTimeout(this.viewportTimer),this.viewportUnsub?.(),this.paneActionUnsub?.();for(let e of this.registry.all())e.session?.stop(),e.native?.started&&e.native.instance.stop();for(let e of this.typeEngines.values())e.stop();this.typeEngines.clear(),this.activeEngineStyle=null,this.unresolvedUnsub?.(),this.unresolvedUnsub=null,this.feed.destroy?.(),this.drawings.destroy(),this.marks.destroy(),this.renderer.destroy(),this.events.clear();}claimIndicatorId(e){if(e===void 0)return this.registry.nextId("ind",t=>this.handles.has(t));if(typeof e!="string"||e.length===0)throw new TypeError("[vela] addIndicator: `id` must be a non-empty string");if(this.handles.has(e)||this.registry.get(e))throw new Error(`[vela] addIndicator: indicator id "${e}" is already live on this chart`);return e}async startIndicator(e,t,n,o){try{if(await this.readyPromise,!this.registry.get(e))return;await j1();let i=this.registry.get(e);if(!i)return;let s=this.engineFor(n.language);i.engine=s;let a=await s.prepare(t,e);if(i.source!==t)return;i.prepared=a;let l={};for(let d of a.inputs)l[d.key]=d.defval;i.inputValues={...l,...i.inputValues},o.setSchema(a.inputs);let c={};for(let d of a.props??[])c[d.key]=d.defval;i.propValues={...c,...i.propValues},o.setPropsSchema(a.props??[]),this.mountLoadingPlaceholder(e,i),this.executeIndicator(e,o);}catch(i){this.fail(e,o,i);}}executeIndicator(e,t){let n=this.registry.get(e);if(!n||!n.engine||!n.prepared||n.hidden)return;let o=this.config.live&&!n.prepared.reactsToViewport&&n.engine.capabilities.streaming?"live":"static";n.session=n.engine.execute({prepared:n.prepared,market:this.market(),bars:this.bars,getBars:()=>this.bars,fetchSeries:(i,s,a)=>this.fetchSeries(i,s,a),inputs:n.inputValues,props:n.propValues,visibleRange:this.currentVisibleRange(),mode:o,historyState:this.historyState},{onModel:i=>{let s=!n.announced,a=n.pendingCause??"history";this.applyModel(e,i)&&(n.pendingCause=void 0,this.emitContextChanged(e),this.emitScriptRun(e,a,s));},onAlert:i=>{if(this.replayQueue||this.replayCarrying)return;let s=n.options?.title??n.prepared?.meta.title??n.title;this.events.emit("alert",{...i,indicator:s}),t.emit("alert",{id:i.id,message:i.message,title:i.title,time:i.time});},onWarning:i=>this.events.emit("warning",i),onError:i=>this.fail(e,t,i)}),this.emitContextChanged(e);}async startNativeIndicator(e,t){try{await this.readyPromise;let n=this.registry.get(e);if(!n?.native||n.hidden)return;let o=this.nativeChannel(n),i={id:e,symbol:this.config.market.symbol??"TEST",timeframe:this.config.market.timeframe??"60",live:this.config.live&&this.replayQueue===null,session:this.config.market.session,bars:()=>this.bars,data:this.dataControl,emit:s=>this.applyModel(e,this.buildNativeModel(n,s)),pushData:s=>this.renderer.setNativeData?.(o,s),setStatus:s=>{n.renderHandle&&!n.hidden&&this.renderer.setIndicatorStatus?.(n.renderHandle,s);}};n.native.instance.start(i,n.inputValues),n.native.started=!0;}catch(n){this.fail(e,t,n);}}nativeChannel(e){let{type:t,descriptor:n}=e.native;return n.multiInstance?Am(t,e.id):t}buildNativeModel(e,t){let n=e.native.descriptor,o=e.native.type,i=this.nativeChannel(e);return {id:e.id,title:e.title,...n.shortTitle?{shorttitle:n.shortTitle}:{},overlay:n.overlay,paneHint:n.paneHint,native:{type:o,...i!==o?{channel:i}:{}},...n.legend===false?{legend:false}:{},...t.paneAxis!=null?{paneAxis:t.paneAxis}:{},series:t.series??[],fills:t.fills??[],backgrounds:t.backgrounds??[],priceLines:t.priceLines??[],...t.lines?{lines:t.lines}:{},...t.boxes?{boxes:t.boxes}:{},...t.labels?{labels:t.labels}:{},...t.polylines?{polylines:t.polylines}:{},...t.linefills?{linefills:t.linefills}:{},...t.tables?{tables:t.tables}:{},inputs:n.inputsSchema(),inputValues:e.inputValues}}mountLoadingPlaceholder(e,t){if(t.renderHandle||!t.prepared)return;let n=t.prepared.meta,o={id:e,title:t.options?.title??n.title,overlay:n.overlay,paneHint:n.overlay?"price":"new",series:[],fills:[],backgrounds:[],priceLines:[],inputs:t.prepared.inputs,inputValues:t.inputValues,...t.prepared.props?{props:t.prepared.props,propValues:t.propValues}:{}},i=this.routePane(e,o,t.options??{});if(this.placeModel(o,e,i),t.model=o,this.ensurePaneFor(i),t.renderHandle=this.renderer.mountIndicator(o),t.pendingStructural=true,t.hidden){this.renderer.setIndicatorVisible?.(t.renderHandle,false),this.announce(t,this.handles.get(e));return}this.setLoading(t,true);}mountHiddenNativeRow(e,t){if(t.renderHandle||!t.native)return;let n=this.buildNativeModel(t,{}),o=this.routePane(e,n,t.options??{});this.placeModel(n,e,o),t.model=n,this.ensurePaneFor(o),t.renderHandle=this.renderer.mountIndicator(n),t.pendingStructural=true,this.renderer.setIndicatorVisible?.(t.renderHandle,false),this.announce(t,this.handles.get(e));}setLoading(e,t){e.loading=t,e.renderHandle&&!e.hidden&&this.renderer.setIndicatorStatus?.(e.renderHandle,t?"loading":"idle");}ensurePaneFor(e){this.paneOrder.includes(e)||this.paneOrder.push(e),this.renderer.ensurePane({id:e,kind:e==="price"?"price":"study",order:this.paneOrder.indexOf(e)});}paneStillUsed(e){for(let t of this.registry.all())if(t.model?.paneId===e)return true;return false}forgetPane(e){let t=this.paneOrder.indexOf(e);t>0&&this.paneOrder.splice(t,1),this.collapsedPanes.delete(e),this.maximizedPaneId===e&&(this.maximizedPaneId=null);}paneManagementSupported(){return this.renderer.capabilities.paneManagement===true&&typeof this.renderer.setIndicatorPane=="function"}listPanes(){let e=new Map;for(let n of this.registry.all()){let o=n.model;if(!o||o.legend===false)continue;let i=o.paneId??"price";e.has(i)||e.set(i,[]),e.get(i).push({id:n.id,title:o.title||n.title,...o.shorttitle?{shorttitle:o.shorttitle}:{},ownScale:o.ownScale===true});}let t=[];for(let n of this.paneOrder)n!=="price"&&!e.has(n)||t.push({id:n,kind:n==="price"?"price":"study",order:t.length,collapsed:this.collapsedPanes.has(n),maximized:this.maximizedPaneId===n,indicators:e.get(n)??[]});return t}movePane(e,t){if(e==="price")return;let n=this.existingPaneIds(),o=n.indexOf(e);if(o<0)return;let i=t==="up"?o-1:o+1;i<=0||i>=n.length||([n[o],n[i]]=[n[i],n[o]],this.reorderPanes(n),this.events.emit("pane:moved",{paneId:e,dir:t}));}removePaneAndIndicators(e){if(e!=="price")for(let t of [...this.registry.all()])t.model?.paneId===e&&this.removeIndicator(t.id);}collapsePane(e,t){t?this.collapsedPanes.add(e):this.collapsedPanes.delete(e),this.renderer.setPaneCollapsed?.(e,t),this.events.emit("pane:changed",void 0);}maximizePane(e){this.maximizedPaneId=e,this.renderer.setPaneMaximized?.(e),this.events.emit("pane:changed",void 0);}moveIndicator(e,t){if(!this.paneManagementSupported()||!this.renderer.setIndicatorPane){console.warn("[vela] the active renderer does not support moving indicators between panes.");return}let n=this.registry.get(e);if(!n?.renderHandle||!n.model)return;let o=n.model,i=o.paneId??"price",s=this.resolveMoveTarget(e,o,t);if(!s)return;let{paneId:a,ownScale:l,insert:c}=s;a===i&&o.ownScale===true===l||(c?this.insertPaneOrder(a,c):this.paneOrder.includes(a)||this.paneOrder.push(a),o.ownScale=l,n.paneLocked=true,this.placeModel(o,e,a),this.ensurePaneFor(a),this.renderer.setIndicatorPane(n.renderHandle,a,{ownScale:l}),i!=="price"&&i!==a&&!this.paneStillUsed(i)&&(this.renderer.removePane(i),this.forgetPane(i)),this.reorderPanes(this.existingPaneIds()),this.events.emit("indicator:moved",{id:e,paneId:a}),this.events.emit("pane:changed",void 0));}resolveMoveTarget(e,t,n){if(n==="price"||typeof n=="object"&&"pane"in n&&n.pane==="price")return {paneId:"price",ownScale:!t.overlay};if("pane"in n)return this.existingPaneIds().includes(n.pane)?{paneId:n.pane,ownScale:true}:null;let o=n.newPane===true?{}:n.newPane;return {paneId:this.freshPaneId(e,t.paneId??"price"),ownScale:false,insert:o}}freshPaneId(e,t){let n=new Set(this.existingPaneIds()),o=`pane-${e}`;for(let i=2;o===t||n.has(o);i+=1)o=`pane-${e}-${i}`;return o}insertPaneOrder(e,t){let n=this.paneOrder.indexOf(e);n>0&&this.paneOrder.splice(n,1);let o=this.paneOrder.length;t.before&&this.paneOrder.includes(t.before)?o=this.paneOrder.indexOf(t.before):t.after&&this.paneOrder.includes(t.after)&&(o=this.paneOrder.indexOf(t.after)+1),o<1&&(o=1),this.paneOrder.splice(o,0,e);}existingPaneIds(){return this.paneOrder.filter(e=>e==="price"||this.paneStillUsed(e))}reorderPanes(e){this.paneOrder.length=0,this.paneOrder.push(...e),this.renderer.orderPanes?.(e),this.events.emit("pane:changed",void 0);}handlePaneAction(e){switch(e.type){case "remove":this.removePaneAndIndicators(e.paneId);break;case "move":{let t=this.existingPaneIds(),n=t.indexOf(e.paneId),o=e.dir==="up"?n-1:n+1;n>0&&o>0&&ol.id!==e&&l.model?.paneId===i)&&(this.renderer.removePane(i),this.forgetPane(i)),this.ensurePaneFor(a),n.pendingStructural=true,i=a);}return this.placeModel(t,e,i),n.paneLocked&&(t.ownScale=s),n.model=t,n.pendingStructural?(n.renderHandle=this.renderer.mountIndicator(t),this.renderer.setIndicatorInputs(n.renderHandle,n.inputValues,n.propValues),n.pendingStructural=false):this.renderer.updateIndicator(n.renderHandle,Z1(t)),n.loading&&this.setLoading(n,false),this.announce(n,o),true}static modelHasOutput(e){return e.series.length>0||e.fills.length>0||e.backgrounds.length>0||e.priceLines.length>0||(e.lines?.length??0)>0||(e.boxes?.length??0)>0||(e.labels?.length??0)>0||(e.polylines?.length??0)>0||(e.linefills?.length??0)>0||(e.tables?.length??0)>0||(e.barColors?.length??0)>0||(e.trades?.length??0)>0}routePane(e,t,n){return n.pane==="new"?`pane-${e}`:n.pane==="price"||(n.overlay??t.overlay)?"price":`pane-${e}`}static plotsAtLastBar(e){let t={};for(let n of e.series)Ge(n)&&(t[n.title]=n.points[n.points.length-1]?.value??null);return t}placeModel(e,t,n){e.id=t,e.paneId=n;let o=i=>i.overlay===true?"price":n;for(let i of e.series)i.paneId=o(i);for(let i of e.fills)i.paneId=o(i);for(let i of e.backgrounds)i.paneId=o(i);for(let i of e.priceLines)i.paneId=n;if(e.lines)for(let i of e.lines)i.paneId=o(i);if(e.boxes)for(let i of e.boxes)i.paneId=o(i);if(e.labels)for(let i of e.labels)i.paneId=o(i);if(e.polylines)for(let i of e.polylines)i.paneId=o(i);if(e.linefills)for(let i of e.linefills)i.paneId=o(i);if(e.tables)for(let i of e.tables)i.paneId=o(i);}emitContextChanged(e){if(!this.registry.get(e)?.session?.getContext)return;let t=Date.now();t-(this.contextEmitAt.get(e)??0)<1e3||(this.contextEmitAt.set(e,t),this.events.emit("context:changed",{id:e}));}emitScriptRun(e,t,n){let o=this.registry.get(e);if(!o||o.native||!this.events.hasListeners("script:run"))return;let i=Date.now();t==="tick"&&i-(this.runEmitAt.get(e)??0)this.buildScriptRun(o,t,n)).then(s=>{s&&this.registry.get(e)&&this.events.emit("script:run",s);}));}async buildScriptRun(e,t,n){let o=e.model;if(!o)return null;let i=await this.pullContext(e,["variables","strategy","warnings"]),s=this.bars[this.bars.length-1];return {id:e.id,title:o.title,kind:i?.strategy||(o.trades?.length??0)>0?"strategy":"indicator",cause:t,first:n,bar:Math.max(0,this.bars.length-1),time:s?.time??0,forming:this.config.live&&this.bars.length>0,complete:this.historyState!=="backfill",plots:r.plotsAtLastBar(o),vars:i?.variables??{},...i?.strategy?{strategy:i.strategy}:{},warnings:i?.warnings??[],trades:async()=>(await this.pullContext(e,["trades"]))?.trades??[],series:async a=>((await this.pullContext(e,["plots"]))?.plots?.[a]??[]).map(c=>({time:c.time,value:typeof c.value=="number"?c.value:null}))}}async pullContext(e,t){try{return await e.session?.getContext?.(t)??null}catch{return null}}fail(e,t,n){let o=this.registry.get(e);o?.loading&&this.setLoading(o,false);let i=n instanceof Error?n:new Error(String(n));console.error(`[vela] indicator "${e}" failed:`,i.message),this.events.emit("indicator:error",{id:e,error:i}),t?.emit("error",{error:i});}};function Rf(){return typeof performance<"u"?performance.now():Date.now()}function X1(r){if(!Array.isArray(r))return [];let e=t=>t===void 0||Number.isFinite(t);return r.filter(t=>t!=null&&Number.isFinite(t.price)&&e(t.volume)&&e(t.high)&&e(t.low)&&e(t.open))}function j1(){return typeof requestAnimationFrame=="function"?new Promise(r=>requestAnimationFrame(()=>requestAnimationFrame(()=>r()))):new Promise(r=>setTimeout(r,0))}function Df(r,e){let t={},n=new Set;for(let o of r)t[o.key]=o.defval,n.add(o.key),n.add(o.title);for(let[o,i]of Object.entries(e))n.has(o)&&(t[o]=i);return t}function q1(r){return {...r,series:r.series.map(e=>e.kind==="candle"||e.kind==="bar"?{...e,bars:[]}:e.kind==="markers"?{...e,markers:[]}:{...e,points:[]}),fills:[],backgrounds:[],priceLines:[],lines:[],boxes:[],labels:[],polylines:[],linefills:[],tables:[],barColors:[],trades:[]}}function Z1(r){let e=[],t=Number.POSITIVE_INFINITY,n=0;for(let o of r.series)if(o.kind==="candle"||o.kind==="bar"){e.push({seriesId:o.id,kind:"bars",bars:o.bars});for(let i of o.bars)i.timen&&(n=i.time);}else if(Ge(o)){e.push({seriesId:o.id,kind:"points",points:o.points});for(let i of o.points)i.timen&&(n=i.time);}return {kind:"value",indicatorId:r.id,dirty:{from:Number.isFinite(t)?t:0,to:n},anchorTime:r.anchorTime??null,series:e,lines:r.lines??[],boxes:r.boxes??[],labels:r.labels??[],polylines:r.polylines??[],linefills:r.linefills??[],tables:r.tables??[],trades:r.trades??[]}}var Pi=class{constructor(e){this.renderer=e;}get name(){return this.renderer.name}get capabilities(){return this.renderer.capabilities}supports(e){return this.renderer.features.includes(e)}get(e){return this.renderer.readFeature(e)}set(e,t){let n=typeof e=="string"?[[e,t]]:Object.entries(e);for(let[o,i]of n)this.renderer.features.includes(o)?this.renderer.applyFeature(o,i):console.warn(`[vela] renderer "${this.renderer.name}" has no feature "${o}" \u2014 set ignored.`);return this}setLegendActions(e){this.renderer.setLegendActions?.(e);}setLegendCallouts(e){this.renderer.setLegendCallouts?.(e);}setLegendOverviewAction(e){return this.renderer.setLegendOverviewAction?.(e),this}get supportsIndicatorSettings(){return typeof this.renderer.openIndicatorSettings=="function"}openIndicatorSettings(e){return this.renderer.openIndicatorSettings?.(e),this}screenshot(){return typeof this.renderer.screenshot=="function"?this.renderer.screenshot():(console.warn(`[vela] renderer "${this.renderer.name}" does not support screenshot().`),null)}screenshotCanvas(){return typeof this.renderer.screenshotCanvas=="function"?this.renderer.screenshotCanvas():null}getConfig(){return typeof this.renderer.getConfig=="function"?this.renderer.getConfig():(console.warn(`[vela] renderer "${this.renderer.name}" does not support getConfig().`),null)}applyConfig(e){return typeof this.renderer.applyConfig=="function"?this.renderer.applyConfig(e):console.warn(`[vela] renderer "${this.renderer.name}" does not support applyConfig().`),this}onConfigChanged(e){return this.renderer.onConfigChanged?.(e)??(()=>{})}onCrosshairMove(e){return this.renderer.onCrosshairMove(e)}onClick(e){return this.renderer.onClick(e)}onAxisLongPress(e){return this.renderer.onAxisLongPress?.(e)??(()=>{})}dataWindowReadout(){return this.renderer.getDataWindowReadout?.()??null}setSymbolPicker(e){return typeof this.renderer.setSymbolPicker=="function"?this.renderer.setSymbolPicker(e):console.warn(`[vela] renderer "${this.renderer.name}" does not support setSymbolPicker().`),this}focus(){return this.renderer.focus?.(),this}get supportsExternalCrosshair(){return typeof this.renderer.setExternalCrosshair=="function"}setExternalCrosshair(e,t=null){return this.renderer.setExternalCrosshair?.(e,t),this}closeDialogs(){return this.renderer.closeDialogs?.(),this}openSettings(e){return this.renderer.openSettingsDialog?.(e),this}setSettingsSections(e){return this.renderer.setSettingsSections?.(e),this}setSettingsVisibility(e){return this.renderer.setSettingsVisibility?.(e),this}listSettingsIds(){return this.renderer.listSettingsIds?.()??[]}setLayoutMode(e){return this.renderer.setLayoutMode?.(e),this}setWallClock(e){return this.renderer.setWallClock?.(e),this}};var po=new Map;function Q1(r){let e=Object.entries(r);for(let[t,n]of e)po.set(t,n);return ()=>{for(let[t,n]of e)po.get(t)===n&&po.delete(t);}}function J1(...r){if(r.length===0)po.clear();else for(let e of r)po.delete(e);}function cu(){return Object.fromEntries(po)}var Sl=class{constructor(e){this.controller=e;}get supported(){return this.controller.paneManagementSupported()}list(){return this.controller.listPanes()}move(e,t){return this.guard()&&this.controller.movePane(e,t),this}remove(e){return this.guard()&&this.controller.removePaneAndIndicators(e),this}collapse(e,t=true){return this.guard()&&this.controller.collapsePane(e,t),this}maximize(e){return this.guard()&&this.controller.maximizePane(e),this}moveIndicator(e,t){return this.guard()&&this.controller.moveIndicator(e,t),this}guard(){return this.controller.paneManagementSupported()?true:(console.warn("[vela] the active renderer does not support pane management \u2014 chart.panes mutation ignored."),false)}};function Of(r,e,t,n){return `${r}|${e}|${t}${n&&n!=="regular"?`|${n}`:""}`}function ek(r){return r.split("|")[1]??""}var Tl=class{constructor(){this.series=new Map;this.coveredFrom=new Map;this.retained=new Set;this.retainedByOwner=new Map;}get(e){return this.series.get(e)}markCovered(e,t){this.coveredFrom.set(e,Math.min(this.coveredFrom.get(e)??1/0,t));}coveredFromOf(e){return this.coveredFrom.get(e)}merge(e,t){if(t.length===0)return this.series.get(e)??[];let n=new Map;for(let i of this.series.get(e)??[])n.set(i.time,i);for(let i of t)n.set(i.time,i);let o=[...n.values()].sort((i,s)=>i.time-s.time);return this.series.set(e,o),o}retainSymbol(e){this.currentSymbol!==e&&(this.currentSymbol=e,this.purgeOutside(e));}retain(e,t="default"){e.size===0?this.retainedByOwner.delete(t):this.retainedByOwner.set(t,new Set(e));let n=new Set;for(let o of this.retainedByOwner.values())for(let i of o)n.add(i);this.retained=n,this.purgeOutside(this.currentSymbol);}purgeOutside(e){for(let t of [...this.series.keys()]){let n=ek(t);n!==e&&!this.retained.has(n)&&(this.series.delete(t),this.coveredFrom.delete(t));}}clear(){this.series.clear(),this.coveredFrom.clear();}},Ii=new Tl;function du(r,e,t){let{provider:n,ticker:o}=Jt(r);return Of(n??"",o,e,t)}var Ri=1e4,tk=Ri+1,Di=class{constructor(e,t=Ii){this.inner=e;this.store=t;}async load(e){if(e.data&&e.data.length>0)return this.inner.load(e);let t=e.symbol??"TEST",n=du(t,e.timeframe??"60",e.session);this.store.retainSymbol(t);let o=this.store.get(n),i=e.bars??500,s=o?.[o.length-1];if(o&&s&&o.length>=i-1&&this.inner.loadRange){let{bars:l}=await this.fetchRange(e,{from:s.time}),c=this.store.merge(n,Ai(l));return Nf(c,l[l.length-1]).slice(-i)}let a=await this.inner.load(e);return this.store.merge(n,Ai(a)),a}async loadProgressive(e,t,n){if(e.data&&e.data.length>0)return this.inner.load(e);if(!this.inner.loadProgressive)return null;let o=e.symbol??"TEST",i=du(o,e.timeframe??"60",e.session),s=this.store.get(i),a=e.bars??500,l=s?.[s.length-1];if(s&&l&&s.length>=a-1&&this.inner.loadRange)return this.load(e);this.store.retainSymbol(o);let c=await this.inner.loadProgressive(e,t,n);return c==null?null:(this.store.merge(i,Ai(c)),c)}async loadRange(e,t){if(!this.inner.loadRange)return this.inner.load(e);let n=du(e.symbol??"TEST",e.timeframe??"60",e.session),o=this.store.get(n),i=o?.[o.length-1];if(t.to!=null&&i&&t.tof.time<=t.to),u=this.store.coveredFromOf(n)??1/0;if(t.limit!=null?d.length>=t.limit&&(t.from==null||u<=t.from):t.from!=null&&u<=t.from){let f=t.from!=null?d.filter(g=>g.time>=t.from):d;return t.limit!=null&&f.length>t.limit&&(f=f.slice(-t.limit)),f}let p=await this.fetchRange(e,t),m=p.bars.filter(f=>f.time<=t.to);return m.length>0&&(this.store.merge(n,m),this.store.markCovered(n,p.coveredDownTo??m[0].time)),m}if(i&&t.from!=null){let d=this.store.coveredFromOf(n);if(d!=null&&d>t.from){let{bars:u,coveredDownTo:h}=await this.fetchRange(e,{from:t.from,to:d});this.store.merge(n,u.filter(p=>p.time<=d)),this.store.markCovered(n,h??t.from),o=this.store.get(n),i=o?.[o.length-1];}}let s=this.store.coveredFromOf(n);if(!!o&&o.length>0&&!!i&&(t.from!=null?s!=null&&s<=t.from:t.limit==null||o.length>=t.limit)&&i){let{bars:d}=await this.fetchRange(e,{from:i.time,to:t.to,limit:t.limit}),u=this.store.merge(n,Ai(d)),h=Nf(u,d[d.length-1]),p=t.from!=null?h.filter(m=>m.time>=t.from):h;return t.to!=null&&(p=p.filter(m=>m.time<=t.to)),p}let{bars:l,coveredDownTo:c}=await this.fetchRange(e,t);return this.store.merge(n,Ai(l)),this.store.markCovered(n,c??t.from??l[0]?.time??0),l}async fetchRange(e,t){let n=Ft(e.timeframe??"60"),o=nk(t,n);if(o<=tk){let c=await this.inner.loadRange(e,{...t,limit:t.limit??o});return {bars:c,coveredDownTo:t.from??c[0]?.time}}let i=new Map,s=t.to??Date.now();for(;!(t.from!=null&&s=t.from)&&i.set(h.time,h);if(d.length===0){if(t.from==null)break;s-=Ri*n;continue}if(u-1>=s)break;s=u-1;}let a=[...i.values()].sort((c,d)=>c.time-d.time),l=t.from!=null&&s0?r.slice(0,-1):r}function Nf(r,e){if(!e)return r;let t=r[r.length-1];return !t||e.time>t.time?[...r,e]:r}function rk(r){return {"1m":6e4,"3m":18e4,"5m":3e5,"15m":9e5,"30m":18e5,"1h":36e5,"2h":72e5,"4h":144e5,"1d":864e5,"1w":6048e5,"1M":2592e6,1:6e4,5:3e5,15:9e5,30:18e5,60:36e5,240:144e5,D:864e5,W:6048e5,M:2592e6}[r]??36e5}var Lr=class{constructor(e=Ii){this.registry=new xl;this.primaryProvider=null;this.liveBars=[];this.symInfoCache=new Map;this.symInfoInflight=new Map;this.cache=new Di(new uu(this.registry),e);}registerProvider(e,t){return this.registry.register(e,t)}unregisterProvider(e){this.registry.unregister(e);}providers(){return this.registry.names().map(e=>this.registry.infoOf(e))}resolveSymbol(e){return this.registry.resolve(e,{default:this.primaryProvider})}displayPrefix(e){let t=this.resolveSymbol(e);return t?this.registry.displayPrefixOf(t):null}canonicalSymbol(e){let t=this.resolveSymbol(e);return t?this.registry.canonicalSymbol(t):null}providerInstance(e){return this.registry.get(e)}symbolIconOf(e){return this.registry.symbolIconOf(e)}symbolIcon(e){return this.registry.symbolIcon(this.resolveSymbol(e))}symbols(e){return this.registry.symbolsOf(e)}onUnresolved(e){return this.registry.onUnresolved(e)}destroy(){this.registry.cancelWaits();}ready(){return this.registry.indexReady()}async symbolInfoFor(e){let t=this.registry.resolve(e,{default:this.primaryProvider});if(t)return this.fetchSymbolInfo(t)}fetchSymbolInfo(e){let t=Ff(e),n=this.symInfoCache.get(t);if(n&&Date.now()-n.at(a&&this.symInfoCache.set(t,{info:a,at:Date.now()}),a)).finally(()=>{this.symInfoInflight.delete(t);});return this.symInfoInflight.set(t,s),s}capabilitiesFor(e){let t=this.registry.resolve(e,{default:this.primaryProvider});if(!t)return null;let n=this.registry.get(t.provider);return n?n.capabilitiesFor?.(t.ticker)??this.registry.infoOf(t.provider).capabilities:null}async load(e){if(e.data&&e.data.length>0)return this.liveBars=e.data.map(n=>({...n})),e.data;let t=await this.registry.whenResolvable(Oi(e),{default:this.primaryProvider});return this.primaryProvider=t.provider,this.prefetchSymbolInfo(t),this.cache.load(kl(e,t))}async loadProgressive(e,t,n){if(e.data&&e.data.length>0)return this.liveBars=e.data.map(i=>({...i})),e.data;let o=await this.registry.whenResolvable(Oi(e),{default:this.primaryProvider});return this.primaryProvider=o.provider,this.prefetchSymbolInfo(o),this.cache.loadProgressive(kl(e,o),t,n)}symbolInfo(e){if(e.data&&e.data.length>0)return;let t=this.registry.resolve(Oi(e),{default:this.primaryProvider});return t?this.symInfoCache.get(Ff(t))?.info:void 0}prefetchSymbolInfo(e){this.fetchSymbolInfo(e).catch(()=>{});}async loadRange(e,t){if(e.data&&e.data.length>0)return this.cache.loadRange(e,t);let n=this.registry.resolve(Oi(e),{default:this.primaryProvider});return n?this.cache.loadRange(kl(e,n),t):[]}subscribe(e,t){if(e.data&&e.data.length>0)return this.synthesizeTicks(e,t);let n=this.registry.resolve(Oi(e),{default:this.primaryProvider});return n?this.cache.subscribe(kl(e,n),t):()=>{}}synthesizeTicks(e,t){if(this.liveBars.length===0)return ()=>{};let n=rk(e.timeframe??"60"),o=setInterval(()=>{let i=this.liveBars,s=i[i.length-1];if(!s)return;let a=s.close*.0015*(Math.random()-.5)*2,l=Math.max(0,s.close+a),c={...s,close:l,high:Math.max(s.high,l),low:Math.min(s.low,l)};if(i[i.length-1]=c,t(c),Math.random()<.12){let d={time:c.time+n,open:c.close,high:c.close,low:c.close,close:c.close,volume:0};i.push(d),t(d);}},1e3);return ()=>clearInterval(o)}};function Oi(r){return r.symbol??""}function kl(r,e){return {...r,symbol:`${e.provider}:${e.ticker}`}}function Ff(r){return `${r.provider}|${r.ticker.trim().toUpperCase()}`}var ok=10*6e4;async function Vf(r,e,t,n){try{return await r.getBars(e,t,n)}catch(o){return console.warn(`[vela] data fetch failed for ${e} ${t} \u2014 ${o instanceof Error?o.message:String(o)}`),[]}}var uu=class{constructor(e){this.registry=e;}load(e){let{provider:t,ticker:n}=Jt(e.symbol??""),o=this.registry.get(t??"");return o?Vf(o,n,e.timeframe??"60",{limit:e.bars??500,session:e.session}):Promise.resolve([])}async loadProgressive(e,t,n){let{provider:o,ticker:i}=Jt(e.symbol??""),s=this.registry.get(o??"");if(!s)return [];if(!s.getBarsProgressive)return null;try{return await s.getBarsProgressive(i,e.timeframe??"60",{limit:e.bars??500,session:e.session},t,n)}catch(a){return console.warn(`[vela] progressive fetch failed for ${i} ${e.timeframe??"60"} \u2014 ${a instanceof Error?a.message:String(a)}`),[]}}loadRange(e,t){let{provider:n,ticker:o}=Jt(e.symbol??""),i=this.registry.get(n??"");return i?Vf(i,o,e.timeframe??"60",{...t,session:e.session}):Promise.resolve([])}subscribe(e,t){let{provider:n,ticker:o}=Jt(e.symbol??""),i=this.registry.get(n??"");if(!i)return ()=>{};let s=e.timeframe??"60";if(i.subscribe)return i.subscribe(o,s,t,e.session?{session:e.session}:void 0);let a=false,l=null,c=async()=>{if(!a){try{let d=await i.getBars(o,s,{limit:2,session:e.session});if(a)return;for(let u of d)t(u);}catch{}a||(l=setTimeout(()=>{c();},3e3));}};return l=setTimeout(()=>{c();},3e3),()=>{a=true,l&&clearTimeout(l);}}};var Ni=class{constructor(e){this.registry=e instanceof Lr?e:null;}registerProvider(e,t){return this.registry?(this.registry.registerProvider(e,t),this):(console.warn(`[vela] chart.data.registerProvider("${e}") ignored \u2014 the active data feed is a custom feed (deps.dataFeed), not the default provider registry.`),this)}unregisterProvider(e){return this.registry?.unregisterProvider(e),this}providers(){return this.registry?.providers()??[]}resolve(e){return this.registry?.resolveSymbol(e)??null}displayPrefix(e){return this.registry?.displayPrefix(e)??null}canonicalSymbol(e){return this.registry?.canonicalSymbol(e)??null}providerInstance(e){return this.registry?.providerInstance(e)}symbols(e){return this.registry?.symbols(e)??[]}symbolIcon(e){return this.registry?.symbolIcon(e)}symbolInfo(e){return this.registry?.symbolInfoFor(e)??Promise.resolve(void 0)}capabilities(e){return this.registry?.capabilitiesFor(e)??null}ready(){return this.registry?.ready()??Promise.resolve()}};var Fi=class{constructor(e){this.ctrl=e;}get supported(){return this.ctrl.supported}setTool(e){return this.ok("setTool")&&this.ctrl.setTool(e),this}getTool(){return this.ctrl.getTool()}setSnapMode(e){return this.ok("setSnapMode")&&this.ctrl.setSnapMode(e),this}getSnapMode(){return this.ctrl.getSnapMode()}setStayMode(e){return this.ok("setStayMode")&&this.ctrl.setStayMode(e),this}getStayMode(){return this.ctrl.getStayMode()}setMode(e){return this.ok("setMode")&&this.ctrl.setMode(e),this}getMode(){return this.ctrl.getMode()}showToolbar(e=true){return this.ok("showToolbar")&&this.ctrl.showToolbar(e),this}setToolbar(e){return this.ok("setToolbar")&&this.ctrl.setToolbar(e),this}setToolShortcuts(e){return this.ok("setToolShortcuts")&&this.ctrl.setToolShortcuts(e),this}setExternalGhost(e){return this.ctrl.setExternalGhost(e),this}add(e,t={}){return this.ok("add")?this.ctrl.add(e,t):null}remove(e){return this.ctrl.remove(e),this}update(e,t){return this.ctrl.update(e,t),this}updateMany(e){return this.ctrl.updateMany(e),this}removeMany(e){return this.ctrl.removeMany(e),this}lock(e,t=true){return this.ctrl.setLocked(e,t),this}show(e,t=true){return this.ctrl.setVisible(e,t),this}select(e){return this.ok("select")&&this.ctrl.select(e==null?[]:typeof e=="string"?[e]:e),this}openSettings(e){return this.ok("openSettings")&&this.ctrl.openSettings(e),this}bringToFront(e){return this.ctrl.bringToFront(e),this}sendToBack(e){return this.ctrl.sendToBack(e),this}undo(){return this.ctrl.undo(),this}redo(){return this.ctrl.redo(),this}canUndo(){return this.ctrl.canUndo()}canRedo(){return this.ctrl.canRedo()}clone(e){return this.ok("clone")&&this.ctrl.clone(e),this}duplicate(e){return this.ok("duplicate")&&this.ctrl.duplicate(e),this}copyToClipboard(e){return this.ok("copy")&&this.ctrl.copy(e),this}paste(){return this.ok("paste")&&this.ctrl.paste(),this}all(){return this.ctrl.all()}toJSON(){return this.ctrl.toJSON()}fromJSON(e){return this.ctrl.fromJSON(e),this}favorites(){return this.ctrl.favorites()}isFavorite(e){return this.ctrl.isFavorite(e)}setFavorite(e,t){return this.ok("setFavorite")&&this.ctrl.setFavorite(e,t),this}setFavorites(e){return this.ok("setFavorites")&&this.ctrl.setFavorites([...e]),this}getConfig(){return this.ctrl.toJSON()}applyConfig(e){return this.ctrl.fromJSON(e),this}ok(e){return this.ctrl.supported?true:(console.warn(`[vela] chart.drawings.${e}() ignored \u2014 the active renderer has no userDrawings capability.`),false)}};var Vi=class{constructor(e){this.ctrl=e;}get supported(){return this.ctrl.supported}add(e){return this.ctrl.add(e),this}set(e){return this.ctrl.set(e),this}remove(e){return this.ctrl.remove(e),this}clear(){return this.ctrl.clear(),this}all(){return this.ctrl.all()}defineGroup(e){return this.ctrl.defineGroup(e),this}groups(){return this.ctrl.groupDefinitions()}setGroupVisible(e,t=true){return this.ctrl.setGroupVisible(e,t),this}isGroupVisible(e){return this.ctrl.isGroupVisible(e)}};var Bi=class{constructor(e){this.ctrl=e;}start(e){return this.ctrl.replayStart(e)}step(){return this.ctrl.replayStep()}stepUpdate(){return this.ctrl.replayStepUpdate()}play(e){return this.ctrl.replayPlay(e),this}pause(){return this.ctrl.replayPause(),this}stop(){return this.ctrl.replayStop(),this}get state(){return this.ctrl.replayState()}get bounds(){return this.ctrl.replayBounds()}setTicks(e){return this.ctrl.replaySetTicks(e),this}};var _i=class r{constructor(e=()=>Date.now()){this.now=e;this.subs=new Set;this.timer=null;}onTick(e){return this.subs.add(e),this.timer==null&&this.arm(),()=>{this.subs.delete(e),this.subs.size===0&&this.timer!=null&&(clearTimeout(this.timer),this.timer=null);}}static delayToNextSecond(e){return 1e3-(e%1e3+1e3)%1e3+5}arm(){this.timer=setTimeout(()=>{this.timer=null;let e=this.now();for(let t of this.subs)t(e);this.subs.size>0&&this.arm();},r.delayToNextSecond(this.now()));}};function Ll(r){let e=r.trim(),t=/^#([0-9a-f]{3})$/i.exec(e);if(t){let o=t[1];return {r:parseInt(o[0]+o[0],16),g:parseInt(o[1]+o[1],16),b:parseInt(o[2]+o[2],16)}}if(t=/^#([0-9a-f]{6})[0-9a-f]{0,2}$/i.exec(e),t){let o=t[1];return {r:parseInt(o.slice(0,2),16),g:parseInt(o.slice(2,4),16),b:parseInt(o.slice(4,6),16)}}let n=/^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)/i.exec(e);return n?{r:parseFloat(n[1]),g:parseFloat(n[2]),b:parseFloat(n[3])}:null}function J(r,e){let t=Ll(r);return t?`rgba(${t.r},${t.g},${t.b},${e})`:r}function Bf(r,e,t){let n=Ll(r),o=Ll(e);if(!n||!o)return r;let i=(s,a)=>Math.round(s+(a-s)*t);return `rgb(${i(n.r,o.r)},${i(n.g,o.g)},${i(n.b,o.b)})`}function bt(r){let e=Ll(r);return e?.2126*e.r+.7152*e.g+.0722*e.b<128:true}var Ml={"--vela-space-1":"4px","--vela-space-2":"8px","--vela-space-3":"12px","--vela-space-4":"16px","--vela-radius-sm":"4px","--vela-radius-md":"6px","--vela-radius-lg":"10px","--vela-z-tooltip":"60","--vela-z-menu":"50","--vela-z-dialog":"40","--vela-z-popover":"6000","--vela-ease":"cubic-bezier(0.22, 1, 0.36, 1)","--vela-dur-fast":"90ms","--vela-dur-med":"160ms","--vela-font-size-sm":"11px","--vela-font-size-md":"12px","--vela-font-size-lg":"14px"};function El(r){let e=bt(r.background),t=o=>e?`rgba(255,255,255,${o})`:J(r.textColor,o+.02),n=Bf(r.background,e?"#ffffff":r.textColor,e?.03:.05);return {"--vela-font":r.fontFamily,"--vela-bg":r.background,"--vela-fg":e?"#d1d4dc":r.textColor,"--vela-fg-muted":e?"#868a96":J(r.textColor,.62),"--vela-fg-faint":J(r.textColor,.35),"--vela-fg-bright":e?"#f0f3fa":"#000000","--vela-surface":r.background,"--vela-surface-elev":n,"--vela-surface-overlay":n,"--vela-surface-sunken":r.background,"--vela-border":r.borderColor,"--vela-border-strong":e?"#34353b":J(r.textColor,.28),"--vela-border-soft":r.borderColor,"--vela-border-faint":J(r.textColor,.08),"--vela-hover":t(.06),"--vela-active":t(.1),"--vela-hover-strong":t(.16),"--vela-focus":J(r.textColor,.5),"--vela-focus-soft":J(r.textColor,.12),"--vela-separator-hover-band":J(r.textColor,.1),"--vela-separator-hover-line":J(r.textColor,.55),"--vela-scroll":J(r.textColor,.3),"--vela-accent":nt,"--vela-accent-bright":eo,"--vela-highlight":Vm,"--vela-selected-bg":e?"#f0f3fa":r.textColor,"--vela-selected-fg":e?r.background:"#ffffff","--vela-fg-on-fill":"#ffffff","--vela-up":r.upColor,"--vela-down":r.downColor,"--vela-danger":r.downColor,"--vela-shadow":"0 8px 30px rgba(0,0,0,0.5)","--vela-shadow-dialog":"0 20px 60px rgba(0,0,0,0.5)","--vela-backdrop":"rgba(0,0,0,0.45)"}}function Be(r,e){let t=n=>{for(let o in n)r.style.setProperty(o,n[o]);};t(Ml),t(El(e));}function tn(r,e){let t=null,n=null,o=()=>{t!==null&&(clearTimeout(t),t=null),n?.remove(),n=null;},i=()=>{let a=e.text();if(!a)return;n=r.ownerDocument.createElement("div"),n.textContent=a,n.style.cssText="position:absolute;z-index:var(--vela-z-tooltip);pointer-events:none;background:var(--vela-bg);border:1px solid var(--vela-border);color:var(--vela-fg);border-radius:var(--vela-radius-md);padding:4px 9px;box-shadow:var(--vela-shadow);font:var(--vela-font-size-md) var(--vela-font);"+(e.wrap?"max-width:260px;":"white-space:nowrap;"),Be(n,e.theme()),e.host.appendChild(n);let c=r.getBoundingClientRect(),d=e.host.getBoundingClientRect();if(e.placement==="right")n.style.left=`${c.right-d.left+8}px`,n.style.top=`${c.top-d.top+(c.height-n.offsetHeight)/2}px`;else {let u=Math.min(c.left-d.left,Math.max(0,d.width-n.offsetWidth-4));n.style.left=`${Math.max(0,u)}px`,n.style.top=e.placement==="above"?`${Math.max(0,c.top-d.top-n.offsetHeight-6)}px`:`${c.bottom-d.top+6}px`;}},s=a=>{a.pointerType==="mouse"&&(o(),t=window.setTimeout(i,e.delayMs??700));};return r.addEventListener("pointerenter",s),r.addEventListener("pointerleave",o),r.addEventListener("pointerdown",o),()=>{r.removeEventListener("pointerenter",s),r.removeEventListener("pointerleave",o),r.removeEventListener("pointerdown",o),o();}}function Pl(r,e){let t=e.size??16,n=document.createElement("span");n.className="vela-hint",n.setAttribute("role","img"),n.setAttribute("aria-label",r),n.innerHTML=Re("info",t),n.style.cssText=`flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:${t}px;height:${t}px;border-radius:50%;cursor:help;user-select:none;background:var(--vela-hover);color:var(--vela-fg-muted);transition:background var(--vela-dur-fast) ease,color var(--vela-dur-fast) ease;`;let o=s=>{n.style.background=s?"var(--vela-active)":"var(--vela-hover)",n.style.color=s?"var(--vela-fg-bright)":"var(--vela-fg-muted)";};n.addEventListener("pointerenter",()=>o(true)),n.addEventListener("pointerleave",()=>o(false));let i=tn(n,{host:e.host,theme:e.theme,text:()=>r,wrap:true,delayMs:250});return {el:n,dispose:i}}var ik=Object.defineProperty,sk=(r,e,t)=>e in r?ik(r,e,{enumerable:true,configurable:true,writable:true,value:t}):r[e]=t,ue=(r,e,t)=>sk(r,typeof e!="symbol"?e+"":e,t);function _f(r){return r==null?[]:Array.isArray(r)?r:[r]}var Hf=r=>r[0],zf=r=>r[r.length-1];function Wf(r,e,t={}){let{step:n=1,loop:o=true}=t,i=e+n,s=r.length,a=s-1;return e===-1?n>0?0:a:i<0?o?a:0:i>=s?o?0:e>s?s:e:i}function Gf(r,e,t={}){return r[Wf(r,e,t)]}function ak(r,e,t={}){let{step:n=1,loop:o=true}=t;return Wf(r,e,{step:-n,loop:o})}function $f(r,e,t={}){return r[ak(r,e,t)]}var Uf=r=>r?.constructor.name==="Array",lk=(r,e)=>{if(r.length!==e.length)return false;for(let t=0;t{if(Object.is(r,e))return true;if(r==null&&e!=null||r!=null&&e==null)return false;if(typeof r?.isEqual=="function"&&typeof e?.isEqual=="function")return r.isEqual(e);if(typeof r=="function"&&typeof e=="function")return r.toString()===e.toString();if(Uf(r)&&Uf(e))return lk(Array.from(r),Array.from(e));if(typeof r!="object"||typeof e!="object")return false;let t=Object.keys(e??Object.create(null)),n=t.length;for(let o=0;or!=null&&typeof r=="object";var fo=r=>typeof r=="string",pt=r=>typeof r=="function",Yf=r=>r==null,Hi=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),dk=r=>Object.prototype.toString.call(r),Kf=Function.prototype.toString,uk=Kf.call(Object),Mr=r=>{if(!ck(r)||dk(r)!="[object Object]"||mk(r))return false;let e=Object.getPrototypeOf(r);if(e===null)return true;let t=Hi(e,"constructor")&&e.constructor;return typeof t=="function"&&t instanceof t&&Kf.call(t)==uk},hk=r=>typeof r=="object"&&r!==null&&"$$typeof"in r&&"props"in r,pk=r=>typeof r=="object"&&r!==null&&"__v_isVNode"in r,mk=r=>hk(r)||pk(r);var zi=(r,...e)=>(typeof r=="function"?r(...e):r)??void 0,hu=r=>r,Xf=r=>r(),pu=()=>{},Gn=(...r)=>(...e)=>{r.forEach(function(t){t?.(...e);});};function $n(r){if(!Mr(r)||r===void 0)return r;let e=Reflect.ownKeys(r).filter(n=>typeof n=="string"),t={};for(let n of e){let o=r[n];o!==void 0&&(t[n]=$n(o));}return t}function go(...r){r.length===1?r[0]:r[1];r.length===2?r[0]:true;}function mu(...r){r.length===1?r[0]:r[1];r.length===2?r[0]:true;}function Wi(r,e){if(r==null)throw new Error(e())}var fk=(...r)=>r.map(e=>e?.trim?.()).filter(Boolean).join(" "),gk=/((?:--)?(?:\w+-?)+)\s*:\s*([^;]*)/g,jf=r=>{let e={},t;for(;t=gk.exec(r);)e[t[1]]=t[2];return e},bk=(r,e)=>{if(fo(r)){if(fo(e))return `${r};${e}`;r=jf(r);}else fo(e)&&(e=jf(e));return Object.assign({},r??{},e??{})};function qf(...r){let e={};for(let t of r){if(!t)continue;for(let o in e){if(o.startsWith("on")&&typeof e[o]=="function"&&typeof t[o]=="function"){e[o]=Gn(t[o],e[o]);continue}if(o==="className"||o==="class"){e[o]=fk(e[o],t[o]);continue}if(o==="style"){e[o]=bk(e[o],t[o]);continue}e[o]=t[o]!==void 0?t[o]:e[o];}for(let o in t)e[o]===void 0&&(e[o]=t[o]);let n=Object.getOwnPropertySymbols(t);for(let o of n)e[o]=t[o];}return e}var Un=".",Jf="#",Zf=new WeakMap,eg=new WeakMap;function fu(r){return r.join(Un)}function vk(r){return r.includes(Un)}function tg(r){return r.startsWith(Jf)}function yk(r){return r.startsWith(Un)}function wk(r){return tg(r)?r.slice(Jf.length):r}function gu(r,e){return r?`${r}${Un}${e}`:e}function xk(r){let e=new Map,t=new Map,n=(o,i)=>{e.set(o,i);let s=i.id;s&&(t.has(s)&&mu(`[zag-js] Duplicate state id: "${s}"`),t.set(s,o));let a=i.states;if(a){Wi(i.initial,()=>`[zag-js] Compound state "${o}" has child states but no "initial" property`),i.initial in a||mu(`[zag-js] Compound state "${o}" has initial "${String(i.initial)}" which is not a child state`);for(let[l,c]of Object.entries(a)){if(!c)continue;let d=gu(o,l);n(d,c);}}};for(let[o,i]of Object.entries(r.states))i&&n(o,i);return {index:e,idIndex:t}}function bo(r){let e=Zf.get(r);if(e)return e;let{index:t,idIndex:n}=xk(r);return Zf.set(r,t),eg.set(r,n),t}function Ck(r,e){return bo(r),eg.get(r)?.get(e)}function bu(r){return r?String(r).split(Un).filter(Boolean):[]}function Il(r,e){if(!e)return [];let t=bo(r),n=bu(e),o=[],i=[];for(let s of n){i.push(s);let a=fu(i),l=t.get(a);if(!l)break;o.push({path:a,state:l});}return o}function Gi(r,e){let t=bo(r),n=bu(e);if(!n.length)return e;let o=[];for(let a of n){o.push(a);let l=fu(o);if(!t.has(l))return e}let i=fu(o),s=t.get(i);for(;s?.initial;){let a=`${i}${Un}${s.initial}`,l=t.get(a);if(!l)break;i=a,s=l;}return i}function Qf(r,e){return bo(r).has(e)}function vu(r,e,t){let n=String(e);if(tg(n)){let o=wk(n),i=Ck(r,o);return Wi(i,()=>`[zag-js] Unknown state id: "${o}"`),Gi(r,i)}if(yk(n)&&t){let o=gu(t,n.slice(1));return Gi(r,o)}if(!vk(n)&&t){let o=bu(t);for(let i=o.length-1;i>=1;i--){let s=o.slice(0,i).join(Un),a=gu(s,n);if(Qf(r,a))return Gi(r,a)}if(Qf(r,n))return Gi(r,n)}return Gi(r,n)}function ng(r,e,t){let n=Il(r,e);for(let i=n.length-1;i>=0;i--){let a=n[i]?.state.on?.[t];if(a)return {transitions:a,source:n[i]?.path}}return {transitions:r.on?.[t],source:void 0}}function rg(r,e,t,n){let o=e?Il(r,e):[],i=Il(r,t),s=0;for(;sn.state.tags?.includes(t))}function sg(){return {and:(...r)=>function(t){return r.every(n=>t.guard(n))},or:(...r)=>function(t){return r.some(n=>t.guard(n))},not:r=>function(t){return !t.guard(r)}}}function Al(r){return bo(r),r}var vo=(r=>(r.NotStarted="Not Started",r.Started="Started",r.Stopped="Stopped",r))(vo||{}),$i="__init__";var Sk=Object.defineProperty,Tk=(r,e,t)=>e in r?Sk(r,e,{enumerable:true,configurable:true,writable:true,value:t}):r[e]=t,Rl=(r,e,t)=>Tk(r,typeof e!="symbol"?e+"":e,t);var ag=(r,e)=>r.map((t,n)=>r[(Math.max(e,0)+n)%r.length]);var Ui=()=>{},Yi=r=>typeof r=="object"&&r!==null;var Ct=r=>r?"":void 0,yu=r=>r?"true":void 0;var kk=1,Lk=9,Mk=11;var me=r=>Yi(r)&&r.nodeType===kk&&typeof r.nodeName=="string",Ki=r=>Yi(r)&&r.nodeType===Lk,Ek=r=>Yi(r)&&r===r.window;var lg=r=>me(r)?r.localName||"":"#document";function cg(r){return ["html","body","#document"].includes(lg(r))}var dg=r=>Yi(r)&&r.nodeType!==void 0,Er=r=>dg(r)&&r.nodeType===Mk&&"host"in r,wu=r=>me(r)&&r.localName==="input",ug=r=>!!r?.matches("a[href]"),hg=r=>me(r)?r.offsetWidth>0||r.offsetHeight>0||r.getClientRects().length>0:false;function Xi(r){if(!r)return false;let e=r.getRootNode();return nn(e)===r}var Pk=/(textarea|select)/;function yo(r){if(r==null||!me(r))return false;try{return wu(r)&&r.selectionStart!=null||Pk.test(r.localName)||r.isContentEditable||r.getAttribute("contenteditable")==="true"||r.getAttribute("contenteditable")===""}catch{return false}}function mt(r,e){if(!r||!e||!me(r)||!dg(e))return false;if(me(e)&&r===e||r.contains(e))return true;let t=e.getRootNode?.();if(t&&Er(t)){let n=e;for(;n;){if(r===n)return true;n=n.parentNode||n.host;}}return false}function Oe(r){return Ki(r)?r:Ek(r)?r.document:r?.ownerDocument??document}function Ik(r){return Oe(r).documentElement}function Ie(r){return Er(r)?Ie(r.host):Ki(r)?r.defaultView??window:me(r)?r.ownerDocument?.defaultView??window:window}function nn(r){let e=r.activeElement;for(;e?.shadowRoot;){let t=e.shadowRoot.activeElement;if(!t||t===e)break;e=t;}return e}function pg(r){if(lg(r)==="html")return r;let e=r.assignedSlot||r.parentNode||Er(r)&&r.host||Ik(r);return Er(e)?e.host:e}function Dl(r){let e;try{if(e=r.getRootNode({composed:!0}),Ki(e)||Er(e))return e}catch{}return r.ownerDocument??document}var xu=new WeakMap;function wo(r){return xu.has(r)||xu.set(r,Ie(r).getComputedStyle(r)),xu.get(r)}var Cu=new Set(["menu","listbox","dialog","grid","tree","region","application"]),Ak=r=>Cu.has(r),mg=r=>r.getAttribute("aria-controls")?.split(" ")||[];function Ol(r,e){let t=new Set,n=Dl(r),o=i=>{let s=i.querySelectorAll("[aria-controls]");for(let a of s){if(a.getAttribute("aria-expanded")!=="true")continue;let l=mg(a);for(let c of l){if(!c||t.has(c))continue;t.add(c);let d=n.getElementById(c);if(d){let u=d.getAttribute("role"),h=d.getAttribute("aria-modal")==="true";if(u&&Ak(u)&&!h&&(d===e||d.contains(e)||o(d)))return true}}}return false};return o(r)}function Su(r,e){let t=Dl(r),n=new Set,o=i=>{let s=i.querySelectorAll("[aria-controls]");for(let a of s){if(a.getAttribute("aria-expanded")!=="true")continue;let l=mg(a);for(let c of l){if(!c||n.has(c))continue;n.add(c);let d=t.getElementById(c);if(d){let u=d.getAttribute("role"),h=d.getAttribute("aria-modal")==="true";u&&Cu.has(u)&&!h&&(e(d),o(d));}}}};o(r);}function fg(r){let e=new Set;return Su(r,t=>{r.contains(t)||e.add(t);}),Array.from(e)}function Rk(r){let e=r.getAttribute("role");return !!(e&&Cu.has(e))}function Dk(r){return r.hasAttribute("aria-controls")&&r.getAttribute("aria-expanded")==="true"}function gg(r){return Dk(r)?true:!!r.querySelector?.('[aria-controls][aria-expanded="true"]')}function bg(r){if(!r.id)return false;let e=Dl(r),t=CSS.escape(r.id),n=`[aria-controls~="${t}"][aria-expanded="true"], [aria-controls="${t}"][aria-expanded="true"]`;return !!(e.querySelector(n)&&Rk(r))}var Tu=()=>typeof document<"u";function Ok(){return navigator.userAgentData?.platform??navigator.platform}function Nk(){let r=navigator.userAgentData;return r&&Array.isArray(r.brands)?r.brands.map(({brand:e,version:t})=>`${e}/${t}`).join(" "):navigator.userAgent}var ku=r=>Tu()&&r.test(Ok()),vg=r=>Tu()&&r.test(Nk());var Lu=()=>Tu()&&!!navigator.maxTouchPoints,Fk=()=>ku(/^iPhone/i),Vk=()=>ku(/^iPad/i)||xo()&&navigator.maxTouchPoints>1,yg=()=>Fk()||Vk();var xo=()=>ku(/^Mac/i);var wg=()=>vg(/Firefox/i);var xg=()=>vg(/Android/i);function Bk(r){return r.composedPath?.()??r.nativeEvent?.composedPath?.()}function _e(r){return Bk(r)?.[0]??r.target}function Mu(r){let e=r.currentTarget;if(!e||!e.matches("a[href], button[type='submit'], input[type='submit']"))return false;let n=r.button===1,o=_k(r);return n||o}function Eu(r){let e=r.currentTarget;if(!e)return false;let t=e.localName;return r.altKey?t==="a"||t==="button"&&e.type==="submit"||t==="input"&&e.type==="submit":false}function _k(r){return xo()?r.metaKey:r.ctrlKey}function Sg(r){return r.key.length===1&&!r.ctrlKey&&!r.metaKey}function Tg(r){return r.pointerType===""&&r.isTrusted?true:xg()&&r.pointerType?r.type==="click"&&r.buttons===1:r.detail===0&&!r.pointerType}var Nl=r=>r.button===2||xo()&&r.ctrlKey&&r.button===0,kg=r=>r.ctrlKey||r.altKey||r.metaKey,Hk=r=>"touches"in r&&r.touches.length>0,zk={Up:"ArrowUp",Down:"ArrowDown",Esc:"Escape"," ":"Space",",":"Comma",Left:"ArrowLeft",Right:"ArrowRight"},Cg={ArrowLeft:"ArrowRight",ArrowRight:"ArrowLeft"};function Pu(r,e={}){let{dir:t="ltr",orientation:n="horizontal"}=e,o=r.key;return o=zk[o]??o,t==="rtl"&&n==="horizontal"&&o in Cg&&(o=Cg[o]),o}function Co(r,e="client"){let t=Hk(r)?r.touches[0]||r.changedTouches[0]:r;return {x:t[`${e}X`],y:t[`${e}Y`]}}var ot=(r,e,t,n)=>{let o=typeof r=="function"?r():r;return o?.addEventListener(e,t,n),()=>{o?.removeEventListener(e,t,n);}};var Lg=r=>me(r)&&r.tagName==="IFRAME",Wk=/^(audio|video|details)$/;function Mg(r){let e=r.getAttribute("tabindex");return e?parseInt(e,10):NaN}var Gk=r=>!Number.isNaN(Mg(r)),$k=r=>Mg(r)<0;function Uk(r){return wu(r)&&r.type==="radio"}function Yk(r){if(!Uk(r)||!r.name||r.checked)return true;let e=`input[type="radio"][name="${CSS.escape(r.name)}"]`,t=r.form??r.ownerDocument,n=Array.from(t.querySelectorAll(e)).filter(i=>i.form===r.form&&St(i)),o=n.find(i=>i.checked);return o?o===r:n[0]===r}function Kk(r,e){if(!e)return null;if(e===true)return r.shadowRoot||null;let t=e(r);return (t===true?r.shadowRoot:t)||null}function Eg(r,e,t){let n=[...r],o=[...r],i=new Set,s=new Map;r.forEach((l,c)=>s.set(l,c));let a=0;for(;a{s.set(p,h+m);});for(let p=h+d.length;p{s.set(p,h+m);});}o.push(...d);}}return n}var Fl="input:not([type='hidden']):not([disabled]), select:not([disabled]), textarea:not([disabled]), a[href], button:not([disabled]), [tabindex], iframe, object, embed, area[href], audio[controls], video[controls], [contenteditable]:not([contenteditable='false']), details > summary:first-of-type",Iu=(r,e={})=>{if(!r)return [];let{includeContainer:t=false,getShadowRoot:n}=e,o=Array.from(r.querySelectorAll(Fl));(t==true||t=="if-empty"&&o.length===0)&&me(r)&&St(r)&&o.unshift(r);let s=[];for(let a of o)if(St(a)){if(Lg(a)&&a.contentDocument){let l=a.contentDocument.body;s.push(...Iu(l,{getShadowRoot:n}));continue}s.push(a);}return n?Eg(s,n,St):s};function St(r){return !me(r)||r.closest("[inert]")?false:r.matches(Fl)&&hg(r)}function So(r,e={}){if(!r)return [];let{includeContainer:t,getShadowRoot:n}=e,o=Array.from(r.querySelectorAll(Fl));t&&Yn(r)&&o.unshift(r);let i=[];for(let s of o)if(Yn(s)){if(Lg(s)&&s.contentDocument){let a=s.contentDocument.body;i.push(...So(a,{getShadowRoot:n}));continue}i.push(s);}if(n){let s=Eg(i,n,Yn);return !s.length&&t?o:s}return !i.length&&t?o:i}function Yn(r){return me(r)&&r.tabIndex>0?true:!St(r)||$k(r)?false:Yk(r)}function Pg(r,e={}){let t=So(r,e),n=t[0]||null,o=t[t.length-1]||null;return [n,o]}function To(r){return r.tabIndex<0&&(Wk.test(r.localName)||yo(r))&&!Gk(r)?0:r.tabIndex}function Vl(r){let{root:e,getInitialEl:t,filter:n,enabled:o=true}=r;if(!o)return;let i=null;if(i||(i=typeof t=="function"?t():t),i||(i=e?.querySelector("[data-autofocus],[autofocus]")),!i){let s=So(e);i=n?s.filter(n)[0]:s[0];}return i||e||void 0}function Ig(r){let e=r.currentTarget;if(!e)return false;let[t,n]=Pg(e);return !(Xi(t)&&r.shiftKey||Xi(n)&&!r.shiftKey||!t&&!n)}var Xk=class Ag{constructor(){Rl(this,"id",null),Rl(this,"fn_cleanup"),Rl(this,"cleanup",()=>{this.cancel();});}static create(){return new Ag}request(e){this.cancel(),this.id=globalThis.requestAnimationFrame(()=>{this.id=null,this.fn_cleanup=e?.();});}cancel(){this.id!==null&&(globalThis.cancelAnimationFrame(this.id),this.id=null),this.fn_cleanup?.(),this.fn_cleanup=void 0;}isActive(){return this.id!==null}};function Ve(r){let e=Xk.create();return e.request(r),e.cleanup}function Rg(r){let e=new Set;function t(n){let o=globalThis.requestAnimationFrame(n);e.add(()=>globalThis.cancelAnimationFrame(o));}return t(()=>t(r)),function(){e.forEach(o=>o());}}function Dg(r,e,t){let n=Ve(()=>{r.removeEventListener(e,o,true),t();}),o=()=>{n(),t();};return r.addEventListener(e,o,{once:true,capture:true}),n}function jk(r,e){if(!r)return;let{attributes:t,callback:n}=e,o=r.ownerDocument.defaultView||window,i=new o.MutationObserver(s=>{for(let a of s)a.type==="attributes"&&a.attributeName&&t.includes(a.attributeName)&&n(a);});return i.observe(r,{attributes:true,attributeFilter:t}),()=>i.disconnect()}function Og(r,e){let n=Ve,o=[];return o.push(n(()=>{let i=typeof r=="function"?r():r;o.push(jk(i,e));})),()=>{o.forEach(i=>i?.());}}function Ng(r){let e=()=>{let t=Ie(r);r.dispatchEvent(new t.MouseEvent("click"));};wg()?Dg(r,"keyup",e):queueMicrotask(e);}function Bl(r){let e=pg(r);return cg(e)?Oe(e).body:me(e)&&Au(e)?e:Bl(e)}var qk=/auto|scroll|overlay|hidden|clip/,Zk=new Set(["inline","contents"]);function Au(r){let e=Ie(r),{overflow:t,overflowX:n,overflowY:o,display:i}=e.getComputedStyle(r);return qk.test(t+o+n)&&!Zk.has(i)}function ko(r,e){return Array.from(r?.querySelectorAll(e)??[])}var _l=r=>r.id;function Qk(r,e,t=_l){return r.find(n=>t(n)===e)}function Fg(r,e,t=_l){let n=Qk(r,e,t);return n?r.indexOf(n):-1}function Jk(r){return r.scrollHeight>r.clientHeight||r.scrollWidth>r.clientWidth}function Vg(r,e){let{rootEl:t,...n}=e||{};!r||!t||!Au(t)||!Jk(t)||r.scrollIntoView(n);}var eL=r=>r.split("").map(e=>{let t=e.charCodeAt(0);return t>0&&t<128?e:t>=128&&t<=255?`/x${t.toString(16)}`.replace("/","\\"):""}).join("").trim(),tL=r=>eL(r.dataset?.valuetext??r.textContent??""),nL=(r,e)=>r.trim().toLowerCase().startsWith(e.toLowerCase());function Bg(r,e,t,n=_l){let o=t?Fg(r,t,n):-1,i=t?ag(r,o):r;return e.length===1&&(i=i.filter(a=>n(a)!==t)),i.find(a=>nL(tL(a),e))}function ji(r,e){if(!r)return Ui;let t=Object.keys(e).reduce((n,o)=>(n[o]=r.style.getPropertyValue(o),n),{});return rL(t,e)?Ui:(Object.assign(r.style,e),()=>{Object.assign(r.style,t),r.style.length===0&&r.removeAttribute("style");})}function _g(r,e,t){if(!r)return Ui;let n=r.style.getPropertyValue(e);return n===t?Ui:(r.style.setProperty(e,t),()=>{r.style.setProperty(e,n),r.style.length===0&&r.removeAttribute("style");})}function rL(r,e){return Object.keys(r).every(t=>r[t]===e[t])}function oL(r,e){let{state:t,activeId:n,key:o,timeout:i=350,itemToId:s}=e,a=t.keysSoFar+o,c=a.length>1&&Array.from(a).every(m=>m===a[0])?a[0]:a,d=r.slice(),u=Bg(d,c,n,s);function h(){clearTimeout(t.timer),t.timer=-1;}function p(m){t.keysSoFar=m,h(),m!==""&&(t.timer=+setTimeout(()=>{p(""),h();},i));}return p(a),u}var Hl=Object.assign(oL,{defaultOptions:{keysSoFar:"",timer:-1},isValidEvent:iL});function iL(r){return r.key.length===1&&!r.ctrlKey&&!r.metaKey}function sL(r,e,t){let{signal:n}=e;return [new Promise((s,a)=>{let l=setTimeout(()=>{a(new Error(`Timeout of ${t}ms exceeded`));},t);n.addEventListener("abort",()=>{clearTimeout(l),a(new DOMException("Promise aborted","AbortError"));}),r.then(c=>{n.aborted||(clearTimeout(l),s(c));}).catch(c=>{n.aborted||(clearTimeout(l),a(c));});}),()=>e.abort()]}function Hg(r,e){let{timeout:t,rootNode:n}=e,o=Ie(n),i=Oe(n),s=new o.AbortController;return sL(new Promise(a=>{let l=r();if(l){a(l);return}let c=new o.MutationObserver(()=>{let d=r();d&&d.isConnected&&(c.disconnect(),a(d));});c.observe(i.body,{childList:true,subtree:true});}),s,t)}function zg(r){let e=()=>r.getRootNode?.()??document,t=()=>Oe(e());return {...r,getRootNode:e,getDoc:t,getWin:()=>t().defaultView??window,getActiveElement:()=>nn(e()),isActiveElement:Xi,getById:s=>e().getElementById(s)}}function Wg(r){return new Proxy({},{get(e,t){return t==="style"?n=>r({style:n}).style:r}})}var Gg={onFocus:"onFocusin",onBlur:"onFocusout",onChange:"onInput",onDoubleClick:"onDblclick",htmlFor:"for",className:"class",defaultValue:"value",defaultChecked:"checked"},aL=new Set(["viewBox","preserveAspectRatio"]),lL=r=>{let e="";for(let t in r){let n=r[t];n!=null&&(t.startsWith("--")||(t=t.replace(/[A-Z]/g,o=>`-${o.toLowerCase()}`)),e+=`${t}:${n};`);}return e},Lo=Wg(r=>Object.entries(r).reduce((e,[t,n])=>{if(n===void 0)return e;if(t in Gg&&(t=Gg[t]),t==="style"&&typeof n=="object")return e.style=lL(n),e;let o=aL.has(t)?t:t.toLowerCase();return e[o]=n,e},{}));var zl=new WeakMap,$g=new Set(["value","checked","selected"]),cL=new Set(["viewBox","preserveAspectRatio","clipPath","clipRule","fillRule","strokeWidth","strokeLinecap","strokeLinejoin","strokeDasharray","strokeDashoffset","strokeMiterlimit"]),dL=r=>r.tagName==="svg"||r.namespaceURI==="http://www.w3.org/2000/svg",Wl=(r,e)=>dL(r)&&cL.has(e)?e:e.toLowerCase();function ft(r,e,t){let n=t||"default",o=zl.get(r);o||(o=new Map,zl.set(r,o));let i=o.get(n)||{},s=Object.keys(e),a=(f,g)=>{r.addEventListener(f.toLowerCase(),g);},l=(f,g)=>{r.removeEventListener(f.toLowerCase(),g);},c=f=>f.startsWith("on"),d=f=>!f.startsWith("on"),u=f=>a(f.substring(2),e[f]),h=f=>l(f.substring(2),e[f]),p=f=>{let g=e[f],b=i[f];if(g!==b){if(f==="class"){r.className=g??"";return}if($g.has(f)){r[f]=g??"";return}if(typeof g=="boolean"&&!f.includes("aria-")){r.toggleAttribute(Wl(r,f),g);return}if(f==="children"){r.innerHTML=g;return}if(g!=null){r.setAttribute(Wl(r,f),g);return}r.removeAttribute(Wl(r,f));}};for(let f in i)e[f]==null&&(f==="class"?r.className="":$g.has(f)?r[f]="":r.removeAttribute(Wl(r,f)));return Object.keys(i).filter(c).forEach(f=>{l(f.substring(2),i[f]);}),s.filter(c).forEach(u),s.filter(d).forEach(p),o.set(n,e),function(){s.filter(c).forEach(h);let g=zl.get(r);g&&(g.delete(n),g.size===0&&zl.delete(r));}}function uL(){if(typeof globalThis<"u")return globalThis;if(typeof self<"u")return self;if(typeof window<"u")return window;if(typeof global<"u")return global}function Ru(r,e){let t=uL();return t?(t[r]||(t[r]=e()),t[r]):e()}var Mo=Ru("__zag__refSet",()=>new WeakSet);var hL=r=>typeof r=="object"&&r!==null&&"$$typeof"in r&&"props"in r,pL=r=>typeof r=="object"&&r!==null&&"__v_isVNode"in r,mL=r=>typeof r=="object"&&r!==null&&"nodeType"in r&&typeof r.nodeName=="string",fL=r=>hL(r)||pL(r)||mL(r),Gl=r=>r!==null&&typeof r=="object",Du=r=>Gl(r)&&!Mo.has(r)&&(Array.isArray(r)||!(Symbol.iterator in r))&&!fL(r)&&!(r instanceof WeakMap)&&!(r instanceof WeakSet)&&!(r instanceof Error)&&!(r instanceof Number)&&!(r instanceof Date)&&!(r instanceof String)&&!(r instanceof RegExp)&&!(r instanceof ArrayBuffer)&&!(r instanceof Promise)&&!(r instanceof File)&&!(r instanceof Blob)&&!(r instanceof AbortController);var gL=Symbol();var Ug=Object.getPrototypeOf,Ou=new WeakMap,bL=r=>r&&(Ou.has(r)?Ou.get(r):Ug(r)===Object.prototype||Ug(r)===Array.prototype);var Yg=r=>bL(r)&&r[gL]||null,Nu=(r,e=true)=>{Ou.set(r,e);};var Pr=Ru("__zag__proxyStateMap",()=>new WeakMap),vL=(r=Object.is,e=(a,l)=>new Proxy(a,l),t=new WeakMap,n=(a,l)=>{let c=t.get(a);if(c?.[0]===l)return c[1];let d=Array.isArray(a)?[]:Object.create(Object.getPrototypeOf(a));return Nu(d,true),t.set(a,[l,d]),Reflect.ownKeys(a).forEach(u=>{let h=Reflect.get(a,u);Mo.has(h)?(Nu(h,false),d[u]=h):Pr.has(h)?d[u]=Kg(h):d[u]=h;}),Object.freeze(d)},o=new WeakMap,i=[1,1],s=a=>{if(!Gl(a))throw new Error("object required");let l=o.get(a);if(l)return l;let c=i[0],d=new Set,u=(L,v=++i[0])=>{c!==v&&(c=v,d.forEach(k=>k(L,v)));},h=i[1],p=(L=++i[1])=>(h!==L&&!d.size&&(h=L,f.forEach(([v])=>{let k=v[1](L);k>c&&(c=k);})),c),m=L=>(v,k)=>{let x=[...v];x[1]=[L,...x[1]],u(x,k);},f=new Map,g=(L,v)=>{if(d.size){let k=v[3](m(L));f.set(L,[v,k]);}else f.set(L,[v]);},b=L=>{let v=f.get(L);v&&(f.delete(L),v[1]?.());},y=L=>(d.add(L),d.size===1&&f.forEach(([k,x],E)=>{let I=k[3](m(E));f.set(E,[k,I]);}),()=>{d.delete(L),d.size===0&&f.forEach(([k,x],E)=>{x&&(x(),f.set(E,[k]));});}),w=Array.isArray(a)?[]:Object.create(Object.getPrototypeOf(a)),M=e(w,{deleteProperty(L,v){let k=Reflect.get(L,v);b(v);let x=Reflect.deleteProperty(L,v);return x&&u(["delete",[v],k]),x},set(L,v,k,x){let E=Reflect.has(L,v),I=Reflect.get(L,v,x);if(E&&(r(I,k)||o.has(k)&&r(I,o.get(k))))return true;b(v),Gl(k)&&(k=Yg(k)||k);let N=k;if(!Object.getOwnPropertyDescriptor(L,v)?.set){!Pr.has(k)&&Du(k)&&(N=$l(k));let V=!Mo.has(N)&&Pr.get(N);V&&g(v,V);}return Reflect.set(L,v,N,x),u(["set",[v],k,I]),true}});o.set(a,M);let S=[w,p,n,y];return Pr.set(M,S),Reflect.ownKeys(a).forEach(L=>{let v=Object.getOwnPropertyDescriptor(a,L);v.get||v.set?Object.defineProperty(w,L,v):M[L]=a[L];}),M})=>[s,Pr,Mo,r,e,Du,t,n,o,i],[yL]=vL();function $l(r={}){return yL(r)}function Ul(r,e,t){let n=Pr.get(r);let o,i=[],s=n[3],a=false,c=s(d=>{if(i.push(d),t);o||(o=Promise.resolve().then(()=>{o=void 0,a&&e(i.splice(0));}));});return a=true,()=>{a=false,c();}}function Kg(r){let e=Pr.get(r);let[t,n,o]=e;return o(t,n())}function Zi(r){let e=r().value??r().defaultValue;r().debug&&console.log(`[bindable > ${r().debug}] initial`,e);let t=r().isEqual??Object.is,n=$l({value:e}),o=()=>r().value!==void 0;return {initial:e,ref:n,get(){return o()?r().value:n.value},set(i){let s=o()?r().value:n.value,a=pt(i)?i(s):i;r().debug&&console.log(`[bindable > ${r().debug}] setValue`,{next:a,prev:s}),o()||(n.value=a),t(a,s)||r().onChange?.(a,s);},invoke(i,s){r().onChange?.(i,s);},hash(i){return r().hash?.(i)??String(i)}}}Zi.cleanup=r=>{};Zi.ref=r=>{let e=r;return {get:()=>e,set:t=>{e=t;}}};function Xg(r){let e={current:r};return {get(t){return e.current[t]},set(t,n){e.current[t]=n;}}}function Fu(r,e){if(!Mr(r)||!Mr(e))return e===void 0?r:e;let t={...r};for(let n of Object.keys(e)){let o=e[n],i=r[n];o!==void 0&&(Mr(i)&&Mr(o)?t[n]=Fu(i,o):t[n]=o);}return t}var Vu=class{constructor(r,e={}){ue(this,"machine",r),ue(this,"scope"),ue(this,"context"),ue(this,"prop"),ue(this,"state"),ue(this,"refs"),ue(this,"computed"),ue(this,"event",{type:""}),ue(this,"previousEvent",{type:""}),ue(this,"effects",new Map),ue(this,"transition",null),ue(this,"cleanups",[]),ue(this,"subscriptions",[]),ue(this,"userPropsRef"),ue(this,"getEvent",()=>({...this.event,current:()=>this.event,previous:()=>this.previousEvent})),ue(this,"getState",()=>({...this.state,matches:(...u)=>u.some(h=>og(this.state.get(),h)),hasTag:u=>ig(this.machine,this.state.get(),u)})),ue(this,"debug",(...u)=>{this.machine.debug&&console.log(...u);}),ue(this,"notify",()=>{this.publish();}),ue(this,"send",u=>{this.status===vo.Started&&queueMicrotask(()=>{if(!u)return;this.previousEvent=this.event,this.event=u,this.debug("send",u);let h=this.state.get(),p=u.type,{transitions:m,source:f}=ng(this.machine,h,p),g=this.choose(m);if(!g)return;this.transition=g;let b=vu(this.machine,g.target??h,f);this.debug("transition",g),b!==h?this.state.set(b):g.reenter?this.state.invoke(h,h):this.action(g.actions);});}),ue(this,"action",u=>{let h=pt(u)?u(this.getParams()):u;if(!h)return;let p=h.map(m=>{let f=this.machine.implementations?.actions?.[m];return f||go(`[zag-js] No implementation found for action "${JSON.stringify(m)}"`),f});for(let m of p)m?.(this.getParams());}),ue(this,"guard",u=>{if(pt(u))return u(this.getParams());let h=this.machine.implementations?.guards?.[u];return h||go(`[zag-js] No implementation found for guard "${JSON.stringify(u)}"`),h?.(this.getParams())}),ue(this,"effect",u=>{let h=pt(u)?u(this.getParams()):u;if(!h)return;let p=h.map(f=>{let g=this.machine.implementations?.effects?.[f];return g||go(`[zag-js] No implementation found for effect "${JSON.stringify(f)}"`),g}),m=[];for(let f of p){let g=f?.(this.getParams());g&&m.push(g);}return ()=>m.forEach(f=>f?.())}),ue(this,"choose",u=>_f(u).find(h=>{let p=!h.guard;return fo(h.guard)?p=!!this.guard(h.guard):pt(h.guard)&&(p=h.guard(this.getParams())),p})),ue(this,"subscribe",u=>(this.subscriptions.push(u),()=>{let h=this.subscriptions.indexOf(u);h>-1&&this.subscriptions.splice(h,1);})),ue(this,"status",vo.NotStarted),ue(this,"publish",()=>{this.callTrackers(),this.subscriptions.forEach(u=>u(this.service));}),ue(this,"trackers",[]),ue(this,"setupTrackers",()=>{this.machine.watch?.(this.getParams());}),ue(this,"callTrackers",()=>{this.trackers.forEach(({deps:u,fn:h})=>{let p=u.map(m=>m());mo(h.prev,p)||(h(),h.prev=p);});}),ue(this,"getParams",()=>({state:this.getState(),context:this.context,event:this.getEvent(),prop:this.prop,send:this.send,action:this.action,guard:this.guard,track:(u,h)=>{h.prev=u.map(p=>p()),this.trackers.push({deps:u,fn:h});},refs:this.refs,computed:this.computed,flush:Xf,scope:this.scope,choose:this.choose})),this.userPropsRef={current:e};let{id:t,ids:n,getRootNode:o}=zi(e);this.scope=zg({id:t,ids:n,getRootNode:o});let i=u=>{let h=zi(this.userPropsRef.current);return (r.props?.({props:$n(h),scope:this.scope})??h)[u]};this.prop=i;let s=r.context?.({prop:i,bindable:Zi,scope:this.scope,flush(u){queueMicrotask(u);},getContext(){return a},getComputed(){return l},getRefs(){return c},getEvent:this.getEvent.bind(this)});s&&Object.values(s).forEach(u=>{let h=Ul(u.ref,()=>this.notify());this.cleanups.push(h);});let a={get(u){return s?.[u].get()},set(u,h){s?.[u].set(h);},initial(u){return s?.[u].initial},hash(u){let h=s?.[u].get();return s?.[u].hash(h)}};this.context=a;let l=u=>(Wi(r.computed,()=>"[zag-js] No computed object found on machine"),r.computed[u]({context:a,event:this.getEvent(),prop:i,refs:this.refs,scope:this.scope,computed:l}));this.computed=l;let c=Xg(r.refs?.({prop:i,context:a})??{});this.refs=c;let d=Zi(()=>({defaultValue:vu(r,r.initialState({prop:i})),onChange:(u,h)=>{let{exiting:p,entering:m}=rg(this.machine,h,u,this.transition?.reenter);if(p.forEach(f=>{this.effects.get(f.path)?.(),this.effects.delete(f.path);}),p.forEach(f=>{this.action(f.state?.exit);}),this.action(this.transition?.actions),m.forEach(f=>{let g=this.effect(f.state?.effects);if(g){let b=this.effects.get(f.path);this.effects.set(f.path,b?Gn(b,g):g);}}),h===$i){this.action(r.entry);let f=this.effect(r.effects);if(f){let g=this.effects.get($i);this.effects.set($i,g?Gn(g,f):f);}}m.forEach(f=>{this.action(f.state?.entry);});}}));this.state=d,this.cleanups.push(Ul(this.state.ref,()=>this.notify()));}updateProps(r){let e=this.userPropsRef.current;this.userPropsRef.current=()=>{let t=zi(e),n=zi(r);return Fu(t,n)},this.notify();}start(){this.status=vo.Started,this.debug("initializing..."),this.state.invoke(this.state.initial,$i),this.setupTrackers();}stop(){this.effects.forEach(r=>r?.()),this.effects.clear(),this.transition=null,this.action(this.machine.exit),this.cleanups.forEach(r=>r()),this.cleanups=[],this.subscriptions=[],this.status=vo.Stopped,this.debug("unmounting...");}get service(){return {state:this.getState(),send:this.send,context:this.context,prop:this.prop,scope:this.scope,refs:this.refs,computed:this.computed,event:this.getEvent(),getStatus:()=>this.status}}};function Yl(r,e,t){let n=new Vu(r,e),o=n.subscribe(t);return n.start(),t(n.service),{service:n.service,flush:()=>t(n.service),stop:()=>{o(),n.stop();}}}var wL=0;function Kl(r){return `${r}-${++wL}`}function Ir(r,e=8){return `${r}::-webkit-scrollbar{width:${e}px;height:${e}px;}${r}::-webkit-scrollbar-thumb{background:var(--vela-scroll);border-radius:4px;border:2px solid transparent;background-clip:padding-box;}${r}::-webkit-scrollbar-track{background:transparent;}${r}::-webkit-scrollbar-button{display:none;width:0;height:0;}`}var jg="outline:none;transition:border-color .12s ease,box-shadow .12s ease;",qg="border-color:var(--vela-focus);box-shadow:0 0 0 3px var(--vela-focus-soft);";function he(r,e,t=document){if(typeof document>"u")return;let n=t instanceof Document?t.head:t;if(t.getElementById?.(r)??n.querySelector(`#${CSS.escape(r)}`))return;let o=document.createElement("style");o.id=r,o.textContent=e,n.appendChild(o);}var xL="vela-ui-tokens",CL=Object.entries(Ml).map(([r,e])=>` ${r}: ${e};`).join(` -`),SL=` +var Vela=(function(exports){'use strict';function Kt(r,e,t=1e3){return r===true?e:typeof r!="number"||!Number.isFinite(r)||r<=0?0:Math.min(r,t)}function Xd(r){return Kt(r,90,1e3)}function jd(r){let e={style:false,duration:0};if(r===true)return {style:"settle",duration:650};if(r==="settle"||r==="grow")return {style:r,duration:650};if(r&&typeof r=="object"){let t=r,n=t.duration;return {style:t.style==="grow"?"grow":"settle",duration:typeof n=="number"&&Number.isFinite(n)&&n>0?Math.min(n,5e3):650}}return e}function Fm(r){if(r===false)return {animZoom:0,animPan:0,animScroll:0,animAutoscale:0,animLiveBar:0,animIntro:{style:false,duration:0}};let e=r===true||r==null?{}:r,t=Kt(e.pan??true,110);return {animZoom:Kt(e.zoom??true,70),animPan:t,animScroll:e.scroll===void 0?t>0?130:0:Kt(e.scroll,130),animAutoscale:Kt(e.autoscale??true,80),animLiveBar:Xd(e.liveBar),animIntro:jd(e.intro??true)}}function $e(r){return r.kind!=="candle"&&r.kind!=="bar"&&r.kind!=="markers"}function Rt(r,e){return r.display?r.display[e]!==false:r.visible!==false}function ia(r){return Rt(r,"pane")||Rt(r,"priceScale")}var ur=class{constructor(){this.handlers=new Map;}on(e,t){let n=this.handlers.get(e);n||(n=new Set,this.handlers.set(e,n));let o=n;return o.add(t),()=>{o.delete(t);}}off(e,t){this.handlers.get(e)?.delete(t);}hasListeners(e){return (this.handlers.get(e)?.size??0)>0}emit(e,t){let n=this.handlers.get(e);if(n)for(let o of n)try{o(t);}catch(i){console.error(`[vela] event handler error for "${String(e)}"`,i);}}clear(){this.handlers.clear();}};var sa=class{constructor(){this.records=new Map;this.counter=0;}nextId(e="ind",t=()=>false){let n;do this.counter+=1,n=`${e}-${this.counter}`;while(this.records.has(n)||t(n));return n}add(e){this.records.set(e.id,e);}get(e){return this.records.get(e)}remove(e){let t=this.records.get(e);return this.records.delete(e),t}all(){return [...this.records.values()]}};function Vm(r,e){return `${r}#${e}`}var pi=new Map;function Vn(r){pi.set(r.type,r);}function Bm(r){pi.delete(r);}function mi(r){return pi.get(r)}function _m(){return [...pi.keys()]}function aa(){return [...pi.values()]}var la=class{constructor(e,t,n){this.feed=e;this.market=t;this.onBar=n;this.unsubscribe=null;}start(){this.unsubscribe||(this.unsubscribe=this.feed.subscribe(this.market,this.onBar));}stop(){this.unsubscribe?.(),this.unsubscribe=null;}};var ro=class{constructor(e,t,n,o,i){this.controller=n;this.schema=[];this.propsSchema=[];this.visibleState=true;this.bus=new ur;this.id=e,this.title=t,o!==void 0&&(this.source=o),i!==void 0&&(this.nativeType=i);}get inputs(){return this.schema}get props(){return this.propsSchema}get visible(){return this.visibleState}inputValues(){return this.controller.inputValuesOf(this.id)}propValues(){return this.controller.propValuesOf(this.id)}setInput(e,t){this.controller.applyInputs(this.id,{[e]:t});}setInputs(e){this.controller.applyInputs(this.id,e);}setProp(e,t){this.controller.applyProps(this.id,{[e]:t});}setProps(e){this.controller.applyProps(this.id,e);}updateCode(e){return this.controller.updateCode(this.id,e)}setVisible(e){this.controller.setVisible(this.id,e);}moveTo(e){this.controller.moveIndicator(this.id,e);}on(e,t){return this.bus.on(e,t)}context(e){return this.controller.getIndicatorContext(this.id,e)}remove(){this.controller.removeIndicator(this.id);}setSchema(e){this.schema=e;}setPropsSchema(e){this.propsSchema=e;}setSource(e){this.source=e;}setVisibleState(e){this.visibleState=e;}emit(e,t){this.bus.emit(e,t);}};function uC(r){let e={};for(let o of r.series)e[o.kind]=(e[o.kind]??0)+1;let t=o=>o?.filter(i=>i.overlay===true).length??0,n=t(r.series)+t(r.fills)+t(r.backgrounds)+t(r.lines)+t(r.boxes)+t(r.labels)+t(r.polylines)+t(r.linefills)+t(r.tables);return {id:r.id,title:r.title,overlay:r.overlay,paneId:r.paneId,native:!!r.native,nativeType:r.native?.type,series:e,fills:r.fills.length,backgrounds:r.backgrounds.length,priceLines:r.priceLines.length,lines:r.lines?.length??0,boxes:r.boxes?.length??0,labels:r.labels?.length??0,polylines:r.polylines?.length??0,linefills:r.linefills?.length??0,tables:r.tables?.length??0,barColors:r.barColors?.length??0,trades:r.trades?.length??0,inputs:r.inputs.length,forcedOverlay:n}}function Hm(r){let e=r.map(uC),t=n=>e.reduce((o,i)=>o+n(i),0);return {indicators:e,totals:{panes:new Set(e.map(n=>n.paneId??"price")).size,series:t(n=>Object.values(n.series).reduce((o,i)=>o+i,0)),fills:t(n=>n.fills),backgrounds:t(n=>n.backgrounds),priceLines:t(n=>n.priceLines),lines:t(n=>n.lines),boxes:t(n=>n.boxes),labels:t(n=>n.labels),polylines:t(n=>n.polylines),linefills:t(n=>n.linefills),tables:t(n=>n.tables),barColors:t(n=>n.barColors),trades:t(n=>n.trades),forcedOverlay:t(n=>n.forcedOverlay)}}}var hC={"1D":864e5,"1W":6048e5,"1M":2592e6,"3M":7776e6,"6M":15552e6,"1Y":31536e6,"5Y":15768e7};function zm(r,e){if(e.length===0)return null;let t=e[0].time,n=e[e.length-1].time;if(r==="ALL")return {from:t,to:n};let o;return r==="YTD"?o=Date.UTC(new Date(n).getUTCFullYear(),0,1):o=n-hC[r],{from:Math.max(t,o),to:n}}var nt="#2962ff",oo="#38c0fd",O="#089981",D="#f23645",A="#787b86",Gm="#e0b400",Y="#ff9800",ce="#5b9cf6",$m="#ff5d00",ca="#0ecb81",da="#f6465d",kO="#f97316",LO="#0ea5e9",MO="#9ca3af",fi="#3b82f6",Um="#9aa0ad",Ym="#1e293b",Km="#475569",Xm="#595959",jm=nt,qm=D,Zm="#d500f9",Wm=[nt,O,D,Y,"#7e57c2","#26a69a",ce,"#e573b5"];function EO(r){let e=0;for(let t=0;t>>0;return Wm[e%Wm.length]}var _=oo;function qd(){return {lineColor:_,lineWidth:2,lineStyle:"solid"}}function bn(r=""){return {value:r,size:"normal",hAlign:"left",vAlign:"top"}}var ua=class ua{constructor(e){this.locked=false;this.visible=true;this.zIndex=0;this.id=e.id??`dw-${ua.seq+=1}`,this.paneId=e.paneId,this.anchors=(e.anchors??[]).map(t=>({time:t.time,price:t.price})),this.style=e.style?{...e.style}:qd(),this.text=e.text?{...e.text}:void 0,this.locked=e.locked??false,this.visible=e.visible??true,this.zIndex=e.zIndex??0,this.createdAt=e.createdAt??Date.now(),e.props&&this.readProps(e.props);}isComplete(){return this.anchors.length>=this.anchorSchema().min}placementMode(){return "click"}onPlaced(e){}constrainHandleDrag(e){}translateBody(e,t,n){return n.map(o=>({time:o.time+e,price:o.price+t}))}timeExtent(){if(this.anchors.length===0)return null;let e=1/0,t=-1/0;for(let n of this.anchors)n.timet&&(t=n.time);return {min:e,max:t}}editableLevels(){return null}applySettings(e){for(let[t,n]of Object.entries(e))t.startsWith("text.")&&!this.text&&(this.text=bn()),Qm(this,t,n);}applyProps(e){this.readProps(e);}serialize(){return {id:this.id,type:this.type,paneId:this.paneId,anchors:this.anchors.map(e=>({time:e.time,price:e.price})),style:{...this.style},text:this.text?{...this.text}:void 0,locked:this.locked,visible:this.visible,zIndex:this.zIndex,createdAt:this.createdAt,props:this.writeProps()}}writeProps(){}readProps(e){}};ua.seq=0;var K=ua;function Qm(r,e,t){let n=e.split("."),o=r;for(let i=0;i${r}`}function B(r,e=""){return `${r}`}function Qd(r){return `${r}`}var U=Jm;H("style-candles",U(''));H("style-bars",U(''));H("style-line",U(''));H("style-area",U(''));H("style-baseline",U(''));H("style-heikinashi",U(''));H("indicators",U(''));H("undo",U(''));H("redo",U(''));H("objects",U(''));H("clock",U(''));H("calendar",U(''));H("datawindow",U(''));H("camera",U(''));H("gear",U(''));H("search",U(''));H("bell",U(''));H("market-open",B(''));H("market-pre",B(''));H("market-post",B(''));H("market-extended",B(''));H("market-closed",B(''));H("market-holiday",B(''));H("chevron-right",U(''));H("chevron-left",U(''));H("chevron-down",U(''));H("chevron-up",U(''));H("chevrons-right",U(''));H("chevrons-left",U(''));H("replay",U(''));H("check",U(''));H("close",U(''));H("pin",U(''));H("pin-filled",U(''));H("eye",U(''));H("eye-off",U(''));H("lock",U(''));H("unlock",U(''));H("trash",U(''));H("group",U(''));H("ungroup",U(''));H("clone",U(''));H("arrow-up",U(''));H("arrow-down",U(''));H("move-vertical",U(''));H("move",U(''));H("pen",U(''));H("wave",U(''));H("folder-plus",U(''));H("folder-minus",U(''));H("collapse",U(''));H("expand",U(''));H("plus",U(''));H("minus",U(''));H("maximize",U(''));H("restore",U(''));H("restore",U(''));H("star",U(''));H("star-filled",U('','fill="currentColor"'));H("grip",U('','fill="currentColor" stroke="none"'));H("kebab",U('','fill="currentColor" stroke="none"'));H("burger",U(''));H("info",U(''));H("reset",U(''));H("pane-collapse",U(''));H("pane-expand",U(''));H("cursor",B('','fill="currentColor" stroke="none"'));H("ruler",B(''));H("magnet",B(''));H("eraser",B(''));H("pen-lock",B(''));H("pen-sync",B(''));H("brush",B(''));H("bucket",B(''));H("type",B(''));H("bold",B('','stroke-width="2.4"'));H("italic",B('','stroke-width="2.2"'));H("price-delta",B(''));H("date-delta",B(''));H("bring-front",B(''));H("send-back",B(''));H("r-squared",'R\xB2');H("bands",B(''));H("dedekind",B(''));H("sonic",B(''));H("supersonic",B(''));var rt=[{value:"solid",label:"Solid"},{value:"dashed",label:"Dashed"},{value:"dotted",label:"Dotted"}],G=[{path:"style.lineColor",label:"Line color",kind:"color",group:"line"},{path:"style.lineWidth",label:"Line width",kind:"number",min:1,max:10,step:1,group:"line"},{path:"style.lineStyle",label:"Line style",kind:"lineStyle",options:rt,group:"line"}],fe=[{path:"style.fillColor",label:"Fill color",kind:"color",group:"fill"}],Dt=[{value:"small",label:"Small"},{value:"normal",label:"Normal"},{value:"large",label:"Large"},{value:"huge",label:"Huge"}],$=[{path:"text.value",label:"Text",kind:"text",group:"text"},{path:"text.color",label:"Text color",kind:"color",group:"text"},{path:"text.size",label:"Text size",kind:"select",options:Dt,group:"text"},{path:"text.bold",label:"Bold",kind:"boolean",group:"text"},{path:"text.italic",label:"Italic",kind:"boolean",group:"text"}];function ae(r,e,t,n,o,i){let s=o-t,a=i-n,l=s*s+a*a;if(l<=1e-9)return Math.hypot(r-t,e-n);let c=((r-t)*s+(e-n)*a)/l;return c=c<0?0:c>1?1:c,Math.hypot(r-(t+c*s),e-(n+c*a))}function so(r,e,t){let n=1/0;for(let o=1;o=a&&r<=l&&e>=c&&e<=d}function Xt(r,e,t){let n=false;for(let o=0,i=t.length-1;oe!=a[1]>e&&r<(a[0]-s[0])*(e-s[1])/(a[1]-s[1])+s[0]&&(n=!n);}return n}function Jd(r,e,t,n,o,i,s,a){let l=t-r,c=n-e,d=s-o,u=a-i,h=d*c-u*l;if(Math.abs(h)<1e-9)return null;let p=((i-e)*l-(o-r)*c)/h;return p<0||p>1?null:[o+p*d,i+p*u]}function j(r,e,t,n=6){for(let o=0;o=e;return c?m?[r,e,t,s]:[r,e,t,0]:m?[r,0,t,n]:[r,s,t,n]}let d=(n-e)/a,u=m=>e+d*(m-r),h=l?-2:Math.min(r,t),p=c?i+2:Math.max(r,t);return [h,u(h),p,u(p)]}var ha=class extends K{constructor(){super(...arguments);this.type="trendline";}anchorSchema(){return {min:2,max:2,slots:[{role:"p1",free:"both"},{role:"p2",free:"both"}]}}pixels(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);return i==null||s==null?null:[t.xOf(n.time),i,t.xOf(o.time),s]}hitTest(t,n,o,i){let s=this.pixels(o);return s!=null&&ae(t,n,s[0],s[1],s[2],s[3])<=i}handlePoints(t){let n=this.pixels(t);return n?[[n[0],n[1]],[n[2],n[3]]]:[]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.pixels(t);if(!n)return null;let o=Math.min(n[0],n[2]),i=Math.min(n[1],n[3]);return {x:o,y:i,w:Math.abs(n[2]-n[0]),h:Math.abs(n[3]-n[1])}}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}schema(){return {fields:[...G,{path:"style.arrowRight",label:"Arrow",kind:"boolean",group:"line"},...$]}}};var pa=class extends K{constructor(){super(...arguments);this.type="hline";}anchorSchema(){return {min:1,max:1,slots:[{role:"p",free:"y"}]}}y(t){let n=this.anchors[0];return n?t.yOf(n.price,this.paneId):null}hitTest(t,n,o,i){let s=this.y(o);return s!=null&&Math.abs(n-s)<=i}handlePoints(t){let n=this.anchors[0],o=this.y(t);return !n||o==null?[]:[[t.xOf(n.time),o]]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.y(t);return n==null?null:{x:0,y:n-1,w:t.width,h:2}}priceRange(){let t=this.anchors[0];return t?{min:t.price,max:t.price}:null}timeExtent(){return null}schema(){return {fields:[...G,...$]}}};var ma=class extends K{constructor(){super(...arguments);this.type="ray";}anchorSchema(){return {min:2,max:2,slots:[{role:"p1",free:"both"},{role:"p2",free:"both"}]}}pixels(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);return i==null||s==null?null:[t.xOf(n.time),i,t.xOf(o.time),s]}hitTest(t,n,o,i){let s=this.pixels(o);if(!s)return false;let[a,l,c,d]=Pe(s[0],s[1],s[2],s[3],"right",o.width,o.height);return ae(t,n,a,l,c,d)<=i}handlePoints(t){let n=this.pixels(t);return n?[[n[0],n[1]],[n[2],n[3]]]:[]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.pixels(t);return n?{x:Math.min(n[0],n[2]),y:Math.min(n[1],n[3]),w:Math.abs(n[2]-n[0]),h:Math.abs(n[3]-n[1])}:null}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}schema(){return {fields:[...G,...$]}}};var Bn=class extends K{anchorSchema(){return {min:2,max:2,slots:[{role:"p1",free:"both"},{role:"p2",free:"both"}]}}pixels(e){let t=this.anchors[0],n=this.anchors[1];if(!t||!n)return null;let o=e.yOf(t.price,this.paneId),i=e.yOf(n.price,this.paneId);return o==null||i==null?null:[e.xOf(t.time),o,e.xOf(n.time),i]}hitTest(e,t,n,o){let i=this.pixels(n);return i!=null&&ae(e,t,i[0],i[1],i[2],i[3])<=o}handlePoints(e){let t=this.pixels(e);return t?[[t[0],t[1]],[t[2],t[3]]]:[]}hitHandle(e,t,n,o){return j(e,t,this.handlePoints(n),o+3)}bounds(e){let t=this.pixels(e);return t?{x:Math.min(t[0],t[2]),y:Math.min(t[1],t[3]),w:Math.abs(t[2]-t[0]),h:Math.abs(t[3]-t[1])}:null}priceRange(){let e=this.anchors[0],t=this.anchors[1];return !e||!t?null:{min:Math.min(e.price,t.price),max:Math.max(e.price,t.price)}}schema(){return {fields:[...G,...$]}}};var fa=class extends Bn{constructor(){super(...arguments);this.type="extendedline";}hitTest(t,n,o,i){let s=this.pixels(o);if(!s)return false;let[a,l,c,d]=Pe(s[0],s[1],s[2],s[3],"both",o.width,o.height);return ae(t,n,a,l,c,d)<=i}timeExtent(){return null}};var ga=class extends K{constructor(){super(...arguments);this.type="vline";}anchorSchema(){return {min:1,max:1,slots:[{role:"p",free:"x"}]}}x(t){let n=this.anchors[0];return n?t.xOf(n.time):null}hitTest(t,n,o,i){let s=this.x(o);return s!=null&&Math.abs(t-s)<=i}handlePoints(t){let n=this.anchors[0],o=this.x(t);if(!n||o==null)return [];let i=t.yOf(n.price,this.paneId);return i==null?[]:[[o,i]]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.x(t);return n==null?null:{x:n-1,y:0,w:2,h:t.height}}priceRange(){return null}schema(){return {fields:[...G,...$]}}};var ba=class extends K{constructor(){super(...arguments);this.type="hray";}anchorSchema(){return {min:1,max:1,slots:[{role:"p",free:"both"}]}}pt(t){let n=this.anchors[0];if(!n)return null;let o=t.yOf(n.price,this.paneId);return o==null?null:[t.xOf(n.time),o]}hitTest(t,n,o,i){let s=this.pt(o);return s!=null&&ae(t,n,s[0],s[1],o.width,s[1])<=i}handlePoints(t){let n=this.pt(t);return n?[n]:[]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.pt(t);return n?{x:n[0],y:n[1]-1,w:Math.max(0,t.width-n[0]),h:2}:null}priceRange(){let t=this.anchors[0];return t?{min:t.price,max:t.price}:null}timeExtent(){let t=this.anchors[0];return t?{min:t.time,max:Number.POSITIVE_INFINITY}:null}schema(){return {fields:[...G,...$]}}};var va=class extends K{constructor(){super(...arguments);this.type="crossline";}anchorSchema(){return {min:1,max:1,slots:[{role:"p",free:"both"}]}}pt(t){let n=this.anchors[0];if(!n)return null;let o=t.yOf(n.price,this.paneId);return o==null?null:[t.xOf(n.time),o]}hitTest(t,n,o,i){let s=this.pt(o);return s!=null&&(Math.abs(n-s[1])<=i||Math.abs(t-s[0])<=i)}handlePoints(t){let n=this.pt(t);return n?[n]:[]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.pt(t);return n?{x:n[0]-1,y:n[1]-1,w:2,h:2}:null}priceRange(){let t=this.anchors[0];return t?{min:t.price,max:t.price}:null}timeExtent(){return null}schema(){return {fields:[...G,...$]}}};var ya=class extends Bn{constructor(){super(...arguments);this.type="infoline";}};var wa=class extends Bn{constructor(){super(...arguments);this.type="trendangle";}};var xa=class extends K{constructor(){super(...arguments);this.type="box";}anchorSchema(){return {min:2,max:2,slots:[{role:"c1",free:"both"},{role:"c2",free:"both"}]}}rect(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);return i==null||s==null?null:{x1:t.xOf(n.time),y1:i,x2:t.xOf(o.time),y2:s}}hitTest(t,n,o,i){let s=this.rect(o);return s?this.style.fillColor&&Ue(t,n,s.x1,s.y1,s.x2,s.y2)?true:[[s.x1,s.y1,s.x2,s.y1],[s.x2,s.y1,s.x2,s.y2],[s.x2,s.y2,s.x1,s.y2],[s.x1,s.y2,s.x1,s.y1]].some(l=>ae(t,n,l[0],l[1],l[2],l[3])<=i):false}handlePoints(t){let n=this.rect(t);return n?[[n.x1,n.y1],[n.x2,n.y2]]:[]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.rect(t);return n?{x:Math.min(n.x1,n.x2),y:Math.min(n.y1,n.y2),w:Math.abs(n.x2-n.x1),h:Math.abs(n.y2-n.y1)}:null}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}schema(){return {fields:[...G.map(t=>({...t,label:t.label.replace("Line","Border")})),{path:"style.fillColor",label:"Fill color",kind:"color",group:"fill"},...$]}}};var pC={tiny:10,small:12,normal:14,large:18,huge:24,auto:14},_n=class extends K{defaultLabel(){return "Text"}labelText(){return this.text?.value??this.defaultLabel()}anchorSchema(){return {min:1,max:1,slots:[{role:"p",free:"both"}]}}box(e){let t=this.anchors[0];if(!t)return null;let n=e.yOf(t.price,this.paneId);if(n==null)return null;let o=pC[this.text?.size??"normal"]??14,i=this.labelText().split(` +`),s=Math.max(1,...i.map(a=>a.length));return {x:e.xOf(t.time),y:n,w:Math.max(12,s*o*.6)+8,h:i.length*o*1.4+4}}hitTest(e,t,n,o){let i=this.box(n);return i!=null&&Ue(e,t,i.x,i.y,i.x+i.w,i.y+i.h)}handlePoints(e){let t=this.anchors[0],n=t?e.yOf(t.price,this.paneId):null;return t&&n!=null?[[e.xOf(t.time),n]]:[]}hitHandle(e,t,n,o){return j(e,t,this.handlePoints(n),o+3)}bounds(e){return this.box(e)}priceRange(){let e=this.anchors[0];return e?{min:e.price,max:e.price}:null}};var vn=class extends _n{constructor(t){super(t);this.type="text";this.text||(this.text={...bn(),size:"large"});}schema(){return {fields:[...$],textIsContent:true}}};var hr=class extends _n{constructor(t){super(t);this.type="note";this.text||(this.text=bn("Note"));}defaultLabel(){return "Note"}schema(){return {fields:[...G,...fe,...$],textIsContent:true}}};var pr=class extends _n{constructor(){super(...arguments);this.type="pricelabel";}labelText(){let t=this.anchors[0]?.price;return t==null?"0.00":t.toFixed(2)}schema(){return {fields:[...G,...fe,...$.filter(t=>t.path!=="text.value")]}}};var mC={tiny:10,small:12,normal:14,large:18,huge:24,auto:14},vt=class extends K{constructor(e){super(e),this.text||(this.text=bn(this.defaultLabel()));}defaultLabel(){return "Callout"}labelText(){return this.text?.value??this.defaultLabel()}anchorSchema(){return {min:2,max:2,slots:[{role:"target",free:"both"},{role:"box",free:"both"}]}}box(e){let t=this.anchors[1];if(!t)return null;let n=e.yOf(t.price,this.paneId);if(n==null)return null;let o=mC[this.text?.size??"normal"]??14,i=this.labelText().split(` +`),s=Math.max(1,...i.map(c=>c.length)),a=Math.max(20,s*o*.6)+16,l=i.length*o*1.4+12;return {x:e.xOf(t.time)-a/2,y:n-l/2,w:a,h:l}}points(e){let t=this.anchors[0],n=this.anchors[1];if(!t||!n)return null;let o=e.yOf(t.price,this.paneId),i=e.yOf(n.price,this.paneId);return o==null||i==null?null:[[e.xOf(t.time),o],[e.xOf(n.time),i]]}hitTest(e,t,n,o){let i=this.box(n);if(i&&Ue(e,t,i.x,i.y,i.x+i.w,i.y+i.h,o))return true;let s=this.points(n);return s!=null&&ae(e,t,s[0][0],s[0][1],s[1][0],s[1][1])<=o}handlePoints(e){let t=this.points(e);return t?[t[0]]:[]}hitHandle(e,t,n,o){return j(e,t,this.handlePoints(n),o+3)}translateBody(e,t,n){let o=n[0],i=n[1];return !o||!i?n.map(s=>({time:s.time+e,price:s.price+t})):[{time:o.time,price:o.price},{time:i.time+e,price:i.price+t}]}bounds(e){return this.box(e)}priceRange(){let e=this.anchors[0],t=this.anchors[1];return !e||!t?null:{min:Math.min(e.price,t.price),max:Math.max(e.price,t.price)}}schema(){return {fields:[...G,...fe,...$],textIsContent:true}}};var jt=class extends vt{constructor(){super(...arguments);this.type="callout";}};var mr=class extends vt{constructor(){super(...arguments);this.type="pricenote";}defaultLabel(){return ""}labelText(){let t=this.anchors[0]?.price;return t==null?"0.00":t.toFixed(2)}schema(){return {fields:[...G,...fe,...$.filter(t=>t.path!=="text.value")]}}};var fr=class extends vt{constructor(){super(...arguments);this.type="comment";}defaultLabel(){return "Comment"}};var gr=class extends vt{constructor(){super(...arguments);this.type="signpost";}defaultLabel(){return "Signpost"}};var ve=class extends K{hitTest(e,t,n,o){let i=this.geometry(n);return i?this.style.fillColor&&i.fill&&Xt(e,t,i.fill)?true:i.segments.some(s=>ae(e,t,s[0],s[1],s[2],s[3])<=o):false}handlePoints(e){let t=[];for(let n of this.anchors){let o=e.yOf(n.price,this.paneId);if(o==null)return [];t.push([e.xOf(n.time),o]);}return t}hitHandle(e,t,n,o){return j(e,t,this.handlePoints(n),o+3)}bounds(e){let t=this.handlePoints(e);if(t.length===0)return null;let n=t.map(a=>a[0]),o=t.map(a=>a[1]),i=Math.min(...n),s=Math.min(...o);return {x:i,y:s,w:Math.max(...n)-i,h:Math.max(...o)-s}}};var Sa=class extends ve{constructor(){super(...arguments);this.type="parallelchannel";}anchorSchema(){return {min:3,max:3,slots:[{role:"p1",free:"both"},{role:"p2",free:"both"},{role:"offset",free:"y"}]}}offset(){let t=this.anchors[0],n=this.anchors[1],o=this.anchors[2];return !t||!n||!o?0:o.price-(t.price+n.price)/2}handlePoints(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return [];let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);if(i==null||s==null)return [];let a=[[t.xOf(n.time),i],[t.xOf(o.time),s]],l=this.anchors[2];if(l){let c=t.yOf(l.price,this.paneId);c!=null&&a.push([t.xOf((n.time+o.time)/2),c]);}return a}timeExtent(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.time,n.time),max:Math.max(t.time,n.time)}}geometry(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=this.offset(),s=t.xOf(n.time),a=t.xOf(o.time),l=t.yOf(n.price,this.paneId),c=t.yOf(o.price,this.paneId),d=t.yOf(n.price+i,this.paneId),u=t.yOf(o.price+i,this.paneId);return l==null||c==null||d==null||u==null?null:{segments:[[s,l,a,c],[s,d,a,u]],fill:[[s,l],[a,c],[a,u],[s,d]]}}priceRange(){let t=this.anchors[0],n=this.anchors[1];if(!t||!n)return null;let o=this.offset(),i=[t.price,n.price,t.price+o,n.price+o],s=this.anchors[2];return s&&i.push(s.price),{min:Math.min(...i),max:Math.max(...i)}}schema(){return {fields:[...G,...fe,...$]}}};var Ca=class extends ve{constructor(){super(...arguments);this.type="disjointchannel";}anchorSchema(){return {min:4,max:4,slots:[{role:"top1",free:"both"},{role:"top2",free:"both"},{role:"bot1",free:"both"},{role:"bot2",free:"both"}]}}seg(t,n,o){let i=this.anchors[t],s=this.anchors[n];if(!i||!s)return null;let a=o.yOf(i.price,this.paneId),l=o.yOf(s.price,this.paneId);return a==null||l==null?null:[o.xOf(i.time),a,o.xOf(s.time),l]}geometry(t){let n=this.seg(0,1,t),o=this.seg(2,3,t),i=[n,o].filter(a=>a!=null);if(i.length===0)return null;let s=n&&o?[[n[0],n[1]],[n[2],n[3]],[o[2],o[3]],[o[0],o[1]]]:null;return {segments:i,fill:s}}priceRange(){if(this.anchors.length===0)return null;let t=this.anchors.map(n=>n.price);return {min:Math.min(...t),max:Math.max(...t)}}schema(){return {fields:[...G,...fe,...$]}}};var Ta=class extends ve{constructor(){super(...arguments);this.type="flattopbottom";}anchorSchema(){return {min:3,max:3,slots:[{role:"p1",free:"both"},{role:"p2",free:"both"},{role:"flat",free:"y"}]}}handlePoints(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return [];let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);if(i==null||s==null)return [];let a=[[t.xOf(n.time),i],[t.xOf(o.time),s]],l=this.anchors[2];if(l){let c=t.yOf(l.price,this.paneId);c!=null&&a.push([t.xOf((n.time+o.time)/2),c]);}return a}timeExtent(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.time,n.time),max:Math.max(t.time,n.time)}}geometry(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.xOf(n.time),s=t.xOf(o.time),a=t.yOf(n.price,this.paneId),l=t.yOf(o.price,this.paneId);if(a==null||l==null)return null;let c=this.anchors[2];if(!c)return {segments:[[i,a,s,l]],fill:null};let d=t.yOf(c.price,this.paneId);return d==null?null:{segments:[[i,a,s,l],[i,d,s,d]],fill:[[i,a],[s,l],[s,d],[i,d]]}}priceRange(){let t=this.anchors[0],n=this.anchors[1];if(!t||!n)return null;let o=[t.price,n.price],i=this.anchors[2];return i&&o.push(i.price),{min:Math.min(...o),max:Math.max(...o)}}schema(){return {fields:[...G,...fe,...$]}}};var fC=2;function ef(){return {midColor:A,midStyle:"solid",upperColor:O,upperStyle:"solid",lowerColor:D,lowerStyle:"solid",upperFill:`${O}26`,lowerFill:`${D}26`,showR2:true}}function tf(r){let e=r.length;if(e<2)return null;let t=0,n=0,o=0,i=0,s=0;for(let m=0;mae(t,n,c[0],c[1],c[2],c[3])<=i)}handlePoints(t){let n=this.layout(t);if(n)return [[n.x0,n.midY0],[n.x1,n.midY1]];let o=[];for(let i of this.anchors){let s=t.yOf(i.price,this.paneId);if(s==null)return [];o.push([t.xOf(i.time),s]);}return o}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.band(t);if(!n)return null;let o=n.map(l=>l[0]),i=n.map(l=>l[1]),s=Math.min(...o),a=Math.min(...i);return {x:s,y:a,w:Math.max(...o)-s,h:Math.max(...i)-a}}priceRange(){if(this.cachedRange)return this.cachedRange;let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}schema(){return {fields:[{path:"reg.midColor",label:"Midline color",kind:"color",group:"line"},{path:"reg.midStyle",label:"Midline style",kind:"lineStyle",group:"line"},{path:"reg.upperColor",label:"Upper line color",kind:"color",group:"line"},{path:"reg.upperStyle",label:"Upper line style",kind:"lineStyle",group:"line"},{path:"reg.lowerColor",label:"Lower line color",kind:"color",group:"line"},{path:"reg.lowerStyle",label:"Lower line style",kind:"lineStyle",group:"line"},{path:"reg.upperFill",label:"Upper fill",kind:"color",group:"fill"},{path:"reg.lowerFill",label:"Lower fill",kind:"color",group:"fill"},{path:"reg.showR2",label:"Show R\xB2",kind:"boolean",group:"behavior"}]}}writeProps(){return {...this.reg}}readProps(t){this.reg={...ef(),...t};}};var nf=`${ce}00`;function rf(){return {midColor:ce,midStyle:"solid",multiplier:1,upperColor:nf,upperStyle:"solid",lowerColor:nf,lowerStyle:"solid",bandFill:`${ce}33`}}function of(r,e){let t=r.length;if(t<1)return null;let n=0;for(let c of r)n+=c.volume>0?c.volume:0;let o=n>0,i=0,s=0,a=0,l=[];for(let c=0;c0?s/i:u,m=i>0?Math.max(0,a/i-p*p):0,f=Math.sqrt(m)*e;l.push({time:d.time,mid:p,upper:p+f,lower:p-f});}return l}var br=class extends K{constructor(t){super(t);this.type="anchoredvwap";this.cachedRange=null;this.cachedExtent=null;this.vwap||(this.vwap=rf());}anchorSchema(){return {min:1,max:1,slots:[{role:"anchor",free:"x"}]}}series(t){let n=this.anchors[0];if(!n)return null;let o=t.barsInRange?.(n.time,Number.POSITIVE_INFINITY)??null;if(!o||o.length<1)return null;let i=of(o.map(s=>({time:s.time,high:s.high,low:s.low,close:s.close,volume:s.volume??0})),this.vwap.multiplier);if(i&&i.length>0){let s=1/0,a=-1/0;for(let l of i)l.lowera&&(a=l.upper);this.cachedRange={min:s,max:a},this.cachedExtent={min:i[0].time,max:i[i.length-1].time};}return i}layout(t){let n=this.series(t);if(!n)return null;let o=[],i=[],s=[];for(let a of n){let l=t.xOf(a.time),c=t.yOf(a.mid,this.paneId),d=t.yOf(a.upper,this.paneId),u=t.yOf(a.lower,this.paneId);c==null||d==null||u==null||(o.push([l,c]),i.push([l,d]),s.push([l,u]));}return o.length>0?{mid:o,upper:i,lower:s}:null}bandPolygon(t){return [...t.upper,...[...t.lower].reverse()]}hitTest(t,n,o,i){let s=this.layout(o);return s?Xt(t,n,this.bandPolygon(s))?true:eu(t,n,s.mid,i)||eu(t,n,s.upper,i)||eu(t,n,s.lower,i):false}handlePoints(t){let n=this.layout(t);if(n&&n.mid.length>0)return [n.mid[0]];let o=this.anchors[0];if(!o)return [];let i=t.yOf(o.price,this.paneId);return i==null?[]:[[t.xOf(o.time),i]]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.layout(t);if(!n)return null;let o=[...n.upper,...n.lower],i=o.map(c=>c[0]),s=o.map(c=>c[1]),a=Math.min(...i),l=Math.min(...s);return {x:a,y:l,w:Math.max(...i)-a,h:Math.max(...s)-l}}priceRange(){return this.cachedRange}timeExtent(){return this.cachedExtent}schema(){return {fields:[{path:"vwap.midColor",label:"VWAP color",kind:"color",group:"line"},{path:"vwap.midStyle",label:"VWAP style",kind:"lineStyle",group:"line"},{path:"vwap.multiplier",label:"Band multiplier",kind:"number",min:.5,max:5,step:.5,group:"behavior"},{path:"vwap.upperColor",label:"Upper band color",kind:"color",group:"line"},{path:"vwap.lowerColor",label:"Lower band color",kind:"color",group:"line"},{path:"vwap.bandFill",label:"Band fill",kind:"color",group:"fill"}]}}writeProps(){return {...this.vwap}}readProps(t){this.vwap={...rf(),...t};}};function eu(r,e,t,n){for(let o=1;o=e?e-1:r}function af(r,e,t){let n=r.length,o=0,i=0;for(let d=0;di&&(i=u);}let s=o*Math.min(1,Math.max(0,t)),a=e,l=e,c=i;for(;c0||l0?r[a-1].up+r[a-1].down:-1,u=ld?(l+=1,c+=u):(a-=1,c+=d);}return {vaFrom:a,vaTo:l}}function lf(r,e,t,n){let o=n.volume;if(!(o>0))return;let i=r.length,s=n.close>=n.open?"up":"down",a=new Set;for(let l of [n.open,n.high,n.low,n.close])a.add(wC(Math.floor((l-e)/t),i));for(let l of a)r[l][s]+=o;}function cf(r){let e=0,t=0;for(let n=0;ne&&(e=o,t=n);}return e>0?{poc:t,maxTotal:e}:null}function df(r,e,t){let n=1/0,o=-1/0;for(let p of r)p.volume>0&&(p.lowo&&(o=p.high));if(!Number.isFinite(n))return null;let i=o>n?Math.max(1,Math.round(e)):1,s=o>n?(o-n)/i:1,a=Array.from({length:i},(p,m)=>({price:n+m*s,up:0,down:0}));for(let p of r)lf(a,n,s,p);let l=cf(a);if(!l)return null;let{poc:c,maxTotal:d}=l,{vaFrom:u,vaTo:h}=af(a,c,t);return {rows:a,rowH:s,min:n,maxTotal:d,poc:c,vaFrom:u,vaTo:h}}function uf(r,e,t,n){let o=df(r,e,t);if(!o)return null;if(!n||r.length<1)return {profile:o,developingPoc:[],developingVaHigh:[],developingVaLow:[]};let{min:i,rowH:s}=o,a=o.rows.length,l=Array.from({length:a},(h,p)=>({price:i+p*s,up:0,down:0})),c=[],d=[],u=[];for(let h of r){lf(l,i,s,h);let p=cf(l);if(!p)continue;let{poc:m}=p,{vaFrom:f,vaTo:g}=af(l,m,t);c.push({time:h.time,price:l[m].price+s/2}),d.push({time:h.time,price:l[g].price+s}),u.push({time:h.time,price:l[f].price});}return {profile:o,developingPoc:c,developingVaHigh:d,developingVaLow:u}}var gt=class extends K{constructor(t){super(t);this.type="fixedrangevp";this.cachedRange=null;this.frvp||(this.frvp=sf());}anchorSchema(){return {min:2,max:2,slots:[{role:"start",free:"x"},{role:"end",free:"x"}]}}barsInSpan(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=Math.min(n.time,o.time),s=Math.max(n.time,o.time),a=t.barsInRange?.(i,s)??null;return !a||a.length<1?null:a.map(l=>({time:l.time,open:l.open,high:l.high,low:l.low,close:l.close,volume:l.volume??0}))}compute(t){let n=this.barsInSpan(t);if(!n)return null;let o=this.frvp,i=o.showDevelopingPoc||o.showDevelopingVa,s=uf(n,o.rows,o.valueAreaPct/100,i);if(s){let{profile:a}=s;this.cachedRange={min:a.min,max:a.min+a.rowH*a.rows.length};}return s}layout(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=this.compute(t);if(!i)return null;let{profile:s}=i,a=Math.min(n.time,o.time),l=Math.max(n.time,o.time),c=t.xOf(a),d=t.xOf(l),u=Math.abs(d-c),h=Math.max(1,Math.min(100,Math.max(0,this.frvp.widthPct))/100*u),p=this.frvp.anchor==="left",m=p?Math.min(c,d):Math.max(c,d),f=p?1:-1,g=[];for(let C=0;C<=s.rows.length;C+=1){let L=t.yOf(s.min+C*s.rowH,this.paneId);if(L==null)return null;g.push(L);}let b=C=>t.yOf(C,this.paneId),y=s.rows[s.vaTo].price+s.rowH,w=s.rows[s.vaFrom].price,S=s.rows[s.poc].price+s.rowH/2,M=C=>{let L=[];for(let v of C){let k=b(v.price);k!=null&&L.push([t.xOf(v.time),k]);}return L};return {x0:Math.min(c,d),x1:Math.max(c,d),anchorX:m,maxW:h,grow:f,profile:s,yEdges:g,vahY:b(y),valY:b(w),pocY:b(S),developingPoc:M(i.developingPoc),developingVaHigh:M(i.developingVaHigh),developingVaLow:M(i.developingVaLow)}}hitTest(t,n,o,i){let s=this.layout(o);if(!s)return false;let a=s.grow===1?s.anchorX:s.anchorX-s.maxW,l=s.grow===1?s.anchorX+s.maxW:s.anchorX,c=Math.min(s.yEdges[0],s.yEdges[s.yEdges.length-1]),d=Math.max(s.yEdges[0],s.yEdges[s.yEdges.length-1]);if(Xt(t,n,[[a,c],[l,c],[l,d],[a,d]]))return true;let u=[[s.x0,s.vahY],[s.x0,s.valY],[s.x0,s.pocY]];for(let[,h]of u)if(h!=null&&ae(t,n,s.x0,h,s.x1,h)<=i)return true;for(let h of [s.developingPoc,s.developingVaHigh,s.developingVaLow])for(let p=1;p{let b=t.yOf(g.price,this.paneId);return b==null?null:[t.xOf(g.time),b]},s=i(n),a=i(o);if(!s||!a)return null;let l=this.anchors[2];if(!l)return {segments:[[s[0],s[1],a[0],a[1]]],fill:null};let c=i(l);if(!c)return null;let d=(a[0]+c[0])/2,u=(a[1]+c[1])/2,h=d-s[0],p=u-s[1],m=t.width,f=t.height;return {segments:[Pe(s[0],s[1],d,u,"right",m,f),Pe(a[0],a[1],a[0]+h,a[1]+p,"right",m,f),Pe(c[0],c[1],c[0]+h,c[1]+p,"right",m,f),[a[0],a[1],c[0],c[1]]],fill:null}}priceRange(){if(this.anchors.length===0)return null;let t=this.anchors.map(n=>n.price);return {min:Math.min(...t),max:Math.max(...t)}}schema(){return {fields:[...G,...$]}}};var ao=class extends ve{anchorSchema(){return {min:3,max:3,slots:[{role:"pivot",free:"both"},{role:"upper",free:"both"},{role:"lower",free:"both"}]}}geometry(e){let t=this.anchors[0],n=this.anchors[1];if(!t||!n)return null;let o=g=>{let b=e.yOf(g.price,this.paneId);return b==null?null:[e.xOf(g.time),b]},i=o(t),s=o(n);if(!i||!s)return null;let a=this.anchors[2];if(!a)return {segments:[[i[0],i[1],s[0],s[1]]],fill:null};let l=o(this.medianStart(t,n,a)),c=o(a);if(!l||!c)return null;let d=(s[0]+c[0])/2,u=(s[1]+c[1])/2,h=d-l[0],p=u-l[1],m=e.width,f=e.height;return {segments:[Pe(l[0],l[1],d,u,"right",m,f),Pe(s[0],s[1],s[0]+h,s[1]+p,"right",m,f),Pe(c[0],c[1],c[0]+h,c[1]+p,"right",m,f),[s[0],s[1],c[0],c[1]],[i[0],i[1],s[0],s[1]]],fill:null}}priceRange(){if(this.anchors.length===0)return null;let e=this.anchors.map(t=>t.price);return {min:Math.min(...e),max:Math.max(...e)}}schema(){return {fields:[...G,...$]}}};var La=class extends ao{constructor(){super(...arguments);this.type="schiffpitchfork";}medianStart(t,n){return {time:t.time,price:(t.price+n.price)/2}}};var Ma=class extends ao{constructor(){super(...arguments);this.type="modifiedschiffpitchfork";}medianStart(t,n){return {time:(t.time+n.time)/2,price:(t.price+n.price)/2}}};var Ea=class extends ve{constructor(){super(...arguments);this.type="insidepitchfork";}anchorSchema(){return {min:3,max:3,slots:[{role:"pivot",free:"both"},{role:"upper",free:"both"},{role:"lower",free:"both"}]}}geometry(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=b=>{let y=t.yOf(b.price,this.paneId);return y==null?null:[t.xOf(b.time),y]},s=i(n),a=i(o);if(!s||!a)return null;let l=this.anchors[2];if(!l)return {segments:[[s[0],s[1],a[0],a[1]]],fill:null};let c=i({time:(n.time+o.time)/2,price:(n.price+o.price)/2}),d=i(l);if(!c||!d)return null;let u=(a[0]+d[0])/2,h=(a[1]+d[1])/2,p=d[0]-c[0],m=d[1]-c[1],f=t.width,g=t.height;return {segments:[Pe(u,h,u+p,h+m,"right",f,g),Pe(a[0],a[1],a[0]+p,a[1]+m,"right",f,g),Pe(d[0],d[1],d[0]+p,d[1]+m,"right",f,g),[a[0],a[1],d[0],d[1]],[c[0],c[1],d[0],d[1]],[s[0],s[1],a[0],a[1]]],fill:null}}priceRange(){if(this.anchors.length===0)return null;let t=this.anchors.map(n=>n.price);return {min:Math.min(...t),max:Math.max(...t)}}schema(){return {fields:[...G,...$]}}};var Pa=class extends K{constructor(){super(...arguments);this.type="arrow";}anchorSchema(){return {min:2,max:2,slots:[{role:"p1",free:"both"},{role:"p2",free:"both"}]}}pixels(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);return i==null||s==null?null:[t.xOf(n.time),i,t.xOf(o.time),s]}hitTest(t,n,o,i){let s=this.pixels(o);return s!=null&&ae(t,n,s[0],s[1],s[2],s[3])<=i}handlePoints(t){let n=this.pixels(t);return n?[[n[0],n[1]],[n[2],n[3]]]:[]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.pixels(t);return n?{x:Math.min(n[0],n[2]),y:Math.min(n[1],n[3]),w:Math.abs(n[2]-n[0]),h:Math.abs(n[3]-n[1])}:null}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}schema(){return {fields:[...G,{path:"style.arrowRight",label:"Head (end)",kind:"boolean",group:"line"},{path:"style.arrowLeft",label:"Head (start)",kind:"boolean",group:"line"},...$]}}};var hf=48,Ia=class extends K{constructor(){super(...arguments);this.type="ellipse";}anchorSchema(){return {min:2,max:2,slots:[{role:"c1",free:"both"},{role:"c2",free:"both"}]}}oval(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);if(i==null||s==null)return null;let a=t.xOf(n.time),l=t.xOf(o.time);return {cx:(a+l)/2,cy:(i+s)/2,rx:Math.abs(l-a)/2,ry:Math.abs(s-i)/2}}perimeter(t){let n=[];for(let o=0;o<=hf;o+=1){let i=o/hf*Math.PI*2;n.push([t.cx+t.rx*Math.cos(i),t.cy+t.ry*Math.sin(i)]);}return n}hitTest(t,n,o,i){let s=this.oval(o);if(!s||s.rx<1||s.ry<1)return false;let a=((t-s.cx)/s.rx)**2+((n-s.cy)/s.ry)**2;return this.style.fillColor&&a<=1?true:so(t,n,this.perimeter(s))<=i}handlePoints(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return [];let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);return i==null||s==null?[]:[[t.xOf(n.time),i],[t.xOf(o.time),s]]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.oval(t);return n?{x:n.cx-n.rx,y:n.cy-n.ry,w:n.rx*2,h:n.ry*2}:null}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}schema(){return {fields:[...G,...fe,...$]}}};var Aa=class extends ve{constructor(){super(...arguments);this.type="triangle";}anchorSchema(){return {min:3,max:3,slots:[{role:"v1",free:"both"},{role:"v2",free:"both"},{role:"v3",free:"both"}]}}geometry(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=d=>{let u=t.yOf(d.price,this.paneId);return u==null?null:[t.xOf(d.time),u]},s=i(n),a=i(o);if(!s||!a)return null;let l=this.anchors[2];if(!l)return {segments:[[s[0],s[1],a[0],a[1]]],fill:null};let c=i(l);return c?{segments:[[s[0],s[1],a[0],a[1]],[a[0],a[1],c[0],c[1]],[c[0],c[1],s[0],s[1]]],fill:[s,a,c]}:null}priceRange(){if(this.anchors.length===0)return null;let t=this.anchors.map(n=>n.price);return {min:Math.min(...t),max:Math.max(...t)}}schema(){return {fields:[...G,...fe,...$]}}};var xC=512,Hn=class extends ve{anchorSchema(){return {min:2,max:xC,slots:[]}}geometry(e){let t=[];for(let o of this.anchors){let i=e.yOf(o.price,this.paneId);if(i==null)return null;t.push([e.xOf(o.time),i]);}if(t.length<2)return null;let n=[];for(let o=1;ot.price);return {min:Math.min(...e),max:Math.max(...e)}}schema(){return {fields:[...G,...$]}}};var Ra=class extends Hn{constructor(){super(...arguments);this.type="polyline";}};var gi=class extends Hn{placementMode(){return "freehand"}handlePoints(e){return []}bounds(e){let t=[],n=[];for(let s of this.anchors){let a=e.yOf(s.price,this.paneId);a!=null&&(t.push(e.xOf(s.time)),n.push(a));}if(t.length===0)return null;let o=Math.min(...t),i=Math.min(...n);return {x:o,y:i,w:Math.max(...t)-o,h:Math.max(...n)-i}}},Da=class extends gi{constructor(){super(...arguments);this.type="freehand";}};var SC=[{path:"style.lineColor",label:"Color",kind:"color",group:"line"},{path:"style.lineWidth",label:"Width",kind:"number",min:4,max:60,step:1,group:"line"}],Oa=class extends gi{constructor(){super(...arguments);this.type="highlighter";}schema(){return {fields:SC}}};var Na=class extends K{constructor(){super(...arguments);this.type="circle";}anchorSchema(){return {min:2,max:2,slots:[{role:"center",free:"both"},{role:"edge",free:"both"}]}}geom(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);if(i==null||s==null)return null;let a=t.xOf(n.time),l=t.xOf(o.time);return {cx:a,cy:i,r:Math.hypot(l-a,s-i)}}hitTest(t,n,o,i){let s=this.geom(o);if(!s||s.r<1)return false;let a=Math.hypot(t-s.cx,n-s.cy);return this.style.fillColor&&a<=s.r?true:Math.abs(a-s.r)<=i}handlePoints(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return [];let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);return i==null||s==null?[]:[[t.xOf(n.time),i],[t.xOf(o.time),s]]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.geom(t);return n?{x:n.cx-n.r,y:n.cy-n.r,w:n.r*2,h:n.r*2}:null}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}schema(){return {fields:[...G,...fe,...$]}}};var Fa=class extends ve{constructor(){super(...arguments);this.type="rotatedrect";}anchorSchema(){return {min:3,max:3,slots:[{role:"p1",free:"both"},{role:"p2",free:"both"},{role:"w",free:"both"}]}}px(t,n){let o=this.anchors[n];if(!o)return null;let i=t.yOf(o.price,this.paneId);return i==null?null:[t.xOf(o.time),i]}geometry(t){let n=this.px(t,0),o=this.px(t,1);if(!n||!o)return null;let i=this.px(t,2);if(!i||this.anchors.length<3)return {segments:[[n[0],n[1],o[0],o[1]]],fill:null};let s=o[0]-n[0],a=o[1]-n[1],l=Math.hypot(s,a);if(l<1e-6)return {segments:[[n[0],n[1],o[0],o[1]]],fill:null};let c=-a/l,d=s/l,u=(i[0]-n[0])*c+(i[1]-n[1])*d,h=c*u,p=d*u,m=n,f=o,g=[o[0]+h,o[1]+p],b=[n[0]+h,n[1]+p];return {segments:[[m[0],m[1],f[0],f[1]],[f[0],f[1],g[0],g[1]],[g[0],g[1],b[0],b[1]],[b[0],b[1],m[0],m[1]]],fill:[m,f,g,b]}}priceRange(){if(this.anchors.length===0)return null;let t=this.anchors.map(n=>n.price);return {min:Math.min(...t),max:Math.max(...t)}}schema(){return {fields:[...G.map(t=>({...t,label:t.label.replace("Line","Border")})),...fe,...$]}}};var Va=class extends Hn{constructor(){super(...arguments);this.type="path";}};var pf=40,Ba=class extends ve{constructor(){super(...arguments);this.type="arc";}anchorSchema(){return {min:3,max:3,slots:[{role:"p1",free:"both"},{role:"p2",free:"both"},{role:"apex",free:"both"}]}}pinApex(){let t=this.anchors[0],n=this.anchors[1],o=this.anchors[2];t&&n&&o&&(o.time=(t.time+n.time)/2);}onPlaced(){this.pinApex();}constrainHandleDrag(){this.pinApex();}px(t,n){let o=this.anchors[n];if(!o)return null;let i=t.yOf(o.price,this.paneId);return i==null?null:[t.xOf(o.time),i]}geometry(t){let n=this.px(t,0),o=this.px(t,1);if(!n||!o)return null;let i=this.anchors[2];if(!i||this.anchors.length<3)return {segments:[[n[0],n[1],o[0],o[1]]],fill:null};let s=t.yOf(i.price,this.paneId);if(s==null)return null;let a=(n[0]+o[0])/2,l=(n[1]+o[1])/2,c=(o[0]-n[0])/2,d=(o[1]-n[1])/2,u=Math.hypot(c,d);if(u<1e-6)return {segments:[[n[0],n[1],o[0],o[1]]],fill:null};let h=-d/u,p=c/u,m=(s-l)*p;m<0&&(h=-h,p=-p);let f=Math.abs(m),g=[];for(let y=0;y<=pf;y+=1){let w=y/pf*Math.PI,S=Math.cos(w),M=Math.sin(w);g.push([a+S*c+M*f*h,l+S*d+M*f*p]);}let b=[];for(let y=1;yn.price);return {min:Math.min(...t),max:Math.max(...t)}}schema(){return {fields:[...G.map(t=>({...t,label:t.label.replace("Line","Border")})),...fe,...$]}}};var mf=40,_a=class extends ve{constructor(){super(...arguments);this.type="curve";}anchorSchema(){return {min:3,max:3,slots:[{role:"p1",free:"both"},{role:"p2",free:"both"},{role:"control",free:"both"}]}}px(t,n){let o=this.anchors[n];if(!o)return null;let i=t.yOf(o.price,this.paneId);return i==null?null:[t.xOf(o.time),i]}geometry(t){let n=this.px(t,0),o=this.px(t,1);if(!n||!o)return null;let i=this.px(t,2);if(!i||this.anchors.length<3)return {segments:[[n[0],n[1],o[0],o[1]]],fill:null};let s=[];for(let l=0;l<=mf;l+=1){let c=l/mf,d=1-c;s.push([d*d*n[0]+2*d*c*i[0]+c*c*o[0],d*d*n[1]+2*d*c*i[1]+c*c*o[1]]);}let a=[];for(let l=1;ln.price);return {min:Math.min(...t),max:Math.max(...t)}}schema(){return {fields:[...G,...fe,...$]}}};var CC={head:11,headW:9,stemW:3.5,len:22},vr=class extends K{anchorSchema(){return {min:1,max:1,slots:[{role:"p",free:"both"}]}}glyphPoints(e){let t=this.anchors[0];if(!t)return null;let n=e.yOf(t.price,this.paneId);if(n==null)return null;let o=e.xOf(t.time),{head:i,headW:s,stemW:a,len:l}=CC,c=[[0,0],[-s,i],[-a,i],[-a,l],[a,l],[a,i],[s,i]],d=this.dir(),u=([h,p])=>{switch(d){case "up":return [h,p];case "down":return [h,-p];case "left":return [p,h];default:return [-p,h]}};return c.map(h=>{let[p,m]=u(h);return [o+p,n+m]})}hitTest(e,t,n,o){let i=this.glyphPoints(n);return i!=null&&Xt(e,t,i)}handlePoints(e){let t=this.anchors[0];if(!t)return [];let n=e.yOf(t.price,this.paneId);return n==null?[]:[[e.xOf(t.time),n]]}hitHandle(e,t,n,o){return j(e,t,this.handlePoints(n),o+3)}bounds(e){let t=this.glyphPoints(e);if(!t)return null;let n=t.map(a=>a[0]),o=t.map(a=>a[1]),i=Math.min(...n),s=Math.min(...o);return {x:i,y:s,w:Math.max(...n)-i,h:Math.max(...o)-s}}priceRange(){let e=this.anchors[0];return e?{min:e.price,max:e.price}:null}schema(){return {fields:[{path:"style.lineColor",label:"Color",kind:"color",group:"line"},...$]}}},bi=class extends vr{constructor(){super(...arguments);this.type="arrowmarkup";}dir(){return "up"}},vi=class extends vr{constructor(){super(...arguments);this.type="arrowmarkdown";}dir(){return "down"}};var xi=["\u2605","\u2606","\u25CF","\u25C6","\u25B2","\u25BC","\u27A4","\u2691","\u271A","\u2715","\u2764","\u2666"],Ha=["small","normal","large","huge"],ff={small:16,normal:22,large:32,huge:44},yr=class extends K{constructor(e){super(e),this.glyph||(this.glyph=this.defaultGlyph()),this.size||(this.size="normal");}sizePx(){return ff[this.size]??ff.normal}anchorSchema(){return {min:1,max:1,slots:[{role:"p",free:"both"}]}}center(e){let t=this.anchors[0];if(!t)return null;let n=e.yOf(t.price,this.paneId);return n==null?null:[e.xOf(t.time),n]}hitTest(e,t,n,o){let i=this.center(n);if(!i)return false;let s=this.sizePx()/2+o;return Math.abs(e-i[0])<=s&&Math.abs(t-i[1])<=s}handlePoints(e){let t=this.center(e);return t?[t]:[]}hitHandle(e,t,n,o){return j(e,t,this.handlePoints(n),o+3)}bounds(e){let t=this.center(e);if(!t)return null;let n=this.sizePx();return {x:t[0]-n/2,y:t[1]-n/2,w:n,h:n}}priceRange(){let e=this.anchors[0];return e?{min:e.price,max:e.price}:null}schema(){return {fields:[{path:"glyph",label:"Icon",kind:"select",options:xi.map(e=>({value:e,label:e})),group:"line"},{path:"size",label:"Size",kind:"select",options:Ha.map(e=>({value:e,label:e})),group:"line"},{path:"style.lineColor",label:"Color",kind:"color",group:"line"},...$]}}writeProps(){return {glyph:this.glyph,size:this.size}}readProps(e){typeof e.glyph=="string"&&(this.glyph=e.glyph),typeof e.size=="string"&&(this.size=e.size);}},yi=class extends yr{constructor(){super(...arguments);this.type="flagmark";}defaultGlyph(){return "\u2691"}},wi=class extends yr{constructor(){super(...arguments);this.type="iconstamp";}defaultGlyph(){return "\u2605"}};var gf=r=>r==="small"||r==="normal"||r==="large"||r==="huge";function TC(r){if(!r||typeof r!="object")return null;let e=r;return typeof e.ratio!="number"||typeof e.color!="string"?null:{ratio:e.ratio,color:e.color,enabled:e.enabled!==false,...typeof e.label=="string"&&e.label?{label:e.label}:{}}}var Se=class extends K{constructor(e){super(e),this.levels||(this.levels=this.defaultLevels().map(t=>({...t}))),this.numbersSize||(this.numbersSize="small"),this.labelsSize||(this.labelsSize="normal");}fillBands(e){return []}editableLevels(){return this.levels}anchorSchema(){return {min:2,max:2,slots:[{role:"p1",free:"both"},{role:"p2",free:"both"}]}}hitTest(e,t,n,o){let i=this.entryLines(n);return i!=null&&i.some(s=>ae(e,t,s.x1,s.y1,s.x2,s.y2)<=o)}handlePoints(e){let t=[];for(let n of this.anchors){let o=e.yOf(n.price,this.paneId);if(o==null)return [];t.push([e.xOf(n.time),o]);}return t}hitHandle(e,t,n,o){return j(e,t,this.handlePoints(n),o+3)}bounds(e){let t=this.handlePoints(e);if(t.length===0)return null;let n=t.map(a=>a[0]),o=t.map(a=>a[1]),i=Math.min(...n),s=Math.min(...o);return {x:i,y:s,w:Math.max(...n)-i,h:Math.max(...o)-s}}schema(){return {fields:G.filter(e=>e.path!=="style.lineColor")}}writeProps(){return {levels:this.levels.map(e=>({...e})),numbersSize:this.numbersSize,labelsSize:this.labelsSize}}readProps(e){if(Array.isArray(e.levels)){let t=e.levels.map(TC).filter(n=>n!=null);t.length&&(this.levels=t);}gf(e.numbersSize)&&(this.numbersSize=e.numbersSize),gf(e.labelsSize)&&(this.labelsSize=e.labelsSize);}};var lo=class extends Se{levelPrice(e,t,n){return t+e*(n-t)}levelLines(e){let t=this.anchors[0],n=this.anchors[1];if(!t||!n)return null;let o=e.xOf(t.time),i=e.xOf(n.time),s=Math.min(o,i),a=Math.max(o,i),l=[];for(let c of this.levels){if(!c.enabled)continue;let d=this.levelPrice(c.ratio,t.price,n.price),u=e.yOf(d,this.paneId);u!=null&&l.push({ratio:c.ratio,color:c.color,label:c.label,price:d,x1:s,x2:a,y:u});}return l}entryLines(e){let t=this.levelLines(e);return t?t.map(n=>({color:n.color,label:n.label,x1:n.x1,y1:n.y,x2:n.x2,y2:n.y,numberText:`${n.ratio} (${n.price.toFixed(2)})`,numberX:n.x1+4,numberY:n.y-7,numberAlign:"left",labelX:(n.x1+n.x2)/2,labelY:n.y-7})):null}fillBands(e){let t=this.levelLines(e);if(!t)return [];let n=[];for(let o=1;oo.enabled).map(o=>this.levelPrice(o.ratio,e.price,t.price));return n.length===0?null:{min:Math.min(...n),max:Math.max(...n)}}};var wr=A,qt=D,Zt=Y,xr="#4caf50",zn=O,wn=ce,Sr="#9c27b0",kC="#e91e63",tu="#26a69a",LC="#ab47bc",MC="#ef5350",bf="#ffb74d",EC="#38c0fd",za="#b2b5be",co=[EC,wn,zn,xr,Zt,qt,kC,Sr,wr,tu,LC,MC];function vf(r){return co[(r%co.length+co.length)%co.length]}var PC=[[0,wr],[.125,qt],[.236,qt],[.25,qt],[.382,Zt],[.5,xr],[.618,zn],[.75,wn],[.786,wn],[1,wr],[1.272,wn],[1.382,Zt],[1.618,qt],[2,wr],[2.382,Zt],[2.618,Zt],[3,wr],[4.236,xr],[6.854,zn],[11.09,wn]];function IC(r,e=0){return PC.find(([t])=>t===r)?.[1]??vf(e)}function ye(r){return r.map((e,t)=>{let n=typeof e=="number"?{ratio:e}:e;return {ratio:n.ratio,color:n.color??IC(n.ratio,t),enabled:n.enabled!==false,...n.label?{label:n.label}:{}}})}function yf(r,e=r){return Array.from({length:r},(t,n)=>({ratio:n+1,color:vf(n),enabled:na.enabled).map(a=>o.price+a.ratio*i);return s.push(t.price,n.price,o.price),{min:Math.min(...s),max:Math.max(...s)}}};var OC=ye([.236,.382,.5,.618,.786,1]),$a=class extends Se{constructor(){super(...arguments);this.type="fibfan";}defaultLevels(){return OC}fanLines(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.xOf(n.time),s=t.yOf(n.price,this.paneId);if(s==null)return null;let a=t.xOf(o.time),l=o.price-n.price,c=[];for(let d of this.levels){if(!d.enabled)continue;let u=t.yOf(n.price+d.ratio*l,this.paneId);if(u==null)continue;let[h,p,m,f]=Pe(i,s,a,u,"right",t.width,t.height);c.push({ratio:d.ratio,color:d.color,label:d.label,x1:h,y1:p,x2:m,y2:f,labelX:a+5,labelY:u});}return c}entryLines(t){let n=this.fanLines(t);return n?n.map(o=>({color:o.color,label:o.label,x1:o.x1,y1:o.y1,x2:o.x2,y2:o.y2,numberText:String(o.ratio),numberX:o.labelX,numberY:o.labelY,numberAlign:"left",labelX:o.labelX,labelY:o.labelY+13})):null}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}};var NC=[0,1,2,3,5,8,13,21,34].map(r=>({ratio:r,color:_,enabled:true})),Ua=class extends Se{constructor(){super(...arguments);this.type="fibtimezones";}defaultLevels(){return NC}zoneLines(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=o.time-n.time;if(Math.abs(i)<1e-9)return null;let s=[];for(let a of this.levels)a.enabled&&s.push({n:a.ratio,color:a.color,label:a.label,x:t.xOf(n.time+a.ratio*i)});return s}entryLines(t){let n=this.zoneLines(t);if(!n)return null;let o=t.height;return n.map(i=>({color:i.color,label:i.label,x1:i.x,y1:0,x2:i.x,y2:o,numberText:String(i.n),numberX:i.x,numberY:9,numberAlign:"center",labelX:i.x,labelY:24}))}priceRange(){return null}timeExtent(){return null}};var FC=ye([0,.236,.382,.5,.618,.786,1,1.618,2.618]),Ya=class extends Se{constructor(){super(...arguments);this.type="fibchannel";}defaultLevels(){return FC}anchorSchema(){return {min:3,max:3,slots:[{role:"p1",free:"both"},{role:"p2",free:"both"},{role:"offset",free:"both"}]}}entryLines(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);if(i==null||s==null)return null;let a=t.xOf(n.time),l=t.xOf(o.time),c=0,d=0,u=this.anchors[2];if(u){let p=t.yOf(u.price,this.paneId);if(p==null)return null;c=t.xOf(u.time)-a,d=p-i;}let h=[];for(let p of this.levels){if(!p.enabled)continue;let m=p.ratio*c,f=p.ratio*d,g=l+m,b=s+f;h.push({color:p.color,label:p.label,x1:a+m,y1:i+f,x2:g,y2:b,numberText:String(p.ratio),numberX:g+5,numberY:b,numberAlign:"left",labelX:g+5,labelY:b+13});}return h}priceRange(){let t=this.anchors[0],n=this.anchors[1],o=this.anchors[2];if(!t||!n)return null;let i=o?o.price-t.price:0,s=1/0,a=-1/0;for(let l of this.levels)if(l.enabled)for(let c of [t.price,n.price]){let d=c+l.ratio*i;da&&(a=d);}return s<=a?{min:s,max:a}:null}};var VC=ye([0,.236,.382,.5,.618,.786,1]),Ka=class extends Se{constructor(){super(...arguments);this.type="fibspeedfan";}defaultLevels(){return VC}entryLines(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);if(i==null||s==null)return null;let a=t.xOf(n.time),c=t.xOf(o.time)-a,d=s-i,u=c>=0?"right":"left",h=t.width,p=t.height,m=[];for(let f of this.levels){if(!f.enabled)continue;let g=a+c,b=i+d*f.ratio,y=Pe(a,i,g,b,u,h,p);if(m.push({color:f.color,label:f.label,x1:y[0],y1:y[1],x2:y[2],y2:y[3],numberText:String(f.ratio),numberX:u==="right"?g+5:g-5,numberY:b,numberAlign:u==="right"?"left":"right",labelX:g,labelY:b}),f.ratio===1)continue;let w=a+c*f.ratio,S=i+d,M=Pe(a,i,w,S,u,h,p);m.push({color:f.color,label:f.label,x1:M[0],y1:M[1],x2:M[2],y2:M[3],numberText:String(f.ratio),numberX:w,numberY:S+(d>=0?12:-12),numberAlign:"center",labelX:w,labelY:S+12});}return m}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}};var BC=ye([0,.382,{ratio:.5,enabled:false},.618,1,1.382,1.618,2,2.382,2.618,3]),Xa=class extends Se{constructor(){super(...arguments);this.type="trendfibtime";}defaultLevels(){return BC}anchorSchema(){return {min:3,max:3,slots:[{role:"p1",free:"both"},{role:"p2",free:"both"},{role:"p3",free:"both"}]}}entryLines(t){let n=this.anchors[0],o=this.anchors[1],i=this.anchors[2];if(!n||!o||!i)return null;let s=o.time-n.time;if(Math.abs(s)<1e-9)return null;let a=t.height,l=[];for(let c of this.levels){if(!c.enabled)continue;let d=t.xOf(i.time+c.ratio*s);l.push({color:c.color,label:c.label,x1:d,y1:0,x2:d,y2:a,numberText:String(c.ratio),numberX:d,numberY:9,numberAlign:"center",labelX:d,labelY:24});}return l}priceRange(){return null}timeExtent(){return null}};function _C(r,e,t){if(t-e>=Math.PI*2-.001)return true;let n=r-e,o=Math.PI*2;for(;n<0;)n+=o;for(;n>=o;)n-=o;return n<=t-e+1e-6}var Ot=class extends Se{boundingLines(e){return []}entryLines(e){return []}hitTest(e,t,n,o){let i=this.radial(n);if(i){let s=Math.hypot(e-i.cx,t-i.cy),a=Math.atan2(t-i.cy,e-i.cx);if(_C(a,i.a0,i.a1)){for(let l of this.levels)if(l.enabled&&Math.abs(s-i.R0*l.ratio)<=o)return true}}return this.boundingLines(n).some(s=>ae(e,t,s[0],s[1],s[2],s[3])<=o)}priceRange(){if(this.anchors.length===0)return null;let e=this.anchors.map(t=>t.price);return {min:Math.min(...e),max:Math.max(...e)}}};var HC=ye([.236,.382,.5,.618,.786,1,1.618,2.618]),ja=class extends Ot{constructor(){super(...arguments);this.type="fibcircles";}defaultLevels(){return HC}radial(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);if(i==null||s==null)return null;let a=t.xOf(n.time),l=t.xOf(o.time);return {cx:a,cy:i,R0:Math.hypot(l-a,s-i),a0:0,a1:Math.PI*2}}};var zC=ye([.236,.382,.5,.618,.786,1,1.618,2.618]),qa=class extends Ot{constructor(){super(...arguments);this.type="fibarcs";}defaultLevels(){return zC}pts(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);return i==null||s==null?null:{cx:t.xOf(n.time),cy:i,ex:t.xOf(o.time),ey:s}}radial(t){let n=this.pts(t);if(!n)return null;let o=Math.hypot(n.ex-n.cx,n.ey-n.cy),i=Math.atan2(n.ey-n.cy,n.ex-n.cx);return {cx:n.cx,cy:n.cy,R0:o,a0:i-Math.PI/2,a1:i+Math.PI/2}}boundingLines(t){let n=this.pts(t);return n?[[n.cx,n.cy,n.ex,n.ey]]:[]}};var WC=ye([.236,.382,.5,.618,.786,1]),Za=class extends Ot{constructor(){super(...arguments);this.type="fibwedge";}defaultLevels(){return WC}anchorSchema(){return {min:3,max:3,slots:[{role:"apex",free:"both"},{role:"radius",free:"both"},{role:"angle",free:"both"}]}}px(t,n){let o=this.anchors[n];if(!o)return null;let i=t.yOf(o.price,this.paneId);return i==null?null:[t.xOf(o.time),i]}radial(t){let n=this.px(t,0),o=this.px(t,1),i=this.px(t,2);if(!n||!o||!i)return null;let s=Math.hypot(o[0]-n[0],o[1]-n[1]);if(s<1)return null;let a=Math.atan2(o[1]-n[1],o[0]-n[0]),l=Math.atan2(i[1]-n[1],i[0]-n[0]),c=Math.min(a,l),d=Math.max(a,l);return d-c>Math.PI&&([c,d]=[d,c+Math.PI*2]),{cx:n[0],cy:n[1],R0:s,a0:c,a1:d}}boundingLines(t){let n=this.px(t,0),o=this.px(t,1);if(!n||!o)return [];let i=[[n[0],n[1],o[0],o[1]]],s=this.px(t,2);if(s){let a=Math.hypot(o[0]-n[0],o[1]-n[1]),l=Math.hypot(s[0]-n[0],s[1]-n[1]);l>1e-6&&i.push([n[0],n[1],n[0]+(s[0]-n[0])/l*a,n[1]+(s[1]-n[1])/l*a]);}return i}};var GC=1.6180339887,wf=Math.log(GC)/(Math.PI/2),$C=Math.PI/64,UC=Math.PI,YC=.5,Tr=class extends K{constructor(){super(...arguments);this.type="fibspiral";}anchorSchema(){return {min:2,max:2,slots:[{role:"center",free:"both"},{role:"edge",free:"both"}]}}spiralPoints(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);if(i==null||s==null)return null;let a=t.xOf(n.time),l=t.xOf(o.time),c=Math.hypot(l-a,s-i);if(c<1)return null;let d=Math.atan2(s-i,l-a),u=Math.max(Math.log(YC/c)/wf,-8*Math.PI*2),h=[];for(let p=u;p<=UC;p+=$C){let m=c*Math.exp(wf*p),f=d+p;h.push([a+m*Math.cos(f),i+m*Math.sin(f)]);}return h}hitTest(t,n,o,i){let s=this.spiralPoints(o);return s!=null&&s.length>=2&&so(t,n,s)<=i}handlePoints(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return [];let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);return i==null||s==null?[]:[[t.xOf(n.time),i],[t.xOf(o.time),s]]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.handlePoints(t);if(n.length<2)return null;let o=n.map(l=>l[0]),i=n.map(l=>l[1]),s=Math.min(...o),a=Math.min(...i);return {x:s,y:a,w:Math.max(...o)-s,h:Math.max(...i)-a}}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}schema(){return {fields:[...G,...$]}}};var KC=ye([{ratio:.125,color:qt,label:"1/8"},{ratio:.25,color:Zt,label:"1/4"},{ratio:.333,color:bf,label:"1/3"},{ratio:.5,color:xr,label:"1/2"},{ratio:1,color:za,label:"1/1"},{ratio:2,color:zn,label:"2/1"},{ratio:3,color:wn,label:"3/1"},{ratio:4,color:tu,label:"4/1"},{ratio:8,color:Sr,label:"8/1"}]),Qa=class extends Se{constructor(){super(...arguments);this.type="gannfan";}defaultLevels(){return KC}entryLines(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.xOf(n.time),s=t.yOf(n.price,this.paneId);if(s==null)return null;let a=t.xOf(o.time),l=o.price-n.price,c=[];for(let d of this.levels){if(!d.enabled)continue;let u=t.yOf(n.price+l*d.ratio,this.paneId);if(u==null)continue;let[h,p,m,f]=Pe(i,s,a,u,"right",t.width,t.height);c.push({color:d.color,x1:h,y1:p,x2:m,y2:f,numberText:d.label??String(d.ratio),numberX:a+5,numberY:u,numberAlign:"left",labelX:a+5,labelY:u});}return c}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}};var XC=ye([0,.25,.382,.5,.618,.75,1].map(r=>({ratio:r,label:String(r)}))),Ja=class extends Se{constructor(){super(...arguments);this.type="gannbox";}defaultLevels(){return XC}corners(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.xOf(n.time),s=t.xOf(o.time),a=t.yOf(n.price,this.paneId),l=t.yOf(o.price,this.paneId);return a==null||l==null?null:{c1:n,c2:o,left:Math.min(i,s),right:Math.max(i,s),top:Math.min(a,l),bot:Math.max(a,l)}}entryLines(t){let n=this.corners(t);if(!n)return null;let{c1:o,c2:i,left:s,right:a,top:l,bot:c}=n,d=[];for(let h of this.levels){if(!h.enabled)continue;let p=t.yOf(o.price+h.ratio*(i.price-o.price),this.paneId);p!=null&&d.push({color:h.color,x1:s,y1:p,x2:a,y2:p,numberText:h.label??String(h.ratio),numberX:s-5,numberY:p,numberAlign:"right",labelX:s,labelY:p});let m=t.xOf(o.time+h.ratio*(i.time-o.time));d.push({color:h.color,x1:m,y1:l,x2:m,y2:c,numberText:"",numberX:m,numberY:l,numberAlign:"center",labelX:m,labelY:l});}let u=this.levels.find(h=>h.ratio===1)?.color??wr;return d.push({color:u,x1:s,y1:l,x2:a,y2:c,numberText:"",numberX:0,numberY:0,numberAlign:"left",labelX:0,labelY:0}),d.push({color:u,x1:s,y1:c,x2:a,y2:l,numberText:"",numberX:0,numberY:0,numberAlign:"left",labelX:0,labelY:0}),d}hitTest(t,n,o,i){let s=this.corners(o);return s!=null&&Ue(t,n,s.left,s.top,s.right,s.bot,i)}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}};var jC=ye([0,.25,.382,.5,.618,.75,1].map(r=>({ratio:r,label:String(r)}))),qC=[{label:"3x1",x:3,y:1,color:qt},{label:"2x1",x:2,y:1,color:Zt},{label:"1x1",x:1,y:1,color:za},{label:"1x2",x:1,y:2,color:zn},{label:"1x3",x:1,y:3,color:wn}],nu=[{k:.25,color:qt},{k:.5,color:Zt},{k:.75,color:xr},{k:1,color:zn}],kr=class extends Se{constructor(){super(...arguments);this.type="gannsquare";}defaultLevels(){return jC}box(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);if(i==null||s==null)return null;let a=t.xOf(n.time),l=t.xOf(o.time);return {ox:a,oy:i,bx:l-a,py:s-i,left:Math.min(a,l),top:Math.min(i,s),right:Math.max(a,l),bot:Math.max(i,s)}}arcGeom(t){let n=this.box(t);return n?{ox:n.ox,oy:n.oy,bx:n.bx,py:n.py}:null}entryLines(t){let n=this.box(t);if(!n)return null;let o=this.anchors[0],i=this.anchors[1],s=[];for(let a of this.levels){if(!a.enabled)continue;let l=t.yOf(o.price+a.ratio*(i.price-o.price),this.paneId);l!=null&&s.push({color:a.color,x1:n.left,y1:l,x2:n.right,y2:l,numberText:a.label??String(a.ratio),numberX:n.left-5,numberY:l,numberAlign:"right",labelX:n.left,labelY:l});let c=t.xOf(o.time+a.ratio*(i.time-o.time));s.push({color:a.color,x1:c,y1:n.top,x2:c,y2:n.bot,numberText:"",numberX:c,numberY:n.top,numberAlign:"center",labelX:c,labelY:n.top});}for(let a of qC){let l,c;a.x>a.y?(l=n.ox+n.bx,c=n.oy+a.y/a.x*n.py):(c=n.oy+n.py,l=n.ox+a.x/a.y*n.bx),s.push({color:a.color,x1:n.ox,y1:n.oy,x2:l,y2:c,numberText:a.label,numberX:l+4,numberY:c,numberAlign:"left",labelX:l+4,labelY:c});}return s}hitTest(t,n,o,i){let s=this.box(o);return s!=null&&Ue(t,n,s.left,s.top,s.right,s.bot,i)}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}};var ru=[4,8,12,16,24,32,48,64],ZC=24,QC=.75;function xf(r,e){if(!Number.isInteger(r)||!Number.isInteger(e)||e<=0)return false;let t=r*r-1;return e%2===1?t%e===0:e%8===0?t%e!==0?false:t/e%2!==0:false}function Sf(r){let e=[];for(let t=0;tp+.5||m.push({kind:"vline",x:y,y0:s,y1:i});}for(let b=1;b<=d;b+=1){let y=1/b,w=y*a;if(wh)continue;let x=o+(k-l)*a;x+wp+1||m.push({kind:"arc",cx:x,cy:s,r:w});}}return m}hitTest(t,n,o,i){let s=this.box(o);return s!=null&&Ue(t,n,s.left,s.top,s.right,s.bot,i)}handlePoints(t){let n=this.box(t);return n?[[n.left,n.top],[n.right,n.bot]]:[]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.box(t);return n?{x:n.left,y:n.top,w:n.right-n.left,h:n.bot-n.top}:null}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}schema(){return {fields:[...G,{path:"maxCurvature",label:"Max curvature",kind:"number",min:4,max:64,step:4,group:"behavior"},...$]}}writeProps(){return {maxCurvature:this.maxCurvature}}readProps(t){typeof t.maxCurvature=="number"&&Number.isFinite(t.maxCurvature)&&(this.maxCurvature=Math.max(1,Math.min(64,Math.round(t.maxCurvature))));}};var ou=[3,4,5,6,8,10,12],iu=[1.5,2,2.5,3,4,5],el=6,JC=2;function su(r=el){return [...yf(co.length,r)]}function eT(r){if(!r||typeof r!="object")return null;let e=r;return typeof e.ratio!="number"||typeof e.color!="string"?null:{ratio:e.ratio,color:e.color,enabled:e.enabled!==false,...typeof e.label=="string"&&e.label?{label:e.label}:{}}}var uo={path:"showRatios",label:"Show ratios",kind:"boolean",group:"behavior"},dt=class extends K{constructor(e){super(e),this.waveCount===void 0&&(this.waveCount=el),this.showRatios===void 0&&(this.showRatios=true);let t=Array.isArray(e.props?.levels);this.levels||(this.levels=this.defaultLevels().map(n=>({...n}))),!t&&this.shouldSyncWaveCount()&&this.syncLevelsToWaveCount();}shouldSyncWaveCount(){return true}syncLevelsToWaveCount(){let e=Math.max(1,Math.min(this.levels.length,Math.round(this.waveCount)));this.waveCount=e;for(let t=0;tC.enabled&&C.ratio>0).slice().sort((C,L)=>C.ratio-L.ratio);if(m.length===0)return null;let f=Math.max(1,this.machNumber()),g=[];for(let C of m){let L=C.ratio*d;g.push({cx:l+f*(L-d)*u,cy:c+f*(L-d)*h,r:L,color:C.color,ratio:C.ratio});}let b=l-f*d*u,y=c-f*d*h,w=g[g.length-1].r,S=f*w+2*d,M=[];if(f<=1+1e-9){let C=-h,L=u;M.push([b-C*S,y-L*S,b+C*S,y+L*S]);}else {let C=Math.asin(1/f),L=Math.cos(C),v=Math.sin(C),k=(V,Z,be)=>[V*L-Z*be*v,V*be*v+Z*L],[x,E]=k(u,h,1),[I,N]=k(u,h,-1);M.push([b,y,b+x*S,y+E*S]),M.push([b,y,b+I*S,y+N*S]);}return {c0x:l,c0y:c,R:d,fx:u,fy:h,noseX:b,noseY:y,circles:g,rays:M}}hitTest(e,t,n,o){let i=this.geom(n);if(!i)return false;for(let s of i.circles)if(Math.abs(Math.hypot(e-s.cx,t-s.cy)-s.r)<=o)return true;return i.rays.some(s=>ae(e,t,s[0],s[1],s[2],s[3])<=o)}handlePoints(e){let t=this.anchors[0],n=this.anchors[1];if(!t||!n)return [];let o=e.yOf(t.price,this.paneId),i=e.yOf(n.price,this.paneId);return o==null||i==null?[]:[[e.xOf(t.time),o],[e.xOf(n.time),i]]}hitHandle(e,t,n,o){return j(e,t,this.handlePoints(n),o+3)}bounds(e){let t=this.geom(e);if(!t)return null;let n=t.noseX,o=t.noseX,i=t.noseY,s=t.noseY;for(let a of t.circles)n=Math.min(n,a.cx-a.r),o=Math.max(o,a.cx+a.r),i=Math.min(i,a.cy-a.r),s=Math.max(s,a.cy+a.r);for(let a of t.rays)n=Math.min(n,a[0],a[2]),o=Math.max(o,a[0],a[2]),i=Math.min(i,a[1],a[3]),s=Math.max(s,a[1],a[3]);return {x:n,y:i,w:o-n,h:s-i}}priceRange(){let e=this.anchors[0],t=this.anchors[1];return !e||!t?null:{min:Math.min(e.price,t.price),max:Math.max(e.price,t.price)}}applySettings(e){if(super.applySettings(e),Object.prototype.hasOwnProperty.call(e,"waveCount")&&typeof this.waveCount=="number"){let t=Math.max(1,Math.min(this.levels.length,Math.round(this.waveCount)));this.waveCount=t;for(let n=0;n({...e}))}}readProps(e){if(typeof e.waveCount=="number"&&Number.isFinite(e.waveCount)&&(this.waveCount=Math.max(2,Math.min(12,Math.round(e.waveCount)))),typeof e.showRatios=="boolean"&&(this.showRatios=e.showRatios),Array.isArray(e.levels)){let t=e.levels.map(eT).filter(n=>n!=null);t.length&&(this.levels=t);}}},Si=class extends dt{constructor(){super(...arguments);this.type="sonic";}defaultLevels(){return su(el)}machNumber(){return 1}},Ci=class extends dt{constructor(t){super(t);this.type="supersonic";this.mach===void 0&&(this.mach=JC);}defaultLevels(){return su(el)}machNumber(){return Math.max(1.01,this.mach)}schema(){return {fields:[...G,{path:"mach",label:"Mach number",kind:"number",min:1.5,max:5,step:.5,group:"behavior"},{path:"waveCount",label:"Waves",kind:"number",min:3,max:12,step:1,group:"behavior"},uo,...$]}}writeProps(){return {...super.writeProps(),mach:this.mach}}readProps(t){super.readProps(t),typeof t.mach=="number"&&Number.isFinite(t.mach)&&(this.mach=Math.max(1.01,Math.min(20,t.mach)));}};var Cf=ye([.236,.382,.5,.618,.786,1,1.618,2.618,4.236,6.854,11.09]),tT=2,tl=class extends dt{constructor(){super(...arguments);this.type="goldensonic";}shouldSyncWaveCount(){return false}defaultLevels(){return Cf}machNumber(){return 1}schema(){return {fields:[...G,uo,...$]}}},nl=class extends dt{constructor(t){super(t);this.type="goldensupersonic";this.mach===void 0&&(this.mach=tT);}shouldSyncWaveCount(){return false}defaultLevels(){return Cf}machNumber(){return Math.max(1.01,this.mach)}schema(){return {fields:[...G,{path:"mach",label:"Mach number",kind:"number",min:1.5,max:5,step:.5,group:"behavior"},uo,...$]}}writeProps(){return {...super.writeProps(),mach:this.mach}}readProps(t){super.readProps(t),typeof t.mach=="number"&&Number.isFinite(t.mach)&&(this.mach=Math.max(1.01,Math.min(20,t.mach)));}};var Ge=class extends K{legRatios(){return false}fillTriangles(){return []}necklineIndices(){return null}anchorSchema(){let e=this.vertexLabels().length,t=[];for(let n=0;n=2&&so(e,t,i)<=o}hitHandle(e,t,n,o){return j(e,t,this.handlePoints(n),o+3)}bounds(e){let t=this.handlePoints(e);if(t.length===0)return null;let n=t.map(a=>a[0]),o=t.map(a=>a[1]),i=Math.min(...n),s=Math.min(...o);return {x:i,y:s,w:Math.max(...n)-i,h:Math.max(...o)-s}}priceRange(){if(this.anchors.length===0)return null;let e=this.anchors.map(t=>t.price);return {min:Math.min(...e),max:Math.max(...e)}}patternName(){return null}ratioOk(e){return null}valid(){return null}ratioAt(e){let t=this.anchors[e-2],n=this.anchors[e-1],o=this.anchors[e];if(!t||!n||!o)return null;let i=Math.abs(n.price-t.price);return i<1e-9?null:Math.abs(o.price-n.price)/i}schema(){return {fields:[...G,...this.fillTriangles().length?fe:[]]}}};var rl=class extends Ge{constructor(){super(...arguments);this.type="xabcd";}vertexLabels(){return ["X","A","B","C","D"]}legRatios(){return true}fillTriangles(){return [[0,1,2],[2,3,4]]}};var ol=class extends Ge{constructor(){super(...arguments);this.type="abcd";}vertexLabels(){return ["A","B","C","D"]}legRatios(){return true}};var il=class extends Ge{constructor(){super(...arguments);this.type="elliottimpulse";}vertexLabels(){return ["1","2","3","4","5"]}};var sl=class extends Ge{constructor(){super(...arguments);this.type="elliottcorrection";}vertexLabels(){return ["A","B","C"]}};var al=class extends Ge{constructor(){super(...arguments);this.type="headshoulders";}vertexLabels(){return ["","LS","","H","","RS",""]}necklineIndices(){return [2,4]}};var ut=class extends Ge{vertexLabels(){return ["X","A","B","C","D"]}legRatios(){return true}fillTriangles(){return [[0,1,2],[2,3,4]]}legValue(e){let[t,n,o,i,s]=this.anchors;if(!t||!n||!o||!i||!s)return null;let a=(u,h)=>Math.abs(h.price-u.price),l=a(t,n),c=a(n,o),d=a(o,i);switch(e){case "ab":return l<1e-9?null:c/l;case "bc":return c<1e-9?null:d/c;case "cd":return d<1e-9?null:a(i,s)/d;default:return l<1e-9?null:a(n,s)/l}}inBand(e,t){return e!=null&&e>=t.min&&e<=t.max}ratioOk(e){let t=this.ranges();return e===2?this.inBand(this.legValue("ab"),t.ab):e===3?this.inBand(this.legValue("bc"),t.bc):e===4?this.inBand(this.legValue("cd"),t.cd):null}valid(){if(this.anchors.length<5)return null;let e=this.ranges();return this.inBand(this.legValue("ab"),e.ab)&&this.inBand(this.legValue("bc"),e.bc)&&this.inBand(this.legValue("cd"),e.cd)&&this.inBand(this.legValue("ad"),e.ad)}};var ll=class extends ut{constructor(){super(...arguments);this.type="gartley";}patternName(){return "Gartley"}ranges(){return {ab:{min:.55,max:.68},bc:{min:.382,max:.886},cd:{min:1.13,max:1.618},ad:{min:.74,max:.83}}}};var cl=class extends ut{constructor(){super(...arguments);this.type="bat";}patternName(){return "Bat"}ranges(){return {ab:{min:.382,max:.5},bc:{min:.382,max:.886},cd:{min:1.618,max:2.618},ad:{min:.84,max:.92}}}};var dl=class extends ut{constructor(){super(...arguments);this.type="butterfly";}patternName(){return "Butterfly"}ranges(){return {ab:{min:.74,max:.83},bc:{min:.382,max:.886},cd:{min:1.618,max:2.618},ad:{min:1.272,max:1.618}}}};var ul=class extends ut{constructor(){super(...arguments);this.type="crab";}patternName(){return "Crab"}ranges(){return {ab:{min:.382,max:.618},bc:{min:.382,max:.886},cd:{min:2.618,max:3.618},ad:{min:1.55,max:1.69}}}};var hl=class extends ut{constructor(){super(...arguments);this.type="shark";}patternName(){return "Shark"}ranges(){return {ab:{min:.382,max:.618},bc:{min:1.13,max:1.618},cd:{min:1.618,max:2.24},ad:{min:.886,max:1.13}}}};var nT={min:1.272,max:1.414},rT={min:.74,max:.83},pl=class extends ut{constructor(){super(...arguments);this.type="cypher";}patternName(){return "Cypher"}ranges(){return {ab:{min:.382,max:.618},bc:{min:0,max:1/0},cd:{min:0,max:1/0},ad:{min:0,max:1/0}}}xcOverXa(){let t=this.anchors[0],n=this.anchors[1],o=this.anchors[3];if(!t||!n||!o)return null;let i=Math.abs(n.price-t.price);return i<1e-9?null:Math.abs(o.price-t.price)/i}cdOverXc(){let t=this.anchors[0],n=this.anchors[3],o=this.anchors[4];if(!t||!n||!o)return null;let i=Math.abs(n.price-t.price);return i<1e-9?null:Math.abs(o.price-n.price)/i}ratioOk(t){return t===2?this.inBand(this.legValue("ab"),this.ranges().ab):null}valid(){return this.anchors.length<5?null:this.inBand(this.legValue("ab"),this.ranges().ab)&&this.inBand(this.xcOverXa(),nT)&&this.inBand(this.cdOverXc(),rT)}};function Tf(r){return `${r>=0?"+":""}${r.toFixed(2)}`}function Ti(r){let e=Math.abs(r),t=864e5,n=36e5,o=6e4;if(e>=t){let i=Math.floor(e/t),s=Math.round(e%t/n);return s?`${i}d ${s}h`:`${i}d`}if(e>=n){let i=Math.floor(e/n),s=Math.round(e%n/o);return s?`${i}h ${s}m`:`${i}h`}return e>=o?`${Math.round(e/o)}m`:`${Math.round(e/1e3)}s`}var Mr=class extends K{constructor(e){super(e),this.showPrice===void 0&&(this.showPrice=true),this.showDate===void 0&&(this.showDate=true);}anchorSchema(){return {min:2,max:2,slots:[{role:"c1",free:"both"},{role:"c2",free:"both"}]}}measureLabel(e){let t=[];return this.showPrice&&t.push(this.priceLabel()),this.showDate&&t.push(this.timeLabel(e)),t}isUp(){let e=this.anchors[0],t=this.anchors[1];return e!=null&&t!=null&&t.price>=e.price}priceLabel(){let e=this.anchors[0],t=this.anchors[1];if(!e||!t)return "";let n=t.price-e.price,o=e.price!==0?n/e.price*100:0;return `${Tf(n)} (${Tf(o)}%)`}timeLabel(e){let t=this.anchors[0],n=this.anchors[1];if(!t||!n)return "";let o=Ti(n.time-t.time),i=e.barsBetween?Math.round(e.barsBetween(t.time,n.time)):null;return i!=null?`${i} bars, ${o}`:o}rect(e){let t=this.anchors[0],n=this.anchors[1];if(!t||!n)return null;let o=e.yOf(t.price,this.paneId),i=e.yOf(n.price,this.paneId);return o==null||i==null?null:{x1:e.xOf(t.time),y1:o,x2:e.xOf(n.time),y2:i}}hitTest(e,t,n,o){let i=this.rect(n);return i!=null&&Ue(e,t,i.x1,i.y1,i.x2,i.y2,o)}handlePoints(e){let t=this.rect(e);return t?[[t.x1,t.y1],[t.x2,t.y2]]:[]}hitHandle(e,t,n,o){return j(e,t,this.handlePoints(n),o+3)}bounds(e){let t=this.rect(e);return t?{x:Math.min(t.x1,t.x2),y:Math.min(t.y1,t.y2),w:Math.abs(t.x2-t.x1),h:Math.abs(t.y2-t.y1)}:null}priceRange(){let e=this.anchors[0],t=this.anchors[1];return !e||!t?null:{min:Math.min(e.price,t.price),max:Math.max(e.price,t.price)}}schema(){return {fields:[{path:"showPrice",label:"Show price",kind:"boolean",group:"behavior"},{path:"showDate",label:"Show date",kind:"boolean",group:"behavior"},...G.filter(e=>e.path!=="style.lineColor"),{path:"text.color",label:"Text color",kind:"color",group:"text"},{path:"text.size",label:"Text size",kind:"select",options:Dt,group:"text"}]}}writeProps(){return {showPrice:this.showPrice,showDate:this.showDate}}readProps(e){typeof e.showPrice=="boolean"&&(this.showPrice=e.showPrice),typeof e.showDate=="boolean"&&(this.showDate=e.showDate);}};var ml=class extends Mr{constructor(){super(...arguments);this.type="datepricerange";}};var fl=[{value:"long",label:"Long"},{value:"short",label:"Short"}],De=class De extends K{constructor(t){super(t);this.type="position";this.riskPercent===void 0&&(this.riskPercent=De.DEFAULT_RISK_PERCENT),this.accountBalance===void 0&&(this.accountBalance=De.DEFAULT_ACCOUNT_BALANCE),this.showText===void 0&&(this.showText=true),this.showHeader===void 0&&(this.showHeader=true),this.showPrices===void 0&&(this.showPrices=false),this.showLossSize===void 0&&(this.showLossSize=true),this.showTargetLabel===void 0&&(this.showTargetLabel=true),this.showStopLabel===void 0&&(this.showStopLabel=true),this.profitColor===void 0&&(this.profitColor=De.DEFAULT_PROFIT_COLOR),this.lossColor===void 0&&(this.lossColor=De.DEFAULT_LOSS_COLOR);}directionLabel(){let t=this.prices();return t&&t.target>=t.entry?"LONG":"SHORT"}get direction(){return this.directionLabel()==="LONG"?"long":"short"}set direction(t){let n=this.anchors[0],o=this.anchors[1],i=this.anchors[2];!n||!o||!i||(t==="long"||t==="short")&&t!==this.direction&&(o.price=2*n.price-o.price,i.price=2*n.price-i.price);}get quantity(){return this.positionSize()}set quantity(t){let n=this.prices();if(!n||!Number.isFinite(t)||t<0)return;let o=Math.abs(n.entry-n.stop);o<1e-9||this.accountBalance<=0||(this.riskPercent=t*o/this.accountBalance*100);}get entryPrice(){return this.anchors[0]?.price??0}set entryPrice(t){let n=this.anchors[0];n&&Number.isFinite(t)&&(n.price=t,this.constrainHandleDrag(0));}get stopPrice(){return this.anchors[1]?.price??0}set stopPrice(t){let n=this.anchors[1];n&&Number.isFinite(t)&&(n.price=t,this.constrainHandleDrag(1));}get targetPrice(){return this.anchors[2]?.price??0}set targetPrice(t){let n=this.anchors[2];n&&Number.isFinite(t)&&(n.price=t,this.constrainHandleDrag(2));}anchorSchema(){return {min:2,max:2,slots:[{role:"entry",free:"both"},{role:"stop",free:"both"},{role:"target",free:"both"}]}}onPlaced(t){let n=this.anchors[0];if(!n)return;let o=t.xOf(n.time),i=t.yOf(n.price,this.paneId);if(i==null)return;let s=this.anchors[1],a=s?t.yOf(s.price,this.paneId):null,l,c;s&&a!=null&&Math.abs(a-i)>=De.MIN_DRAG_PX?(l=a,c=o+Math.max(Math.abs(t.xOf(s.time)-o),De.MIN_WIDTH_PX)):(l=i-De.DEFAULT_RISK_PX*De.DEFAULT_RR,c=o+De.DEFAULT_WIDTH_PX);let d=i-(l-i)/De.DEFAULT_RR,u=t.pxToPoint(c,i,this.paneId).time;this.anchors=[{time:n.time,price:n.price},{time:u,price:t.pxToPoint(o,d,this.paneId).price},{time:u,price:t.pxToPoint(o,l,this.paneId).price}];}constrainHandleDrag(t){let n=this.anchors[0],o=this.anchors[1],i=this.anchors[2];if(!n||!o||!i)return;let s=Math.sign(o.price-n.price),a=Math.sign(i.price-n.price);s===0||a===0||s!==a||(t===2?o.price=2*n.price-o.price:i.price=2*n.price-i.price);}resolved(){let t=this.anchors[0],n=this.anchors[1];if(!t||!n)return null;if(this.anchors[2])return [t,n,this.anchors[2]];let o={time:n.time,price:t.price-(n.price-t.price)/De.DEFAULT_RR};return [t,o,n]}prices(){let t=this.resolved();return t?{entry:t[0].price,stop:t[1].price,target:t[2].price}:null}rr(){let t=this.prices();if(!t)return 0;let n=Math.abs(t.entry-t.stop);return n<1e-9?0:Math.abs(t.target-t.entry)/n}rewardPct(){let t=this.prices();return t&&t.entry!==0?Math.abs(t.target-t.entry)/t.entry*100:0}riskPct(){let t=this.prices();return t&&t.entry!==0?Math.abs(t.entry-t.stop)/t.entry*100:0}dollarLoss(){return Math.max(0,this.accountBalance)*(Math.max(0,this.riskPercent)/100)}positionSize(){let t=this.prices();if(!t)return 0;let n=Math.abs(t.entry-t.stop);return n<1e-9?0:this.dollarLoss()/n}headerLabel(){return `${this.directionLabel()} \xB7 R:R ${this.rr().toFixed(2)}`}lossSizeLabel(){return `Loss $${oT(this.dollarLoss())} \xB7 Size ${iT(this.positionSize())}`}targetLabel(){let t=this.prices(),n=this.showPrices&&t?` @ ${kf(t.target)}`:"";return `Target +${this.rewardPct().toFixed(2)}%${n}`}stopLabel(){let t=this.prices(),n=this.showPrices&&t?` @ ${kf(t.stop)}`:"";return `Stop \u2212${this.riskPct().toFixed(2)}%${n}`}levelDisplayValue(t,n){let o=this.prices();if(!o)return 0;let i=t==="stop"?o.stop:o.target;return Lf(n==="price"?i:Math.abs(i-o.entry))}levelPriceFromDisplay(t,n,o){let i=this.prices();if(!i||n==="price")return o;let s=t==="stop"?i.stop:i.target,a=Math.sign(s-i.entry);return a===0&&(a=(t==="target"?1:-1)*(this.direction==="long"?1:-1)),i.entry+a*Math.abs(o)}box(t){let n=this.handlePoints(t);if(n.length<3)return null;let o=n.map(i=>i[0]);return {x1:Math.min(...o),x2:Math.max(...o),ey:n[0][1],sy:n[1][1],ty:n[2][1]}}layout(t){return this.box(t)}hitTest(t,n,o,i){let s=this.box(o);if(!s)return false;let a=Math.min(s.ey,s.sy,s.ty),l=Math.max(s.ey,s.sy,s.ty);return Ue(t,n,s.x1,a,s.x2,l,i)}handlePoints(t){let n=this.resolved();if(!n)return [];let o=[];for(let i of n){let s=t.yOf(i.price,this.paneId);if(s==null)return [];o.push([t.xOf(i.time),s]);}return o}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.box(t);if(!n)return null;let o=Math.min(n.ey,n.sy,n.ty);return {x:n.x1,y:o,w:n.x2-n.x1,h:Math.max(n.ey,n.sy,n.ty)-o}}priceRange(){let t=this.resolved();if(!t)return null;let n=t.map(o=>o.price);return {min:Math.min(...n),max:Math.max(...n)}}schema(){return {fields:[{path:"riskPercent",label:"Risk %",kind:"number",min:0,max:100,step:.1,group:"behavior"},{path:"accountBalance",label:"Account balance",kind:"number",min:0,max:1e12,step:1,group:"behavior"},{path:"quantity",label:"Position size",kind:"number",group:"behavior"},{path:"direction",label:"Direction",kind:"select",options:fl,group:"behavior"},{path:"entryPrice",label:"Entry price",kind:"number",group:"behavior"},{path:"stopPrice",label:"Stop price",kind:"number",group:"behavior"},{path:"targetPrice",label:"Target price",kind:"number",group:"behavior"},{path:"showText",label:"Show text",kind:"boolean",group:"behavior"},{path:"showHeader",label:"Show direction & ratio",kind:"boolean",group:"behavior"},{path:"showLossSize",label:"Show loss & size",kind:"boolean",group:"behavior"},{path:"showTargetLabel",label:"Show target label",kind:"boolean",group:"behavior"},{path:"showStopLabel",label:"Show stop label",kind:"boolean",group:"behavior"},{path:"showPrices",label:"Show level prices",kind:"boolean",group:"behavior"},{path:"profitColor",label:"Profit zone",kind:"color",group:"fill"},{path:"lossColor",label:"Loss zone",kind:"color",group:"fill"},...G.filter(t=>t.path!=="style.lineColor"),{path:"text.color",label:"Text color",kind:"color",group:"text"},{path:"text.size",label:"Text size",kind:"select",options:Dt,group:"text"}]}}writeProps(){return {riskPercent:this.riskPercent,accountBalance:this.accountBalance,showText:this.showText,showHeader:this.showHeader,showPrices:this.showPrices,showLossSize:this.showLossSize,showTargetLabel:this.showTargetLabel,showStopLabel:this.showStopLabel,profitColor:this.profitColor,lossColor:this.lossColor}}readProps(t){typeof t.riskPercent=="number"&&Number.isFinite(t.riskPercent)&&(this.riskPercent=t.riskPercent),typeof t.accountBalance=="number"&&Number.isFinite(t.accountBalance)&&(this.accountBalance=t.accountBalance),typeof t.showText=="boolean"&&(this.showText=t.showText),typeof t.showHeader=="boolean"&&(this.showHeader=t.showHeader),typeof t.showPrices=="boolean"&&(this.showPrices=t.showPrices),typeof t.showLossSize=="boolean"&&(this.showLossSize=t.showLossSize),typeof t.showTargetLabel=="boolean"&&(this.showTargetLabel=t.showTargetLabel),typeof t.showStopLabel=="boolean"&&(this.showStopLabel=t.showStopLabel),typeof t.profitColor=="string"&&(this.profitColor=t.profitColor),typeof t.lossColor=="string"&&(this.lossColor=t.lossColor);}};De.DEFAULT_RR=2,De.MIN_DRAG_PX=6,De.DEFAULT_RISK_PX=64,De.DEFAULT_WIDTH_PX=150,De.MIN_WIDTH_PX=48,De.DEFAULT_RISK_PERCENT=1,De.DEFAULT_ACCOUNT_BALANCE=1e4,De.DEFAULT_PROFIT_COLOR=ca,De.DEFAULT_LOSS_COLOR=da;var yt=De;function oT(r){if(!Number.isFinite(r))return "0";let e=Math.round(r*100)/100;return Number.isInteger(e)?String(e):e.toFixed(2)}function iT(r){return !Number.isFinite(r)||r===0?"0":r>=100?r.toFixed(2):r>=1?r.toFixed(4).replace(/\.?0+$/,""):r.toPrecision(4).replace(/\.?0+$/,"")}function kf(r){return Number.isFinite(r)?Math.abs(r)>=1?r.toFixed(2):r.toPrecision(4).replace(/\.?0+$/,""):"0"}function Lf(r){return Math.round(r*1e8)/1e8}var Er=[{value:"auto",label:"Auto",ms:0},{value:"1",label:"1m",ms:6e4},{value:"5",label:"5m",ms:3e5},{value:"15",label:"15m",ms:9e5},{value:"30",label:"30m",ms:18e5},{value:"60",label:"1h",ms:36e5},{value:"240",label:"4h",ms:144e5},{value:"D",label:"1D",ms:864e5}];function ki(r){let e=Er.find(n=>n.value===r);if(e)return e.label;let t=Number(r);return Number.isFinite(t)&&t>0?t%1440===0?`${t/1440}D`:t%60===0?`${t/60}h`:`${t}m`:r}function Mf(){return {timeframe:"auto",upColor:"",downColor:""}}var ht=class extends K{constructor(t){super(t);this.type="magnifier";this.chipRect=null;this.magnifier||(this.magnifier=Mf());}anchorSchema(){return {min:2,max:2,slots:[{role:"c1",free:"both"},{role:"c2",free:"both"}]}}placementMode(){return "drag"}rect(t){let n=this.anchors[0],o=this.anchors[1];if(!n||!o)return null;let i=t.yOf(n.price,this.paneId),s=t.yOf(o.price,this.paneId);return i==null||s==null?null:{x1:t.xOf(n.time),y1:i,x2:t.xOf(o.time),y2:s}}hitTest(t,n,o,i){let s=this.rect(o);return s?Ue(t,n,s.x1,s.y1,s.x2,s.y2)?true:[[s.x1,s.y1,s.x2,s.y1],[s.x2,s.y1,s.x2,s.y2],[s.x2,s.y2,s.x1,s.y2],[s.x1,s.y2,s.x1,s.y1]].some(l=>ae(t,n,l[0],l[1],l[2],l[3])<=i):false}handlePoints(t){let n=this.rect(t);return n?[[n.x1,n.y1],[n.x2,n.y2]]:[]}hitHandle(t,n,o,i){return j(t,n,this.handlePoints(o),i+3)}bounds(t){let n=this.rect(t);return n?{x:Math.min(n.x1,n.x2),y:Math.min(n.y1,n.y2),w:Math.abs(n.x2-n.x1),h:Math.abs(n.y2-n.y1)}:null}priceRange(){let t=this.anchors[0],n=this.anchors[1];return !t||!n?null:{min:Math.min(t.price,n.price),max:Math.max(t.price,n.price)}}schema(){return {fields:[{path:"magnifier.timeframe",label:"Timeframe",kind:"select",options:Er,group:"behavior"},...G.map(t=>({...t,label:t.label.replace("Line","Border")})),{path:"magnifier.upColor",label:"Up candles",kind:"color",group:"fill"},{path:"magnifier.downColor",label:"Down candles",kind:"color",group:"fill"}]}}writeProps(){return {...this.magnifier}}readProps(t){this.magnifier={...Mf(),...t};}};var Li=new Map;function W(r){Li.set(r.type,r);}function Nt(r){return Li.get(r)}function gl(){return [...Li.values()]}function Wn(r,e){let t=Li.get(r);if(!t)return null;let n={...t.defaultStyle,...e.style??{}};return t.create({...e,style:n})}function bl(r){let e=Wn(r.type,{paneId:r.paneId});if(!e)return;r.style={...e.style};let t=r.text?.value;e.text?(r.text={...e.text},t!==void 0&&(r.text.value=t)):r.text=void 0;let n=e.serialize().props;n!==void 0&&r.applyProps(n);}function wt(r){let e=Li.get(r.type);return e?e.create(r):null}var sT=B(''),aT=B('');W({type:"trendline",group:"lines",label:"Trend Line",icon:sT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new ha(r)});W({type:"hline",group:"lines",label:"Horizontal Line",icon:aT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"dashed"},create:r=>new pa(r)});var lT=B(''),cT=B(''),dT=B('');W({type:"ray",group:"lines",label:"Ray",icon:lT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new ma(r)});var uT=B(''),hT=B(''),pT=B(''),mT=B(''),fT=B(''),gT=B('');W({type:"extendedline",group:"lines",label:"Extended Line",icon:uT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new fa(r)});W({type:"vline",group:"lines",label:"Vertical Line",icon:hT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new ga(r)});W({type:"hray",group:"lines",label:"Horizontal Ray",icon:pT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new ba(r)});W({type:"crossline",group:"lines",label:"Cross Line",icon:mT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new va(r)});W({type:"infoline",group:"lines",label:"Info Line",icon:fT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new ya(r)});W({type:"trendangle",group:"lines",label:"Trend Angle",icon:gT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new wa(r)});W({type:"box",group:"shapes",label:"Rectangle",icon:cT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid",fillColor:`${_}26`},create:r=>new xa(r)});W({type:"text",group:"annotations",label:"Text",icon:dT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new vn(r)});var bT=B('');W({type:"callout",group:"annotations",label:"Callout",icon:bT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid",fillColor:`${_}d9`},create:r=>new jt(r)});var vT=B(''),yT=B(''),wT=B(''),xT=B(''),ST=B('');W({type:"note",group:"annotations",label:"Note",icon:vT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid",fillColor:`${_}d9`},create:r=>new hr(r)});W({type:"pricenote",group:"annotations",label:"Price Note",icon:yT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid",fillColor:`${_}d9`},create:r=>new mr(r)});W({type:"comment",group:"annotations",label:"Comment",icon:wT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid",fillColor:`${_}d9`},create:r=>new fr(r)});W({type:"pricelabel",group:"annotations",label:"Price Label",icon:xT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid",fillColor:`${_}d9`},create:r=>new pr(r)});W({type:"signpost",group:"annotations",label:"Signpost",icon:ST,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid",fillColor:`${_}d9`},create:r=>new gr(r)});var CT=B(''),TT=B(''),kT=B('');W({type:"parallelchannel",group:"channels",label:"Parallel Channel",icon:CT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid",fillColor:`${_}1a`},create:r=>new Sa(r)});W({type:"disjointchannel",group:"channels",label:"Disjoint Channel",icon:TT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid",fillColor:`${_}1a`},create:r=>new Ca(r)});var LT=B('');W({type:"flattopbottom",group:"channels",label:"Flat Top/Bottom",icon:LT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid",fillColor:`${_}1a`},create:r=>new Ta(r)});var MT=B('');W({type:"regressionchannel",group:"channels",label:"Linear Regression",icon:MT,defaultStyle:{lineColor:A,lineWidth:1,lineStyle:"solid"},create:r=>new yn(r)});W({type:"pitchfork",group:"pitchforks",label:"Pitchfork",icon:kT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new ka(r)});var ET=B(''),PT=B(''),IT=B('');W({type:"schiffpitchfork",group:"pitchforks",label:"Schiff Pitchfork",icon:ET,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new La(r)});W({type:"modifiedschiffpitchfork",group:"pitchforks",label:"Modified Schiff Pitchfork",icon:PT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new Ma(r)});W({type:"insidepitchfork",group:"pitchforks",label:"Inside Pitchfork",icon:IT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new Ea(r)});var AT=B(''),RT=B(''),DT=B('');W({type:"arrow",group:"shapes",label:"Arrow",icon:AT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid",arrowRight:true},create:r=>new Pa(r)});W({type:"ellipse",group:"shapes",label:"Ellipse",icon:RT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid",fillColor:`${_}1a`},create:r=>new Ia(r)});W({type:"triangle",group:"shapes",label:"Triangle",icon:DT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid",fillColor:`${_}1a`},create:r=>new Aa(r)});var OT=B(''),NT=B(''),FT=B('');W({type:"polyline",group:"shapes",label:"Polyline",icon:OT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new Ra(r)});W({type:"freehand",group:"shapes",label:"Brush",icon:NT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new Da(r)});W({type:"highlighter",group:"shapes",label:"Highlighter",icon:FT,defaultStyle:{lineColor:`${$m}59`,lineWidth:14,lineStyle:"solid"},create:r=>new Oa(r)});var VT=B(''),BT=B(''),_T=B(''),HT=B(''),zT=B(''),WT=B(''),GT=B('');W({type:"circle",group:"shapes",label:"Circle",icon:VT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid",fillColor:`${_}1a`},create:r=>new Na(r)});W({type:"rotatedrect",group:"shapes",label:"Rotated Rectangle",icon:BT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid",fillColor:`${_}26`},create:r=>new Fa(r)});W({type:"path",group:"shapes",label:"Path",icon:_T,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new Va(r)});W({type:"arc",group:"shapes",label:"Arc",icon:HT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid",fillColor:`${_}26`},create:r=>new Ba(r)});W({type:"curve",group:"shapes",label:"Curve",icon:zT,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new _a(r)});W({type:"arrowmarkup",group:"shapes",label:"Arrow Mark Up",icon:WT,defaultStyle:{lineColor:O,lineWidth:1,lineStyle:"solid"},create:r=>new bi(r)});W({type:"arrowmarkdown",group:"shapes",label:"Arrow Mark Down",icon:GT,defaultStyle:{lineColor:D,lineWidth:1,lineStyle:"solid"},create:r=>new vi(r)});var $T=B(''),UT=B('');W({type:"flagmark",group:"stamps",label:"Flag",icon:$T,defaultStyle:{lineColor:nt,lineWidth:1,lineStyle:"solid"},create:r=>new yi(r)});W({type:"iconstamp",group:"stamps",label:"Icon",icon:UT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new wi(r)});var YT=B(''),KT=B('');W({type:"fibretracement",group:"fibonacci",label:"Fib Retracement",icon:YT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new Cr(r)});W({type:"fibextension",group:"fibonacci",label:"Fib Extension",icon:KT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new Wa(r)});var XT=B('');W({type:"fibextensiontrend",group:"fibonacci",label:"Trend-Based Fib Extension",icon:XT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new Ga(r)});var jT=B(''),qT=B('');W({type:"fibfan",group:"fibonacci",label:"Fib Fan",icon:jT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new $a(r)});W({type:"fibtimezones",group:"fibonacci",label:"Fib Time Zones",icon:qT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"dashed"},create:r=>new Ua(r)});var ZT=B(''),QT=B(''),JT=B('');W({type:"fibchannel",group:"fibonacci",label:"Fib Channel",icon:ZT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new Ya(r)});W({type:"fibspeedfan",group:"fibonacci",label:"Fib Speed Resistance Fan",icon:QT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new Ka(r)});W({type:"trendfibtime",group:"fibonacci",label:"Trend-Based Fib Time",icon:JT,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"dashed"},create:r=>new Xa(r)});var e1=B(''),t1=B(''),n1=B(''),r1=B('');W({type:"fibcircles",group:"fibonacci",label:"Fib Circles",icon:e1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new ja(r)});W({type:"fibarcs",group:"fibonacci",label:"Fib Speed Resistance Arcs",icon:t1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new qa(r)});W({type:"fibwedge",group:"fibonacci",label:"Fib Wedge",icon:n1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new Za(r)});W({type:"fibspiral",group:"fibonacci",label:"Fib Spiral",icon:r1,defaultStyle:{lineColor:_,lineWidth:2,lineStyle:"solid"},create:r=>new Tr(r)});var o1=B(''),i1=B('');W({type:"gannfan",group:"fibonacci",label:"Gann Fan",icon:o1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new Qa(r)});W({type:"gannbox",group:"fibonacci",label:"Gann Box",icon:i1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new Ja(r)});var s1=B('');W({type:"gannsquare",group:"fibonacci",label:"Gann Square",icon:s1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new kr(r)});var a1=B('');W({type:"dedekind",group:"geometry",label:"Dedekind Tessellation",icon:a1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new Lr(r)});var l1=B(''),c1=B('');W({type:"sonic",group:"geometry",label:"Sonic",icon:l1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new Si(r)});W({type:"supersonic",group:"geometry",label:"Supersonic",icon:c1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new Ci(r)});var d1=B(''),u1=B('');W({type:"goldensonic",group:"geometry",label:"Golden Sonic",icon:d1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new tl(r)});W({type:"goldensupersonic",group:"geometry",label:"Golden Supersonic",icon:u1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new nl(r)});var h1=B(''),p1=B(''),m1=B(''),f1=B(''),g1=B('');W({type:"xabcd",group:"patterns",label:"XABCD Pattern",icon:h1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new rl(r)});W({type:"abcd",group:"patterns",label:"ABCD Pattern",icon:p1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new ol(r)});W({type:"elliottimpulse",group:"patterns",label:"Elliott Impulse Wave (1-5)",icon:m1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new il(r)});W({type:"elliottcorrection",group:"patterns",label:"Elliott Correction Wave (ABC)",icon:f1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new sl(r)});W({type:"headshoulders",group:"patterns",label:"Head & Shoulders",icon:g1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new al(r)});var b1=B(''),ho={group:"patterns",icon:b1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"}};W({type:"gartley",label:"Gartley",...ho,create:r=>new ll(r)});W({type:"bat",label:"Bat",...ho,create:r=>new cl(r)});W({type:"butterfly",label:"Butterfly",...ho,create:r=>new dl(r)});W({type:"crab",label:"Crab",...ho,create:r=>new ul(r)});W({type:"shark",label:"Shark",...ho,create:r=>new hl(r)});W({type:"cypher",label:"Cypher",...ho,create:r=>new pl(r)});var v1=B('');W({type:"datepricerange",group:"measure",label:"Date & Price Range",icon:v1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new ml(r)});var y1=B('');W({type:"position",group:"measure",label:"Long/Short Position",icon:y1,defaultStyle:{lineColor:_,lineWidth:1,lineStyle:"solid"},create:r=>new yt(r)});var w1=B('');W({type:"magnifier",group:"measure",label:"Magnifier",icon:w1,defaultStyle:{lineColor:"",lineWidth:1,lineStyle:"solid"},coversSeries:true,placementHint:"Drag an area on the chart to view it at a lower timeframe",create:r=>new ht(r)});var x1=B('');W({type:"anchoredvwap",group:"measure",label:"Anchored VWAP",icon:x1,defaultStyle:{lineColor:ce,lineWidth:2,lineStyle:"solid"},create:r=>new br(r)});var S1=B('');W({type:"fixedrangevp",group:"measure",label:"Fixed Range Volume Profile",icon:S1,defaultStyle:{lineColor:O,lineWidth:1,lineStyle:"solid"},create:r=>new gt(r)});var C1=["fibretracement","fibextension","fibextensiontrend","fibfan","fibtimezones","fibchannel","fibspeedfan","trendfibtime","fibcircles","fibarcs","fibwedge","fibspiral"],T1=["gannfan","gannbox","gannsquare"],k1=["dedekind","sonic","supersonic","goldensonic","goldensupersonic"],L1=["xabcd","abcd","headshoulders"],M1=["elliottimpulse","elliottcorrection"],E1=["gartley","bat","butterfly","crab","shark","cypher"],P1=["position","datepricerange","magnifier"],I1=["anchoredvwap","fixedrangevp"],A1=["freehand","highlighter"],R1=["arrow","arrowmarkup","arrowmarkdown"],D1=["box","ellipse","triangle","polyline","circle","rotatedrect","path","arc","curve"],O1=["text","callout","note","pricenote","comment","pricelabel","signpost"],N1=["flagmark","iconstamp"],F1=[{id:"lines-channels-pitchforks",label:"Lines",sections:[{label:"Lines",registryGroup:"lines"},{label:"Channels",registryGroup:"channels"},{label:"Pitchforks",registryGroup:"pitchforks"}]},{id:"fibonacci-gann",label:"Fibonacci",sections:[{label:"Fibonacci",types:C1},{label:"Gann",types:T1},{label:"Geometry",types:k1}]},{id:"patterns-waves-harmonics",label:"Patterns",sections:[{label:"Patterns",types:L1},{label:"Elliott Waves",types:M1},{label:"Harmonics",types:E1}]},{id:"measurements",label:"Measurements",sections:[{label:"Measurements",types:P1},{label:"Volume",types:I1}]},{id:"brushes-arrows-shapes",label:"Shapes",sections:[{label:"Brushes",types:A1},{label:"Arrows",types:R1},{label:"Shapes",types:D1}]},{id:"text",label:"Text",sections:[{label:"Text",types:O1}]},{id:"icons",label:"Icons",sections:[{label:"Icons",types:N1}]}];function V1(r){let e=Nt(r);return e?{type:e.type,label:e.label,icon:e.icon}:null}function B1(r){let e=new Map;for(let t of gl()){if(r&&!r.has(t.type))continue;let n={type:t.type,label:t.label,icon:t.icon};e.has(t.group)||e.set(t.group,[]),e.get(t.group).push(n);}return e}function _1(r,e,t){return "registryGroup"in r?e.get(r.registryGroup)??[]:r.types.map(n=>t.get(n)).filter(n=>n!=null)}function Ef(r){let e=B1(r),t=new Map;for(let o of e.values())for(let i of o)t.set(i.type,i);let n=[];for(let o of F1){let i=[],s=[];for(let a of o.sections){let l=_1(a,e,t);l.length!==0&&(i.push({label:a.label,tools:l}),s.push(...l));}s.length!==0&&n.push({id:o.id,label:o.label,tools:s,sections:i.length>0?i:void 0});}return {groups:n}}function H1(r){let e=new Set;for(let t of r)Nt(t)&&e.add(t);return Ef(e)}function z1(r){let e=[];for(let t of r){let n=t.tools.map(V1).filter(o=>o!=null);n.length>0&&e.push({id:t.id,label:t.label,tools:n});}return {groups:e}}function Mi(){return Ef()}function Ei(r){if(r===false)return {definition:Mi(),visible:false};if(r===void 0||r===true)return {definition:Mi(),visible:true};let e=r.toolbar??true;return r.groups?{definition:z1(r.groups),visible:e}:r.tools?{definition:H1(r.tools),visible:e}:{definition:Mi(),visible:e}}function Qt(r){let e=globalThis.structuredClone;return e?e(r):JSON.parse(JSON.stringify(r))}function Pf(r){if(!r||typeof r!="object")return false;let e=r;return typeof e.id=="string"&&typeof e.type=="string"&&typeof e.paneId=="string"&&Array.isArray(e.anchors)&&e.anchors.every(t=>t&&typeof t.time=="number"&&typeof t.price=="number")&&!!e.style&&typeof e.style=="object"}function au(r){let e=r;return !e||typeof e!="object"||e.version!==1||!Array.isArray(e.drawings)?{version:1,drawings:[]}:{version:1,drawings:e.drawings.filter(Pf)}}var po=class{constructor(){this.byId=new Map;this.seq=0;this.zCounter=1;this.listeners=new Set;}nextId(){return this.seq+=1,`dw-${this.seq}`}add(e){return e.zIndex||(e.zIndex=this.zCounter),this.zCounter=Math.max(this.zCounter,Math.ceil(e.zIndex))+1,this.byId.set(e.id,e),this.emit(),e}remove(e){let t=this.byId.delete(e);return t&&this.emit(),t}get(e){return this.byId.get(e)}has(e){return this.byId.has(e)}update(e,t){let n=this.byId.get(e);return n?(t.anchors&&(n.anchors=t.anchors.map(o=>({time:o.time,price:o.price}))),t.style&&(n.style={...t.style}),t.text!==void 0&&(n.text=t.text?{...t.text}:void 0),t.paneId!==void 0&&(n.paneId=t.paneId),t.locked!==void 0&&(n.locked=t.locked),t.visible!==void 0&&(n.visible=t.visible),t.zIndex!==void 0&&(n.zIndex=t.zIndex),t.props!==void 0&&n.applyProps(t.props),this.emit(),n):null}all(){return [...this.byId.values()].sort((e,t)=>e.zIndex-t.zIndex)}byPane(e){return this.all().filter(t=>t.paneId===e)}bringToFront(e,t=0){let n=this.byId.get(e);n&&(n.zIndex=Math.max(this.zCounter,Math.floor(t)+1),this.zCounter=n.zIndex+1,this.emit());}sendToBack(e,t=1){let n=this.byId.get(e);if(!n)return;let o=Math.min(...[...this.byId.values()].map(i=>i.zIndex),Math.ceil(t));n.zIndex=o-1,this.emit();}setLocked(e,t){let n=this.byId.get(e);n&&(n.locked=t,this.emit());}setVisible(e,t){let n=this.byId.get(e);n&&(n.visible=t,this.emit());}clear(){this.byId.size!==0&&(this.byId.clear(),this.emit());}serialize(){return {version:1,drawings:this.all().map(e=>e.serialize())}}load(e){let t=au(e);this.byId.clear(),this.seq=0,this.zCounter=1;for(let n of t.drawings){let o=wt(n);o&&(this.byId.set(o.id,o),this.zCounter=Math.max(this.zCounter,o.zIndex)+1,this.bumpSeqPast(o.id));}this.emit();}onChange(e){return this.listeners.add(e),()=>this.listeners.delete(e)}bumpSeqPast(e){let t=/^dw-(\d+)$/.exec(e);t&&(this.seq=Math.max(this.seq,Number(t[1])));}emit(){for(let e of this.listeners)e();}};var vl=class{constructor(e=100){this.cap=e;this.undoStack=[];this.redoStack=[];this.pending=null;this.dirtied=false;this.depth=0;}begin(e){this.depth+=1,this.depth===1&&(this.pending=Qt(e),this.dirtied=false);}markDirty(){this.depth===0||this.dirtied||!this.pending||(this.push(this.pending),this.dirtied=true);}commit(){this.depth!==0&&(this.depth-=1,this.depth===0&&(this.pending=null,this.dirtied=false));}abort(){this.commit();}record(e){if(this.depth>0){this.markDirty();return}this.push(Qt(e));}undo(e){let t=this.undoStack.pop();return t?(this.redoStack.push(Qt(e)),t):null}redo(e){let t=this.redoStack.pop();return t?(this.undoStack.push(Qt(e)),t):null}canUndo(){return this.undoStack.length>0}canRedo(){return this.redoStack.length>0}clear(){this.undoStack=[],this.redoStack=[],this.pending=null,this.dirtied=false,this.depth=0;}push(e){this.undoStack.push(e),this.undoStack.length>this.cap&&this.undoStack.shift(),this.redoStack=[];}};var yl=class{constructor(e,t,n,o){this.events=t;this.store=new po;this.history=new vl;this.activeTool=null;this.snapMode="off";this.stayInDrawingMode=false;this.mode=null;this.favs=new Set;this.selectedIds=[];this.clipboard=[];this.lastStyle=new Map;this.subs=[];if(this.enabled=!!e.capabilities.userDrawings&&!!e.userDrawingsPort,this.port=this.enabled?e.userDrawingsPort:null,this.port){let{definition:i,visible:s}=Ei(n);this.port.setToolbar(i),this.port.showToolbar(s),o&&this.port.setSeriesGateway?.(o),this.subs.push(this.port.onDrawingIntent(a=>this.onIntent(a))),this.subs.push(this.store.onChange(()=>this.sync()));}}get supported(){return this.enabled}setTool(e){if(!this.port)return;let t=e!==this.activeTool;this.activeTool=e,this.port.setActiveTool(e,e?this.lastStyle.get(e):void 0),t&&this.events.emit("drawing:tool",{type:e});}getTool(){return this.activeTool}getSnapMode(){return this.snapMode}setSnapMode(e){!this.port||e===this.snapMode||(this.snapMode=e,this.port.setSnapMode?.(e),this.events.emit("drawing:snap",{mode:e}));}getStayMode(){return this.stayInDrawingMode}setStayMode(e){!this.port||e===this.stayInDrawingMode||(this.stayInDrawingMode=e,this.port.setStayMode?.(e),this.events.emit("drawing:stay",{on:e}));}getMode(){return this.mode}setMode(e){!this.port||e===this.mode||(this.mode=e,this.port.setMode?.(e),this.events.emit("drawing:mode",{mode:e}));}showToolbar(e){this.port?.showToolbar(e);}favorites(){return [...this.favs]}isFavorite(e){return this.favs.has(e)}setFavorite(e,t){Nt(e)&&t!==this.favs.has(e)&&(t?this.favs.add(e):this.favs.delete(e),this.pushFavorites());}setFavorites(e){let t=e.filter(n=>Nt(n)!=null);t.length===this.favs.size&&t.every(n=>this.favs.has(n))||(this.favs=new Set(t),this.pushFavorites());}pushFavorites(){let e=[...this.favs];this.port?.setFavorites?.(e),this.events.emit("drawing:favorites",{favorites:e});}setToolbar(e){this.port?.setToolbar(Ei(e).definition);}setExternalGhost(e){this.port?.setExternalGhost?.(e);}setToolShortcuts(e){this.port?.setToolShortcuts?.(e);}add(e,t={}){if(!this.enabled)return null;let o={...this.lastStyle.get(e)??{},...t.style??{}},i=Wn(e,{id:this.store.nextId(),paneId:t.paneId??"price",anchors:t.anchors,style:o,text:t.text,props:t.props,zIndex:t.zIndex??this.startZ(e,t.paneId??"price")});return i?(this.history.record(this.store.serialize()),this.store.add(i),this.captureStyle(i.id),this.events.emit("drawing:created",{id:i.id}),i):null}remove(e){this.deleteMany([e]);}update(e,t){let n=this.store.serialize(),o=t.style?this.store.get(e):void 0,i=t.style&&o?{...t,style:{...o.style,...t.style}}:t;this.store.update(e,i)&&(this.history.record(n),this.captureStyle(e),this.events.emit("drawing:edited",{id:e}));}updateMany(e){this.history.begin(this.store.serialize());for(let{id:t,patch:n}of e)this.store.update(t,n)&&(this.history.markDirty(),this.events.emit("drawing:edited",{id:t}));this.history.commit();}removeMany(e){this.deleteMany(e);}setLocked(e,t){let n=this.store.serialize();this.history.record(n),this.store.setLocked(e,t),this.events.emit("drawing:edited",{id:e});}setVisible(e,t){let n=this.store.serialize();this.history.record(n),this.store.setVisible(e,t),this.events.emit("drawing:edited",{id:e});}bringToFront(e){let t=this.store.serialize();this.history.record(t),this.store.bringToFront(e,this.seriesTopZ(this.store.get(e)?.paneId)),this.events.emit("drawing:edited",{id:e});}sendToBack(e){let t=this.store.serialize();this.history.record(t),this.store.sendToBack(e,this.seriesBottomZ(this.store.get(e)?.paneId)),this.events.emit("drawing:edited",{id:e});}seriesTopZ(e){return e!==void 0?this.port?.stackRange?.(e)?.front??0:0}seriesBottomZ(e){return e!==void 0?this.port?.stackRange?.(e)?.back??1:1}startZ(e,t){let n=this.port?.stackRange?.(t);if(n)return Nt(e)?.coversSeries?n.front+.5:(n.price??n.front)-.5}select(e,t=false){this.setSelection(e,t);}openSettings(e){this.port?.openSettings(e);}undo(){let e=this.history.undo(this.store.serialize());e&&this.restoreSnapshot(e);}redo(){let e=this.history.redo(this.store.serialize());e&&this.restoreSnapshot(e);}canUndo(){return this.history.canUndo()}canRedo(){return this.history.canRedo()}duplicate(e){if(!this.enabled)return [];let t=this.resolve(e);return t.length===0?[]:this.insertClones(t.map(n=>n.serialize()))}clone(e){return this.duplicate([e])[0]??null}copy(e){let t=this.resolve(e).map(n=>Qt(n.serialize()));t.length&&(this.clipboard=t);}paste(){return !this.enabled||this.clipboard.length===0?[]:this.insertClones(this.clipboard)}all(){return this.store.serialize().drawings}toJSON(){return this.store.serialize()}fromJSON(e){this.history.clear(),this.selectedIds=[],this.store.load(e);}destroy(){for(let e of this.subs)e();this.subs.length=0;}setSelection(e,t=false){let n;if(t){n=[...this.selectedIds];for(let o of e){let i=n.indexOf(o);i>=0?n.splice(i,1):n.push(o);}}else n=[...e];this.selectedIds=n.filter(o=>this.store.has(o)),this.announceSelection();}announceSelection(){this.port?.setSelection(this.selectedIds),this.events.emit("drawing:selected",{id:this.selectedIds[0]??null,ids:[...this.selectedIds]});}restoreSnapshot(e){this.store.load(e),this.selectedIds=this.selectedIds.filter(t=>this.store.has(t)),this.announceSelection();}deleteMany(e){this.history.begin(this.store.serialize());let t=[];for(let o of e)this.store.remove(o)&&t.push(o),this.history.markDirty();if(this.history.commit(),t.length===0)return;let n=this.selectedIds.filter(o=>this.store.has(o));n.length!==this.selectedIds.length&&this.setSelection(n);for(let o of t)this.events.emit("drawing:removed",{id:o});}insertClones(e){this.history.begin(this.store.serialize());let t=[];for(let n of e){let o=wt({...n,id:this.store.nextId()});o&&(this.store.add(o),this.history.markDirty(),t.push(o));}if(this.history.commit(),t.length){this.setSelection(t.map(n=>n.id));for(let n of t)this.events.emit("drawing:created",{id:n.id});}return t}resolve(e){return e.map(t=>this.store.get(t)).filter(t=>t!=null)}captureStyle(e){let t=this.store.get(e);t&&this.lastStyle.set(t.type,{...t.style});}sync(){this.port?.syncDrawings(this.store.serialize().drawings);}onIntent(e){switch(e.kind){case "arm":this.setTool(e.type);break;case "draft":this.events.emit("drawing:draft",{doc:e.doc});break;case "create":{let t=this.store.serialize(),n=this.lastStyle.get(e.doc.type),o=n?{...e.doc.style,...n}:e.doc.style,i=wt({...e.doc,id:this.store.nextId(),style:o});if(!i)return;i.zIndex||(i.zIndex=this.startZ(i.type,i.paneId)??0),this.history.record(t),this.store.add(i),this.captureStyle(i.id),this.events.emit("drawing:created",{id:i.id});break}case "edit":{let t=this.store.serialize();this.store.update(e.doc.id,e.doc)&&(this.history.record(t),this.captureStyle(e.doc.id),this.events.emit("drawing:edited",{id:e.doc.id}));break}case "edit-many":{this.history.begin(this.store.serialize());for(let t of e.docs)this.store.update(t.id,t)&&(this.history.markDirty(),this.events.emit("drawing:edited",{id:t.id}));this.history.commit();break}case "select":this.setSelection(e.ids,e.additive);break;case "delete":this.deleteMany(e.ids);break;case "reorder":e.to==="front"?this.bringToFront(e.id):this.sendToBack(e.id);break;case "settings":this.events.emit("drawing:settings",{id:e.id});break;case "favorite":this.setFavorite(e.type,e.on);break;case "snap-mode":e.mode!==this.snapMode&&(this.snapMode=e.mode,this.events.emit("drawing:snap",{mode:e.mode}));break;case "stay-mode":e.on!==this.stayInDrawingMode&&(this.stayInDrawingMode=e.on,this.events.emit("drawing:stay",{on:e.on}));break;case "mode":e.mode!==this.mode&&(this.mode=e.mode,this.events.emit("drawing:mode",{mode:e.mode}));break;case "tool-finished":!this.stayInDrawingMode&&e.type!=="freehand"&&e.type!=="highlighter"&&this.setTool(null);break;case "undo":this.undo();break;case "redo":this.redo();break;case "duplicate":this.duplicate(e.ids);break;case "clone":this.enabled&&e.docs.length&&this.insertClones(e.docs);break;case "copy":this.copy(e.ids);break;case "paste":this.paste();break}}};function wl(r,e,t){let n=r[e];return typeof n=="boolean"?n:t.find(o=>o.id===e)?.visible!==false}function xl(r,e,t){if(e===void 0)return true;let n=new Set,o=e;for(;o!==void 0&&!n.has(o);){if(n.add(o),!wl(r,o,t))return false;let i=t.find(s=>s.id===o)?.parent;o=i!==void 0&&t.some(s=>s.id===i)?i:void 0;}return true}function lu(r){let e=new Set(r.map(i=>i.id)),t=[],n=new Set,o=(i,s)=>{if(!n.has(i.id)){n.add(i.id),t.push({group:i,depth:s});for(let a of r)a.parent===i.id&&a.id!==i.id&&o(a,s+1);}};for(let i of r)i.parent!==void 0&&e.has(i.parent)&&i.parent!==i.id||o(i,0);for(let i of r)o(i,0);return t}var Sl=class{constructor(e,t){this.renderer=e;this.marks=new Map;this.groups=new Map;this.subs=[];this.enabled=!!e.capabilities.timelineMarks&&typeof e.setTimelineMarks=="function",this.enabled&&e.onMarkClick&&this.subs.push(e.onMarkClick(n=>t.emit("mark:click",n)));}get supported(){return this.enabled}add(e){this.marks.set(e.id,Af(e)),this.sync();}set(e){this.marks.clear();for(let t of e)this.marks.set(t.id,Af(t));this.sync();}remove(e){let t=this.marks.delete(e);return t&&this.sync(),t}clear(){this.marks.size!==0&&(this.marks.clear(),this.sync());}all(){return [...this.marks.values()].map(e=>({...e,glyph:{...e.glyph}}))}defineGroup(e){if(!e||typeof e.id!="string"||e.id.length===0)throw new Error("[vela] marks.defineGroup: `id` must be a non-empty string");if(typeof e.label!="string")throw new Error(`[vela] marks.defineGroup: group "${e.id}" needs a string \`label\``);if(e.parent!==void 0&&(typeof e.parent!="string"||e.parent.length===0))throw new Error(`[vela] marks.defineGroup: group "${e.id}" has a \`parent\` that is not a group id`);this.groups.set(e.id,{...e}),this.sync();}groupDefinitions(){return [...this.groups.values()].map(e=>({...e}))}setGroupVisible(e,t){if(!this.renderer.features.includes("marks")){console.warn(`[vela] renderer "${this.renderer.name}" does not paint timeline marks \u2014 setGroupVisible ignored.`);return}this.renderer.applyFeature("marks",{groups:{[e]:t}});}isGroupVisible(e){let t=this.renderer.readFeature("marks"),n={};for(let[o,i]of Object.entries(t?.groups??{}))typeof i=="boolean"&&(n[o]=i);return xl(n,e,[...this.groups.values()])}destroy(){for(let e of this.subs)e();this.subs.length=0;}sync(){this.enabled&&this.renderer.setTimelineMarks([...this.marks.values()],[...this.groups.values()]);}};function Af(r){if(!r||typeof r!="object")throw new Error("[vela] marks: a mark must be an object");if(typeof r.id!="string"||r.id.length===0)throw new Error("[vela] marks: `id` must be a non-empty string");if(typeof r.time!="number"||!Number.isFinite(r.time))throw new Error(`[vela] marks: mark "${r.id}" needs a finite epoch-ms \`time\``);if(!r.glyph||typeof r.glyph!="object"||typeof r.glyph.color!="string")throw new Error(`[vela] marks: mark "${r.id}" needs a glyph with a \`color\``);return {...r,glyph:{...r.glyph}}}var Rf={D:864e5,W:6048e5,M:2592e6};function Ft(r){let e=r.trim();if(Rf[e])return Rf[e];let t=/^(\d+)\s*(m|h|d|w)?$/i.exec(e);if(t){let n=parseInt(t[1],10),o=(t[2]??"m").toLowerCase();return n*(o==="m"?6e4:o==="h"?36e5:o==="d"?864e5:6048e5)}return 36e5}var W1=5e3,G1=.25,$1=16,U1=15e3,cu=["240","60","30","15","5","1"],Cl=class{constructor(e){this.deps=e;this.cache=new Map;this.listeners=new Set;}seriesInRange(e,t,n){if(!this.deps.canFetch())return {state:"unavailable",reason:"no-source"};let o=this.resolveTimeframe(e);if(typeof o!="string")return {state:"unavailable",reason:o.reason};let i=Ft(o),s=Math.min(t,n),a=Math.max(t,n);if(!(a>s)||!(i>0))return {state:"unavailable",reason:"not-lower"};if((a-s)/i>W1)return {state:"unavailable",reason:"too-wide"};let l=`${this.deps.marketKey()}|${o}`,c=this.cache.get(l)??[],d=c.find(u=>u.from<=s&&u.to>=a);if(d){if(d.pending)return this.loading(c,o,i,s,a);if(d.failedAt>0){if(Date.now()-d.failedAtthis.listeners.delete(e)}resolveTimeframe(e){let t=Ft(this.deps.chartTimeframe()),n=cu[cu.length-1];if(Ft(n)>=t)return {reason:"none-lower"};let o=e.trim()||"auto";if(o==="auto"){for(let i of cu)if(Ft(i)<=t/4)return i;return n}return Ft(o)0)&&!(l.toi))for(let c of this.slice(l.bars,o,i))s.set(c.time,c);if(s.size===0)return {state:"loading",timeframe:t,barMs:n};let a=[...s.values()].sort((l,c)=>l.time-c.time);return {state:"loading",timeframe:t,barMs:n,bars:a}}fetchWindow(e,t,n,o,i){if(t.some(l=>l.pending&&l.to>=o&&l.from<=i))return;let s=(i-o)*G1,a={from:o-s,to:i+s,bars:[],fetchedAt:0,pending:true,failedAt:0};t.push(a),this.cache.set(e,t),this.evict(),this.deps.fetchBars(n,{from:a.from,to:a.to}).then(l=>{a.bars=l,a.fetchedAt=Date.now(),a.pending=false,this.absorbOverlaps(e,a),this.fire();}).catch(()=>{a.pending=false,a.failedAt=Date.now(),this.fire();});}maybeRefresh(e,t,n,o,i){if(t.pending)return;let s=t.bars.length>0?t.bars[t.bars.length-1].time:t.from;i{t.bars=a,t.fetchedAt=Date.now(),t.pending=false,this.fire();}).catch(()=>{t.pending=false,t.fetchedAt=Date.now();}));}absorbOverlaps(e,t){let n=this.cache.get(e);if(n)for(let o=n.length-1;o>=0;o-=1){let i=n[o];if(i===t||i.pending||i.failedAt>0||i.tot.to)continue;let s=new Map;for(let a of i.bars)s.set(a.time,a);for(let a of t.bars)s.set(a.time,a);t.bars=[...s.values()].sort((a,l)=>a.time-l.time),t.from=Math.min(t.from,i.from),t.to=Math.max(t.to,i.to),t.fetchedAt=Math.min(t.fetchedAt,i.fetchedAt||t.fetchedAt),n.splice(o,1);}}evict(){let e=0;for(let t of this.cache.values())e+=t.length;for(;e>$1;){let t=null,n=-1,o=1/0;for(let[s,a]of this.cache)for(let l=0;ln)break;o.push(i);}return o}fire(){for(let e of [...this.listeners])e();}};function Pi(r){return r.group!=null&&r.ticker===r.group}function Df(r){return `${(r.prefix??r.provider??"").toLowerCase()}:${(r.group??"").toUpperCase()}`}function Y1(r,e){let t=Df(e);return r.filter(n=>n.group!=null&&!Pi(n)&&Df(n)===t)}function Of(r,e){let t=Y1(r,e),n=t.filter(o=>o.default);return (n.length===1?n[0]:t[0])??null}var Jt=r=>r.trim().toLowerCase(),xn=r=>r.trim().toUpperCase();function en(r){let e=r.trim(),t=/^(?:([A-Za-z0-9_.]+):)?(.+)$/.exec(e);if(!t)return {provider:null,ticker:e};let n=t[1]?Jt(t[1]):null,o=t[2],i=o.lastIndexOf("."),s=i>0?o.slice(i+1):void 0;return {provider:n,ticker:o,ext:s}}var Tl=class{constructor(){this.entries=new Map;this.changeListeners=new Set;this.waits=new Set;this.unresolvedCbs=new Set;}register(e,t){let n=Jt(e),o={name:n,provider:t,index:null,prefixIndex:null,byTicker:null,descriptors:[],settled:false,settle:Promise.resolve()};return this.entries.set(n,o),o.settle=this.buildIndex(o),queueMicrotask(()=>this.notify(false)),o.settle}async buildIndex(e){await Promise.resolve();try{if(e.provider.listSymbols){let t=await e.provider.listSymbols();e.descriptors=t,e.index=new Set(t.map(n=>xn(n.ticker))),e.byTicker=new Map(t.map(n=>[xn(n.ticker),n])),e.prefixIndex=new Map;for(let n of t)n.prefix&&e.prefixIndex.set(`${Jt(n.prefix)}:${xn(n.ticker)}`,n);}}catch{e.index=null;}finally{e.settled=true,this.notify(true);}}notify(e){for(let t of [...this.changeListeners])t(e);}onChange(e){return this.changeListeners.add(e),()=>this.changeListeners.delete(e)}unregister(e){this.entries.delete(Jt(e)),this.notify(false);}has(e){return this.entries.has(Jt(e))}get(e){return this.entries.get(Jt(e))?.provider}names(){return [...this.entries.keys()]}parse(e){return en(e)}resolve(e,t={}){let{provider:n,ticker:o}=this.parse(e);if(n){if(this.entries.has(n)){let a=this.entries.get(n).byTicker?.get(xn(o));return {provider:n,ticker:a!=null&&Pi(a)?this.loadableTicker(n,a):o}}let s=`${n}:${xn(o)}`;for(let a of this.candidateOrder(t.default)){let l=this.entries.get(a).prefixIndex?.get(s);if(l)return {provider:a,ticker:this.loadableTicker(a,l)}}return null}let i=xn(o);for(let s of this.candidateOrder(t.default)){let a=this.entries.get(s);if(a.index?.has(i)){let l=a.byTicker?.get(i);return {provider:s,ticker:l!=null&&Pi(l)?this.loadableTicker(s,l):o}}}if(t.lenient&&this.entries.size===1){let s=this.names()[0],a=this.entries.get(s);if(a.settled&&a.index==null)return {provider:s,ticker:o}}return null}loadableTicker(e,t){return Pi(t)?Of(this.entries.get(e)?.descriptors??[],t)?.ticker??t.ticker:t.ticker}whenResolvable(e,t={}){let n=this.resolve(e,{...t,lenient:true});return n?Promise.resolve(n):new Promise(o=>{let i=this.onChange(a=>{let l=this.resolve(e,{...t,lenient:true});l?(s(),o(l)):a&&this.allSettled()&&this.reportUnresolved(e);}),s=()=>{i(),this.waits.delete(s);};this.waits.add(s);})}allSettled(){for(let e of this.entries.values())if(!e.settled)return false;return true}cancelWaits(){for(let e of [...this.waits])e();}onUnresolved(e){return this.unresolvedCbs.add(e),()=>this.unresolvedCbs.delete(e)}reportUnresolved(e){let t=this.names();console.warn(`[vela] symbol "${e}" not yet resolvable \u2014 registered providers: [${t.join(", ")||"none"}]. Register a provider that serves it.`);for(let n of this.unresolvedCbs)n({symbol:e,providers:t});}candidateOrder(e){let t=this.names();if(e){let n=Jt(e);if(this.entries.has(n))return [n,...t.filter(o=>o!==n)]}return t}displayPrefixOf(e){return this.entries.get(e.provider)?.byTicker?.get(xn(e.ticker))?.prefix??e.provider}canonicalSymbol(e){let t=this.entries.get(e.provider)?.byTicker?.get(xn(e.ticker));return `${t?.prefix??e.provider}:${t?.ticker??e.ticker}`}symbolIconOf(e){let t=e.provider?Jt(e.provider):[...this.entries.keys()][0],n=t!==void 0?this.entries.get(t):void 0;try{return n?.provider.resolveSymbolIcon?.(e)??void 0}catch{return}}symbolIcon(e){if(!e)return;let t=this.entries.get(e.provider)?.byTicker?.get(xn(e.ticker));return this.symbolIconOf({...t??{ticker:e.ticker},provider:t?.provider??e.provider})}symbolsOf(e){return e!=null?this.entries.get(Jt(e))?.descriptors??[]:[...this.entries.entries()].flatMap(([t,n])=>n.descriptors.map(o=>({...o,provider:t})))}infoOf(e){let t=Jt(e),n=this.entries.get(t);if(!n)return {name:t,capabilities:{enumerate:false,stream:false,symbolInfo:false}};let o=n.provider;return o.info?.()??{name:n.name,capabilities:{enumerate:!!o.listSymbols,stream:!!o.subscribe,symbolInfo:!!o.getSymbolInfo}}}indexReady(){return Promise.all([...this.entries.values()].map(e=>e.settle)).then(()=>{})}};function mo(r){switch(r.kind){case "row":return {label:r.label,toggle:r.toggle,controls:r.controls,when:r.when};case "toggle":{let e=[];r.number&&e.push({kind:"number",...r.number});for(let t of r.colors??[])e.push({kind:"color",...t});return r.width&&e.push({kind:"width",...r.width}),{label:r.label,toggle:{key:r.key,defval:r.defval},controls:e,when:r.when}}case "number":return {label:r.label,controls:[{kind:"number",key:r.key,label:r.label,defval:r.defval,min:r.min,max:r.max,step:r.step}],when:r.when};case "color":return {label:r.label,controls:[{kind:"color",key:r.key,label:r.label,defval:r.defval}],when:r.when};case "select":return {label:r.label,controls:[{kind:"select",key:r.key,label:r.label,options:r.options,defval:r.defval}],when:r.when};case "range":return {label:r.label,controls:[{kind:"number",key:r.minKey,label:`${r.label} \u2014 min`,defval:r.defval,min:r.min,max:r.max,step:r.step,placeholder:r.placeholder},{kind:"hint",text:"\u2013"},{kind:"number",key:r.maxKey,label:`${r.label} \u2014 max`,defval:r.defval,min:r.min,max:r.max,step:r.step,placeholder:r.placeholder}],when:r.when}}}function Ii(r){if(r.kind==="heading"||r.kind==="header")return [];let e=mo(r),t=[];e.toggle&&t.push({key:e.toggle.key,type:"boolean",defval:e.toggle.defval});for(let n of e.controls)n.kind!=="hint"&&(n.kind==="color"||n.kind==="select"?t.push({key:n.key,type:"string",defval:n.defval}):t.push({key:n.key,type:"number",defval:n.defval}));return t}function Pr(r,e){return r?(Array.isArray(r)?r:[r]).every(n=>n.anyOf?n.anyOf.some(o=>o===e[n.key]):e[n.key]===n.equals):true}var Ai=new Map;function du(r){Ai.set(r.id,r);}function K1(r){Ai.delete(r);}function Sn(r){return typeof r=="string"?Ai.get(r):void 0}function xt(){return [...Ai.values()]}function uu(){return [...Ai.values()].filter(r=>r.tickerModifier??r.barTransform!=null).map(r=>r.id)}function fo(r){return Sn(r)?.barTransform??null}function Nf(r){let e=r.lastIndexOf(";");if(e<=0||e===r.length-1)return {symbol:r,modifier:null,transform:null};let t=r.slice(e+1).toLowerCase();return t!=="standard"&&!uu().includes(t)?{symbol:r,modifier:null,transform:null}:{symbol:r.slice(0,e),modifier:t,transform:fo(t)}}var tn={background:"#151619",textColor:"#b2b5be",gridColor:"#20222c",borderColor:"#2a2b30",upColor:O,downColor:D,fontFamily:"sans-serif"},Ri={background:"#ffffff",textColor:"#1e293b",gridColor:"#cccccc",borderColor:"#d4dae3",upColor:O,downColor:D,fontFamily:"sans-serif"};function go(r){return !r||r==="dark"?tn:r==="light"?Ri:r}var X1=150,j1=1e3,q1=300,Z1=5e3,Ff=1e4,Q1=20,J1=1.5,Vf=5e3,ek=16,kl=class r{constructor(e,t,n,o,i,s){this.renderer=t;this.feed=n;this.config=i;this.dataControl=s;this.events=new ur;this.registry=new sa;this.paneOrder=["price"];this.collapsedPanes=new Set;this.maximizedPaneId=null;this.paneActionUnsub=null;this.handles=new Map;this.engines=new Map;this.live=null;this.bars=[];this.rawBars=[];this.barTransform=null;this.typeEngines=new Map;this.typeSettings=new Map;this.activeEngineStyle=null;this.priceStyle="candles";this.priceStyleWillChangeUnsub=null;this.unresolvedUnsub=null;this.visibleRange=null;this.viewportUnsub=null;this.viewportTimer=null;this.healing=false;this.healBuffer=[];this.lastHealAt=0;this.onVisible=null;this.replayQueue=null;this.replayTimer=null;this.replayPlaying=false;this.replayIntervalMs=1e3;this.replayDepth=null;this.replayLoading=null;this.replayCarrying=null;this.replayTickSource=null;this.replayForming=null;this.replayTickFetches=new Map;this.replayTickAbort=null;this.barCause="tick";this.historyState="complete";this.generation=0;this.progressiveAbort=null;this.supersedeWaiters=[];this.historyCompleted=false;this.historyCompletePromise=new Promise(e=>{this.resolveHistoryComplete=e;});this.switchingMarket=false;this.loadingUp=false;this.volumeOptedOut=false;this.contextEmitAt=new Map;this.runEmitAt=new Map;for(let c of o)this.registerEngine(c.language,c);this.defaultLanguage=i.defaultLanguage,this.renderer.mount(e,i.theme),this.renderer.onInputChange(c=>c.kind==="prop"?this.applyProps(c.indicatorId,{[c.key]:c.value}):this.applyInputs(c.indicatorId,{[c.key]:c.value})),this.renderer.onRemoveIndicator(c=>this.removeIndicator(c)),this.renderer.onToggleIndicatorVisible?.((c,d)=>this.setVisible(c,d)),this.paneActionUnsub=this.renderer.onPaneAction?.(c=>this.handlePaneAction(c))??null,this.renderer.onChartTypeSettingsChange?.((c,d)=>{this.typeSettings.set(c,d),this.typeEngines.get(c)?.onSettings?.(d);}),this.renderer.onMoveIndicator?.((c,d)=>this.moveIndicator(c,d)),this.renderer.onThemeSelect?.(c=>this.setTheme(go(c))),this.viewportUnsub=this.renderer.onViewportChange(c=>this.onViewportChange(c)),this.renderer.onPriceStyleChange?.(c=>this.syncPriceStyle(c)),this.priceStyleWillChangeUnsub=this.renderer.onPriceStyleWillChange?.((c,d)=>this.events.emit("priceStyle:change",{from:c,to:d}))??null;let a=this.renderer.readFeature("priceStyle");typeof a=="string"&&(this.priceStyle=a),this.barTransform=fo(a);let l=new Cl({fetchBars:(c,d)=>this.fetchSeries(this.config.market.symbol??"",c,d),canFetch:()=>!!this.feed.loadRange&&!this.config.market.data?.length&&!!this.config.market.symbol,chartTimeframe:()=>this.config.market.timeframe??"60",marketKey:()=>`${this.config.market.symbol??""}|${this.config.market.session??""}`});this.drawings=new yl(this.renderer,this.events,i.drawings,l),this.marks=new Sl(this.renderer,this.events),this.unresolvedUnsub=this.feed.onUnresolved?.(c=>{this.endLoad(),this.events.emit("data:unresolved",c);})??null,this.readyPromise=this.init(),Sn(a)?.dataEngine&&this.syncChartTypeEngine(a);}currentVisibleRange(){if(this.visibleRange)return this.visibleRange;let e=this.renderer.getVisibleRange();return e?{left:e.from,right:e.to}:void 0}engineFor(e){let t=e??this.defaultLanguage,n=this.engines.get(t);if(!n)throw new Error(`[vela] no scripting engine registered for language "${t}". Vela ships none \u2014 install one (Pine Script: @luxalgo/vela-pinets) and register it before addIndicator, e.g. chart.registerEngine('pine', new PineEngine()).`);return n}market(){return {symbol:this.config.market.symbol??"TEST",timeframe:this.config.market.timeframe??"60",symbolInfo:this.feed.symbolInfo?.(this.config.market),chartStyle:this.priceStyle}}async fetchSeries(e,t,n){let o=Nf(e),i={symbol:o.symbol,timeframe:t},s=await(this.feed.loadRange?this.feed.loadRange(i,n):this.feed.load({...i,bars:n.limit}));return o.transform?o.transform.full(s):s}onViewportChange(e){this.visibleRange={left:e.from,right:e.to},this.events.emit("viewport:changed",{from:e.from,to:e.to}),this.viewportTimer!=null&&clearTimeout(this.viewportTimer),this.viewportTimer=setTimeout(()=>{if(this.viewportTimer=null,this.switchingMarket)return;let t=this.visibleRange;if(t){for(let n of this.registry.all())!n.renderHandle||n.hidden||(n.session&&n.prepared?.reactsToViewport?(n.pendingCause="viewport",n.session.setVisibleRange(t)):n.native?.descriptor.reactsToViewport&&n.native.instance.onViewport({from:t.left,to:t.right}));this.activeEngineStyle&&this.typeEngines.get(this.activeEngineStyle)?.onViewport?.({from:t.left,to:t.right});}},X1);}async init(){let e=this.bumpGeneration();this.beginLoad(true),await this.loadMarket(e,{firstLoad:true}),this.generation===e&&(this.startLive(),this.events.emit("ready",void 0));}bumpGeneration(){let e=++this.generation;this.progressiveAbort?.abort(),this.progressiveAbort=null;for(let t of this.supersedeWaiters.splice(0))t();return e}beginLoad(e){if(this.loadingUp)return;this.loadingUp=true,this.renderer.setLoading?.(true);let t=this.config.market;this.events.emit("load:start",{symbol:t.symbol??"TEST",timeframe:t.timeframe??"60",firstLoad:e});}endLoad(){if(!this.loadingUp)return;this.loadingUp=false,this.renderer.setLoading?.(false);let e=this.config.market;this.events.emit("load:end",{symbol:e.symbol??"TEST",timeframe:e.timeframe??"60",bars:this.bars.length});}async loadMarket(e,t){try{await this.loadMarketInner(e,t);}finally{this.generation===e&&this.endLoad();}}async loadMarketInner(e,t){let n=this.config.market,o=n.bars??500,i=n.visibleRange,s=!n.data?.length&&i==null&&o>Z1,a=false;if(!n.data?.length&&i==null&&this.feed.loadProgressive){let l=false,c=(u,h)=>{if(!(this.generation!==e||!h&&u.length===0)&&!(!l&&!h&&u.length0&&(l=true,t.firstLoad&&this.activateBarLayers(),h||(this.historyState="backfill"));}},d=new AbortController;this.progressiveAbort=d,a=await new Promise(u=>{let h=false,p=m=>{h||(h=true,u(m));};d.signal.addEventListener("abort",()=>p(true),{once:true}),this.feed.loadProgressive(n,m=>{c(m,false),l&&p(true);},{signal:d.signal}).then(m=>{if(this.progressiveAbort===d&&(this.progressiveAbort=null),m==null)return p(false);if(this.generation!==e)return p(true);c(m,true),this.completeHistory(m.length>=o?"depth":"genesis"),p(true);}).catch(()=>{this.progressiveAbort===d&&(this.progressiveAbort=null),this.generation===e&&this.completeHistory("aborted"),p(true);});});}if(!a)if(s&&this.feed.loadRange){let l=await this.feed.load({...n,bars:Math.min(o,Ff)});if(this.generation!==e)return;this.setBarSeries(l),t.firstLoad&&this.activateBarLayers(),l.length>0&&o>l.length?(this.historyState="backfill",this.backfillHistory(e,o)):this.completeHistory("depth");}else if(s){let l=await this.feed.load({...n,bars:q1});if(this.generation!==e)return;this.setBarSeries(l),t.firstLoad&&this.activateBarLayers();let c=await this.feed.load(n);if(this.generation!==e)return;this.setBarSeries(c,{preserveView:true}),this.completeHistory("depth");}else {let l=await this.feed.load(n);if(this.generation!==e)return;this.setBarSeries(l),t.firstLoad&&this.activateBarLayers(),this.completeHistory("depth");}i!=null&&(typeof i=="string"?this.setVisibleRangePreset(i):this.renderer.setVisibleRange(i)),this.refreshPriceFormat(),this.ensurePriceFormat();}startLive(){this.config.live&&(this.live=new la(this.feed,this.config.market,e=>this.onBar(e)),this.live.start(),typeof document<"u"&&(this.onVisible=()=>{if(document.visibilityState!=="visible")return;let e=this.bars[this.bars.length-1];!e||this.healing||!this.canHeal()||Date.now()-this.lastHealAt<=Vf||this.healGap(e.time);},document.addEventListener("visibilitychange",this.onVisible)));}stopLive(){this.live?.stop(),this.live=null,this.onVisible&&typeof document<"u"&&document.removeEventListener("visibilitychange",this.onVisible),this.onVisible=null,this.healing=false,this.healBuffer=[],this.lastHealAt=0;}resetHistoryTracking(){this.resolveHistoryComplete(),this.historyCompleted=false,this.historyState="complete",this.historyCompletePromise=new Promise(e=>{this.resolveHistoryComplete=e;});}marketSnapshot(){let e=this.config.market;return {symbol:e.symbol,provider:en(e.symbol??"").provider??void 0,timeframe:e.timeframe,bars:e.bars,session:e.session,offline:e.data!==void 0}}async setMarket(e){let t=this.config.market,n=e.symbol!==void 0&&e.symbol!==t.symbol||e.timeframe!==void 0&&e.timeframe!==t.timeframe||e.session!==void 0&&e.session!==t.session||e.data!==void 0,o=e.bars!==void 0&&e.bars!==t.bars,i=n&&e.data===void 0&&(e.symbol===void 0||e.symbol===t.symbol)&&(e.timeframe!==void 0||e.session!==void 0),s=n?this.replayCarrying:null;s&&(this.replayCarrying=null,i||(s.cancelled=true,this.events.emit("replay:end",{reason:"market"})));let a=this.replayQueue&&i&&this.rawBars.length>0?{revealedEnd:this.rawBars[this.rawBars.length-1].time+this.barIntervalMs(),playing:this.replayPlaying,cancelled:false}:s&&i?{revealedEnd:s.revealedEnd,playing:s.playing,cancelled:false}:null;if(s&&(s.cancelled=true),a&&(this.replayCarrying=a),a&&this.replayQueue){this.endReplay(null,{restore:false,resume:false});let y=this.replayDepth;this.replayDepth=null,y&&e.bars===void 0&&(y.bars===void 0?delete t.bars:t.bars=y.bars);}if(this.replayQueue&&(n||o)&&this.endReplay("market",{restore:!n,resume:false}),this.replayLoading&&(n||o)){let y=this.replayDepth;this.abandonReplayLoad("market"),y&&e.bars===void 0&&(y.bars===void 0?delete t.bars:t.bars=y.bars);}let l=o&&!n&&this.rawBars.length>0&&!t.data?.length&&((e.bars??0)<=this.rawBars.length||typeof this.feed.loadRange=="function");if(!n&&!o){typeof e.visibleRange=="string"?this.setVisibleRangePreset(e.visibleRange):e.visibleRange&&this.renderer.setVisibleRange(e.visibleRange);return}let c={symbol:t.symbol??"TEST",timeframe:t.timeframe??"60"},u=n&&e.session!==void 0&&e.data===void 0&&(e.symbol===void 0||e.symbol===t.symbol)&&(e.timeframe===void 0||e.timeframe===t.timeframe)&&e.visibleRange===void 0?this.currentVisibleRange():void 0,h=u?this.rawBars.filter(y=>y.time>=u.left&&y.time<=u.right).length:0,p=this.bumpGeneration();this.switchingMarket=true;try{if(this.stopLive(),this.viewportTimer!=null&&(clearTimeout(this.viewportTimer),this.viewportTimer=null),this.visibleRange=null,this.resetHistoryTracking(),e.symbol!==void 0&&(t.symbol=e.symbol),e.timeframe!==void 0&&(t.timeframe=e.timeframe),e.bars!==void 0&&(t.bars=e.bars),e.session!==void 0&&(t.session=e.session),u){let y=Math.min(Math.ceil((Date.now()-u.left)/this.barIntervalMs())+50,5e3);y>(t.bars??500)&&(t.bars=y);}if(e.data!==void 0?t.data=e.data:e.symbol!==void 0&&delete t.data,t.visibleRange=e.visibleRange??(u?{from:u.left,to:u.right}:void 0),n&&(this.beginLoad(!1),this.setBarSeries([],{clearing:!0}),this.blankIndicatorVisuals(),this.activeEngineStyle&&(this.typeEngines.get(this.activeEngineStyle)?.suspend(),this.renderer.setNativeData?.(this.activeEngineStyle,void 0),this.renderer.setNativeData?.(`${this.activeEngineStyle}-pending`,[]))),l?this.extendDepth(p,t.bars??500):await Promise.race([this.loadMarket(p,{firstLoad:!1}),new Promise(y=>this.supersedeWaiters.push(y))]),this.generation!==p)return}finally{this.generation===p&&(this.switchingMarket=false);}if(u&&h>=2&&this.rawBars.length>0){let y=this.rawBars,w=y.length-1;for(;w>0&&y[w].time>u.right;)w-=1;let S=y[Math.max(0,w-(h-1))].time;this.renderer.setVisibleRange({from:S,to:Math.max(u.right,y[w].time+1)});}let m=a&&!a.cancelled?a:null,f=m?m.revealedEnd-this.barIntervalMs():0,g=m!=null&&this.rawBars.length>0&&f>=this.rawBars[0].time,b=g&&this.resumeCarriedReplay(this.replayStart({from:f}),m);!l&&!b&&(this.restartNativeIndicators(),this.restartChartTypeEngine(),this.reexecuteIndicators()),b||this.startLive(),n&&this.events.emit("market:changed",{symbol:t.symbol??"TEST",timeframe:t.timeframe??"60",prev:c}),m&&!g&&this.resumeCarriedReplay(this.replayStart({from:f}),m);}restartNativeIndicators(){for(let e of this.registry.all())if(e.native)if(e.native.started&&e.native.instance.stop(),e.native.instance=e.native.descriptor.create(),e.native.started=false,e.pendingStructural=true,e.hidden)e.native.stale=true;else {let t=this.handles.get(e.id);t&&this.startNativeIndicator(e.id,t);}}restartChartTypeEngine(){for(let e of this.typeEngines.values())e.stop();this.typeEngines.clear(),this.activeEngineStyle&&this.startChartTypeEngine(this.activeEngineStyle);}activateBarLayers(){this.maybeAutoAddVolume();}extendDepth(e,t){if(this.rawBars.length>t){this.setBarSeries(this.rawBars.slice(this.rawBars.length-t),{preserveView:true}),this.completeHistory("depth");return}if(this.rawBars.length===t){this.completeHistory("depth");return}this.historyState="backfill",this.backfillHistory(e,t);}async backfillHistory(e,t){try{for(;this.generation===e&&this.rawBars.length0;){let n=t-this.rawBars.length,o=Ff,i=await this.feed.loadRange(this.config.market,{to:this.rawBars[0].time,limit:Math.min(o,n)+1});if(this.generation!==e)return;let s=this.rawBars[0].time,a=i.filter(l=>l.time=o.length){console.warn("[vela] chart.replay.start() ignored \u2014 no bar opens after the requested time");return}let s=this.replayPlaying;this.clearReplayTimer(),this.replayQueue||this.stopLive(),this.replayQueue=o.slice(i),this.setBarSeries(o.slice(0,i)),this.restartBarConsumers({blank:true}),s&&this.events.emit("replay:pause",void 0),this.events.emit("replay:start",{cursorTime:o[i-1].time,remaining:this.replayQueue.length}),this.prefetchTicks();}replayStep(){if(this.replayForming)return this.finishFormingBar(),true;let e=this.replayQueue,t=e?.shift();return !e||!t?false:(this.replayTickFetches.delete(t.time),this.applyBar(t),this.completeReveal(t),this.prefetchTicks(),true)}resumeCarriedReplay(e,t){return this.replayQueue&&this.replayCarrying===t&&(this.replayCarrying=null),e.then(()=>{this.replayCarrying===t&&(this.replayCarrying=null),!t.cancelled&&(this.replayQueue?t.playing&&this.replayPlay():this.events.emit("replay:end",{reason:"market"}));}),this.replayQueue!==null}replayStepUpdate(){if(!this.replayQueue)return false;if(this.replayForming)return this.applyReplayTicks(1),true;let e=this.replayQueue[0];if(!e)return false;let t=this.replayTickSource?this.requestTicks(e):null;if(t&&!t.ticks){let n=this.replayTickAbort;return t.done.then(()=>{!this.replayPlaying&&!this.replayForming&&this.replayTickAbort===n&&this.replayQueue?.[0]===e&&this.replayStepUpdate();}),true}return t?.ticks?.length?(this.openFormingBar(t.ticks,1),true):this.replayStep()}replaySetTicks(e){this.finishFormingBar(),this.dropTickFetches(),this.replayTickSource=e,this.prefetchTicks();}replayPlay(e){if(this.replayQueue){if(e!==void 0){if(!(Number.isFinite(e)&&e>0)){console.warn(`[vela] chart.replay.play(${e}) ignored \u2014 the interval must be a positive number of ms`);return}this.replayIntervalMs=e;}this.clearReplayTimer(),this.replayPlaying=true,this.replayForming&&this.paceFormingBar(this.replayForming),this.scheduleReplayStep(this.replayForming?.delayMs),this.events.emit("replay:play",{intervalMs:this.replayIntervalMs});}}replayPause(){this.replayPlaying&&(this.clearReplayTimer(),this.events.emit("replay:pause",void 0));}replayStop(){let e=this.replayCarrying;if(e&&(e.cancelled=true,this.replayCarrying=null,this.events.emit("replay:end",{reason:"stopped"})),this.replayLoading){let t=this.replayDepth;this.abandonReplayLoad("stopped"),this.setMarket({bars:t?.bars??500});return}this.endReplay("stopped",{restore:true,resume:true});}abandonReplayLoad(e){let t=this.replayLoading;t&&(this.replayLoading=null,this.replayDepth=null,t.seek&&this.events.emit("replay:end",{reason:e}));}replayState(){let e=this.replayQueue!==null;return {active:e||this.replayCarrying!==null,playing:this.replayCarrying?.playing??this.replayPlaying,cursorTime:e?this.rawBars[this.rawBars.length-1]?.time??null:null,remaining:this.replayQueue?.length??0,nextTime:this.replayForming?.bar.time??this.replayQueue?.[0]?.time??null,intervalMs:this.replayIntervalMs}}replayBounds(){let e=this.rawBars[0],t=this.replayQueue?.[this.replayQueue.length-1]??this.rawBars[this.rawBars.length-1];return e&&t?{first:e.time,last:t.time}:null}scheduleReplayStep(e=this.replayIntervalMs){this.replayTimer=setTimeout(()=>{this.replayTimer=null,this.replayAdvance();},e);}replayAdvance(){if(!this.replayPlaying||!this.replayQueue)return;let e=this.replayForming;if(e){let o=Math.floor((Bf()-e.origin)/this.replayIntervalMs)+1;this.applyReplayTicks(Math.max(e.batch,o-e.next)),this.replayPlaying&&this.scheduleReplayStep(e.delayMs);return}let t=this.replayQueue[0];if(!t)return;let n=this.replayTickSource?this.requestTicks(t):null;if(n&&!n.ticks){let o=this.replayTickAbort;n.done.then(()=>{this.replayPlaying&&this.replayTimer==null&&this.replayTickAbort===o&&this.replayQueue?.[0]===t&&this.replayAdvance();});return}if(!n?.ticks?.length){this.replayStep()&&this.replayPlaying&&this.scheduleReplayStep();return}this.openFormingBar(n.ticks),this.replayPlaying&&this.scheduleReplayStep(this.replayForming?.delayMs);}openFormingBar(e,t){let n=this.replayQueue.shift(),o=e.every(s=>s.volume===void 0)?(n.volume??0)/e.length:null,i={bar:n,ticks:e,next:0,candle:null,volumeEach:o,batch:1,delayMs:this.replayIntervalMs,origin:0};this.paceFormingBar(i),this.replayForming=i,this.applyReplayTicks(t??i.batch),this.prefetchTicks();}paceFormingBar(e){e.batch=Math.max(1,Math.ceil(ek/this.replayIntervalMs)),e.delayMs=this.replayIntervalMs*e.batch,e.origin=Bf()-Math.max(0,e.next-1)*this.replayIntervalMs;}applyReplayTicks(e){let t=this.replayForming;if(!t)return;let n=t.candle,o=Math.min(t.ticks.length,t.next+e);for(;t.next=t.ticks.length){this.finishFormingBar();return}this.applyBar(n),this.events.emit("replay:tick",{cursorTime:t.bar.time,index:t.next-1,count:t.ticks.length});}finishFormingBar(){let e=this.replayForming;e&&(this.replayForming=null,this.replayTickFetches.delete(e.bar.time),this.applyBar(e.bar),this.events.emit("replay:tick",{cursorTime:e.bar.time,index:e.ticks.length-1,count:e.ticks.length}),this.completeReveal(e.bar));}settleFormingBar(){let e=this.replayForming;e&&(this.replayForming=null,this.applyBar(e.bar));}mergeHistoryIntoReplay(e){let t=this.replayQueue,n=this.rawBars[0];if(!t||!n)return;let o=t[t.length-1]??this.rawBars[this.rawBars.length-1],i=0;for(;ii&&e[s-1].time>o.time;)s-=1;s0&&(this.setBarSeries([...e.slice(0,i),...this.rawBars],{preserveView:true}),this.notifySessionsBars("backfill"));}completeReveal(e){let t=this.replayQueue;t&&(this.events.emit("replay:step",{cursorTime:e.time,remaining:t.length}),t.length===0&&this.endReplay("finished",{restore:true,resume:true}));}prefetchTicks(){let e=this.replayQueue?.[0];e&&this.replayTickSource&&this.requestTicks(e);}requestTicks(e){let t=this.replayTickFetches.get(e.time);if(t)return t;let n=this.replayTickSource;this.replayTickAbort??(this.replayTickAbort=new AbortController);let o=this.replayTickAbort.signal,i=this.replayQueue??[],s=i[i.indexOf(e)+1]?.time??e.time+this.barIntervalMs(),a={ticks:null,done:Promise.resolve()},l=d=>{a.ticks=tk(d);},c=d=>{o.aborted||console.warn(`[vela] replay tick source failed \u2014 revealing the bar whole (${d instanceof Error?d.message:String(d)})`),l([]);};try{let d=n(e,{end:s,signal:o});Array.isArray(d)?l(d):a.done=Promise.resolve(d).then(l,c);}catch(d){c(d);}return this.replayTickFetches.set(e.time,a),a}dropTickFetches(){this.replayTickAbort?.abort(),this.replayTickAbort=null,this.replayTickFetches.clear();}clearReplayTimer(){this.replayTimer!=null&&clearTimeout(this.replayTimer),this.replayTimer=null,this.replayPlaying=false;}endReplay(e,t){let n=this.replayQueue;if(!n)return;this.clearReplayTimer(),t.restore?this.settleFormingBar():this.replayForming=null,this.dropTickFetches(),this.replayQueue=null;let o=e?this.replayDepth:null;if(e&&(this.replayDepth=null),o&&(o.bars===void 0?delete this.config.market.bars:this.config.market.bars=o.bars),t.restore){let i=o?o.bars??500:1/0;if(n.length>0||this.rawBars.length>i){let s=[...this.rawBars,...n];this.setBarSeries(s.length>i?s.slice(s.length-i):s),this.restartBarConsumers({blank:false});}else this.config.live&&(this.restartNativeIndicators(),this.restartChartTypeEngine());}if(t.resume&&this.config.live){this.startLive();let i=this.rawBars[this.rawBars.length-1];i&&this.canHeal()&&this.healGap(i.time);}e&&this.events.emit("replay:end",{reason:e});}restartBarConsumers(e){e.blank&&this.blankIndicatorVisuals(),this.restartNativeIndicators(),this.restartChartTypeEngine(),this.reexecuteIndicators();}qualifiedSymbol(){let e=this.config.market;return e.symbol?e.symbol:null}refreshPriceFormat(){if(!this.renderer.setPricePrecision)return;let e=this.feed.symbolInfo?.(this.config.market)?.mintick;this.renderer.setPricePrecision(typeof e=="number"&&e>0?e:void 0);}async ensurePriceFormat(){if(!this.renderer.setPricePrecision)return;let e=this.qualifiedSymbol();if(e)try{await this.dataControl.symbolInfo(e),this.refreshPriceFormat();}catch{}}maybeAutoAddVolume(){!this.config.volume||this.volumeOptedOut||!this.renderer.setNativeData||mi("volume")&&this.addNativeIndicator("volume");}syncPriceStyle(e){typeof e=="string"&&(this.priceStyle=e),this.syncBarTransform(e),this.syncChartTypeEngine(e);}syncChartTypeEngine(e){let t=typeof e=="string"?e:null,o=Sn(t)?.dataEngine?t:null;o!==this.activeEngineStyle&&(this.activeEngineStyle&&this.typeEngines.get(this.activeEngineStyle)?.suspend(),this.activeEngineStyle=o,o&&this.startChartTypeEngine(o));}async startChartTypeEngine(e){if(!this.renderer.setNativeData||(await this.readyPromise,this.activeEngineStyle!==e))return;let t=this.typeEngines.get(e);if(t){t.resume();return}let n=Sn(e);if(!n?.dataEngine)return;let o=n.dataEngine();this.typeEngines.set(e,o);let i=this.typeSettings.get(e);i&&o.onSettings?.(i),o.start({symbol:this.config.market.symbol??"TEST",timeframe:this.config.market.timeframe??"60",live:(this.config.live??false)&&this.replayQueue===null,session:this.config.market.session,bars:()=>this.bars,data:this.dataControl,pushData:s=>this.renderer.setNativeData?.(e,s),pushPending:s=>this.renderer.setNativeData?.(`${e}-pending`,s)});}syncBarTransform(e){let t=fo(e);t!==this.barTransform&&(this.barTransform=t,this.rawBars.length!==0&&(this.bars=t?t.full(this.rawBars):this.rawBars,this.renderer.setBars(this.bars,{preserveView:true}),this.reexecuteIndicators()));}blankIndicatorVisuals(){for(let e of this.registry.all())e.hidden||!e.renderHandle||!e.model||(e.model=ok(e.model),e.renderHandle=this.renderer.mountIndicator(e.model),e.pendingStructural=true,this.setLoading(e,true));}reexecuteIndicators(){for(let e of this.registry.all()){if(e.hidden||!e.session)continue;e.session.stop(),e.session=void 0,e.pendingStructural=true,e.pendingCause="market",this.setLoading(e,true);let t=this.handles.get(e.id);t&&this.executeIndicator(e.id,t);}}onBar(e){if(this.healing){this.healBuffer.push(e);return}let t=this.rawBars[this.rawBars.length-1];if(t&&this.canHeal()&&e.time>t.time+this.barIntervalMs()*J1&&Date.now()-this.lastHealAt>Vf){this.healBuffer.push(e),this.healGap(t.time);return}this.applyBar(e);}setBarSeries(e,t){this.rawBars=e,this.bars=this.barTransform?this.barTransform.full(e):e,this.renderer.setBars(this.bars,{preserveView:t?.preserveView}),!t?.clearing&&this.bars.length>0&&this.endLoad();}applyBar(e,t=true){let n=this.rawBars[this.rawBars.length-1],o=e;if(n&&e.time===n.time)this.rawBars[this.rawBars.length-1]=e,this.barCause="tick",this.barTransform&&(o=this.barTransform.next(e,this.bars[this.bars.length-2]),this.bars[this.bars.length-1]=o);else if(!n||e.time>n.time)this.rawBars.push(e),this.barCause="bar",this.barTransform&&(o=this.barTransform.next(e,this.bars[this.bars.length-1]),this.bars.push(o));else return;this.renderer.updateBar(o),this.events.emit("bar",e),t&&this.notifySessionsBars(this.historyState==="backfill"?"backfill":void 0);}notifySessionsBars(e){if(this.switchingMarket)return;let t=e?"history":this.barCause;for(let n of this.registry.all())!n.renderHandle||n.hidden||(n.session?(n.pendingCause=t,n.session.notifyBars(e)):n.native&&n.native.instance.onBars());this.activeEngineStyle&&this.typeEngines.get(this.activeEngineStyle)?.onBars?.();}canHeal(){return !!this.feed.loadRange&&!this.config.market.data?.length}barIntervalMs(){return Ft(this.config.market.timeframe??"60")}async healGap(e){let t=this.generation;this.healing=true,this.lastHealAt=Date.now();try{let n=await this.feed.loadRange(this.config.market,{from:e});if(this.generation!==t||this.replayQueue)return;for(let o of n)this.applyBar(o,!1);}catch{}finally{if(this.generation===t&&!this.replayQueue){this.healing=false;let n=this.healBuffer;this.healBuffer=[];for(let o of n)this.applyBar(o,false);this.notifySessionsBars(this.historyState==="backfill"?"backfill":void 0);}}}registerEngine(e,t){let n=this.engines.get(e);n&&n!==t&&console.warn(`[vela] re-registering scripting engine for language "${e}"; replacing ${n.constructor.name} with ${t.constructor.name}.`),this.engines.set(e,t);}addIndicator(e,t={}){let n=this.claimIndicatorId(t.id),o=t.title??"Indicator",i=new ro(n,o,this,e);return this.handles.set(n,i),this.registry.add({id:n,title:o,source:e,options:t,inputValues:{...t.inputs??{}},propValues:{...t.props??{}}}),this.startIndicator(n,e,t,i),i}addNativeIndicator(e,t={}){let n=mi(e);if(!n?.multiInstance){let l=this.registry.all().find(c=>c.native?.type===e);if(l)return this.handles.get(l.id)??new ro(l.id,l.title,this,void 0,e)}let o=this.registry.nextId("native",l=>this.handles.has(l)),i=n?.title??e,s=new ro(o,i,this,void 0,e);if(this.handles.set(o,s),!n)return console.warn(`[vela] addNativeIndicator("${e}") \u2014 no native indicator registered for this type.`),s;let a={...n.defaultInputs(),...t.inputs??{}};return this.registry.add({id:o,title:i,source:e,inputValues:a,propValues:{},native:{type:e,instance:n.create(),descriptor:n}}),s.setSchema(n.inputsSchema()),this.startNativeIndicator(o,s),s}presentNativeIndicators(){return this.registry.all().map(e=>e.native?.type).filter(e=>!!e)}async availableNativeIndicators(){let e=this.qualifiedSymbol(),t=new Set(this.presentNativeIndicators());return Promise.all(aa().map(async n=>({type:n.type,title:n.title,supported:await this.isNativeSupported(n,e),present:t.has(n.type),beta:n.beta,...n.multiInstance?{multiInstance:true}:{}})))}async isNativeSupported(e,t){if(!e.isSupported)return true;if(!t)return false;try{return await e.isSupported(t,this.dataControl)}catch{return false}}applyInputs(e,t){let n=this.registry.get(e);!n||!n.session&&!n.native||(n.inputValues={...n.inputValues,...t},n.renderHandle&&this.renderer.setIndicatorInputs(n.renderHandle,n.inputValues),n.pendingStructural=true,!n.hidden&&!n.native&&this.setLoading(n,true),n.pendingCause="inputs",n.session?n.session.update(n.inputValues):n.native&&!n.hidden&&n.native.instance.setInputs(n.inputValues),this.events.emit("indicator:inputs",{id:e}));}inputValuesOf(e){return {...this.registry.get(e)?.inputValues}}propValuesOf(e){return {...this.registry.get(e)?.propValues}}applyProps(e,t){let n=this.registry.get(e);n?.session&&(n.propValues={...n.propValues,...t},n.renderHandle&&this.renderer.setIndicatorInputs(n.renderHandle,n.inputValues,n.propValues),n.pendingStructural=true,n.hidden||this.setLoading(n,true),n.pendingCause="inputs",n.session.update(n.inputValues,n.propValues),this.events.emit("indicator:inputs",{id:e}));}updateCode(e,t){let n=this.registry.get(e),o=this.handles.get(e);return !n||!o?Promise.resolve({ok:false,error:new Error(`[vela] updateCode("${e}") \u2014 the indicator is no longer on the chart.`)}):n.native?(console.warn(`[vela] updateCode("${e}") \u2014 a native indicator has no script to update.`),Promise.resolve({ok:false,error:new Error(`[vela] updateCode("${e}") \u2014 a native indicator has no script to update.`)})):!(n.pendingSource!==void 0||n.codeTrial!==void 0)&&t===n.source?Promise.resolve({ok:true,error:null}):new Promise(s=>{(n.codeWaiters??(n.codeWaiters=[])).push(s),!(n.pendingSource===t||n.pendingSource===void 0&&n.codeTrial&&n.source===t)&&(n.pendingSource=t,this.swapSource(e,t,o));})}async swapSource(e,t,n){let o=this.registry.get(e)?.engine??this.engineFor(this.registry.get(e)?.options?.language),i;try{i=await o.prepare(t,e);}catch(l){let c=this.registry.get(e);c?.pendingSource===t&&(c.pendingSource=void 0,this.rejectCode(e,c,n,l));return}let s=this.registry.get(e);if(!s||s.pendingSource!==t)return;s.pendingSource=void 0;let a=s.codeTrial?.previous??{source:s.source,engine:s.engine,prepared:s.prepared,inputValues:s.inputValues,propValues:s.propValues,inputs:[...n.inputs],props:[...n.props]};if(s.inputValues=_f(i.inputs,s.inputValues,s.prepared?.inputs),s.propValues=_f(i.props??[],s.propValues,s.prepared?.props),s.source=t,s.engine=o,s.prepared=i,n.setSource(t),n.setSchema(i.inputs),n.setPropsSchema(i.props??[]),s.session?.stop(),s.session=void 0,s.pendingStructural=true,s.pendingCause="code",s.hidden){s.codeTrial=void 0,s.renderHandle&&this.renderer.setIndicatorInputs(s.renderHandle,s.inputValues,s.propValues),this.settleCode(s,{ok:true,error:null});return}s.codeTrial={previous:a},s.renderHandle?(this.renderer.setIndicatorInputs(s.renderHandle,s.inputValues,s.propValues),this.setLoading(s,true)):this.mountLoadingPlaceholder(e,s),this.executeIndicator(e,n),this.bars.length===0&&s.codeTrial&&(s.codeTrial=void 0,this.settleCode(s,{ok:true,error:null}));}settleCode(e,t){let n=e.codeWaiters;if(e.codeWaiters=void 0,n)for(let o of n)o(t);}rejectCode(e,t,n,o){let i=t.codeTrial;if(t.codeTrial=void 0,this.fail(e,n,o),i){let a=i.previous;t.session?.stop(),t.session=void 0,t.source=a.source,t.engine=a.engine,t.prepared=a.prepared,t.inputValues=a.inputValues,t.propValues=a.propValues,n.setSource(a.source),n.setSchema(a.inputs),n.setPropsSchema(a.props),t.pendingStructural=true,t.pendingCause=void 0,t.renderHandle&&this.renderer.setIndicatorInputs(t.renderHandle,t.inputValues,t.propValues),t.hidden||this.executeIndicator(e,n);}let s=o instanceof Error?o:new Error(String(o));this.settleCode(t,{ok:false,error:s});}listIndicators(){return [...this.handles.values()]}getIndicatorContext(e,t){return this.registry.get(e)?.session?.getContext?.(t)??Promise.resolve(null)}removeIndicator(e){let t=this.registry.remove(e);t?.native?.type==="volume"&&(this.volumeOptedOut=true),t&&this.settleCode(t,{ok:false,error:new Error(`[vela] updateCode("${e}") \u2014 the indicator was removed.`)}),t?.session?.stop(),t?.native?.started&&t.native.instance.stop(),this.handles.delete(e),t?.renderHandle&&this.renderer.removeIndicator(t.renderHandle);let n=t?.model?.paneId;n&&n!=="price"&&!this.paneStillUsed(n)&&(this.renderer.removePane(n),this.forgetPane(n),this.events.emit("pane:changed",void 0)),this.events.emit("indicator:removed",{id:e});}setVisible(e,t){let n=this.registry.get(e);if(!(!n||n.hidden===!t)){if(n.hidden=!t,this.handles.get(e)?.setVisibleState(t),!t)n.session?.stop(),n.session=void 0,n.codeTrial&&(n.codeTrial=void 0,this.settleCode(n,{ok:true,error:null})),n.native?.started&&n.native.instance.suspend(),n.renderHandle?this.renderer.setIndicatorVisible?.(n.renderHandle,false):n.native&&this.mountHiddenNativeRow(e,n);else if(n.renderHandle&&this.renderer.setIndicatorVisible?.(n.renderHandle,true),n.pendingStructural=true,n.native)if(n.native.stale||!n.native.started){n.native.stale=false;let o=this.handles.get(e);o&&this.startNativeIndicator(e,o);}else n.native.instance.resume();else {this.setLoading(n,true);let o=this.handles.get(e);o&&this.executeIndicator(e,o);}this.events.emit("indicator:visibility",{id:e,visible:t});}}ready(){return this.readyPromise}inspect(){let e=[...this.registry.all()].filter(t=>!t.loading).sort((t,n)=>(n.native?1:0)-(t.native?1:0));return Hm(e.map(t=>t.model).filter(t=>t!=null))}resize(){this.renderer.resize();}setTheme(e){let t=this.config.theme;Object.keys(e).every(n=>e[n]===t[n])||(this.config.theme=e,this.renderer.setTheme(e),this.events.emit("theme:changed",e));}getVisibleRange(){return this.renderer.getVisibleRange()}setVisibleRange(e){this.renderer.setVisibleRange(e);}panBy(e){if(this.renderer.panBy){this.renderer.panBy(e);return}let t=this.renderer.getVisibleRange();if(!t)return;let n=(t.to-t.from)*e;this.renderer.setVisibleRange({from:t.from+n,to:t.to+n});}setVisibleRangePreset(e){let t=zm(e,this.bars);t&&this.renderer.setVisibleRange(t);}destroy(){this.bumpGeneration(),this.resolveHistoryComplete(),this.clearReplayTimer(),this.replayQueue=null,this.replayForming=null,this.replayCarrying=null,this.dropTickFetches(),this.replayDepth=null,this.replayLoading=null,this.stopLive(),this.viewportTimer!=null&&clearTimeout(this.viewportTimer),this.viewportUnsub?.(),this.paneActionUnsub?.(),this.priceStyleWillChangeUnsub?.(),this.priceStyleWillChangeUnsub=null;for(let e of this.registry.all())this.settleCode(e,{ok:false,error:new Error("[vela] updateCode \u2014 the chart was destroyed.")}),e.session?.stop(),e.native?.started&&e.native.instance.stop();for(let e of this.typeEngines.values())e.stop();this.typeEngines.clear(),this.activeEngineStyle=null,this.unresolvedUnsub?.(),this.unresolvedUnsub=null,this.feed.destroy?.(),this.drawings.destroy(),this.marks.destroy(),this.renderer.destroy(),this.events.clear();}claimIndicatorId(e){if(e===void 0)return this.registry.nextId("ind",t=>this.handles.has(t));if(typeof e!="string"||e.length===0)throw new TypeError("[vela] addIndicator: `id` must be a non-empty string");if(this.handles.has(e)||this.registry.get(e))throw new Error(`[vela] addIndicator: indicator id "${e}" is already live on this chart`);return e}async startIndicator(e,t,n,o){try{if(await this.readyPromise,!this.registry.get(e))return;await nk();let i=this.registry.get(e);if(!i)return;let s=this.engineFor(n.language);i.engine=s;let a=await s.prepare(t,e);if(i.source!==t)return;i.prepared=a;let l={};for(let d of a.inputs)l[d.key]=d.defval;i.inputValues={...l,...i.inputValues},o.setSchema(a.inputs);let c={};for(let d of a.props??[])c[d.key]=d.defval;i.propValues={...c,...i.propValues},o.setPropsSchema(a.props??[]),this.mountLoadingPlaceholder(e,i),this.executeIndicator(e,o);}catch(i){this.fail(e,o,i);}}executeIndicator(e,t){let n=this.registry.get(e);if(!n||!n.engine||!n.prepared||n.hidden)return;let o=this.config.live&&!n.prepared.reactsToViewport&&n.engine.capabilities.streaming?"live":"static",i=n.prepared,s=n.engine.execute({prepared:n.prepared,market:this.market(),bars:this.bars,getBars:()=>this.bars,fetchSeries:(a,l,c)=>this.fetchSeries(a,l,c),inputs:n.inputValues,props:n.propValues,visibleRange:this.currentVisibleRange(),mode:o,historyState:this.historyState},{onModel:a=>{let l=!n.announced,c=n.pendingCause??"history";this.applyModel(e,a)&&(n.pendingCause=void 0,n.codeTrial&&(n.codeTrial=void 0,this.settleCode(n,{ok:true,error:null})),this.emitContextChanged(e),this.emitScriptRun(e,c,l));},onAlert:a=>{if(this.replayQueue||this.replayCarrying)return;let l=n.options?.title??n.prepared?.meta.title??n.title;this.events.emit("alert",{...a,indicator:l}),t.emit("alert",{id:a.id,message:a.message,title:a.title,time:a.time});},onWarning:a=>this.events.emit("warning",a),onError:a=>{n.codeTrial?this.rejectCode(e,n,t,a):this.fail(e,t,a);}});if(n.prepared!==i){s.stop();return}n.session=s,this.emitContextChanged(e);}async startNativeIndicator(e,t){try{await this.readyPromise;let n=this.registry.get(e);if(!n?.native||n.hidden)return;let o=this.nativeChannel(n),i={id:e,symbol:this.config.market.symbol??"TEST",timeframe:this.config.market.timeframe??"60",live:this.config.live&&this.replayQueue===null,session:this.config.market.session,bars:()=>this.bars,data:this.dataControl,emit:s=>this.applyModel(e,this.buildNativeModel(n,s)),pushData:s=>this.renderer.setNativeData?.(o,s),setStatus:s=>{n.renderHandle&&!n.hidden&&this.renderer.setIndicatorStatus?.(n.renderHandle,s);}};n.native.instance.start(i,n.inputValues),n.native.started=!0;}catch(n){this.fail(e,t,n);}}nativeChannel(e){let{type:t,descriptor:n}=e.native;return n.multiInstance?Vm(t,e.id):t}buildNativeModel(e,t){let n=e.native.descriptor,o=e.native.type,i=this.nativeChannel(e);return {id:e.id,title:e.title,...n.shortTitle?{shorttitle:n.shortTitle}:{},overlay:n.overlay,paneHint:n.paneHint,native:{type:o,...i!==o?{channel:i}:{}},...n.legend===false?{legend:false}:{},...t.paneAxis!=null?{paneAxis:t.paneAxis}:{},series:t.series??[],fills:t.fills??[],backgrounds:t.backgrounds??[],priceLines:t.priceLines??[],...t.lines?{lines:t.lines}:{},...t.boxes?{boxes:t.boxes}:{},...t.labels?{labels:t.labels}:{},...t.polylines?{polylines:t.polylines}:{},...t.linefills?{linefills:t.linefills}:{},...t.tables?{tables:t.tables}:{},inputs:n.inputsSchema(),inputValues:e.inputValues}}mountLoadingPlaceholder(e,t){if(t.renderHandle||!t.prepared)return;let n=t.prepared.meta,o={id:e,title:t.options?.title??n.title,overlay:n.overlay,paneHint:n.overlay?"price":"new",series:[],fills:[],backgrounds:[],priceLines:[],inputs:t.prepared.inputs,inputValues:t.inputValues,...t.prepared.props?{props:t.prepared.props,propValues:t.propValues}:{}},i=this.routePane(e,o,t.options??{});if(this.placeModel(o,e,i),t.model=o,this.ensurePaneFor(i),t.renderHandle=this.renderer.mountIndicator(o),t.pendingStructural=true,t.hidden){this.renderer.setIndicatorVisible?.(t.renderHandle,false),this.announce(t,this.handles.get(e));return}this.setLoading(t,true);}mountHiddenNativeRow(e,t){if(t.renderHandle||!t.native)return;let n=this.buildNativeModel(t,{}),o=this.routePane(e,n,t.options??{});this.placeModel(n,e,o),t.model=n,this.ensurePaneFor(o),t.renderHandle=this.renderer.mountIndicator(n),t.pendingStructural=true,this.renderer.setIndicatorVisible?.(t.renderHandle,false),this.announce(t,this.handles.get(e));}setLoading(e,t){e.loading=t,e.renderHandle&&!e.hidden&&this.renderer.setIndicatorStatus?.(e.renderHandle,t?"loading":"idle");}ensurePaneFor(e){this.paneOrder.includes(e)||this.paneOrder.push(e),this.renderer.ensurePane({id:e,kind:e==="price"?"price":"study",order:this.paneOrder.indexOf(e)});}paneStillUsed(e){for(let t of this.registry.all())if(t.model?.paneId===e)return true;return false}forgetPane(e){let t=this.paneOrder.indexOf(e);t>0&&this.paneOrder.splice(t,1),this.collapsedPanes.delete(e),this.maximizedPaneId===e&&(this.maximizedPaneId=null);}paneManagementSupported(){return this.renderer.capabilities.paneManagement===true&&typeof this.renderer.setIndicatorPane=="function"}listPanes(){let e=new Map;for(let n of this.registry.all()){let o=n.model;if(!o||o.legend===false)continue;let i=o.paneId??"price";e.has(i)||e.set(i,[]),e.get(i).push({id:n.id,title:o.title||n.title,...o.shorttitle?{shorttitle:o.shorttitle}:{},ownScale:o.ownScale===true});}let t=[];for(let n of this.paneOrder)n!=="price"&&!e.has(n)||t.push({id:n,kind:n==="price"?"price":"study",order:t.length,collapsed:this.collapsedPanes.has(n),maximized:this.maximizedPaneId===n,indicators:e.get(n)??[]});return t}movePane(e,t){if(e==="price")return;let n=this.existingPaneIds(),o=n.indexOf(e);if(o<0)return;let i=t==="up"?o-1:o+1;i<=0||i>=n.length||([n[o],n[i]]=[n[i],n[o]],this.reorderPanes(n),this.events.emit("pane:moved",{paneId:e,dir:t}));}removePaneAndIndicators(e){if(e!=="price")for(let t of [...this.registry.all()])t.model?.paneId===e&&this.removeIndicator(t.id);}collapsePane(e,t){t?this.collapsedPanes.add(e):this.collapsedPanes.delete(e),this.renderer.setPaneCollapsed?.(e,t),this.events.emit("pane:changed",void 0);}maximizePane(e){this.maximizedPaneId=e,this.renderer.setPaneMaximized?.(e),this.events.emit("pane:changed",void 0);}moveIndicator(e,t){if(!this.paneManagementSupported()||!this.renderer.setIndicatorPane){console.warn("[vela] the active renderer does not support moving indicators between panes.");return}let n=this.registry.get(e);if(!n?.renderHandle||!n.model)return;let o=n.model,i=o.paneId??"price",s=this.resolveMoveTarget(e,o,t);if(!s)return;let{paneId:a,ownScale:l,insert:c}=s;a===i&&o.ownScale===true===l||(c?this.insertPaneOrder(a,c):this.paneOrder.includes(a)||this.paneOrder.push(a),o.ownScale=l,n.paneLocked=true,this.placeModel(o,e,a),this.ensurePaneFor(a),this.renderer.setIndicatorPane(n.renderHandle,a,{ownScale:l}),i!=="price"&&i!==a&&!this.paneStillUsed(i)&&(this.renderer.removePane(i),this.forgetPane(i)),this.reorderPanes(this.existingPaneIds()),this.events.emit("indicator:moved",{id:e,paneId:a}),this.events.emit("pane:changed",void 0));}resolveMoveTarget(e,t,n){if(n==="price"||typeof n=="object"&&"pane"in n&&n.pane==="price")return {paneId:"price",ownScale:!t.overlay};if("pane"in n)return this.existingPaneIds().includes(n.pane)?{paneId:n.pane,ownScale:true}:null;let o=n.newPane===true?{}:n.newPane;return {paneId:this.freshPaneId(e,t.paneId??"price"),ownScale:false,insert:o}}freshPaneId(e,t){let n=new Set(this.existingPaneIds()),o=`pane-${e}`;for(let i=2;o===t||n.has(o);i+=1)o=`pane-${e}-${i}`;return o}insertPaneOrder(e,t){let n=this.paneOrder.indexOf(e);n>0&&this.paneOrder.splice(n,1);let o=this.paneOrder.length;t.before&&this.paneOrder.includes(t.before)?o=this.paneOrder.indexOf(t.before):t.after&&this.paneOrder.includes(t.after)&&(o=this.paneOrder.indexOf(t.after)+1),o<1&&(o=1),this.paneOrder.splice(o,0,e);}existingPaneIds(){return this.paneOrder.filter(e=>e==="price"||this.paneStillUsed(e))}reorderPanes(e){this.paneOrder.length=0,this.paneOrder.push(...e),this.renderer.orderPanes?.(e),this.events.emit("pane:changed",void 0);}handlePaneAction(e){switch(e.type){case "remove":this.removePaneAndIndicators(e.paneId);break;case "move":{let t=this.existingPaneIds(),n=t.indexOf(e.paneId),o=e.dir==="up"?n-1:n+1;n>0&&o>0&&ol.id!==e&&l.model?.paneId===i)&&(this.renderer.removePane(i),this.forgetPane(i)),this.ensurePaneFor(a),n.pendingStructural=true,i=a);}return this.placeModel(t,e,i),n.paneLocked&&(t.ownScale=s),n.model=t,n.pendingStructural?(n.renderHandle=this.renderer.mountIndicator(t),this.renderer.setIndicatorInputs(n.renderHandle,n.inputValues,n.propValues),n.pendingStructural=false):this.renderer.updateIndicator(n.renderHandle,ik(t)),n.loading&&this.setLoading(n,false),this.announce(n,o),true}static modelHasOutput(e){return e.series.length>0||e.fills.length>0||e.backgrounds.length>0||e.priceLines.length>0||(e.lines?.length??0)>0||(e.boxes?.length??0)>0||(e.labels?.length??0)>0||(e.polylines?.length??0)>0||(e.linefills?.length??0)>0||(e.tables?.length??0)>0||(e.barColors?.length??0)>0||(e.trades?.length??0)>0}routePane(e,t,n){return n.pane==="new"?`pane-${e}`:n.pane==="price"||(n.overlay??t.overlay)?"price":`pane-${e}`}static plotsAtLastBar(e){let t={};for(let n of e.series)$e(n)&&(t[n.title]=n.points[n.points.length-1]?.value??null);return t}placeModel(e,t,n){e.id=t,e.paneId=n;let o=i=>i.overlay===true?"price":n;for(let i of e.series)i.paneId=o(i);for(let i of e.fills)i.paneId=o(i);for(let i of e.backgrounds)i.paneId=o(i);for(let i of e.priceLines)i.paneId=n;if(e.lines)for(let i of e.lines)i.paneId=o(i);if(e.boxes)for(let i of e.boxes)i.paneId=o(i);if(e.labels)for(let i of e.labels)i.paneId=o(i);if(e.polylines)for(let i of e.polylines)i.paneId=o(i);if(e.linefills)for(let i of e.linefills)i.paneId=o(i);if(e.tables)for(let i of e.tables)i.paneId=o(i);}emitContextChanged(e){if(!this.registry.get(e)?.session?.getContext)return;let t=Date.now();t-(this.contextEmitAt.get(e)??0)<1e3||(this.contextEmitAt.set(e,t),this.events.emit("context:changed",{id:e}));}emitScriptRun(e,t,n){let o=this.registry.get(e);if(!o||o.native||!this.events.hasListeners("script:run"))return;let i=Date.now();t==="tick"&&i-(this.runEmitAt.get(e)??0)this.buildScriptRun(o,t,n)).then(s=>{s&&this.registry.get(e)&&this.events.emit("script:run",s);}));}async buildScriptRun(e,t,n){let o=e.model;if(!o)return null;let i=await this.pullContext(e,["variables","strategy","warnings"]),s=this.bars[this.bars.length-1];return {id:e.id,title:o.title,kind:i?.strategy||(o.trades?.length??0)>0?"strategy":"indicator",cause:t,first:n,bar:Math.max(0,this.bars.length-1),time:s?.time??0,forming:this.config.live&&this.bars.length>0,complete:this.historyState!=="backfill",plots:r.plotsAtLastBar(o),vars:i?.variables??{},...i?.strategy?{strategy:i.strategy}:{},warnings:i?.warnings??[],trades:async()=>(await this.pullContext(e,["trades"]))?.trades??[],series:async a=>((await this.pullContext(e,["plots"]))?.plots?.[a]??[]).map(c=>({time:c.time,value:typeof c.value=="number"?c.value:null}))}}async pullContext(e,t){try{return await e.session?.getContext?.(t)??null}catch{return null}}fail(e,t,n){let o=this.registry.get(e);o?.loading&&this.setLoading(o,false);let i=n instanceof Error?n:new Error(String(n));console.error(`[vela] indicator "${e}" failed:`,i.message),this.events.emit("indicator:error",{id:e,error:i}),t?.emit("error",{error:i});}};function Bf(){return typeof performance<"u"?performance.now():Date.now()}function tk(r){if(!Array.isArray(r))return [];let e=t=>t===void 0||Number.isFinite(t);return r.filter(t=>t!=null&&Number.isFinite(t.price)&&e(t.volume)&&e(t.high)&&e(t.low)&&e(t.open))}function nk(){return typeof requestAnimationFrame=="function"?new Promise(r=>requestAnimationFrame(()=>requestAnimationFrame(()=>r()))):new Promise(r=>setTimeout(r,0))}function _f(r,e,t=[]){let n={},o=new Set;for(let s of r)n[s.key]=s.defval,o.add(s.key),o.add(s.title);let i=new Map;for(let s of t)i.set(s.key,s.defval),i.has(s.title)||i.set(s.title,s.defval);for(let[s,a]of Object.entries(e))o.has(s)&&(i.has(s)&&rk(i.get(s),a)||(n[s]=a));return n}function rk(r,e){return r===e?true:typeof r=="object"&&r!==null&&typeof e=="object"&&e!==null&&JSON.stringify(r)===JSON.stringify(e)}function ok(r){return {...r,series:r.series.map(e=>e.kind==="candle"||e.kind==="bar"?{...e,bars:[]}:e.kind==="markers"?{...e,markers:[]}:{...e,points:[]}),fills:[],backgrounds:[],priceLines:[],lines:[],boxes:[],labels:[],polylines:[],linefills:[],tables:[],barColors:[],trades:[]}}function ik(r){let e=[],t=Number.POSITIVE_INFINITY,n=0;for(let o of r.series)if(o.kind==="candle"||o.kind==="bar"){e.push({seriesId:o.id,kind:"bars",bars:o.bars});for(let i of o.bars)i.timen&&(n=i.time);}else if($e(o)){e.push({seriesId:o.id,kind:"points",points:o.points});for(let i of o.points)i.timen&&(n=i.time);}return {kind:"value",indicatorId:r.id,dirty:{from:Number.isFinite(t)?t:0,to:n},anchorTime:r.anchorTime??null,series:e,lines:r.lines??[],boxes:r.boxes??[],labels:r.labels??[],polylines:r.polylines??[],linefills:r.linefills??[],tables:r.tables??[],trades:r.trades??[]}}var Di=class{constructor(e){this.renderer=e;}get name(){return this.renderer.name}get capabilities(){return this.renderer.capabilities}supports(e){return this.renderer.features.includes(e)}get(e){return this.renderer.readFeature(e)}set(e,t){let n=typeof e=="string"?[[e,t]]:Object.entries(e);for(let[o,i]of n)this.renderer.features.includes(o)?this.renderer.applyFeature(o,i):console.warn(`[vela] renderer "${this.renderer.name}" has no feature "${o}" \u2014 set ignored.`);return this}setLegendActions(e){this.renderer.setLegendActions?.(e);}setLegendCallouts(e){this.renderer.setLegendCallouts?.(e);}setLegendOverviewAction(e){return this.renderer.setLegendOverviewAction?.(e),this}get supportsIndicatorSettings(){return typeof this.renderer.openIndicatorSettings=="function"}openIndicatorSettings(e){return this.renderer.openIndicatorSettings?.(e),this}screenshot(){return typeof this.renderer.screenshot=="function"?this.renderer.screenshot():(console.warn(`[vela] renderer "${this.renderer.name}" does not support screenshot().`),null)}screenshotCanvas(){return typeof this.renderer.screenshotCanvas=="function"?this.renderer.screenshotCanvas():null}getConfig(){return typeof this.renderer.getConfig=="function"?this.renderer.getConfig():(console.warn(`[vela] renderer "${this.renderer.name}" does not support getConfig().`),null)}applyConfig(e){return typeof this.renderer.applyConfig=="function"?this.renderer.applyConfig(e):console.warn(`[vela] renderer "${this.renderer.name}" does not support applyConfig().`),this}onConfigChanged(e){return this.renderer.onConfigChanged?.(e)??(()=>{})}onCrosshairMove(e){return this.renderer.onCrosshairMove(e)}onClick(e){return this.renderer.onClick(e)}onAxisLongPress(e){return this.renderer.onAxisLongPress?.(e)??(()=>{})}dataWindowReadout(){return this.renderer.getDataWindowReadout?.()??null}setSymbolPicker(e){return typeof this.renderer.setSymbolPicker=="function"?this.renderer.setSymbolPicker(e):console.warn(`[vela] renderer "${this.renderer.name}" does not support setSymbolPicker().`),this}focus(){return this.renderer.focus?.(),this}get supportsExternalCrosshair(){return typeof this.renderer.setExternalCrosshair=="function"}setExternalCrosshair(e,t=null){return this.renderer.setExternalCrosshair?.(e,t),this}closeDialogs(){return this.renderer.closeDialogs?.(),this}openSettings(e){return this.renderer.openSettingsDialog?.(e),this}setSettingsSections(e){return this.renderer.setSettingsSections?.(e),this}setSettingsVisibility(e){return this.renderer.setSettingsVisibility?.(e),this}listSettingsIds(){return this.renderer.listSettingsIds?.()??[]}setLayoutMode(e){return this.renderer.setLayoutMode?.(e),this}setWallClock(e){return this.renderer.setWallClock?.(e),this}};var bo=new Map;function sk(r){let e=Object.entries(r);for(let[t,n]of e)bo.set(t,n);return ()=>{for(let[t,n]of e)bo.get(t)===n&&bo.delete(t);}}function ak(...r){if(r.length===0)bo.clear();else for(let e of r)bo.delete(e);}function hu(){return Object.fromEntries(bo)}var Ll=class{constructor(e){this.controller=e;}get supported(){return this.controller.paneManagementSupported()}list(){return this.controller.listPanes()}move(e,t){return this.guard()&&this.controller.movePane(e,t),this}remove(e){return this.guard()&&this.controller.removePaneAndIndicators(e),this}collapse(e,t=true){return this.guard()&&this.controller.collapsePane(e,t),this}maximize(e){return this.guard()&&this.controller.maximizePane(e),this}moveIndicator(e,t){return this.guard()&&this.controller.moveIndicator(e,t),this}guard(){return this.controller.paneManagementSupported()?true:(console.warn("[vela] the active renderer does not support pane management \u2014 chart.panes mutation ignored."),false)}};function Hf(r,e,t,n){return `${r}|${e}|${t}${n&&n!=="regular"?`|${n}`:""}`}function lk(r){return r.split("|")[1]??""}var Ml=class{constructor(){this.series=new Map;this.coveredFrom=new Map;this.retained=new Set;this.retainedByOwner=new Map;}get(e){return this.series.get(e)}markCovered(e,t){this.coveredFrom.set(e,Math.min(this.coveredFrom.get(e)??1/0,t));}coveredFromOf(e){return this.coveredFrom.get(e)}merge(e,t){if(t.length===0)return this.series.get(e)??[];let n=new Map;for(let i of this.series.get(e)??[])n.set(i.time,i);for(let i of t)n.set(i.time,i);let o=[...n.values()].sort((i,s)=>i.time-s.time);return this.series.set(e,o),o}retainSymbol(e){this.currentSymbol!==e&&(this.currentSymbol=e,this.purgeOutside(e));}retain(e,t="default"){e.size===0?this.retainedByOwner.delete(t):this.retainedByOwner.set(t,new Set(e));let n=new Set;for(let o of this.retainedByOwner.values())for(let i of o)n.add(i);this.retained=n,this.purgeOutside(this.currentSymbol);}purgeOutside(e){for(let t of [...this.series.keys()]){let n=lk(t);n!==e&&!this.retained.has(n)&&(this.series.delete(t),this.coveredFrom.delete(t));}}clear(){this.series.clear(),this.coveredFrom.clear();}},Oi=new Ml;function pu(r,e,t){let{provider:n,ticker:o}=en(r);return Hf(n??"",o,e,t)}var Fi=1e4,ck=Fi+1,Vi=class{constructor(e,t=Oi){this.inner=e;this.store=t;}async load(e){if(e.data&&e.data.length>0)return this.inner.load(e);let t=e.symbol??"TEST",n=pu(t,e.timeframe??"60",e.session);this.store.retainSymbol(t);let o=this.store.get(n),i=e.bars??500,s=o?.[o.length-1];if(o&&s&&o.length>=i-1&&this.inner.loadRange){let{bars:l}=await this.fetchRange(e,{from:s.time}),c=this.store.merge(n,Ni(l));return zf(c,l[l.length-1]).slice(-i)}let a=await this.inner.load(e);return this.store.merge(n,Ni(a)),a}async loadProgressive(e,t,n){if(e.data&&e.data.length>0)return this.inner.load(e);if(!this.inner.loadProgressive)return null;let o=e.symbol??"TEST",i=pu(o,e.timeframe??"60",e.session),s=this.store.get(i),a=e.bars??500,l=s?.[s.length-1];if(s&&l&&s.length>=a-1&&this.inner.loadRange)return this.load(e);this.store.retainSymbol(o);let c=await this.inner.loadProgressive(e,t,n);return c==null?null:(this.store.merge(i,Ni(c)),c)}async loadRange(e,t){if(!this.inner.loadRange)return this.inner.load(e);let n=pu(e.symbol??"TEST",e.timeframe??"60",e.session),o=this.store.get(n),i=o?.[o.length-1];if(t.to!=null&&i&&t.tof.time<=t.to),u=this.store.coveredFromOf(n)??1/0;if(t.limit!=null?d.length>=t.limit&&(t.from==null||u<=t.from):t.from!=null&&u<=t.from){let f=t.from!=null?d.filter(g=>g.time>=t.from):d;return t.limit!=null&&f.length>t.limit&&(f=f.slice(-t.limit)),f}let p=await this.fetchRange(e,t),m=p.bars.filter(f=>f.time<=t.to);return m.length>0&&(this.store.merge(n,m),this.store.markCovered(n,p.coveredDownTo??m[0].time)),m}if(i&&t.from!=null){let d=this.store.coveredFromOf(n);if(d!=null&&d>t.from){let{bars:u,coveredDownTo:h}=await this.fetchRange(e,{from:t.from,to:d});this.store.merge(n,u.filter(p=>p.time<=d)),this.store.markCovered(n,h??t.from),o=this.store.get(n),i=o?.[o.length-1];}}let s=this.store.coveredFromOf(n);if(!!o&&o.length>0&&!!i&&(t.from!=null?s!=null&&s<=t.from:t.limit==null||o.length>=t.limit)&&i){let{bars:d}=await this.fetchRange(e,{from:i.time,to:t.to,limit:t.limit}),u=this.store.merge(n,Ni(d)),h=zf(u,d[d.length-1]),p=t.from!=null?h.filter(m=>m.time>=t.from):h;return t.to!=null&&(p=p.filter(m=>m.time<=t.to)),p}let{bars:l,coveredDownTo:c}=await this.fetchRange(e,t);return this.store.merge(n,Ni(l)),this.store.markCovered(n,c??t.from??l[0]?.time??0),l}async fetchRange(e,t){let n=Ft(e.timeframe??"60"),o=dk(t,n);if(o<=ck){let c=await this.inner.loadRange(e,{...t,limit:t.limit??o});return {bars:c,coveredDownTo:t.from??c[0]?.time}}let i=new Map,s=t.to??Date.now();for(;!(t.from!=null&&s=t.from)&&i.set(h.time,h);if(d.length===0){if(t.from==null)break;s-=Fi*n;continue}if(u-1>=s)break;s=u-1;}let a=[...i.values()].sort((c,d)=>c.time-d.time),l=t.from!=null&&s0?r.slice(0,-1):r}function zf(r,e){if(!e)return r;let t=r[r.length-1];return !t||e.time>t.time?[...r,e]:r}function uk(r){return {"1m":6e4,"3m":18e4,"5m":3e5,"15m":9e5,"30m":18e5,"1h":36e5,"2h":72e5,"4h":144e5,"1d":864e5,"1w":6048e5,"1M":2592e6,1:6e4,5:3e5,15:9e5,30:18e5,60:36e5,240:144e5,D:864e5,W:6048e5,M:2592e6}[r]??36e5}var Ir=class{constructor(e=Oi){this.registry=new Tl;this.primaryProvider=null;this.liveBars=[];this.symInfoCache=new Map;this.symInfoInflight=new Map;this.cache=new Vi(new mu(this.registry),e);}registerProvider(e,t){return this.registry.register(e,t)}unregisterProvider(e){this.registry.unregister(e);}providers(){return this.registry.names().map(e=>this.registry.infoOf(e))}resolveSymbol(e){return this.registry.resolve(e,{default:this.primaryProvider})}displayPrefix(e){let t=this.resolveSymbol(e);return t?this.registry.displayPrefixOf(t):null}canonicalSymbol(e){let t=this.resolveSymbol(e);return t?this.registry.canonicalSymbol(t):null}providerInstance(e){return this.registry.get(e)}symbolIconOf(e){return this.registry.symbolIconOf(e)}symbolIcon(e){return this.registry.symbolIcon(this.resolveSymbol(e))}symbols(e){return this.registry.symbolsOf(e)}onUnresolved(e){return this.registry.onUnresolved(e)}destroy(){this.registry.cancelWaits();}ready(){return this.registry.indexReady()}async symbolInfoFor(e){let t=this.registry.resolve(e,{default:this.primaryProvider});if(t)return this.fetchSymbolInfo(t)}fetchSymbolInfo(e){let t=Wf(e),n=this.symInfoCache.get(t);if(n&&Date.now()-n.at(a&&this.symInfoCache.set(t,{info:a,at:Date.now()}),a)).finally(()=>{this.symInfoInflight.delete(t);});return this.symInfoInflight.set(t,s),s}capabilitiesFor(e){let t=this.registry.resolve(e,{default:this.primaryProvider});if(!t)return null;let n=this.registry.get(t.provider);return n?n.capabilitiesFor?.(t.ticker)??this.registry.infoOf(t.provider).capabilities:null}async load(e){if(e.data&&e.data.length>0)return this.liveBars=e.data.map(n=>({...n})),e.data;let t=await this.registry.whenResolvable(Bi(e),{default:this.primaryProvider});return this.primaryProvider=t.provider,this.prefetchSymbolInfo(t),this.cache.load(El(e,t))}async loadProgressive(e,t,n){if(e.data&&e.data.length>0)return this.liveBars=e.data.map(i=>({...i})),e.data;let o=await this.registry.whenResolvable(Bi(e),{default:this.primaryProvider});return this.primaryProvider=o.provider,this.prefetchSymbolInfo(o),this.cache.loadProgressive(El(e,o),t,n)}symbolInfo(e){if(e.data&&e.data.length>0)return;let t=this.registry.resolve(Bi(e),{default:this.primaryProvider});return t?this.symInfoCache.get(Wf(t))?.info:void 0}prefetchSymbolInfo(e){this.fetchSymbolInfo(e).catch(()=>{});}async loadRange(e,t){if(e.data&&e.data.length>0)return this.cache.loadRange(e,t);let n=this.registry.resolve(Bi(e),{default:this.primaryProvider});return n?this.cache.loadRange(El(e,n),t):[]}subscribe(e,t){if(e.data&&e.data.length>0)return this.synthesizeTicks(e,t);let n=this.registry.resolve(Bi(e),{default:this.primaryProvider});return n?this.cache.subscribe(El(e,n),t):()=>{}}synthesizeTicks(e,t){if(this.liveBars.length===0)return ()=>{};let n=uk(e.timeframe??"60"),o=setInterval(()=>{let i=this.liveBars,s=i[i.length-1];if(!s)return;let a=s.close*.0015*(Math.random()-.5)*2,l=Math.max(0,s.close+a),c={...s,close:l,high:Math.max(s.high,l),low:Math.min(s.low,l)};if(i[i.length-1]=c,t(c),Math.random()<.12){let d={time:c.time+n,open:c.close,high:c.close,low:c.close,close:c.close,volume:0};i.push(d),t(d);}},1e3);return ()=>clearInterval(o)}};function Bi(r){return r.symbol??""}function El(r,e){return {...r,symbol:`${e.provider}:${e.ticker}`}}function Wf(r){return `${r.provider}|${r.ticker.trim().toUpperCase()}`}var hk=10*6e4;async function Gf(r,e,t,n){try{return await r.getBars(e,t,n)}catch(o){return console.warn(`[vela] data fetch failed for ${e} ${t} \u2014 ${o instanceof Error?o.message:String(o)}`),[]}}var mu=class{constructor(e){this.registry=e;}load(e){let{provider:t,ticker:n}=en(e.symbol??""),o=this.registry.get(t??"");return o?Gf(o,n,e.timeframe??"60",{limit:e.bars??500,session:e.session}):Promise.resolve([])}async loadProgressive(e,t,n){let{provider:o,ticker:i}=en(e.symbol??""),s=this.registry.get(o??"");if(!s)return [];if(!s.getBarsProgressive)return null;try{return await s.getBarsProgressive(i,e.timeframe??"60",{limit:e.bars??500,session:e.session},t,n)}catch(a){return console.warn(`[vela] progressive fetch failed for ${i} ${e.timeframe??"60"} \u2014 ${a instanceof Error?a.message:String(a)}`),[]}}loadRange(e,t){let{provider:n,ticker:o}=en(e.symbol??""),i=this.registry.get(n??"");return i?Gf(i,o,e.timeframe??"60",{...t,session:e.session}):Promise.resolve([])}subscribe(e,t){let{provider:n,ticker:o}=en(e.symbol??""),i=this.registry.get(n??"");if(!i)return ()=>{};let s=e.timeframe??"60";if(i.subscribe)return i.subscribe(o,s,t,e.session?{session:e.session}:void 0);let a=false,l=null,c=async()=>{if(!a){try{let d=await i.getBars(o,s,{limit:2,session:e.session});if(a)return;for(let u of d)t(u);}catch{}a||(l=setTimeout(()=>{c();},3e3));}};return l=setTimeout(()=>{c();},3e3),()=>{a=true,l&&clearTimeout(l);}}};var _i=class{constructor(e){this.registry=e instanceof Ir?e:null;}registerProvider(e,t){return this.registry?(this.registry.registerProvider(e,t),this):(console.warn(`[vela] chart.data.registerProvider("${e}") ignored \u2014 the active data feed is a custom feed (deps.dataFeed), not the default provider registry.`),this)}unregisterProvider(e){return this.registry?.unregisterProvider(e),this}providers(){return this.registry?.providers()??[]}resolve(e){return this.registry?.resolveSymbol(e)??null}displayPrefix(e){return this.registry?.displayPrefix(e)??null}canonicalSymbol(e){return this.registry?.canonicalSymbol(e)??null}providerInstance(e){return this.registry?.providerInstance(e)}symbols(e){return this.registry?.symbols(e)??[]}symbolIcon(e){return this.registry?.symbolIcon(e)}symbolInfo(e){return this.registry?.symbolInfoFor(e)??Promise.resolve(void 0)}capabilities(e){return this.registry?.capabilitiesFor(e)??null}ready(){return this.registry?.ready()??Promise.resolve()}};var Hi=class{constructor(e){this.ctrl=e;}get supported(){return this.ctrl.supported}setTool(e){return this.ok("setTool")&&this.ctrl.setTool(e),this}getTool(){return this.ctrl.getTool()}setSnapMode(e){return this.ok("setSnapMode")&&this.ctrl.setSnapMode(e),this}getSnapMode(){return this.ctrl.getSnapMode()}setStayMode(e){return this.ok("setStayMode")&&this.ctrl.setStayMode(e),this}getStayMode(){return this.ctrl.getStayMode()}setMode(e){return this.ok("setMode")&&this.ctrl.setMode(e),this}getMode(){return this.ctrl.getMode()}showToolbar(e=true){return this.ok("showToolbar")&&this.ctrl.showToolbar(e),this}setToolbar(e){return this.ok("setToolbar")&&this.ctrl.setToolbar(e),this}setToolShortcuts(e){return this.ok("setToolShortcuts")&&this.ctrl.setToolShortcuts(e),this}setExternalGhost(e){return this.ctrl.setExternalGhost(e),this}add(e,t={}){return this.ok("add")?this.ctrl.add(e,t):null}remove(e){return this.ctrl.remove(e),this}update(e,t){return this.ctrl.update(e,t),this}updateMany(e){return this.ctrl.updateMany(e),this}removeMany(e){return this.ctrl.removeMany(e),this}lock(e,t=true){return this.ctrl.setLocked(e,t),this}show(e,t=true){return this.ctrl.setVisible(e,t),this}select(e){return this.ok("select")&&this.ctrl.select(e==null?[]:typeof e=="string"?[e]:e),this}openSettings(e){return this.ok("openSettings")&&this.ctrl.openSettings(e),this}bringToFront(e){return this.ctrl.bringToFront(e),this}sendToBack(e){return this.ctrl.sendToBack(e),this}undo(){return this.ctrl.undo(),this}redo(){return this.ctrl.redo(),this}canUndo(){return this.ctrl.canUndo()}canRedo(){return this.ctrl.canRedo()}clone(e){return this.ok("clone")&&this.ctrl.clone(e),this}duplicate(e){return this.ok("duplicate")&&this.ctrl.duplicate(e),this}copyToClipboard(e){return this.ok("copy")&&this.ctrl.copy(e),this}paste(){return this.ok("paste")&&this.ctrl.paste(),this}all(){return this.ctrl.all()}toJSON(){return this.ctrl.toJSON()}fromJSON(e){return this.ctrl.fromJSON(e),this}favorites(){return this.ctrl.favorites()}isFavorite(e){return this.ctrl.isFavorite(e)}setFavorite(e,t){return this.ok("setFavorite")&&this.ctrl.setFavorite(e,t),this}setFavorites(e){return this.ok("setFavorites")&&this.ctrl.setFavorites([...e]),this}getConfig(){return this.ctrl.toJSON()}applyConfig(e){return this.ctrl.fromJSON(e),this}ok(e){return this.ctrl.supported?true:(console.warn(`[vela] chart.drawings.${e}() ignored \u2014 the active renderer has no userDrawings capability.`),false)}};var zi=class{constructor(e){this.ctrl=e;}get supported(){return this.ctrl.supported}add(e){return this.ctrl.add(e),this}set(e){return this.ctrl.set(e),this}remove(e){return this.ctrl.remove(e),this}clear(){return this.ctrl.clear(),this}all(){return this.ctrl.all()}defineGroup(e){return this.ctrl.defineGroup(e),this}groups(){return this.ctrl.groupDefinitions()}setGroupVisible(e,t=true){return this.ctrl.setGroupVisible(e,t),this}isGroupVisible(e){return this.ctrl.isGroupVisible(e)}};var Wi=class{constructor(e){this.ctrl=e;}start(e){return this.ctrl.replayStart(e)}step(){return this.ctrl.replayStep()}stepUpdate(){return this.ctrl.replayStepUpdate()}play(e){return this.ctrl.replayPlay(e),this}pause(){return this.ctrl.replayPause(),this}stop(){return this.ctrl.replayStop(),this}get state(){return this.ctrl.replayState()}get bounds(){return this.ctrl.replayBounds()}setTicks(e){return this.ctrl.replaySetTicks(e),this}};var Gi=class r{constructor(e=()=>Date.now()){this.now=e;this.subs=new Set;this.timer=null;}onTick(e){return this.subs.add(e),this.timer==null&&this.arm(),()=>{this.subs.delete(e),this.subs.size===0&&this.timer!=null&&(clearTimeout(this.timer),this.timer=null);}}static delayToNextSecond(e){return 1e3-(e%1e3+1e3)%1e3+5}arm(){this.timer=setTimeout(()=>{this.timer=null;let e=this.now();for(let t of this.subs)t(e);this.subs.size>0&&this.arm();},r.delayToNextSecond(this.now()));}};function Pl(r){let e=r.trim(),t=/^#([0-9a-f]{3})$/i.exec(e);if(t){let o=t[1];return {r:parseInt(o[0]+o[0],16),g:parseInt(o[1]+o[1],16),b:parseInt(o[2]+o[2],16)}}if(t=/^#([0-9a-f]{6})[0-9a-f]{0,2}$/i.exec(e),t){let o=t[1];return {r:parseInt(o.slice(0,2),16),g:parseInt(o.slice(2,4),16),b:parseInt(o.slice(4,6),16)}}let n=/^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)/i.exec(e);return n?{r:parseFloat(n[1]),g:parseFloat(n[2]),b:parseFloat(n[3])}:null}function J(r,e){let t=Pl(r);return t?`rgba(${t.r},${t.g},${t.b},${e})`:r}function $f(r,e,t){let n=Pl(r),o=Pl(e);if(!n||!o)return r;let i=(s,a)=>Math.round(s+(a-s)*t);return `rgb(${i(n.r,o.r)},${i(n.g,o.g)},${i(n.b,o.b)})`}function bt(r){let e=Pl(r);return e?.2126*e.r+.7152*e.g+.0722*e.b<128:true}var Il={"--vela-space-1":"4px","--vela-space-2":"8px","--vela-space-3":"12px","--vela-space-4":"16px","--vela-radius-sm":"4px","--vela-radius-md":"6px","--vela-radius-lg":"10px","--vela-z-tooltip":"60","--vela-z-menu":"50","--vela-z-dialog":"40","--vela-z-popover":"6000","--vela-ease":"cubic-bezier(0.22, 1, 0.36, 1)","--vela-dur-fast":"90ms","--vela-dur-med":"160ms","--vela-font-size-sm":"11px","--vela-font-size-md":"12px","--vela-font-size-lg":"14px"};function Al(r){let e=bt(r.background),t=o=>e?`rgba(255,255,255,${o})`:J(r.textColor,o+.02),n=$f(r.background,e?"#ffffff":r.textColor,e?.03:.05);return {"--vela-font":r.fontFamily,"--vela-bg":r.background,"--vela-fg":e?"#d1d4dc":r.textColor,"--vela-fg-muted":e?"#868a96":J(r.textColor,.62),"--vela-fg-faint":J(r.textColor,.35),"--vela-fg-bright":e?"#f0f3fa":"#000000","--vela-surface":r.background,"--vela-surface-elev":n,"--vela-surface-overlay":n,"--vela-surface-sunken":r.background,"--vela-border":r.borderColor,"--vela-border-strong":e?"#34353b":J(r.textColor,.28),"--vela-border-soft":r.borderColor,"--vela-border-faint":J(r.textColor,.08),"--vela-hover":t(.06),"--vela-active":t(.1),"--vela-hover-strong":t(.16),"--vela-focus":J(r.textColor,.5),"--vela-focus-soft":J(r.textColor,.12),"--vela-separator-hover-band":J(r.textColor,.1),"--vela-separator-hover-line":J(r.textColor,.55),"--vela-scroll":J(r.textColor,.3),"--vela-accent":nt,"--vela-accent-bright":oo,"--vela-highlight":Gm,"--vela-selected-bg":e?"#f0f3fa":r.textColor,"--vela-selected-fg":e?r.background:"#ffffff","--vela-fg-on-fill":"#ffffff","--vela-up":r.upColor,"--vela-down":r.downColor,"--vela-danger":r.downColor,"--vela-shadow":"0 8px 30px rgba(0,0,0,0.5)","--vela-shadow-dialog":"0 20px 60px rgba(0,0,0,0.5)","--vela-backdrop":"rgba(0,0,0,0.45)"}}function _e(r,e){let t=n=>{for(let o in n)r.style.setProperty(o,n[o]);};t(Il),t(Al(e));}function nn(r,e){let t=null,n=null,o=()=>{t!==null&&(clearTimeout(t),t=null),n?.remove(),n=null;},i=()=>{let a=e.text();if(!a)return;n=r.ownerDocument.createElement("div"),n.textContent=a,n.style.cssText="position:absolute;z-index:var(--vela-z-tooltip);pointer-events:none;background:var(--vela-bg);border:1px solid var(--vela-border);color:var(--vela-fg);border-radius:var(--vela-radius-md);padding:4px 9px;box-shadow:var(--vela-shadow);font:var(--vela-font-size-md) var(--vela-font);"+(e.wrap?"max-width:260px;":"white-space:nowrap;"),_e(n,e.theme()),e.host.appendChild(n);let c=r.getBoundingClientRect(),d=e.host.getBoundingClientRect();if(e.placement==="right")n.style.left=`${c.right-d.left+8}px`,n.style.top=`${c.top-d.top+(c.height-n.offsetHeight)/2}px`;else {let u=Math.min(c.left-d.left,Math.max(0,d.width-n.offsetWidth-4));n.style.left=`${Math.max(0,u)}px`,n.style.top=e.placement==="above"?`${Math.max(0,c.top-d.top-n.offsetHeight-6)}px`:`${c.bottom-d.top+6}px`;}},s=a=>{a.pointerType==="mouse"&&(o(),t=window.setTimeout(i,e.delayMs??700));};return r.addEventListener("pointerenter",s),r.addEventListener("pointerleave",o),r.addEventListener("pointerdown",o),()=>{r.removeEventListener("pointerenter",s),r.removeEventListener("pointerleave",o),r.removeEventListener("pointerdown",o),o();}}function Rl(r,e){let t=e.size??16,n=document.createElement("span");n.className="vela-hint",n.setAttribute("role","img"),n.setAttribute("aria-label",r),n.innerHTML=Re("info",t),n.style.cssText=`flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:${t}px;height:${t}px;border-radius:50%;cursor:help;user-select:none;background:var(--vela-hover);color:var(--vela-fg-muted);transition:background var(--vela-dur-fast) ease,color var(--vela-dur-fast) ease;`;let o=s=>{n.style.background=s?"var(--vela-active)":"var(--vela-hover)",n.style.color=s?"var(--vela-fg-bright)":"var(--vela-fg-muted)";};n.addEventListener("pointerenter",()=>o(true)),n.addEventListener("pointerleave",()=>o(false));let i=nn(n,{host:e.host,theme:e.theme,text:()=>r,wrap:true,delayMs:250});return {el:n,dispose:i}}var pk=Object.defineProperty,mk=(r,e,t)=>e in r?pk(r,e,{enumerable:true,configurable:true,writable:true,value:t}):r[e]=t,ue=(r,e,t)=>mk(r,typeof e!="symbol"?e+"":e,t);function Uf(r){return r==null?[]:Array.isArray(r)?r:[r]}var Yf=r=>r[0],Kf=r=>r[r.length-1];function Xf(r,e,t={}){let{step:n=1,loop:o=true}=t,i=e+n,s=r.length,a=s-1;return e===-1?n>0?0:a:i<0?o?a:0:i>=s?o?0:e>s?s:e:i}function jf(r,e,t={}){return r[Xf(r,e,t)]}function fk(r,e,t={}){let{step:n=1,loop:o=true}=t;return Xf(r,e,{step:-n,loop:o})}function qf(r,e,t={}){return r[fk(r,e,t)]}var Zf=r=>r?.constructor.name==="Array",gk=(r,e)=>{if(r.length!==e.length)return false;for(let t=0;t{if(Object.is(r,e))return true;if(r==null&&e!=null||r!=null&&e==null)return false;if(typeof r?.isEqual=="function"&&typeof e?.isEqual=="function")return r.isEqual(e);if(typeof r=="function"&&typeof e=="function")return r.toString()===e.toString();if(Zf(r)&&Zf(e))return gk(Array.from(r),Array.from(e));if(typeof r!="object"||typeof e!="object")return false;let t=Object.keys(e??Object.create(null)),n=t.length;for(let o=0;or!=null&&typeof r=="object";var yo=r=>typeof r=="string",pt=r=>typeof r=="function",Qf=r=>r==null,$i=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),vk=r=>Object.prototype.toString.call(r),Jf=Function.prototype.toString,yk=Jf.call(Object),Ar=r=>{if(!bk(r)||vk(r)!="[object Object]"||Sk(r))return false;let e=Object.getPrototypeOf(r);if(e===null)return true;let t=$i(e,"constructor")&&e.constructor;return typeof t=="function"&&t instanceof t&&Jf.call(t)==yk},wk=r=>typeof r=="object"&&r!==null&&"$$typeof"in r&&"props"in r,xk=r=>typeof r=="object"&&r!==null&&"__v_isVNode"in r,Sk=r=>wk(r)||xk(r);var Ui=(r,...e)=>(typeof r=="function"?r(...e):r)??void 0,fu=r=>r,eg=r=>r(),gu=()=>{},Gn=(...r)=>(...e)=>{r.forEach(function(t){t?.(...e);});};function $n(r){if(!Ar(r)||r===void 0)return r;let e=Reflect.ownKeys(r).filter(n=>typeof n=="string"),t={};for(let n of e){let o=r[n];o!==void 0&&(t[n]=$n(o));}return t}function wo(...r){r.length===1?r[0]:r[1];r.length===2?r[0]:true;}function bu(...r){r.length===1?r[0]:r[1];r.length===2?r[0]:true;}function Yi(r,e){if(r==null)throw new Error(e())}var Ck=(...r)=>r.map(e=>e?.trim?.()).filter(Boolean).join(" "),Tk=/((?:--)?(?:\w+-?)+)\s*:\s*([^;]*)/g,tg=r=>{let e={},t;for(;t=Tk.exec(r);)e[t[1]]=t[2];return e},kk=(r,e)=>{if(yo(r)){if(yo(e))return `${r};${e}`;r=tg(r);}else yo(e)&&(e=tg(e));return Object.assign({},r??{},e??{})};function ng(...r){let e={};for(let t of r){if(!t)continue;for(let o in e){if(o.startsWith("on")&&typeof e[o]=="function"&&typeof t[o]=="function"){e[o]=Gn(t[o],e[o]);continue}if(o==="className"||o==="class"){e[o]=Ck(e[o],t[o]);continue}if(o==="style"){e[o]=kk(e[o],t[o]);continue}e[o]=t[o]!==void 0?t[o]:e[o];}for(let o in t)e[o]===void 0&&(e[o]=t[o]);let n=Object.getOwnPropertySymbols(t);for(let o of n)e[o]=t[o];}return e}var Un=".",ig="#",rg=new WeakMap,sg=new WeakMap;function vu(r){return r.join(Un)}function Lk(r){return r.includes(Un)}function ag(r){return r.startsWith(ig)}function Mk(r){return r.startsWith(Un)}function Ek(r){return ag(r)?r.slice(ig.length):r}function yu(r,e){return r?`${r}${Un}${e}`:e}function Pk(r){let e=new Map,t=new Map,n=(o,i)=>{e.set(o,i);let s=i.id;s&&(t.has(s)&&bu(`[zag-js] Duplicate state id: "${s}"`),t.set(s,o));let a=i.states;if(a){Yi(i.initial,()=>`[zag-js] Compound state "${o}" has child states but no "initial" property`),i.initial in a||bu(`[zag-js] Compound state "${o}" has initial "${String(i.initial)}" which is not a child state`);for(let[l,c]of Object.entries(a)){if(!c)continue;let d=yu(o,l);n(d,c);}}};for(let[o,i]of Object.entries(r.states))i&&n(o,i);return {index:e,idIndex:t}}function xo(r){let e=rg.get(r);if(e)return e;let{index:t,idIndex:n}=Pk(r);return rg.set(r,t),sg.set(r,n),t}function Ik(r,e){return xo(r),sg.get(r)?.get(e)}function wu(r){return r?String(r).split(Un).filter(Boolean):[]}function Dl(r,e){if(!e)return [];let t=xo(r),n=wu(e),o=[],i=[];for(let s of n){i.push(s);let a=vu(i),l=t.get(a);if(!l)break;o.push({path:a,state:l});}return o}function Ki(r,e){let t=xo(r),n=wu(e);if(!n.length)return e;let o=[];for(let a of n){o.push(a);let l=vu(o);if(!t.has(l))return e}let i=vu(o),s=t.get(i);for(;s?.initial;){let a=`${i}${Un}${s.initial}`,l=t.get(a);if(!l)break;i=a,s=l;}return i}function og(r,e){return xo(r).has(e)}function xu(r,e,t){let n=String(e);if(ag(n)){let o=Ek(n),i=Ik(r,o);return Yi(i,()=>`[zag-js] Unknown state id: "${o}"`),Ki(r,i)}if(Mk(n)&&t){let o=yu(t,n.slice(1));return Ki(r,o)}if(!Lk(n)&&t){let o=wu(t);for(let i=o.length-1;i>=1;i--){let s=o.slice(0,i).join(Un),a=yu(s,n);if(og(r,a))return Ki(r,a)}if(og(r,n))return Ki(r,n)}return Ki(r,n)}function lg(r,e,t){let n=Dl(r,e);for(let i=n.length-1;i>=0;i--){let a=n[i]?.state.on?.[t];if(a)return {transitions:a,source:n[i]?.path}}return {transitions:r.on?.[t],source:void 0}}function cg(r,e,t,n){let o=e?Dl(r,e):[],i=Dl(r,t),s=0;for(;sn.state.tags?.includes(t))}function hg(){return {and:(...r)=>function(t){return r.every(n=>t.guard(n))},or:(...r)=>function(t){return r.some(n=>t.guard(n))},not:r=>function(t){return !t.guard(r)}}}function Ol(r){return xo(r),r}var So=(r=>(r.NotStarted="Not Started",r.Started="Started",r.Stopped="Stopped",r))(So||{}),Xi="__init__";var Ak=Object.defineProperty,Rk=(r,e,t)=>e in r?Ak(r,e,{enumerable:true,configurable:true,writable:true,value:t}):r[e]=t,Nl=(r,e,t)=>Rk(r,typeof e!="symbol"?e+"":e,t);var pg=(r,e)=>r.map((t,n)=>r[(Math.max(e,0)+n)%r.length]);var ji=()=>{},qi=r=>typeof r=="object"&&r!==null;var St=r=>r?"":void 0,Su=r=>r?"true":void 0;var Dk=1,Ok=9,Nk=11;var me=r=>qi(r)&&r.nodeType===Dk&&typeof r.nodeName=="string",Zi=r=>qi(r)&&r.nodeType===Ok,Fk=r=>qi(r)&&r===r.window;var mg=r=>me(r)?r.localName||"":"#document";function fg(r){return ["html","body","#document"].includes(mg(r))}var gg=r=>qi(r)&&r.nodeType!==void 0,Rr=r=>gg(r)&&r.nodeType===Nk&&"host"in r,Cu=r=>me(r)&&r.localName==="input",bg=r=>!!r?.matches("a[href]"),vg=r=>me(r)?r.offsetWidth>0||r.offsetHeight>0||r.getClientRects().length>0:false;function Qi(r){if(!r)return false;let e=r.getRootNode();return rn(e)===r}var Vk=/(textarea|select)/;function Co(r){if(r==null||!me(r))return false;try{return Cu(r)&&r.selectionStart!=null||Vk.test(r.localName)||r.isContentEditable||r.getAttribute("contenteditable")==="true"||r.getAttribute("contenteditable")===""}catch{return false}}function mt(r,e){if(!r||!e||!me(r)||!gg(e))return false;if(me(e)&&r===e||r.contains(e))return true;let t=e.getRootNode?.();if(t&&Rr(t)){let n=e;for(;n;){if(r===n)return true;n=n.parentNode||n.host;}}return false}function Oe(r){return Zi(r)?r:Fk(r)?r.document:r?.ownerDocument??document}function Bk(r){return Oe(r).documentElement}function Ie(r){return Rr(r)?Ie(r.host):Zi(r)?r.defaultView??window:me(r)?r.ownerDocument?.defaultView??window:window}function rn(r){let e=r.activeElement;for(;e?.shadowRoot;){let t=e.shadowRoot.activeElement;if(!t||t===e)break;e=t;}return e}function yg(r){if(mg(r)==="html")return r;let e=r.assignedSlot||r.parentNode||Rr(r)&&r.host||Bk(r);return Rr(e)?e.host:e}function Fl(r){let e;try{if(e=r.getRootNode({composed:!0}),Zi(e)||Rr(e))return e}catch{}return r.ownerDocument??document}var Tu=new WeakMap;function To(r){return Tu.has(r)||Tu.set(r,Ie(r).getComputedStyle(r)),Tu.get(r)}var ku=new Set(["menu","listbox","dialog","grid","tree","region","application"]),_k=r=>ku.has(r),wg=r=>r.getAttribute("aria-controls")?.split(" ")||[];function Vl(r,e){let t=new Set,n=Fl(r),o=i=>{let s=i.querySelectorAll("[aria-controls]");for(let a of s){if(a.getAttribute("aria-expanded")!=="true")continue;let l=wg(a);for(let c of l){if(!c||t.has(c))continue;t.add(c);let d=n.getElementById(c);if(d){let u=d.getAttribute("role"),h=d.getAttribute("aria-modal")==="true";if(u&&_k(u)&&!h&&(d===e||d.contains(e)||o(d)))return true}}}return false};return o(r)}function Lu(r,e){let t=Fl(r),n=new Set,o=i=>{let s=i.querySelectorAll("[aria-controls]");for(let a of s){if(a.getAttribute("aria-expanded")!=="true")continue;let l=wg(a);for(let c of l){if(!c||n.has(c))continue;n.add(c);let d=t.getElementById(c);if(d){let u=d.getAttribute("role"),h=d.getAttribute("aria-modal")==="true";u&&ku.has(u)&&!h&&(e(d),o(d));}}}};o(r);}function xg(r){let e=new Set;return Lu(r,t=>{r.contains(t)||e.add(t);}),Array.from(e)}function Hk(r){let e=r.getAttribute("role");return !!(e&&ku.has(e))}function zk(r){return r.hasAttribute("aria-controls")&&r.getAttribute("aria-expanded")==="true"}function Sg(r){return zk(r)?true:!!r.querySelector?.('[aria-controls][aria-expanded="true"]')}function Cg(r){if(!r.id)return false;let e=Fl(r),t=CSS.escape(r.id),n=`[aria-controls~="${t}"][aria-expanded="true"], [aria-controls="${t}"][aria-expanded="true"]`;return !!(e.querySelector(n)&&Hk(r))}var Mu=()=>typeof document<"u";function Wk(){return navigator.userAgentData?.platform??navigator.platform}function Gk(){let r=navigator.userAgentData;return r&&Array.isArray(r.brands)?r.brands.map(({brand:e,version:t})=>`${e}/${t}`).join(" "):navigator.userAgent}var Eu=r=>Mu()&&r.test(Wk()),Tg=r=>Mu()&&r.test(Gk());var Pu=()=>Mu()&&!!navigator.maxTouchPoints,$k=()=>Eu(/^iPhone/i),Uk=()=>Eu(/^iPad/i)||ko()&&navigator.maxTouchPoints>1,kg=()=>$k()||Uk();var ko=()=>Eu(/^Mac/i);var Lg=()=>Tg(/Firefox/i);var Mg=()=>Tg(/Android/i);function Yk(r){return r.composedPath?.()??r.nativeEvent?.composedPath?.()}function He(r){return Yk(r)?.[0]??r.target}function Iu(r){let e=r.currentTarget;if(!e||!e.matches("a[href], button[type='submit'], input[type='submit']"))return false;let n=r.button===1,o=Kk(r);return n||o}function Au(r){let e=r.currentTarget;if(!e)return false;let t=e.localName;return r.altKey?t==="a"||t==="button"&&e.type==="submit"||t==="input"&&e.type==="submit":false}function Kk(r){return ko()?r.metaKey:r.ctrlKey}function Pg(r){return r.key.length===1&&!r.ctrlKey&&!r.metaKey}function Ig(r){return r.pointerType===""&&r.isTrusted?true:Mg()&&r.pointerType?r.type==="click"&&r.buttons===1:r.detail===0&&!r.pointerType}var Bl=r=>r.button===2||ko()&&r.ctrlKey&&r.button===0,Ag=r=>r.ctrlKey||r.altKey||r.metaKey,Xk=r=>"touches"in r&&r.touches.length>0,jk={Up:"ArrowUp",Down:"ArrowDown",Esc:"Escape"," ":"Space",",":"Comma",Left:"ArrowLeft",Right:"ArrowRight"},Eg={ArrowLeft:"ArrowRight",ArrowRight:"ArrowLeft"};function Ru(r,e={}){let{dir:t="ltr",orientation:n="horizontal"}=e,o=r.key;return o=jk[o]??o,t==="rtl"&&n==="horizontal"&&o in Eg&&(o=Eg[o]),o}function Lo(r,e="client"){let t=Xk(r)?r.touches[0]||r.changedTouches[0]:r;return {x:t[`${e}X`],y:t[`${e}Y`]}}var ot=(r,e,t,n)=>{let o=typeof r=="function"?r():r;return o?.addEventListener(e,t,n),()=>{o?.removeEventListener(e,t,n);}};var Rg=r=>me(r)&&r.tagName==="IFRAME",qk=/^(audio|video|details)$/;function Dg(r){let e=r.getAttribute("tabindex");return e?parseInt(e,10):NaN}var Zk=r=>!Number.isNaN(Dg(r)),Qk=r=>Dg(r)<0;function Jk(r){return Cu(r)&&r.type==="radio"}function eL(r){if(!Jk(r)||!r.name||r.checked)return true;let e=`input[type="radio"][name="${CSS.escape(r.name)}"]`,t=r.form??r.ownerDocument,n=Array.from(t.querySelectorAll(e)).filter(i=>i.form===r.form&&Ct(i)),o=n.find(i=>i.checked);return o?o===r:n[0]===r}function tL(r,e){if(!e)return null;if(e===true)return r.shadowRoot||null;let t=e(r);return (t===true?r.shadowRoot:t)||null}function Og(r,e,t){let n=[...r],o=[...r],i=new Set,s=new Map;r.forEach((l,c)=>s.set(l,c));let a=0;for(;a{s.set(p,h+m);});for(let p=h+d.length;p{s.set(p,h+m);});}o.push(...d);}}return n}var _l="input:not([type='hidden']):not([disabled]), select:not([disabled]), textarea:not([disabled]), a[href], button:not([disabled]), [tabindex], iframe, object, embed, area[href], audio[controls], video[controls], [contenteditable]:not([contenteditable='false']), details > summary:first-of-type",Du=(r,e={})=>{if(!r)return [];let{includeContainer:t=false,getShadowRoot:n}=e,o=Array.from(r.querySelectorAll(_l));(t==true||t=="if-empty"&&o.length===0)&&me(r)&&Ct(r)&&o.unshift(r);let s=[];for(let a of o)if(Ct(a)){if(Rg(a)&&a.contentDocument){let l=a.contentDocument.body;s.push(...Du(l,{getShadowRoot:n}));continue}s.push(a);}return n?Og(s,n,Ct):s};function Ct(r){return !me(r)||r.closest("[inert]")?false:r.matches(_l)&&vg(r)}function Mo(r,e={}){if(!r)return [];let{includeContainer:t,getShadowRoot:n}=e,o=Array.from(r.querySelectorAll(_l));t&&Yn(r)&&o.unshift(r);let i=[];for(let s of o)if(Yn(s)){if(Rg(s)&&s.contentDocument){let a=s.contentDocument.body;i.push(...Mo(a,{getShadowRoot:n}));continue}i.push(s);}if(n){let s=Og(i,n,Yn);return !s.length&&t?o:s}return !i.length&&t?o:i}function Yn(r){return me(r)&&r.tabIndex>0?true:!Ct(r)||Qk(r)?false:eL(r)}function Ng(r,e={}){let t=Mo(r,e),n=t[0]||null,o=t[t.length-1]||null;return [n,o]}function Eo(r){return r.tabIndex<0&&(qk.test(r.localName)||Co(r))&&!Zk(r)?0:r.tabIndex}function Hl(r){let{root:e,getInitialEl:t,filter:n,enabled:o=true}=r;if(!o)return;let i=null;if(i||(i=typeof t=="function"?t():t),i||(i=e?.querySelector("[data-autofocus],[autofocus]")),!i){let s=Mo(e);i=n?s.filter(n)[0]:s[0];}return i||e||void 0}function Fg(r){let e=r.currentTarget;if(!e)return false;let[t,n]=Ng(e);return !(Qi(t)&&r.shiftKey||Qi(n)&&!r.shiftKey||!t&&!n)}var nL=class Vg{constructor(){Nl(this,"id",null),Nl(this,"fn_cleanup"),Nl(this,"cleanup",()=>{this.cancel();});}static create(){return new Vg}request(e){this.cancel(),this.id=globalThis.requestAnimationFrame(()=>{this.id=null,this.fn_cleanup=e?.();});}cancel(){this.id!==null&&(globalThis.cancelAnimationFrame(this.id),this.id=null),this.fn_cleanup?.(),this.fn_cleanup=void 0;}isActive(){return this.id!==null}};function Ve(r){let e=nL.create();return e.request(r),e.cleanup}function Bg(r){let e=new Set;function t(n){let o=globalThis.requestAnimationFrame(n);e.add(()=>globalThis.cancelAnimationFrame(o));}return t(()=>t(r)),function(){e.forEach(o=>o());}}function _g(r,e,t){let n=Ve(()=>{r.removeEventListener(e,o,true),t();}),o=()=>{n(),t();};return r.addEventListener(e,o,{once:true,capture:true}),n}function rL(r,e){if(!r)return;let{attributes:t,callback:n}=e,o=r.ownerDocument.defaultView||window,i=new o.MutationObserver(s=>{for(let a of s)a.type==="attributes"&&a.attributeName&&t.includes(a.attributeName)&&n(a);});return i.observe(r,{attributes:true,attributeFilter:t}),()=>i.disconnect()}function Hg(r,e){let n=Ve,o=[];return o.push(n(()=>{let i=typeof r=="function"?r():r;o.push(rL(i,e));})),()=>{o.forEach(i=>i?.());}}function zg(r){let e=()=>{let t=Ie(r);r.dispatchEvent(new t.MouseEvent("click"));};Lg()?_g(r,"keyup",e):queueMicrotask(e);}function zl(r){let e=yg(r);return fg(e)?Oe(e).body:me(e)&&Ou(e)?e:zl(e)}var oL=/auto|scroll|overlay|hidden|clip/,iL=new Set(["inline","contents"]);function Ou(r){let e=Ie(r),{overflow:t,overflowX:n,overflowY:o,display:i}=e.getComputedStyle(r);return oL.test(t+o+n)&&!iL.has(i)}function Po(r,e){return Array.from(r?.querySelectorAll(e)??[])}var Wl=r=>r.id;function sL(r,e,t=Wl){return r.find(n=>t(n)===e)}function Wg(r,e,t=Wl){let n=sL(r,e,t);return n?r.indexOf(n):-1}function aL(r){return r.scrollHeight>r.clientHeight||r.scrollWidth>r.clientWidth}function Gg(r,e){let{rootEl:t,...n}=e||{};!r||!t||!Ou(t)||!aL(t)||r.scrollIntoView(n);}var lL=r=>r.split("").map(e=>{let t=e.charCodeAt(0);return t>0&&t<128?e:t>=128&&t<=255?`/x${t.toString(16)}`.replace("/","\\"):""}).join("").trim(),cL=r=>lL(r.dataset?.valuetext??r.textContent??""),dL=(r,e)=>r.trim().toLowerCase().startsWith(e.toLowerCase());function $g(r,e,t,n=Wl){let o=t?Wg(r,t,n):-1,i=t?pg(r,o):r;return e.length===1&&(i=i.filter(a=>n(a)!==t)),i.find(a=>dL(cL(a),e))}function Ji(r,e){if(!r)return ji;let t=Object.keys(e).reduce((n,o)=>(n[o]=r.style.getPropertyValue(o),n),{});return uL(t,e)?ji:(Object.assign(r.style,e),()=>{Object.assign(r.style,t),r.style.length===0&&r.removeAttribute("style");})}function Ug(r,e,t){if(!r)return ji;let n=r.style.getPropertyValue(e);return n===t?ji:(r.style.setProperty(e,t),()=>{r.style.setProperty(e,n),r.style.length===0&&r.removeAttribute("style");})}function uL(r,e){return Object.keys(r).every(t=>r[t]===e[t])}function hL(r,e){let{state:t,activeId:n,key:o,timeout:i=350,itemToId:s}=e,a=t.keysSoFar+o,c=a.length>1&&Array.from(a).every(m=>m===a[0])?a[0]:a,d=r.slice(),u=$g(d,c,n,s);function h(){clearTimeout(t.timer),t.timer=-1;}function p(m){t.keysSoFar=m,h(),m!==""&&(t.timer=+setTimeout(()=>{p(""),h();},i));}return p(a),u}var Gl=Object.assign(hL,{defaultOptions:{keysSoFar:"",timer:-1},isValidEvent:pL});function pL(r){return r.key.length===1&&!r.ctrlKey&&!r.metaKey}function mL(r,e,t){let{signal:n}=e;return [new Promise((s,a)=>{let l=setTimeout(()=>{a(new Error(`Timeout of ${t}ms exceeded`));},t);n.addEventListener("abort",()=>{clearTimeout(l),a(new DOMException("Promise aborted","AbortError"));}),r.then(c=>{n.aborted||(clearTimeout(l),s(c));}).catch(c=>{n.aborted||(clearTimeout(l),a(c));});}),()=>e.abort()]}function Yg(r,e){let{timeout:t,rootNode:n}=e,o=Ie(n),i=Oe(n),s=new o.AbortController;return mL(new Promise(a=>{let l=r();if(l){a(l);return}let c=new o.MutationObserver(()=>{let d=r();d&&d.isConnected&&(c.disconnect(),a(d));});c.observe(i.body,{childList:true,subtree:true});}),s,t)}function Kg(r){let e=()=>r.getRootNode?.()??document,t=()=>Oe(e());return {...r,getRootNode:e,getDoc:t,getWin:()=>t().defaultView??window,getActiveElement:()=>rn(e()),isActiveElement:Qi,getById:s=>e().getElementById(s)}}function Xg(r){return new Proxy({},{get(e,t){return t==="style"?n=>r({style:n}).style:r}})}var jg={onFocus:"onFocusin",onBlur:"onFocusout",onChange:"onInput",onDoubleClick:"onDblclick",htmlFor:"for",className:"class",defaultValue:"value",defaultChecked:"checked"},fL=new Set(["viewBox","preserveAspectRatio"]),gL=r=>{let e="";for(let t in r){let n=r[t];n!=null&&(t.startsWith("--")||(t=t.replace(/[A-Z]/g,o=>`-${o.toLowerCase()}`)),e+=`${t}:${n};`);}return e},Io=Xg(r=>Object.entries(r).reduce((e,[t,n])=>{if(n===void 0)return e;if(t in jg&&(t=jg[t]),t==="style"&&typeof n=="object")return e.style=gL(n),e;let o=fL.has(t)?t:t.toLowerCase();return e[o]=n,e},{}));var $l=new WeakMap,qg=new Set(["value","checked","selected"]),bL=new Set(["viewBox","preserveAspectRatio","clipPath","clipRule","fillRule","strokeWidth","strokeLinecap","strokeLinejoin","strokeDasharray","strokeDashoffset","strokeMiterlimit"]),vL=r=>r.tagName==="svg"||r.namespaceURI==="http://www.w3.org/2000/svg",Ul=(r,e)=>vL(r)&&bL.has(e)?e:e.toLowerCase();function ft(r,e,t){let n=t||"default",o=$l.get(r);o||(o=new Map,$l.set(r,o));let i=o.get(n)||{},s=Object.keys(e),a=(f,g)=>{r.addEventListener(f.toLowerCase(),g);},l=(f,g)=>{r.removeEventListener(f.toLowerCase(),g);},c=f=>f.startsWith("on"),d=f=>!f.startsWith("on"),u=f=>a(f.substring(2),e[f]),h=f=>l(f.substring(2),e[f]),p=f=>{let g=e[f],b=i[f];if(g!==b){if(f==="class"){r.className=g??"";return}if(qg.has(f)){r[f]=g??"";return}if(typeof g=="boolean"&&!f.includes("aria-")){r.toggleAttribute(Ul(r,f),g);return}if(f==="children"){r.innerHTML=g;return}if(g!=null){r.setAttribute(Ul(r,f),g);return}r.removeAttribute(Ul(r,f));}};for(let f in i)e[f]==null&&(f==="class"?r.className="":qg.has(f)?r[f]="":r.removeAttribute(Ul(r,f)));return Object.keys(i).filter(c).forEach(f=>{l(f.substring(2),i[f]);}),s.filter(c).forEach(u),s.filter(d).forEach(p),o.set(n,e),function(){s.filter(c).forEach(h);let g=$l.get(r);g&&(g.delete(n),g.size===0&&$l.delete(r));}}function yL(){if(typeof globalThis<"u")return globalThis;if(typeof self<"u")return self;if(typeof window<"u")return window;if(typeof global<"u")return global}function Nu(r,e){let t=yL();return t?(t[r]||(t[r]=e()),t[r]):e()}var Ao=Nu("__zag__refSet",()=>new WeakSet);var wL=r=>typeof r=="object"&&r!==null&&"$$typeof"in r&&"props"in r,xL=r=>typeof r=="object"&&r!==null&&"__v_isVNode"in r,SL=r=>typeof r=="object"&&r!==null&&"nodeType"in r&&typeof r.nodeName=="string",CL=r=>wL(r)||xL(r)||SL(r),Yl=r=>r!==null&&typeof r=="object",Fu=r=>Yl(r)&&!Ao.has(r)&&(Array.isArray(r)||!(Symbol.iterator in r))&&!CL(r)&&!(r instanceof WeakMap)&&!(r instanceof WeakSet)&&!(r instanceof Error)&&!(r instanceof Number)&&!(r instanceof Date)&&!(r instanceof String)&&!(r instanceof RegExp)&&!(r instanceof ArrayBuffer)&&!(r instanceof Promise)&&!(r instanceof File)&&!(r instanceof Blob)&&!(r instanceof AbortController);var TL=Symbol();var Zg=Object.getPrototypeOf,Vu=new WeakMap,kL=r=>r&&(Vu.has(r)?Vu.get(r):Zg(r)===Object.prototype||Zg(r)===Array.prototype);var Qg=r=>kL(r)&&r[TL]||null,Bu=(r,e=true)=>{Vu.set(r,e);};var Dr=Nu("__zag__proxyStateMap",()=>new WeakMap),LL=(r=Object.is,e=(a,l)=>new Proxy(a,l),t=new WeakMap,n=(a,l)=>{let c=t.get(a);if(c?.[0]===l)return c[1];let d=Array.isArray(a)?[]:Object.create(Object.getPrototypeOf(a));return Bu(d,true),t.set(a,[l,d]),Reflect.ownKeys(a).forEach(u=>{let h=Reflect.get(a,u);Ao.has(h)?(Bu(h,false),d[u]=h):Dr.has(h)?d[u]=Jg(h):d[u]=h;}),Object.freeze(d)},o=new WeakMap,i=[1,1],s=a=>{if(!Yl(a))throw new Error("object required");let l=o.get(a);if(l)return l;let c=i[0],d=new Set,u=(L,v=++i[0])=>{c!==v&&(c=v,d.forEach(k=>k(L,v)));},h=i[1],p=(L=++i[1])=>(h!==L&&!d.size&&(h=L,f.forEach(([v])=>{let k=v[1](L);k>c&&(c=k);})),c),m=L=>(v,k)=>{let x=[...v];x[1]=[L,...x[1]],u(x,k);},f=new Map,g=(L,v)=>{if(d.size){let k=v[3](m(L));f.set(L,[v,k]);}else f.set(L,[v]);},b=L=>{let v=f.get(L);v&&(f.delete(L),v[1]?.());},y=L=>(d.add(L),d.size===1&&f.forEach(([k,x],E)=>{let I=k[3](m(E));f.set(E,[k,I]);}),()=>{d.delete(L),d.size===0&&f.forEach(([k,x],E)=>{x&&(x(),f.set(E,[k]));});}),w=Array.isArray(a)?[]:Object.create(Object.getPrototypeOf(a)),M=e(w,{deleteProperty(L,v){let k=Reflect.get(L,v);b(v);let x=Reflect.deleteProperty(L,v);return x&&u(["delete",[v],k]),x},set(L,v,k,x){let E=Reflect.has(L,v),I=Reflect.get(L,v,x);if(E&&(r(I,k)||o.has(k)&&r(I,o.get(k))))return true;b(v),Yl(k)&&(k=Qg(k)||k);let N=k;if(!Object.getOwnPropertyDescriptor(L,v)?.set){!Dr.has(k)&&Fu(k)&&(N=Kl(k));let V=!Ao.has(N)&&Dr.get(N);V&&g(v,V);}return Reflect.set(L,v,N,x),u(["set",[v],k,I]),true}});o.set(a,M);let C=[w,p,n,y];return Dr.set(M,C),Reflect.ownKeys(a).forEach(L=>{let v=Object.getOwnPropertyDescriptor(a,L);v.get||v.set?Object.defineProperty(w,L,v):M[L]=a[L];}),M})=>[s,Dr,Ao,r,e,Fu,t,n,o,i],[ML]=LL();function Kl(r={}){return ML(r)}function Xl(r,e,t){let n=Dr.get(r);let o,i=[],s=n[3],a=false,c=s(d=>{if(i.push(d),t);o||(o=Promise.resolve().then(()=>{o=void 0,a&&e(i.splice(0));}));});return a=true,()=>{a=false,c();}}function Jg(r){let e=Dr.get(r);let[t,n,o]=e;return o(t,n())}function ts(r){let e=r().value??r().defaultValue;r().debug&&console.log(`[bindable > ${r().debug}] initial`,e);let t=r().isEqual??Object.is,n=Kl({value:e}),o=()=>r().value!==void 0;return {initial:e,ref:n,get(){return o()?r().value:n.value},set(i){let s=o()?r().value:n.value,a=pt(i)?i(s):i;r().debug&&console.log(`[bindable > ${r().debug}] setValue`,{next:a,prev:s}),o()||(n.value=a),t(a,s)||r().onChange?.(a,s);},invoke(i,s){r().onChange?.(i,s);},hash(i){return r().hash?.(i)??String(i)}}}ts.cleanup=r=>{};ts.ref=r=>{let e=r;return {get:()=>e,set:t=>{e=t;}}};function eb(r){let e={current:r};return {get(t){return e.current[t]},set(t,n){e.current[t]=n;}}}function _u(r,e){if(!Ar(r)||!Ar(e))return e===void 0?r:e;let t={...r};for(let n of Object.keys(e)){let o=e[n],i=r[n];o!==void 0&&(Ar(i)&&Ar(o)?t[n]=_u(i,o):t[n]=o);}return t}var Hu=class{constructor(r,e={}){ue(this,"machine",r),ue(this,"scope"),ue(this,"context"),ue(this,"prop"),ue(this,"state"),ue(this,"refs"),ue(this,"computed"),ue(this,"event",{type:""}),ue(this,"previousEvent",{type:""}),ue(this,"effects",new Map),ue(this,"transition",null),ue(this,"cleanups",[]),ue(this,"subscriptions",[]),ue(this,"userPropsRef"),ue(this,"getEvent",()=>({...this.event,current:()=>this.event,previous:()=>this.previousEvent})),ue(this,"getState",()=>({...this.state,matches:(...u)=>u.some(h=>dg(this.state.get(),h)),hasTag:u=>ug(this.machine,this.state.get(),u)})),ue(this,"debug",(...u)=>{this.machine.debug&&console.log(...u);}),ue(this,"notify",()=>{this.publish();}),ue(this,"send",u=>{this.status===So.Started&&queueMicrotask(()=>{if(!u)return;this.previousEvent=this.event,this.event=u,this.debug("send",u);let h=this.state.get(),p=u.type,{transitions:m,source:f}=lg(this.machine,h,p),g=this.choose(m);if(!g)return;this.transition=g;let b=xu(this.machine,g.target??h,f);this.debug("transition",g),b!==h?this.state.set(b):g.reenter?this.state.invoke(h,h):this.action(g.actions);});}),ue(this,"action",u=>{let h=pt(u)?u(this.getParams()):u;if(!h)return;let p=h.map(m=>{let f=this.machine.implementations?.actions?.[m];return f||wo(`[zag-js] No implementation found for action "${JSON.stringify(m)}"`),f});for(let m of p)m?.(this.getParams());}),ue(this,"guard",u=>{if(pt(u))return u(this.getParams());let h=this.machine.implementations?.guards?.[u];return h||wo(`[zag-js] No implementation found for guard "${JSON.stringify(u)}"`),h?.(this.getParams())}),ue(this,"effect",u=>{let h=pt(u)?u(this.getParams()):u;if(!h)return;let p=h.map(f=>{let g=this.machine.implementations?.effects?.[f];return g||wo(`[zag-js] No implementation found for effect "${JSON.stringify(f)}"`),g}),m=[];for(let f of p){let g=f?.(this.getParams());g&&m.push(g);}return ()=>m.forEach(f=>f?.())}),ue(this,"choose",u=>Uf(u).find(h=>{let p=!h.guard;return yo(h.guard)?p=!!this.guard(h.guard):pt(h.guard)&&(p=h.guard(this.getParams())),p})),ue(this,"subscribe",u=>(this.subscriptions.push(u),()=>{let h=this.subscriptions.indexOf(u);h>-1&&this.subscriptions.splice(h,1);})),ue(this,"status",So.NotStarted),ue(this,"publish",()=>{this.callTrackers(),this.subscriptions.forEach(u=>u(this.service));}),ue(this,"trackers",[]),ue(this,"setupTrackers",()=>{this.machine.watch?.(this.getParams());}),ue(this,"callTrackers",()=>{this.trackers.forEach(({deps:u,fn:h})=>{let p=u.map(m=>m());vo(h.prev,p)||(h(),h.prev=p);});}),ue(this,"getParams",()=>({state:this.getState(),context:this.context,event:this.getEvent(),prop:this.prop,send:this.send,action:this.action,guard:this.guard,track:(u,h)=>{h.prev=u.map(p=>p()),this.trackers.push({deps:u,fn:h});},refs:this.refs,computed:this.computed,flush:eg,scope:this.scope,choose:this.choose})),this.userPropsRef={current:e};let{id:t,ids:n,getRootNode:o}=Ui(e);this.scope=Kg({id:t,ids:n,getRootNode:o});let i=u=>{let h=Ui(this.userPropsRef.current);return (r.props?.({props:$n(h),scope:this.scope})??h)[u]};this.prop=i;let s=r.context?.({prop:i,bindable:ts,scope:this.scope,flush(u){queueMicrotask(u);},getContext(){return a},getComputed(){return l},getRefs(){return c},getEvent:this.getEvent.bind(this)});s&&Object.values(s).forEach(u=>{let h=Xl(u.ref,()=>this.notify());this.cleanups.push(h);});let a={get(u){return s?.[u].get()},set(u,h){s?.[u].set(h);},initial(u){return s?.[u].initial},hash(u){let h=s?.[u].get();return s?.[u].hash(h)}};this.context=a;let l=u=>(Yi(r.computed,()=>"[zag-js] No computed object found on machine"),r.computed[u]({context:a,event:this.getEvent(),prop:i,refs:this.refs,scope:this.scope,computed:l}));this.computed=l;let c=eb(r.refs?.({prop:i,context:a})??{});this.refs=c;let d=ts(()=>({defaultValue:xu(r,r.initialState({prop:i})),onChange:(u,h)=>{let{exiting:p,entering:m}=cg(this.machine,h,u,this.transition?.reenter);if(p.forEach(f=>{this.effects.get(f.path)?.(),this.effects.delete(f.path);}),p.forEach(f=>{this.action(f.state?.exit);}),this.action(this.transition?.actions),m.forEach(f=>{let g=this.effect(f.state?.effects);if(g){let b=this.effects.get(f.path);this.effects.set(f.path,b?Gn(b,g):g);}}),h===Xi){this.action(r.entry);let f=this.effect(r.effects);if(f){let g=this.effects.get(Xi);this.effects.set(Xi,g?Gn(g,f):f);}}m.forEach(f=>{this.action(f.state?.entry);});}}));this.state=d,this.cleanups.push(Xl(this.state.ref,()=>this.notify()));}updateProps(r){let e=this.userPropsRef.current;this.userPropsRef.current=()=>{let t=Ui(e),n=Ui(r);return _u(t,n)},this.notify();}start(){this.status=So.Started,this.debug("initializing..."),this.state.invoke(this.state.initial,Xi),this.setupTrackers();}stop(){this.effects.forEach(r=>r?.()),this.effects.clear(),this.transition=null,this.action(this.machine.exit),this.cleanups.forEach(r=>r()),this.cleanups=[],this.subscriptions=[],this.status=So.Stopped,this.debug("unmounting...");}get service(){return {state:this.getState(),send:this.send,context:this.context,prop:this.prop,scope:this.scope,refs:this.refs,computed:this.computed,event:this.getEvent(),getStatus:()=>this.status}}};function jl(r,e,t){let n=new Hu(r,e),o=n.subscribe(t);return n.start(),t(n.service),{service:n.service,flush:()=>t(n.service),stop:()=>{o(),n.stop();}}}var EL=0;function ql(r){return `${r}-${++EL}`}function Or(r,e=8){return `${r}::-webkit-scrollbar{width:${e}px;height:${e}px;}${r}::-webkit-scrollbar-thumb{background:var(--vela-scroll);border-radius:4px;border:2px solid transparent;background-clip:padding-box;}${r}::-webkit-scrollbar-track{background:transparent;}${r}::-webkit-scrollbar-button{display:none;width:0;height:0;}`}var tb="outline:none;transition:border-color .12s ease,box-shadow .12s ease;",nb="border-color:var(--vela-focus);box-shadow:0 0 0 3px var(--vela-focus-soft);";function he(r,e,t=document){if(typeof document>"u")return;let n=t instanceof Document?t.head:t;if(t.getElementById?.(r)??n.querySelector(`#${CSS.escape(r)}`))return;let o=document.createElement("style");o.id=r,o.textContent=e,n.appendChild(o);}var PL="vela-ui-tokens",IL=Object.entries(Il).map(([r,e])=>` ${r}: ${e};`).join(` +`),AL=` .vela-ui, .vela-ui-layer { -${CL} +${IL} font-family: var(--vela-font, -apple-system, system-ui, sans-serif); box-sizing: border-box; /* Chrome text (titles, buttons, menus, readouts) is UI, not copy \u2014 never selectable. */ @@ -21,7 +21,7 @@ ${CL} .vela-ui[data-layout='mobile'] :is(input, textarea, select) { font-size: 16px; } .vela-icon { display: inline-flex; align-items: center; flex: none; } .vela-icon svg { display: block; } -`;function TL(r,e){let t=El(e);for(let n in t)r.style.setProperty(n,t[n]);}function Xl(r,e){return r.closest(".vela-ui")??e??r}function Zg(r,e){he(xL,SL,r.getRootNode()),r.classList.add("vela-ui"),e&&TL(r,e);}function Ue(r,e=document){let t=e.createElement("span");t.className="vela-icon",t.setAttribute("aria-hidden","true");let n=to(r);return n&&(t.innerHTML=n),t}var Cn=(r,e=[])=>({parts:(...t)=>{if(kL(e))return Cn(r,t);throw new Error("createAnatomy().parts(...) should only be called once. Did you mean to use .extendWith(...) ?")},extendWith:(...t)=>Cn(r,[...e,...t]),omit:(...t)=>Cn(r,e.filter(n=>!t.includes(n))),rename:t=>Cn(t,e),keys:()=>e,build:()=>[...new Set(e)].reduce((t,n)=>Object.assign(t,{[n]:{selector:[`&[data-scope="${Eo(r)}"][data-part="${Eo(n)}"]`,`& [data-scope="${Eo(r)}"][data-part="${Eo(n)}"]`].join(", "),attrs:{"data-scope":Eo(r),"data-part":Eo(n)}}}),{})}),Eo=r=>r.replace(/([A-Z])([A-Z])/g,"$1-$2").replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[\s_]+/g,"-").toLowerCase(),kL=r=>r.length===0;var LL=Cn("menu").parts("arrow","arrowTip","content","contextTrigger","indicator","item","itemGroup","itemGroupLabel","itemIndicator","itemText","positioner","separator","trigger","triggerItem"),Qe=LL.build();var eb=["top","right","bottom","left"];var rn=Math.min,Vt=Math.max,Ji=Math.round,es=Math.floor,on=r=>({x:r,y:r}),ML={left:"right",right:"left",bottom:"top",top:"bottom"};function Bu(r,e,t){return Vt(r,rn(e,t))}function sn(r,e){return typeof r=="function"?r(e):r}function Sn(r){return r.split("-")[0]}function Ar(r){return r.split("-")[1]}function ql(r){return r==="x"?"y":"x"}function Zl(r){return r==="y"?"height":"width"}function Bt(r){let e=r[0];return e==="t"||e==="b"?"y":"x"}function Ql(r){return ql(Bt(r))}function tb(r,e,t){t===void 0&&(t=false);let n=Ar(r),o=Ql(r),i=Zl(o),s=o==="x"?n===(t?"end":"start")?"right":"left":n==="start"?"bottom":"top";return e.reference[i]>e.floating[i]&&(s=Qi(s)),[s,Qi(s)]}function nb(r){let e=Qi(r);return [jl(r),e,jl(e)]}function jl(r){return r.includes("start")?r.replace("start","end"):r.replace("end","start")}var Qg=["left","right"],Jg=["right","left"],EL=["top","bottom"],PL=["bottom","top"];function IL(r,e,t){switch(r){case "top":case "bottom":return t?e?Jg:Qg:e?Qg:Jg;case "left":case "right":return e?EL:PL;default:return []}}function rb(r,e,t,n){let o=Ar(r),i=IL(Sn(r),t==="start",n);return o&&(i=i.map(s=>s+"-"+o),e&&(i=i.concat(i.map(jl)))),i}function Qi(r){let e=Sn(r);return ML[e]+r.slice(e.length)}function AL(r){var e,t,n,o;return {top:(e=r.top)!=null?e:0,right:(t=r.right)!=null?t:0,bottom:(n=r.bottom)!=null?n:0,left:(o=r.left)!=null?o:0}}function _u(r){return typeof r!="number"?AL(r):{top:r,right:r,bottom:r,left:r}}function Rr(r){let{x:e,y:t,width:n,height:o}=r;return {width:n,height:o,top:t,left:e,right:e+n,bottom:t+o,x:e,y:t}}function ob(r,e,t){let{reference:n,floating:o}=r,i=Bt(e),s=Ql(e),a=Zl(s),l=Sn(e),c=i==="y",d=n.x+n.width/2-o.width/2,u=n.y+n.height/2-o.height/2,h=n[a]/2-o[a]/2,p;switch(l){case "top":p={x:d,y:n.y-o.height};break;case "bottom":p={x:d,y:n.y+n.height};break;case "right":p={x:n.x+n.width,y:u};break;case "left":p={x:n.x-o.width,y:u};break;default:p={x:n.x,y:n.y};}let m=Ar(e);return m&&(p[s]+=h*(m==="end"?1:-1)*(t&&c?-1:1)),p}async function ab(r,e){var t;e===void 0&&(e={});let{x:n,y:o,platform:i,rects:s,elements:a,strategy:l}=r,{boundary:c="clippingAncestors",rootBoundary:d="viewport",elementContext:u="floating",altBoundary:h=false,padding:p=0}=sn(e,r),m=_u(p),g=a[h?u==="floating"?"reference":"floating":u],b=Rr(await i.getClippingRect({element:(t=await(i.isElement==null?void 0:i.isElement(g)))==null||t?g:g.contextElement||await(i.getDocumentElement==null?void 0:i.getDocumentElement(a.floating)),boundary:c,rootBoundary:d,strategy:l})),y=u==="floating"?{x:n,y:o,width:s.floating.width,height:s.floating.height}:s.reference,w=await(i.getOffsetParent==null?void 0:i.getOffsetParent(a.floating)),C=await(i.isElement==null?void 0:i.isElement(w))&&await(i.getScale==null?void 0:i.getScale(w))||{x:1,y:1},M=Rr(i.convertOffsetParentRelativeRectToViewportRelativeRect?await i.convertOffsetParentRelativeRectToViewportRelativeRect({elements:a,rect:y,offsetParent:w,strategy:l}):y);return {top:(b.top-M.top+m.top)/C.y,bottom:(M.bottom-b.bottom+m.bottom)/C.y,left:(b.left-M.left+m.left)/C.x,right:(M.right-b.right+m.right)/C.x}}var RL=50,lb=async(r,e,t)=>{let{placement:n="bottom",strategy:o="absolute",middleware:i=[],platform:s}=t,a=s.detectOverflow?s:{...s,detectOverflow:ab},l=await(s.isRTL==null?void 0:s.isRTL(e)),c=await s.getElementRects({reference:r,floating:e,strategy:o}),{x:d,y:u}=ob(c,n,l),h=n,p=0,m={};for(let f=0;f({name:"arrow",options:r,async fn(e){let{x:t,y:n,placement:o,rects:i,platform:s,elements:a,middlewareData:l}=e,{element:c,padding:d=0}=sn(r,e)||{};if(c==null)return {};let u=_u(d),h={x:t,y:n},p=Ql(o),m=Zl(p),f=await s.getDimensions(c),g=p==="y",b=g?"top":"left",y=g?"bottom":"right",w=g?"clientHeight":"clientWidth",C=i.reference[m]+i.reference[p]-h[p]-i.floating[m],M=h[p]-i.reference[p],S=await(s.getOffsetParent==null?void 0:s.getOffsetParent(c)),L=S?S[w]:0;(!L||!await(s.isElement==null?void 0:s.isElement(S)))&&(L=a.floating[w]||i.floating[m]);let v=C/2-M/2,k=L/2-f[m]/2-1,x=rn(u[b],k),E=rn(u[y],k),I=L-f[m]-E,N=L/2-f[m]/2+v,V=Bu(x,N,I),Z=!l.arrow&&Ar(o)!=null&&N!==V&&i.reference[m]/2-(NV<=0)){var E,I;let V=(((E=i.flip)==null?void 0:E.index)||0)+1,Z=L[V];if(Z&&(!(u==="alignment"?y!==Bt(Z):false)||x.every(At=>Bt(At.placement)===y?At.overflows[0]>0:true)))return {data:{index:V,overflows:x},reset:{placement:Z}};let be=(I=x.filter(fn=>fn.overflows[0]<=0).sort((fn,At)=>fn.overflows[1]-At.overflows[1])[0])==null?void 0:I.placement;if(!be)switch(p){case "bestFit":{var N;let fn=(N=x.filter(At=>{if(S){let Fn=Bt(At.placement);return Fn===y||Fn==="y"}return true}).map(At=>[At.placement,At.overflows.filter(Fn=>Fn>0).reduce((Fn,rS)=>Fn+rS,0)]).sort((At,Fn)=>At[1]-Fn[1])[0])==null?void 0:N[0];fn&&(be=fn);break}case "initialPlacement":be=a;break}if(o!==be)return {reset:{placement:be}}}return {}}}};function ib(r,e){return {top:r.top-e.height,right:r.right-e.width,bottom:r.bottom-e.height,left:r.left-e.width}}function sb(r){return eb.some(e=>r[e]>=0)}var ub=function(r){return r===void 0&&(r={}),{name:"hide",options:r,async fn(e){let{rects:t,platform:n}=e,{strategy:o="referenceHidden",...i}=sn(r,e);switch(o){case "referenceHidden":{let s=await n.detectOverflow(e,{...i,elementContext:"reference"}),a=ib(s,t.reference);return {data:{referenceHiddenOffsets:a,referenceHidden:sb(a)}}}case "escaped":{let s=await n.detectOverflow(e,{...i,altBoundary:true}),a=ib(s,t.floating);return {data:{escapedOffsets:a,escaped:sb(a)}}}default:return {}}}}};var hb=new Set(["left","top"]);async function DL(r,e){let{placement:t,platform:n,elements:o}=r,i=await(n.isRTL==null?void 0:n.isRTL(o.floating)),s=Sn(t),a=Ar(t),l=Bt(t)==="y",c=hb.has(s)?-1:1,d=i&&l?-1:1,u=sn(e,r),{mainAxis:h,crossAxis:p,alignmentAxis:m}=typeof u=="number"?{mainAxis:u,crossAxis:0,alignmentAxis:null}:{mainAxis:u.mainAxis||0,crossAxis:u.crossAxis||0,alignmentAxis:u.alignmentAxis};return a&&typeof m=="number"&&(p=a==="end"?m*-1:m),l?{x:p*d,y:h*c}:{x:h*c,y:p*d}}var pb=function(r){return r===void 0&&(r=0),{name:"offset",options:r,async fn(e){var t,n;let{x:o,y:i,placement:s,middlewareData:a}=e,l=await DL(e,r);return s===((t=a.offset)==null?void 0:t.placement)&&(n=a.arrow)!=null&&n.alignmentOffset?{}:{x:o+l.x,y:i+l.y,data:{...l,placement:s}}}}},mb=function(r){return r===void 0&&(r={}),{name:"shift",options:r,async fn(e){let{x:t,y:n,placement:o,platform:i}=e,{mainAxis:s=true,crossAxis:a=false,limiter:l={fn:y=>{let{x:w,y:C}=y;return {x:w,y:C}}},...c}=sn(r,e),d={x:t,y:n},u=await i.detectOverflow(e,c),h=Bt(o),p=ql(h),m=d[p],f=d[h],g=(y,w)=>Bu(w+u[y==="y"?"top":"left"],w,w-u[y==="y"?"bottom":"right"]);s&&(m=g(p,m)),a&&(f=g(h,f));let b=l.fn({...e,[p]:m,[h]:f});return {...b,data:{x:b.x-t,y:b.y-n,enabled:{[p]:s,[h]:a}}}}}},fb=function(r){return r===void 0&&(r={}),{options:r,fn(e){var t,n;let{x:o,y:i,placement:s,rects:a,middlewareData:l}=e,{offset:c=0,mainAxis:d=true,crossAxis:u=true}=sn(r,e),h={x:o,y:i},p=Bt(s),m=ql(p),f=h[m],g=h[p],b=sn(c,e),y=typeof b=="number"?{mainAxis:b,crossAxis:0}:{mainAxis:(t=b.mainAxis)!=null?t:0,crossAxis:(n=b.crossAxis)!=null?n:0};if(d){let M=m==="y"?"height":"width",S=a.reference[m]-a.floating[M]+y.mainAxis,L=a.reference[m]+a.reference[M]-y.mainAxis;fL&&(f=L);}if(u){var w,C;let M=m==="y"?"width":"height",S=hb.has(Sn(s)),L=a.reference[p]-a.floating[M]+(S&&((w=l.offset)==null?void 0:w[p])||0)+(S?0:y.crossAxis),v=a.reference[p]+a.reference[M]+(S?0:((C=l.offset)==null?void 0:C[p])||0)-(S?y.crossAxis:0);gv&&(g=v);}return {[m]:f,[p]:g}}}},gb=function(r){return r===void 0&&(r={}),{name:"size",options:r,async fn(e){let{placement:t,rects:n,platform:o,elements:i}=e,{apply:s=()=>{},...a}=sn(r,e),l=await o.detectOverflow(e,a),c=Sn(t),d=Ar(t),u=Bt(t)==="y",{width:h,height:p}=n.floating,m,f;c==="top"||c==="bottom"?(m=c,f=d===(await(o.isRTL==null?void 0:o.isRTL(i.floating))?"start":"end")?"left":"right"):(f=c,m=d==="end"?"top":"bottom");let g=p-l.top-l.bottom,b=h-l.left-l.right,y=rn(p-l[m],g),w=rn(h-l[f],b),C=e.middlewareData.shift,M=!C,S=y,L=w;C!=null&&C.enabled.x&&(L=b),C!=null&&C.enabled.y&&(S=g),M&&!d&&(u?L=h-2*Vt(l.left,l.right):S=p-2*Vt(l.top,l.bottom)),await s({...e,availableWidth:L,availableHeight:S});let v=await o.getDimensions(i.floating);return h!==v.width||p!==v.height?{reset:{rects:true}}:{}}}};function Jl(){return typeof window<"u"}function Or(r){return vb(r)?(r.nodeName||"").toLowerCase():"#document"}function it(r){var e;return (r==null||(e=r.ownerDocument)==null?void 0:e.defaultView)||window}function an(r){var e;return (e=(vb(r)?r.ownerDocument:r.document)||window.document)==null?void 0:e.documentElement}function vb(r){return Jl()?r instanceof Node||r instanceof it(r).Node:false}function _t(r){return Jl()?r instanceof Element||r instanceof it(r).Element:false}function Tn(r){return Jl()?r instanceof HTMLElement||r instanceof it(r).HTMLElement:false}function bb(r){return !Jl()||typeof ShadowRoot>"u"?false:r instanceof ShadowRoot||r instanceof it(r).ShadowRoot}function ts(r){let{overflow:e,overflowX:t,overflowY:n,display:o}=Ht(r);return /auto|scroll|overlay|hidden|clip/.test(e+n+t)&&o!=="inline"&&o!=="contents"}function yb(r){return /^(table|td|th)$/.test(Or(r))}function ns(r){try{if(r.matches(":popover-open"))return !0}catch{}try{return r.matches(":modal")}catch{return false}}var OL=/transform|translate|scale|rotate|perspective|filter/,NL=/paint|layout|strict|content/,Dr=r=>!!r&&r!=="none",Hu;function ec(r){let e=_t(r)?Ht(r):r;return Dr(e.transform)||Dr(e.translate)||Dr(e.scale)||Dr(e.rotate)||Dr(e.perspective)||!tc()&&(Dr(e.backdropFilter)||Dr(e.filter))||OL.test(e.willChange||"")||NL.test(e.contain||"")}function wb(r){let e=Kn(r);for(;Tn(e)&&!Io(e);){if(ec(e))return e;if(ns(e))return null;e=Kn(e);}return null}function tc(){return Hu==null&&(Hu=typeof CSS<"u"&&CSS.supports&&CSS.supports("-webkit-backdrop-filter","none")),Hu}function Io(r){return /^(html|body|#document)$/.test(Or(r))}function Ht(r){return it(r).getComputedStyle(r)}function rs(r){return _t(r)?{scrollLeft:r.scrollLeft,scrollTop:r.scrollTop}:{scrollLeft:r.scrollX,scrollTop:r.scrollY}}function Kn(r){if(Or(r)==="html")return r;let e=r.assignedSlot||r.parentNode||bb(r)&&r.host||an(r);return bb(e)?e.host:e}function xb(r){let e=Kn(r);return Io(e)?(r.ownerDocument||r).body:Tn(e)&&ts(e)?e:xb(e)}function Po(r,e,t){var n;e===void 0&&(e=[]),t===void 0&&(t=true);let o=xb(r),i=o===((n=r.ownerDocument)==null?void 0:n.body),s=it(o);if(i){let a=nc(s);return e.concat(s,s.visualViewport||[],ts(o)?o:[],a&&t?Po(a):[])}else return e.concat(o,Po(o,[],t))}function nc(r){return r.parent&&Object.getPrototypeOf(r.parent)?r.frameElement:null}function Tb(r){let e=Ht(r),t=parseFloat(e.width)||0,n=parseFloat(e.height)||0,o=Tn(r),i=o?r.offsetWidth:t,s=o?r.offsetHeight:n,a=Ji(t)!==i||Ji(n)!==s;return a&&(t=i,n=s),{width:t,height:n,$:a}}function Wu(r){return _t(r)?r:r.contextElement}function Ao(r){let e=Wu(r);if(!Tn(e))return on(1);let t=e.getBoundingClientRect(),{width:n,height:o,$:i}=Tb(e),s=(i?Ji(t.width):t.width)/n,a=(i?Ji(t.height):t.height)/o;return (!s||!Number.isFinite(s))&&(s=1),(!a||!Number.isFinite(a))&&(a=1),{x:s,y:a}}var FL=on(0);function kb(r){let e=it(r);return !tc()||!e.visualViewport?FL:{x:e.visualViewport.offsetLeft,y:e.visualViewport.offsetTop}}function VL(r,e,t){return e===void 0&&(e=false),!!t&&e&&t===it(r)}function Nr(r,e,t,n){e===void 0&&(e=false),t===void 0&&(t=false);let o=r.getBoundingClientRect(),i=Wu(r),s=on(1);e&&(n?_t(n)&&(s=Ao(n)):s=Ao(r));let a=VL(i,t,n)?kb(i):on(0),l=(o.left+a.x)/s.x,c=(o.top+a.y)/s.y,d=o.width/s.x,u=o.height/s.y;if(i&&n){let h=it(i),p=_t(n)?it(n):n,m=h,f=nc(m);for(;f&&p!==m;){let g=Ao(f),b=f.getBoundingClientRect(),y=Ht(f),w=b.left+(f.clientLeft+parseFloat(y.paddingLeft))*g.x,C=b.top+(f.clientTop+parseFloat(y.paddingTop))*g.y;l*=g.x,c*=g.y,d*=g.x,u*=g.y,l+=w,c+=C,m=it(f),f=nc(m);}}return Rr({width:d,height:u,x:l,y:c})}function rc(r,e){let t=rs(r).scrollLeft;return e?e.left+t:Nr(an(r)).left+t}function Lb(r,e){let t=r.getBoundingClientRect(),n=t.left+e.scrollLeft-rc(r,t),o=t.top+e.scrollTop;return {x:n,y:o}}function BL(r){let{elements:e,rect:t,offsetParent:n,strategy:o}=r,i=o==="fixed",s=an(n),a=e?ns(e.floating):false;if(n===s||a&&i)return t;let l={scrollLeft:0,scrollTop:0},c=on(1),d=on(0),u=Tn(n);if((u||!i)&&((Or(n)!=="body"||ts(s))&&(l=rs(n)),u)){let p=Nr(n);c=Ao(n),d.x=p.x+n.clientLeft,d.y=p.y+n.clientTop;}let h=s&&!u&&!i?Lb(s,l):on(0);return {width:t.width*c.x,height:t.height*c.y,x:t.x*c.x-l.scrollLeft*c.x+d.x+h.x,y:t.y*c.y-l.scrollTop*c.y+d.y+h.y}}function _L(r){return r.getClientRects?Array.from(r.getClientRects()):[]}function HL(r){let e=rs(r),t=r.ownerDocument.body,n=Vt(r.scrollWidth,r.clientWidth,t.scrollWidth,t.clientWidth),o=Vt(r.scrollHeight,r.clientHeight,t.scrollHeight,t.clientHeight),i=-e.scrollLeft+rc(r),s=-e.scrollTop;return Ht(t).direction==="rtl"&&(i+=Vt(r.clientWidth,t.clientWidth)-n),{width:n,height:o,x:i,y:s}}var zL=25;function WL(r,e,t){t===void 0&&(t="viewport");let n=t==="layoutViewport",o=it(r),i=an(r),s=o.visualViewport,a=i.clientWidth,l=i.clientHeight,c=0,d=0;if(s){let h=!tc()||e==="fixed";n?h||(c=-s.offsetLeft,d=-s.offsetTop):(a=s.width,l=s.height,h&&(c=s.offsetLeft,d=s.offsetTop));}if(rc(i)<=0){let h=i.ownerDocument,p=h.body,m=getComputedStyle(p),f=h.compatMode==="CSS1Compat"&&parseFloat(m.marginLeft)+parseFloat(m.marginRight)||0,g=Math.abs(i.clientWidth-p.clientWidth-f),b=getComputedStyle(i).scrollbarGutter==="stable both-edges"?g/2:g;b<=zL&&(a-=b);}return {width:a,height:l,x:c,y:d}}function GL(r,e){let t=Nr(r,true,e==="fixed"),n=t.top+r.clientTop,o=t.left+r.clientLeft,i=Ao(r),s=r.clientWidth*i.x,a=r.clientHeight*i.y,l=o*i.x,c=n*i.y;return {width:s,height:a,x:l,y:c}}function Cb(r,e,t){let n;if(e==="viewport"||e==="layoutViewport")n=WL(r,t,e);else if(e==="document")n=HL(an(r));else if(_t(e))n=GL(e,t);else {let o=kb(r);n={x:e.x-o.x,y:e.y-o.y,width:e.width,height:e.height};}return Rr(n)}function $L(r,e){let t=e.get(r);if(t)return t;let n=Po(r,[],false).filter(a=>_t(a)&&Or(a)!=="body"),o=null,i=Ht(r).position==="fixed",s=i?Kn(r):r;for(;_t(s)&&!Io(s);){let a=Ht(s),l=ec(s),c=o?o.position:i?"fixed":"";!l&&(c==="fixed"||c==="absolute"&&a.position==="static")?n=n.filter(u=>u!==s):o=a,s=Kn(s);}return e.set(r,n),n}function UL(r){let{element:e,boundary:t,rootBoundary:n,strategy:o}=r,s=[...t==="clippingAncestors"?ns(e)?[]:$L(e,this._c):[].concat(t),n],a=Cb(e,s[0],o),l=a.top,c=a.right,d=a.bottom,u=a.left;for(let h=1;h{a(false,1e-7);},1e3);}L=false;}try{n=new IntersectionObserver(v,{...S,root:i.ownerDocument});}catch{n=new IntersectionObserver(v,S);}n.observe(r);}let l=it(r),c=()=>a(t);return l.addEventListener("resize",c),a(true),()=>{l.removeEventListener("resize",c),s();}}function Pb(r,e,t,n){n===void 0&&(n={});let{ancestorScroll:o=true,ancestorResize:i=true,elementResize:s=typeof ResizeObserver=="function",layoutShift:a=typeof IntersectionObserver=="function",animationFrame:l=false}=n,c=Wu(r),d=o||i?[...c?Po(c):[],...e?Po(e):[]]:[];d.forEach(b=>{o&&b.addEventListener("scroll",t),i&&b.addEventListener("resize",t);});let u=c&&a?ZL(c,t,i):null,h=-1,p=null;s&&(p=new ResizeObserver(b=>{let[y]=b;y&&y.target===c&&p&&e&&(p.unobserve(e),cancelAnimationFrame(h),h=requestAnimationFrame(()=>{var w;(w=p)==null||w.observe(e);})),t();}),c&&!l&&p.observe(c),e&&p.observe(e));let m,f=l?Nr(r):null;l&&g();function g(){let b=Nr(r);f&&!Eb(f,b)&&t(),f=b,m=requestAnimationFrame(g);}return t(),()=>{var b;d.forEach(y=>{o&&y.removeEventListener("scroll",t),i&&y.removeEventListener("resize",t);}),u?.(),(b=p)==null||b.disconnect(),p=null,l&&cancelAnimationFrame(m);}}var Ib=pb;var Ab=mb,Rb=db,Db=gb,Ob=ub,Nb=cb;var Fb=fb,Vb=(r,e,t)=>{let n=new Map,o=t??{},i={...qL,...o.platform,_c:n};return lb(r,e,{...o,platform:i})};function Bb(r=0,e=0,t=0,n=0){if(typeof DOMRect=="function")return new DOMRect(r,e,t,n);let o={x:r,y:e,width:t,height:n,top:e,right:r+t,bottom:e+n,left:r};return {...o,toJSON:()=>o}}function QL(r){if(!r)return Bb();let{x:e,y:t,width:n,height:o}=r;return Bb(e,t,n,o)}function _b(r,e){return {contextElement:me(r)?r:r?.contextElement,getBoundingClientRect:()=>{let t=r,n=e?.(t);return n||!t?QL(n):t.getBoundingClientRect()}}}var os=r=>({variable:r,reference:`var(${r})`}),ln={arrowSize:os("--arrow-size"),arrowSizeHalf:os("--arrow-size-half"),arrowBg:os("--arrow-background"),transformOrigin:os("--transform-origin"),arrowOffset:os("--arrow-offset")},JL=r=>r==="top"||r==="bottom"?"y":"x";function Hb(r,e){return {name:"transformOrigin",fn(t){let{elements:n,middlewareData:o,placement:i,rects:s,y:a}=t,l=i.split("-")[0],c=JL(l),d=o.arrow?.x||0,u=o.arrow?.y||0,h=e?.clientWidth||0,p=e?.clientHeight||0,m=d+h/2,f=u+p/2,g=Math.abs(o.shift?.y||0),b=s.reference.height/2,y=p/2,w=r.offset?.mainAxis??r.gutter,C=typeof w=="number"?w+y:w??y,M=g>C,S={top:`${m}px calc(100% + ${C}px)`,bottom:`${m}px ${-C}px`,left:`calc(100% + ${C}px) ${f}px`,right:`${-C}px ${f}px`}[l],L=`${m}px ${s.reference.y+b-a}px`,v=!!r.overlap&&c==="y"&&M;return n.floating.style.setProperty(ln.transformOrigin.variable,v?L:S),{data:{transformOrigin:v?L:S}}}}}var zb={name:"rects",fn({rects:r}){return {data:r}}},Wb=r=>{if(r)return {name:"shiftArrow",fn({placement:e,middlewareData:t}){if(!t.arrow)return {};let{x:n,y:o}=t.arrow,i=e.split("-")[0];return Object.assign(r.style,{left:n!=null?`${n}px`:"",top:o!=null?`${o}px`:"",[i]:`calc(100% + ${ln.arrowOffset.reference})`}),{}}}};function Gb(r){let[e,t]=r.split("-");return {side:e,align:t,hasAlign:t!=null}}function is(r){return r.split("-")[0]}var eM={strategy:"absolute",placement:"bottom",listeners:true,restoreStyles:false,gutter:8,flip:true,slide:true,overlap:false,sameWidth:false,fitViewport:false,overflowPadding:8,arrowPadding:4};function $b(r,e){let t=r.devicePixelRatio||1;return Math.round(e*t)/t}function Ro(r,e){return r!=null&&Math.abs(r-e)<.5}function oc(r){return typeof r=="function"?r():r==="clipping-ancestors"?"clippingAncestors":r}function tM(r,e,t){let n=r||e.createElement("div");return Nb({element:n,padding:t.arrowPadding})}function nM(r,e){if(!Yf(e.offset??e.gutter))return Ib(({placement:t})=>{let n=(r?.clientHeight||0)/2,o=e.offset?.mainAxis??e.gutter,i=typeof o=="number"?o+n:o??n,{hasAlign:s}=Gb(t),a=s?void 0:e.shift,l=e.offset?.crossAxis??a;return $n({crossAxis:l,mainAxis:i,alignmentAxis:e.shift})})}function rM(r){if(r.flip)return Rb(()=>{let e=oc(r.boundary);return {...e?{boundary:e}:void 0,padding:r.overflowPadding,fallbackPlacements:r.flip===true?void 0:r.flip}})}function oM(r){if(!(!r.slide&&!r.overlap))return Ab(()=>{let e=oc(r.boundary);return {...e?{boundary:e}:void 0,mainAxis:r.slide,crossAxis:r.overlap,padding:r.overflowPadding,limiter:Fb()}})}function iM(r){if(r.sizeMiddleware===false&&!r.sameWidth&&!r.fitViewport)return;let e,t,n,o;return Db(()=>{let i=oc(r.boundary);return {padding:r.overflowPadding,...i?{boundary:i}:void 0,apply({elements:s,rects:a,availableHeight:l,availableWidth:c}){let d=s.floating,u=Math.round(a.reference.width),h=Math.round(a.reference.height);c=Math.floor(c),l=Math.floor(l),Ro(e,u)||(d.style.setProperty("--reference-width",`${u}px`),e=u),Ro(t,h)||(d.style.setProperty("--reference-height",`${h}px`),t=h),Ro(n,c)||(d.style.setProperty("--available-width",`${c}px`),n=c),Ro(o,l)||(d.style.setProperty("--available-height",`${l}px`),o=l);}}})}function sM(r){if(r.hideWhenDetached)return Ob(()=>({strategy:"referenceHidden",boundary:oc(r.boundary)??"clippingAncestors"}))}function aM(r){return r?r===true?{ancestorResize:true,ancestorScroll:true,elementResize:true,layoutShift:true}:r:{}}var lM=["transform","visibility","pointer-events","--x","--y","--z-index","--reference-width","--reference-height","--available-width","--available-height","--transform-origin"],cM=["top","right","bottom","left"];function Ub(r,e){if(!r)return pu;let t=new Map(e.map(n=>[n,r.style.getPropertyValue(n)]));return ()=>{t.forEach((n,o)=>{n?r.style.setProperty(o,n):r.style.removeProperty(o);}),r.style.length===0&&r.removeAttribute("style");}}function Yb(r){return r==null?null:me(r)?r:typeof r=="object"&&r&&"contextElement"in r&&r.contextElement?r.contextElement:r}function dM(r,e,t={}){let n=()=>(typeof e=="function"?e():e)??null,o=()=>{let x=typeof r=="function"?r():r;return t.getAnchorElement?.()??x},i=()=>{let x=o();return !x&&!t.getAnchorRect?null:_b(x,t.getAnchorRect)},s=Object.assign({},eM,t),a=[],l=null,c,d;function u(x){c?.(),d?.(),l=x,c=s.restoreStyles?Ub(x,lM):void 0;let E=x.querySelector("[data-part=arrow]");d=s.restoreStyles?Ub(E,cM):void 0,a=[nM(E,s),rM(s),oM(s),tM(E,x.ownerDocument,s),Wb(E),Hb({gutter:s.gutter,offset:s.offset,overlap:s.overlap},E),iM(s),sM(s),zb];}let{placement:h,strategy:p,onComplete:m,onPositioned:f}=s,g,b,y=false,w,C,M=pu,S=aM(s.listeners);function L(){if(!s.listeners)return;let x=o(),E=i(),I=n();if(!E||!I)return;(Yb(x)!==Yb(w)||I!==C)&&(M(),w=x,C=I,M=Pb(E,I,k,S));}async function v(){L();let x=n();if(!x)return;x!==l&&(u(x),y=false);let E=i();if(!E)return;let I=await Vb(E,x,{placement:h,middleware:a,strategy:p});m?.(I);let N=Ie(x),V=$b(N,I.x),Z=$b(N,I.y);if(Ro(g,V)||(x.style.setProperty("--x",`${V}px`),g=V),Ro(b,Z)||(x.style.setProperty("--y",`${Z}px`),b=Z),s.hideWhenDetached&&(I.middlewareData.hide?.referenceHidden?(x.style.setProperty("visibility","hidden"),x.style.setProperty("pointer-events","none")):(x.style.removeProperty("visibility"),x.style.removeProperty("pointer-events"))),!y){let be=x.firstElementChild;be&&(x.style.setProperty("--z-index",wo(be).zIndex),y=true);}}async function k(){t.updatePosition?(await t.updatePosition({updatePosition:v,floatingElement:n()}),f?.({placed:true})):await v();}return k(),()=>{M(),d?.(),c?.(),f?.({placed:false});}}function ic(r,e,t={}){let{defer:n,...o}=t,i=n?Ve:a=>a(),s=[];return s.push(i(()=>{s.push(dM(r,e,o));})),()=>{s.forEach(a=>a?.());}}var uM={bottom:"rotate(45deg)",left:"rotate(135deg)",top:"rotate(225deg)",right:"rotate(315deg)"};function Gu(r={}){let{placement:e,sameWidth:t,fitViewport:n,strategy:o="absolute"}=r;return {arrow:{position:"absolute",width:ln.arrowSize.reference,height:ln.arrowSize.reference,[ln.arrowSizeHalf.variable]:`calc(${ln.arrowSize.reference} / 2)`,[ln.arrowOffset.variable]:`calc(${ln.arrowSizeHalf.reference} * -1)`},arrowTip:{transform:e?uM[e.split("-")[0]]:void 0,background:ln.arrowBg.reference,top:"0",left:"0",width:"100%",height:"100%",position:"absolute",zIndex:"inherit"},floating:{position:o,isolation:"isolate",minWidth:t?void 0:"max-content",width:t?"var(--reference-width)":void 0,maxWidth:n?"var(--available-width)":void 0,maxHeight:n?"var(--available-height)":void 0,pointerEvents:e?void 0:"none",top:"0px",left:"0px",transform:e?"translate3d(var(--x), var(--y), 0)":"translate3d(0, -100vh, 0)",zIndex:"var(--z-index)"}}}var cn=(r,e)=>{let t=r.ids?.trigger;return t!=null?pt(t)?t(e):t:e?`menu:${r.id}:trigger:${e}`:`menu:${r.id}:trigger`},sc=(r,e)=>{let t=r.ids?.contextTrigger;return t!=null?pt(t)?t(e):t:e?`menu:${r.id}:ctx-trigger:${e}`:`menu:${r.id}:ctx-trigger`},Xn=r=>r.ids?.content??`menu:${r.id}:content`,Kb=r=>r.ids?.arrow??`menu:${r.id}:arrow`,$u=r=>r.ids?.positioner??`menu:${r.id}:popper`,Xb=(r,e)=>r.ids?.group?.(e)??`menu:${r.id}:group:${e}`,Fr=(r,e)=>`${r.id}/${e}`,jn=r=>r?.dataset.value??null,Uu=(r,e)=>r.ids?.groupLabel?.(e)??`menu:${r.id}:group-label:${e}`,zt=r=>r.getById(Xn(r)),Yu=r=>r.getById($u(r)),Ku=r=>r.getById(cn(r)),jb=(r,e)=>e?r.getById(Fr(r,e)):null;var qb=r=>r.getById(sc(r)),Xu=r=>ko(r.getRootNode(),`[data-scope="menu"][data-part="trigger"][data-ownedby="${r.id}"]`),ju=r=>ko(r.getRootNode(),`[data-scope="menu"][data-part="context-trigger"][data-ownedby="${r.id}"]`),ss=(r,e)=>e==null?Ku(r)??Xu(r)[0]:r.getById(cn(r,e)),as=r=>{let t=`[role^="menuitem"][data-ownedby=${CSS.escape(Xn(r))}]:not([data-disabled])`;return ko(zt(r),t)},Zb=r=>Hf(as(r)),Qb=r=>zf(as(r)),qu=(r,e)=>e?r.id===e||r.dataset.value===e:false,Jb=(r,e)=>{let t=as(r),n=t.findIndex(o=>qu(o,e.value));return Gf(t,n,{loop:e.loop??e.loopFocus})},ev=(r,e)=>{let t=as(r),n=t.findIndex(o=>qu(o,e.value));return $f(t,n,{loop:e.loop??e.loopFocus})},tv=(r,e)=>{let t=as(r),n=t.find(o=>qu(o,e.value));return Hl(t,{state:e.typeaheadState,key:e.key,activeId:n?.id??null})},ls=r=>me(r)&&(r.dataset.disabled===""||r.hasAttribute("disabled")),Zu=r=>!!r?.getAttribute("role")?.startsWith("menuitem")&&!!r?.hasAttribute("data-controls");var ac="menu:select";function nv(r,e){if(!r)return;let t=Ie(r),n=new t.CustomEvent(ac,{detail:{value:e}});r.dispatchEvent(n);}function hM(r){let e=Xn(r);return zt(r)??r.getDoc().getElementById(e)}function Qu(r,e){if(!me(r))return false;for(let t in e){let n=e[t],o=hM(n.scope);if(o&&mt(o,r))return true;let i=n.refs.get("children");if(Object.keys(i).length>0&&Qu(r,i))return true}return false}var cs=(r,e)=>({x:r,y:e});function rv(r){let{x:e,y:t,width:n,height:o}=r,i=e+n/2,s=t+o/2;return {x:e,y:t,width:n,height:o,minX:e,minY:t,maxX:e+n,maxY:t+o,midX:i,midY:s,center:cs(i,s)}}function ov(r){let e=cs(r.minX,r.minY),t=cs(r.maxX,r.minY),n=cs(r.maxX,r.maxY),o=cs(r.minX,r.maxY);return {top:e,right:t,bottom:n,left:o}}function iv(r,e){let t=rv(r),{top:n,right:o,left:i,bottom:s}=ov(t),[a]=e.split("-");return {top:[i,n,o,s],right:[n,o,s,i],bottom:[n,i,s,o],left:[o,n,i,s]}[a]}function lc(r,e){let{x:t,y:n}=e,o=false;for(let i=0,s=r.length-1;in!=d>n&&t<(c-a)*(n-l)/(d-l)+a&&(o=!o);}return o}function eh(r){let e=r.parent;for(;e&&e.context.get("isSubmenu");)e=e.refs.get("parent");e?.send({type:"CLOSE"});}function sv(r,e){return r?lc(r,e):false}function av(r,e,t){let n=Object.keys(r).length>0;if(!e)return null;if(!n)return Fr(t,e);for(let o in r){let i=r[o],s=cn(i.scope);if(s===e)return s}return Fr(t,e)}function qn(r,e){r&&(r.refs.set("pointerRoutingLocked",e),r.context.set("pointerRoutingMode",e?"locked":"interactive"));}function lv(r){let e=r.context.get("highlightedValue");if(!e)return false;let t=r.refs.get("children");for(let n in t){let o=t[n];if(o.state.hasTag("open")&&cn(o.scope)===e)return true}return false}function cv(r,e){r&&(r.refs.get("pointerRoutingLocked")||e&&lv(r)||qn(r,false));}function dv(r){r&&(lv(r)||qn(r,false));}function th(r,e){let{context:t,send:n,state:o,computed:i,prop:s,scope:a}=r,l=o.hasTag("open"),c=t.get("isSubmenu"),d=i("isTypingAhead"),u=s("composite"),h=t.get("currentPlacement"),p=h?is(h):void 0,m=t.get("anchorPoint"),f=t.get("highlightedValue"),g=t.get("triggerValue"),b=Gu({...s("positioning"),placement:h});function y(S){return {id:Fr(a,S.value),disabled:!!S.disabled,highlighted:f===S.value}}function w(S){let L=S.valueText??S.value;return {...S,id:S.value,valueText:L}}function C(S){return {...y(w(S)),checked:!!S.checked}}function M(S){let{closeOnSelect:L,valueText:v,value:k}=S,x=y(S),E=Fr(a,k);return e.element({...Qe.item.attrs,id:E,role:"menuitem","aria-disabled":yu(x.disabled),"data-disabled":Ct(x.disabled),"data-ownedby":Xn(a),"data-highlighted":Ct(x.highlighted),"data-value":k,"data-valuetext":v,onDragStart(I){I.currentTarget.matches("a[href]")&&I.preventDefault();},onPointerMove(I){if(x.disabled||I.pointerType!=="mouse")return;let N=I.currentTarget;if(x.highlighted)return;let V=Co(I);n({type:"ITEM_POINTERMOVE",id:E,target:N,closeOnSelect:L,point:V});},onPointerLeave(I){if(x.disabled||I.pointerType!=="mouse"||!r.event.previous()?.type.includes("POINTER"))return;let V=I.currentTarget;n({type:"ITEM_POINTERLEAVE",id:E,target:V,closeOnSelect:L});},onPointerDown(I){if(x.disabled)return;let N=I.currentTarget;n({type:"ITEM_POINTERDOWN",target:N,id:E,closeOnSelect:L});},onClick(I){if(Eu(I)||Mu(I)||x.disabled)return;let N=I.currentTarget;n({type:"ITEM_CLICK",target:N,id:E,closeOnSelect:L});}})}return {highlightedValue:f,open:l,setOpen(S){o.hasTag("open")!==S&&n({type:S?"OPEN":"CLOSE"});},triggerValue:g,setTriggerValue(S){n({type:"TRIGGER_VALUE.SET",value:S});},setHighlightedValue(S){n({type:"HIGHLIGHTED.SET",value:S});},setParent(S){n({type:"PARENT.SET",value:S,id:S.prop("id")});},setChild(S){n({type:"CHILD.SET",value:S,id:S.prop("id")});},reposition(S={}){n({type:"POSITIONING.SET",options:S});},addItemListener(S){let L=a.getById(S.id);if(!L)return;let v=()=>S.onSelect?.();return L.addEventListener(ac,v),()=>L.removeEventListener(ac,v)},getContextTriggerProps(S={}){let{value:L}=S,v=L==null?false:g===L,k=sc(a,L);return e.element({...Qe.contextTrigger.attrs,dir:s("dir"),id:k,"data-ownedby":a.id,"data-value":L,"data-current":Ct(v),"data-state":l?"open":"closed",onPointerDown(x){if(x.pointerType==="mouse")return;let E=Co(x);n({type:"CONTEXT_MENU_START",point:E,value:L});},onPointerCancel(x){x.pointerType!=="mouse"&&n({type:"CONTEXT_MENU_CANCEL"});},onPointerMove(x){x.pointerType!=="mouse"&&n({type:"CONTEXT_MENU_CANCEL"});},onPointerUp(x){x.pointerType!=="mouse"&&n({type:"CONTEXT_MENU_CANCEL"});},onContextMenu(x){let E=Co(x),I=l&&L!=null&&!v;n({type:I?"TRIGGER_VALUE.SET":"CONTEXT_MENU",point:E,value:L}),x.preventDefault();},style:{WebkitTouchCallout:"none",WebkitUserSelect:"none",userSelect:"none"}})},getTriggerItemProps(S){let L=S.getTriggerProps();return qf(M({value:L.id}),L)},getTriggerProps(S={}){let{value:L}=S,v=L==null?false:g===L,k=cn(a,L);return e.button({...c?Qe.triggerItem.attrs:Qe.trigger.attrs,"data-placement":h,"data-side":p,type:"button",dir:s("dir"),id:k,...L!=null&&{"data-ownedby":a.id,"data-value":L,"data-current":Ct(v)},"data-uid":s("id"),"aria-haspopup":u?"menu":"dialog","aria-controls":Xn(a),"data-controls":Xn(a),"aria-expanded":L==null?l:l&&v,"data-state":l?"open":"closed",onPointerMove(x){if(x.pointerType!=="mouse"||ls(x.currentTarget)||!c)return;let I=Co(x);n({type:"TRIGGER_POINTERMOVE",target:x.currentTarget,point:I});},onPointerLeave(x){if(ls(x.currentTarget)||x.pointerType!=="mouse"||!c)return;qn(r.refs.get("parent"),true);let E=Co(x);n({type:"TRIGGER_POINTERLEAVE",target:x.currentTarget,point:E});},onPointerDown(x){ls(x.currentTarget)||Nl(x)||x.preventDefault();},onClick(x){if(x.defaultPrevented||ls(x.currentTarget))return;let E=l&&L!=null&&!v;n({type:E?"TRIGGER_VALUE.SET":"TRIGGER_CLICK",target:x.currentTarget,value:L});},onBlur(){n({type:"TRIGGER_BLUR"});},onFocus(){n({type:"TRIGGER_FOCUS"});},onKeyDown(x){if(x.defaultPrevented)return;let E={ArrowDown(){n({type:"ARROW_DOWN",value:L});},ArrowUp(){n({type:"ARROW_UP",value:L});},Enter(){n({type:"ARROW_DOWN",src:"enter",value:L});},Space(){n({type:"ARROW_DOWN",src:"space",value:L});}},I=Pu(x,{orientation:"vertical",dir:s("dir")}),N=E[I];N&&(x.preventDefault(),N(x));}})},getIndicatorProps(){return e.element({...Qe.indicator.attrs,dir:s("dir"),"data-state":l?"open":"closed"})},getPositionerProps(){return e.element({...Qe.positioner.attrs,dir:s("dir"),id:$u(a),style:b.floating})},getArrowProps(){return e.element({id:Kb(a),...Qe.arrow.attrs,dir:s("dir"),style:b.arrow})},getArrowTipProps(){return e.element({...Qe.arrowTip.attrs,dir:s("dir"),style:b.arrowTip})},getContentProps(){return e.element({...Qe.content.attrs,id:Xn(a),"aria-label":s("aria-label"),hidden:!l,"data-state":l?"open":"closed",role:u?"menu":"dialog",tabIndex:0,dir:s("dir"),"aria-activedescendant":i("highlightedId")||void 0,"aria-labelledby":m?sc(a,g??void 0):cn(a,g??void 0),"data-placement":h,"data-side":p,onPointerEnter(S){S.pointerType==="mouse"&&n({type:"MENU_POINTERENTER"});},onKeyDown(S){if(S.defaultPrevented||!mt(S.currentTarget,_e(S)))return;let L=_e(S);if(!(L?.closest("[role=menu]")===S.currentTarget||L===S.currentTarget))return;if(S.key==="Tab"&&!Ig(S)){S.preventDefault();return}let k={ArrowDown(){n({type:"ARROW_DOWN"});},ArrowUp(){n({type:"ARROW_UP"});},ArrowLeft(){n({type:"ARROW_LEFT"});},ArrowRight(){n({type:"ARROW_RIGHT"});},Enter(){n({type:"ENTER"});},Space(I){d?n({type:"TYPEAHEAD",key:I.key}):k.Enter?.(I);},Home(){n({type:"HOME"});},End(){n({type:"END"});}},x=Pu(S,{dir:s("dir")}),E=k[x];if(E){E(S),S.stopPropagation(),S.preventDefault();return}s("typeahead")&&Sg(S)&&(kg(S)||yo(L)||(n({type:"TYPEAHEAD",key:S.key}),S.preventDefault()));}})},getSeparatorProps(){return e.element({...Qe.separator.attrs,role:"separator",dir:s("dir"),"aria-orientation":"horizontal"})},getItemState:y,getItemProps:M,getOptionItemState:C,getOptionItemProps(S){let{type:L,disabled:v,closeOnSelect:k}=S,x=w(S),E=C(S);return {...M(x),...e.element({"data-type":L,...Qe.item.attrs,dir:s("dir"),"data-value":x.value,role:`menuitem${L}`,"aria-checked":!!E.checked,"data-state":E.checked?"checked":"unchecked",onClick(I){if(v||Eu(I)||Mu(I))return;let N=I.currentTarget;n({type:"ITEM_CLICK",target:N,option:x,closeOnSelect:k});}})}},getItemIndicatorProps(S){let L=C(hu(S)),v=L.checked?"checked":"unchecked";return e.element({...Qe.itemIndicator.attrs,dir:s("dir"),"data-disabled":Ct(L.disabled),"data-highlighted":Ct(L.highlighted),"data-state":Hi(S,"checked")?v:void 0,hidden:Hi(S,"checked")?!L.checked:void 0})},getItemTextProps(S){let L=C(hu(S)),v=L.checked?"checked":"unchecked";return e.element({...Qe.itemText.attrs,dir:s("dir"),"data-disabled":Ct(L.disabled),"data-highlighted":Ct(L.highlighted),"data-state":Hi(S,"checked")?v:void 0})},getItemGroupLabelProps(S){return e.element({...Qe.itemGroupLabel.attrs,id:Uu(a,S.htmlFor),dir:s("dir")})},getItemGroupProps(S){return e.element({id:Xb(a,S.id),...Qe.itemGroup.attrs,dir:s("dir"),"aria-labelledby":Uu(a,S.id),role:"group"})}}}function uv(r){let e={each(t){for(let n=0;n{try{i.document.addEventListener(t,n,o);}catch{}}),()=>{try{e.removeEventListener(t,n,o);}catch{}}},removeEventListener(t,n,o){e.each(i=>{try{i.document.removeEventListener(t,n,o);}catch{}});}};return e}function hv(r){let e=r.frameElement!=null?r.parent:null;return {addEventListener:(t,n,o)=>{try{e?.addEventListener(t,n,o);}catch{}return ()=>{try{e?.removeEventListener(t,n,o);}catch{}}},removeEventListener:(t,n,o)=>{try{e?.removeEventListener(t,n,o);}catch{}}}}var pv="pointerdown.outside",mv="focus.outside";function pM(r){for(let e of r)if(me(e)&&St(e))return true;return false}var bv=r=>"clientY"in r;function mM(r,e){if(!bv(e)||!r)return false;let t=r.getBoundingClientRect();return t.width===0||t.height===0?false:t.top<=e.clientY&&e.clientY<=t.top+t.height&&t.left<=e.clientX&&e.clientX<=t.left+t.width}function fM(r,e){return r.y<=e.y&&e.y<=r.y+r.height&&r.x<=e.x&&e.x<=r.x+r.width}function fv(r,e){if(!e||!bv(r))return false;let t=e.scrollHeight>e.clientHeight,n=t&&r.clientX>e.offsetLeft+e.clientWidth,o=e.scrollWidth>e.clientWidth,i=o&&r.clientY>e.offsetTop+e.clientHeight,s={x:e.offsetLeft,y:e.offsetTop,width:e.clientWidth+(t?16:0),height:e.clientHeight+(o?16:0)},a={x:r.clientX,y:r.clientY};return fM(s,a)?n||i:false}function gM(r,e){let{exclude:t,onFocusOutside:n,onPointerDownOutside:o,onInteractOutside:i,defer:s,followControlledElements:a=true}=e;if(!r)return;let l=Oe(r),c=Ie(r),d=uv(c),u=hv(c);function h(C,M){if(!me(M)||!M.isConnected||mt(r,M)||mM(r,C)||a&&Ol(r,M))return false;let S=l.querySelector(`[aria-controls="${r.id}"]`);if(S){let v=Bl(S);if(fv(C,v))return false}let L=Bl(r);return fv(C,L)?false:!t?.(M)}let p=new Set,m=Er(r?.getRootNode()),f=false;function g(C){f=true;let M=()=>{f=false;};l.addEventListener("pointerup",M,{once:true}),c.addEventListener("pointerup",M,{once:true});function S(L){let v=s&&!Lu()?Ve:E=>E(),k=L??C,x=k?.composedPath?.()??[k?.target];v(()=>{let E=m?x[0]:_e(C);if(!(!r||!h(C,E))){if(o||i){let I=Gn(o,i);r.addEventListener(pv,I,{once:true});}gv(r,pv,{bubbles:false,cancelable:true,detail:{originalEvent:k,contextmenu:Nl(k),focusable:pM(x),target:E}});}});}C.pointerType==="touch"?(p.forEach(L=>L()),p.add(ot(l,"click",S,{once:true})),p.add(u.addEventListener("click",S,{once:true})),p.add(d.addEventListener("click",S,{once:true}))):S();}let b=new Set,y=setTimeout(()=>{b.add(ot(l,"pointerdown",g,true)),b.add(u.addEventListener("pointerdown",g,true)),b.add(d.addEventListener("pointerdown",g,true));},0);function w(C){if(f)return;(s?Ve:S=>S())(()=>{let S=C?.composedPath?.()??[C?.target],L=m?S[0]:_e(C);if(!(!r||!h(C,L))){if(n||i){let v=Gn(n,i);r.addEventListener(mv,v,{once:true});}gv(r,mv,{bubbles:false,cancelable:true,detail:{originalEvent:C,contextmenu:false,focusable:St(L),target:L}});}});}return Lu()||(b.add(ot(l,"focusin",w,true)),b.add(u.addEventListener("focusin",w,true)),b.add(d.addEventListener("focusin",w,true))),()=>{clearTimeout(y),p.forEach(C=>C()),b.forEach(C=>C());}}function vv(r,e){let{defer:t}=e,n=t?Ve:i=>i(),o=[];return o.push(n(()=>{let i=typeof r=="function"?r():r;o.push(gM(i,e));})),()=>{o.forEach(i=>i?.());}}function gv(r,e,t){let n=r.ownerDocument.defaultView||window,o=new n.CustomEvent(e,t);return r.dispatchEvent(o)}function yv(r,e){let t=n=>{n.key==="Escape"&&(n.isComposing||e?.(n));};return ot(Oe(r),"keydown",t,{capture:true})}var wv="layer:request-dismiss",Je={layers:[],branches:[],recentlyRemoved:new Set,count(){return this.layers.length},pointerBlockingLayers(){return this.layers.filter(r=>r.pointerBlocking)},topMostPointerBlockingLayer(){return [...this.pointerBlockingLayers()].slice(-1)[0]},hasPointerBlockingLayer(){return this.pointerBlockingLayers().length>0},isBelowPointerBlockingLayer(r){let e=this.indexOf(r),t=this.topMostPointerBlockingLayer()?this.indexOf(this.topMostPointerBlockingLayer()?.node):-1;return ee.type===r)},getNestedLayersByType(r,e){let t=this.indexOf(r);return t===-1?[]:this.layers.slice(t+1).filter(n=>n.type===e)},getParentLayerOfType(r,e){let t=this.indexOf(r);if(!(t<=0))return this.layers.slice(0,t).reverse().find(n=>n.type===e)},countNestedLayersOfType(r,e){return this.getNestedLayersByType(r,e).length},isInNestedLayer(r,e){return !!(this.getNestedLayers(r).some(n=>mt(n.node,e))||this.recentlyRemoved.size>0)},isInBranch(r){return Array.from(this.branches).some(e=>mt(e,r))},add(r){let e=this.indexOf(r.node);e!==-1&&this.layers.splice(e,1),this.layers.push(r),this.syncLayers();},addBranch(r){this.branches.push(r);},remove(r){let e=this.indexOf(r);if(e<0)return;this.layers[e].styleTargets?.forEach(n=>{let o=n();o&&bM(o);}),this.recentlyRemoved.add(r),Rg(()=>this.recentlyRemoved.delete(r)),eJe.dismiss(o.node,r)),this.layers.splice(e,1),this.syncLayers();},removeBranch(r){let e=this.branches.indexOf(r);e>=0&&this.branches.splice(e,1);},syncLayers(){this.layers.forEach((r,e)=>{xv(r,e,r.node),r.styleTargets?.forEach(t=>{let n=t();if(!n||n===r.node)return;xv(r,e,n);let{zIndex:o}=wo(r.node);n.style.setProperty("--z-index",o);});});},indexOf(r){return this.layers.findIndex(e=>e.node===r)},dismiss(r,e){let t=this.indexOf(r);if(t===-1)return;let n=this.layers[t];yM(r,wv,o=>{n.requestDismiss?.(o),o.defaultPrevented||n?.dismiss();}),vM(r,wv,{originalLayer:r,targetLayer:e,originalIndex:t,targetIndex:e?this.indexOf(e):-1}),this.syncLayers();},clear(){this.remove(this.layers[0].node);}};function xv(r,e,t){t.style.setProperty("--layer-index",`${e}`),t.removeAttribute("data-nested"),t.removeAttribute("data-has-nested"),Je.getParentLayerOfType(r.node,r.type)&&t.setAttribute("data-nested",r.type);let o=Je.countNestedLayersOfType(r.node,r.type);o>0&&t.setAttribute("data-has-nested",r.type),t.style.setProperty("--nested-layer-count",`${o}`);}function bM(r){r.style.removeProperty("--layer-index"),r.style.removeProperty("--nested-layer-count"),r.style.removeProperty("--z-index"),r.removeAttribute("data-nested"),r.removeAttribute("data-has-nested");}function vM(r,e,t){let n=r.ownerDocument.defaultView||window,o=new n.CustomEvent(e,{cancelable:true,bubbles:true,detail:t});return r.dispatchEvent(o)}function yM(r,e,t){r.addEventListener(e,t,{once:true});}var nh=new WeakMap,ds=new WeakMap;function wM(r){return Je.isBelowPointerBlockingLayer(r)?"none":"auto"}function Cv(r){let e=wM(r);r.style.pointerEvents!==e&&(r.style.pointerEvents=e);}function xM(r){if(ds.has(r))return;let e=Ie(r);if(typeof e.MutationObserver>"u")return;let t=new e.MutationObserver(()=>{ds.has(r)&&Cv(r);});t.observe(r,{attributes:true,attributeFilter:["style"]}),ds.set(r,t);}function rh(){Je.layers.forEach(({node:r})=>{Cv(r),xM(r);});}function Sv(r){let e=ds.get(r);e&&(e.disconnect(),ds.delete(r)),r.style.pointerEvents="";}function Tv(r,e){let t=Oe(r),n=[];return Je.hasPointerBlockingLayer()&&!t.body.hasAttribute("data-inert")&&(nh.set(t.body,t.body.style.pointerEvents),queueMicrotask(()=>{let o=t.body;o&&(o.style.pointerEvents="none",o.setAttribute("data-inert",""));})),e?.forEach(o=>{let[i,s]=Hg(()=>{let a=o();return me(a)?a:null},{timeout:1e3});i.then(a=>n.push(ji(a,{pointerEvents:"auto"}))),n.push(s);}),()=>{Je.hasPointerBlockingLayer()||(queueMicrotask(()=>{let o=t.body;if(!o)return;let i=nh.get(o);i!==void 0&&(o.style.pointerEvents=i,nh.delete(o)),o.removeAttribute("data-inert"),o.style.length===0&&o.removeAttribute("style");}),n.forEach(o=>o()));}}function CM(r,e){let{warnOnMissingNode:t=true}=e;if(t&&!r){go("[@zag-js/dismissable] node is `null` or `undefined`");return}if(!r)return;let{onDismiss:n,onRequestDismiss:o,pointerBlocking:i,exclude:s,debug:a,type:l="dialog",layerStyleTargets:c}=e,d={dismiss:n,node:r,type:l,pointerBlocking:i,requestDismiss:o,styleTargets:c};Je.add(d),rh();function u(g){let b=_e(g.detail.originalEvent);Je.isBelowPointerBlockingLayer(r)||Je.isInBranch(b)||(e.onPointerDownOutside?.(g),e.onInteractOutside?.(g),!g.defaultPrevented&&(a&&console.log("onPointerDownOutside:",g.detail.originalEvent),n?.()));}function h(g){let b=_e(g.detail.originalEvent);Je.isInBranch(b)||(e.onFocusOutside?.(g),e.onInteractOutside?.(g),!g.defaultPrevented&&(a&&console.log("onFocusOutside:",g.detail.originalEvent),n?.()));}function p(g){Je.isTopMost(r)&&(e.onEscapeKeyDown?.(g),!g.defaultPrevented&&n&&(g.preventDefault(),n()));}function m(g){if(!r)return false;let b=typeof s=="function"?s():s,y=Array.isArray(b)?b:[b],w=e.persistentElements?.map(C=>C()).filter(me);return w&&y.push(...w),y.some(C=>mt(C,g))||Je.isInNestedLayer(r,g)}let f=[i?Tv(r,e.persistentElements):void 0,yv(r,p),vv(r,{exclude:m,onFocusOutside:h,onPointerDownOutside:u,defer:e.defer})];return ()=>{Je.remove(r),rh(),Sv(r),f.forEach(g=>g?.());}}function cc(r,e){let{defer:t}=e,n=t?Ve:i=>i(),o=[];return o.push(n(()=>{let i=pt(r)?r():r;o.push(CM(i,e));})),()=>{o.forEach(i=>i?.());}}function SM(r){return !(r.metaKey||!xo()&&r.altKey||r.ctrlKey||r.key==="Control"||r.key==="Shift"||r.key==="Meta")}var TM=new Set(["checkbox","radio","range","color","file","image","button","submit","reset"]);function kM(r,e,t){let n=t?_e(t):null,o=Oe(n),i=Ie(n),s=nn(o);return r=r||s instanceof i.HTMLInputElement&&!TM.has(s?.type)||s instanceof i.HTMLTextAreaElement||s instanceof i.HTMLElement&&s.isContentEditable,!(r&&e==="keyboard"&&t instanceof i.KeyboardEvent&&!Reflect.has(LM,t.key))}var kn=null,oh=new Set,dc=new Map,Vr=false,ih=false,Lv=false,LM={Tab:true,Escape:true};function hc(r,e){for(let t of oh)t(r,e);}function uc(r){Vr=true,SM(r)&&(kn="keyboard",hc("keyboard",r));}function Tt(r){kn="pointer",(r.type==="mousedown"||r.type==="pointerdown")&&(Vr=true,hc("pointer",r));}function Mv(r){Tg(r)&&(Vr=true,kn="virtual");}function Ev(r){let e=_e(r);e===Ie(e)||e===Oe(e)||Lv||!r.isTrusted||(!Vr&&!ih&&(kn="virtual",hc("virtual",r)),Vr=false,ih=false);}function Pv(){(Vr=false,ih=true);}function MM(r){if(typeof window>"u"||dc.get(Ie(r)))return;let e=Ie(r),t=Oe(r),n=e.HTMLElement.prototype.focus;function o(){Vr=true,n.apply(this,arguments);}try{Object.defineProperty(e.HTMLElement.prototype,"focus",{configurable:!0,value:o});}catch{}t.addEventListener("keydown",uc,true),t.addEventListener("keyup",uc,true),t.addEventListener("click",Mv,true),e.addEventListener("focus",Ev,true),e.addEventListener("blur",Pv,false),typeof e.PointerEvent<"u"?(t.addEventListener("pointerdown",Tt,true),t.addEventListener("pointermove",Tt,true),t.addEventListener("pointerup",Tt,true)):(t.addEventListener("mousedown",Tt,true),t.addEventListener("mousemove",Tt,true),t.addEventListener("mouseup",Tt,true)),e.addEventListener("beforeunload",()=>{EM(r);},{once:true}),dc.set(e,{focus:n});}var EM=(r,e)=>{let t=Ie(r),n=Oe(r);let o=dc.get(t);if(o){try{Object.defineProperty(t.HTMLElement.prototype,"focus",{configurable:!0,value:o.focus});}catch{}n.removeEventListener("keydown",uc,true),n.removeEventListener("keyup",uc,true),n.removeEventListener("click",Mv,true),t.removeEventListener("focus",Ev,true),t.removeEventListener("blur",Pv,false),typeof t.PointerEvent<"u"?(n.removeEventListener("pointerdown",Tt,true),n.removeEventListener("pointermove",Tt,true),n.removeEventListener("pointerup",Tt,true)):(n.removeEventListener("mousedown",Tt,true),n.removeEventListener("mousemove",Tt,true),n.removeEventListener("mouseup",Tt,true)),dc.delete(t);}};function Iv(){return kn}function Av(r){kn=r,hc(r,null);}function kv(){return kn==="keyboard"||kn==="virtual"}function Rv(r={}){let{isTextInput:e,autoFocus:t,onChange:n,root:o}=r;MM(o),n?.({isFocusVisible:t||kv(),modality:kn});let i=(s,a)=>{kM(!!e,s,a)&&n?.({isFocusVisible:kv(),modality:s});};return oh.add(i),()=>{oh.delete(i);}}var{not:kt,and:Do,or:PM}=sg(),sh=Al({props({props:r}){return {closeOnSelect:true,typeahead:true,composite:true,loopFocus:false,navigate(e){Ng(e.node);},...r,positioning:{placement:"bottom-start",gutter:8,...r.positioning}}},initialState({prop:r}){return r("open")||r("defaultOpen")?"open":"idle"},context({bindable:r,prop:e,scope:t}){return {highlightedValue:r(()=>({defaultValue:e("defaultHighlightedValue")||null,value:e("highlightedValue"),onChange(n){e("onHighlightChange")?.({highlightedValue:n});}})),lastHighlightedValue:r(()=>({defaultValue:null})),currentPlacement:r(()=>({defaultValue:void 0})),intentPolygon:r(()=>({defaultValue:null})),anchorPoint:r(()=>({defaultValue:null,hash(n){return `x: ${n?.x}, y: ${n?.y}`}})),isSubmenu:r(()=>({defaultValue:false})),triggerValue:r(()=>({defaultValue:e("defaultTriggerValue")??null,value:e("triggerValue"),onChange(n){let o=e("onTriggerValueChange");if(!o)return;let i=ss(t,n);o({value:n,triggerElement:i});}})),pointerRoutingMode:r(()=>({defaultValue:"interactive"}))}},refs(){return {parent:null,children:{},pointerRoutingLocked:false,typeaheadState:{...Hl.defaultOptions},positioningOverride:{}}},computed:{isRtl:({prop:r})=>r("dir")==="rtl",isTypingAhead:({refs:r})=>r.get("typeaheadState").keysSoFar!=="",highlightedId:({context:r,scope:e,refs:t})=>av(t.get("children"),r.get("highlightedValue"),e)},watch({track:r,action:e,context:t,prop:n}){r([()=>t.get("isSubmenu")],()=>{e(["setSubmenuPlacement"]);}),r([()=>t.hash("anchorPoint")],()=>{t.get("anchorPoint")&&e(["reposition"]);}),r([()=>n("open")],()=>{e(["toggleVisibility"]);});},on:{"TRIGGER_VALUE.SET":{actions:["setTriggerValue","setAnchorPoint","reposition","focusMenu"]},"PARENT.SET":{actions:["setParentMenu"]},"CHILD.SET":{actions:["setChildMenu"]},OPEN:[{guard:"isOpenControlled",actions:["setTriggerValue","invokeOnOpen"]},{target:"open",actions:["setTriggerValue","invokeOnOpen"]}],OPEN_AUTOFOCUS:[{guard:"isOpenControlled",actions:["setTriggerValue","invokeOnOpen"]},{target:"open",actions:["setTriggerValue","highlightFirstItem","invokeOnOpen"]}],CLOSE:[{guard:"isOpenControlled",actions:["invokeOnClose","releaseParentRoutingLock"]},{target:"closed",actions:["invokeOnClose","releaseParentRoutingLock","focusTrigger"]}],"HIGHLIGHTED.RESTORE":{actions:["restoreHighlightedItem"]},"HIGHLIGHTED.SET":{actions:["setHighlightedItem"]},"HIGHLIGHTED.SUGGEST":{actions:["suggestHighlightedItem"]}},states:{idle:{tags:["closed"],on:{"CONTROLLED.OPEN":{target:"open"},"CONTROLLED.CLOSE":{target:"closed"},CONTEXT_MENU_START:{target:"opening:contextmenu",actions:["setAnchorPoint","setTriggerValue"]},CONTEXT_MENU:[{guard:"isOpenControlled",actions:["setAnchorPoint","setTriggerValue","invokeOnOpen"]},{target:"open",actions:["setAnchorPoint","setTriggerValue","invokeOnOpen"]}],TRIGGER_CLICK:[{guard:"isOpenControlled",actions:["invokeOnOpen","setTriggerValue"]},{target:"open",actions:["invokeOnOpen","setTriggerValue"]}],TRIGGER_FOCUS:{guard:kt("isSubmenu"),target:"closed"},TRIGGER_POINTERMOVE:{guard:"isSubmenu",target:"opening"}}},"opening:contextmenu":{tags:["closed"],effects:["waitForLongPress"],on:{"CONTROLLED.OPEN":{target:"open",actions:["reposition"]},"CONTROLLED.CLOSE":{target:"closed",actions:["focusTrigger"]},CONTEXT_MENU_CANCEL:[{guard:"isOpenControlled",actions:["invokeOnClose","releaseParentRoutingLock"]},{target:"closed",actions:["invokeOnClose","releaseParentRoutingLock","focusTrigger"]}],"LONG_PRESS.OPEN":[{guard:"isOpenControlled",actions:["setTriggerValue","invokeOnOpen"]},{target:"open",actions:["setTriggerValue","invokeOnOpen","reposition"]}]}},opening:{tags:["closed"],effects:["waitForOpenDelay"],on:{"CONTROLLED.OPEN":{target:"open"},"CONTROLLED.CLOSE":{target:"closed",actions:["focusTrigger"]},BLUR:[{guard:"isOpenControlled",actions:["invokeOnClose","releaseParentRoutingLock"]},{target:"closed",actions:["invokeOnClose","releaseParentRoutingLock","focusTrigger"]}],TRIGGER_POINTERLEAVE:[{guard:"isOpenControlled",actions:["invokeOnClose","releaseParentRoutingLock"]},{target:"closed",actions:["invokeOnClose","releaseParentRoutingLock","focusTrigger"]}],"DELAY.OPEN":[{guard:"isOpenControlled",actions:["invokeOnOpen"]},{target:"open",actions:["invokeOnOpen"]}]}},closing:{tags:["open"],effects:["trackPointerMove","trackInteractOutside","waitForCloseDelay"],on:{"CONTROLLED.OPEN":{target:"open"},"CONTROLLED.CLOSE":{target:"closed",actions:["focusParentMenu","restoreParentHighlightedItem"]},MENU_POINTERENTER:{target:"open",actions:["clearIntentPolygon"]},POINTER_MOVED_AWAY_FROM_SUBMENU:[{guard:"isOpenControlled",actions:["invokeOnClose","releaseParentRoutingLock"]},{target:"closed",actions:["focusParentMenu","restoreParentHighlightedItem"]}],"DELAY.CLOSE":[{guard:"isOpenControlled",actions:["invokeOnClose","releaseParentRoutingLock"]},{target:"closed",actions:["focusParentMenu","restoreParentHighlightedItem","invokeOnClose","releaseParentRoutingLock"]}]}},closed:{tags:["closed"],entry:["clearHighlightedItem","unlockParentOnClose","clearAnchorPoint"],on:{"CONTROLLED.OPEN":[{guard:PM("isOpenAutoFocusEvent","isArrowDownEvent"),target:"open",actions:["highlightFirstItem"]},{guard:"isArrowUpEvent",target:"open",actions:["highlightLastItem"]},{target:"open"}],CONTEXT_MENU_START:{target:"opening:contextmenu",actions:["setAnchorPoint","setTriggerValue"]},CONTEXT_MENU:[{guard:"isOpenControlled",actions:["setAnchorPoint","setTriggerValue","invokeOnOpen"]},{target:"open",actions:["setAnchorPoint","setTriggerValue","invokeOnOpen"]}],TRIGGER_CLICK:[{guard:"isOpenControlled",actions:["invokeOnOpen","setTriggerValue"]},{target:"open",actions:["invokeOnOpen","setTriggerValue"]}],TRIGGER_POINTERMOVE:{guard:"isTriggerItem",target:"opening"},TRIGGER_BLUR:{target:"idle"},ARROW_DOWN:[{guard:"isOpenControlled",actions:["setTriggerValue","invokeOnOpen"]},{target:"open",actions:["setTriggerValue","highlightFirstItem","invokeOnOpen"]}],ARROW_UP:[{guard:"isOpenControlled",actions:["setTriggerValue","invokeOnOpen"]},{target:"open",actions:["setTriggerValue","highlightLastItem","invokeOnOpen"]}]}},open:{tags:["open"],effects:["trackInteractOutside","trackFocusVisible","trackPositioning","scrollToHighlightedItem"],entry:["focusMenu","unlockParentOnOpen"],on:{"CONTROLLED.CLOSE":[{target:"closed",guard:"isArrowLeftEvent",actions:["focusParentMenu"]},{target:"closed",actions:["focusTrigger"]}],TRIGGER_CLICK:[{guard:Do(kt("isTriggerItem"),"isOpenControlled"),actions:["invokeOnClose","releaseParentRoutingLock"]},{guard:kt("isTriggerItem"),target:"closed",actions:["invokeOnClose","releaseParentRoutingLock","focusTrigger"]}],CONTEXT_MENU:{actions:["setAnchorPoint","setTriggerValue","focusMenu"]},ARROW_UP:{actions:["highlightPrevItem","focusMenu"]},ARROW_DOWN:{actions:["highlightNextItem","focusMenu"]},ARROW_LEFT:[{guard:Do("isSubmenu","isOpenControlled"),actions:["invokeOnClose","releaseParentRoutingLock"]},{guard:"isSubmenu",target:"closed",actions:["focusParentMenu","invokeOnClose","releaseParentRoutingLock"]}],HOME:{actions:["highlightFirstItem","focusMenu"]},END:{actions:["highlightLastItem","focusMenu"]},ARROW_RIGHT:{guard:"isTriggerItemHighlighted",actions:["openSubmenu"]},ENTER:[{guard:"isTriggerItemHighlighted",actions:["openSubmenu"]},{actions:["clickHighlightedItem"]}],ITEM_POINTERMOVE:[{guard:kt("isPointerRoutingLocked"),actions:["setHighlightedItem","focusMenu","closeSiblingMenus"]},{actions:["setLastHighlightedItem","closeSiblingMenus"]}],ITEM_POINTERLEAVE:{guard:Do(kt("isPointerRoutingLocked"),kt("isTriggerItem")),actions:["clearHighlightedItem"]},ITEM_CLICK:[{guard:Do(kt("isTriggerItemHighlighted"),kt("isHighlightedItemEditable"),"closeOnSelect","isOpenControlled"),actions:["invokeOnSelect","setOptionState","closeRootMenu","invokeOnClose","releaseParentRoutingLock"]},{guard:Do(kt("isTriggerItemHighlighted"),kt("isHighlightedItemEditable"),"closeOnSelect"),target:"closed",actions:["invokeOnSelect","setOptionState","closeRootMenu","invokeOnClose","releaseParentRoutingLock","focusTrigger"]},{guard:Do(kt("isTriggerItemHighlighted"),kt("isHighlightedItemEditable")),actions:["invokeOnSelect","setOptionState"]},{actions:["setHighlightedItem"]}],TRIGGER_POINTERMOVE:{guard:"isTriggerItem",actions:["setIntentPolygon"]},TRIGGER_POINTERLEAVE:{target:"closing",actions:["setIntentPolygon"]},ITEM_POINTERDOWN:{actions:["setHighlightedItem"]},TYPEAHEAD:{actions:["highlightMatchedItem"]},FOCUS_MENU:{actions:["focusMenu"]},"POSITIONING.SET":{actions:["reposition"]}}}},implementations:{guards:{closeOnSelect:({prop:r,event:e})=>!!(e?.closeOnSelect??r("closeOnSelect")),isTriggerItem:({event:r})=>Zu(r.target),isTriggerItemHighlighted:({event:r,scope:e,computed:t})=>!!(r.target??e.getById(t("highlightedId")))?.hasAttribute("data-controls"),isSubmenu:({context:r})=>r.get("isSubmenu"),isPointerRoutingLocked:({refs:r})=>r.get("pointerRoutingLocked"),isHighlightedItemEditable:({scope:r,computed:e})=>yo(r.getById(e("highlightedId"))),isOpenControlled:({prop:r})=>r("open")!==void 0,isArrowLeftEvent:({event:r})=>r.previousEvent?.type==="ARROW_LEFT",isArrowUpEvent:({event:r})=>r.previousEvent?.type==="ARROW_UP",isArrowDownEvent:({event:r})=>r.previousEvent?.type==="ARROW_DOWN",isOpenAutoFocusEvent:({event:r})=>r.previousEvent?.type==="OPEN_AUTOFOCUS"},effects:{waitForOpenDelay({send:r}){let e=setTimeout(()=>{r({type:"DELAY.OPEN"});},200);return ()=>clearTimeout(e)},waitForCloseDelay({send:r}){let e=setTimeout(()=>{r({type:"DELAY.CLOSE"});},100);return ()=>clearTimeout(e)},waitForLongPress({send:r}){let e=setTimeout(()=>{r({type:"LONG_PRESS.OPEN"});},700);return ()=>clearTimeout(e)},trackFocusVisible({scope:r}){return Rv({root:r.getRootNode?.()})},trackPositioning({context:r,prop:e,scope:t,refs:n}){if(qb(t)||ju(t).length>0)return;let i={...e("positioning"),...n.get("positioningOverride")};return r.set("currentPlacement",i.placement),ic(()=>ss(t,r.get("triggerValue")),()=>Yu(t),{...i,defer:true,onComplete(l){r.set("currentPlacement",l.placement);}})},trackInteractOutside({refs:r,scope:e,prop:t,context:n,send:o}){let i=()=>zt(e),s=true,a=l=>ju(e).some(c=>mt(c,l));return cc(i,{type:"menu",defer:true,exclude:[Ku(e),...Xu(e)].filter(Boolean),onInteractOutside:t("onInteractOutside"),onRequestDismiss:t("onRequestDismiss"),onFocusOutside(l){t("onFocusOutside")?.(l);let c=_e(l.detail.originalEvent);if(a(c)){l.preventDefault();return}if(Qu(c,r.get("children"))){l.preventDefault();return}},onEscapeKeyDown(l){t("onEscapeKeyDown")?.(l),n.get("isSubmenu")&&l.preventDefault(),eh({parent:r.get("parent")});},onPointerDownOutside(l){t("onPointerDownOutside")?.(l);let c=_e(l.detail.originalEvent);if(a(c)&&l.detail.contextmenu){l.preventDefault();return}s=!l.detail.focusable;},onDismiss(){o({type:"CLOSE",src:"interact-outside",restoreFocus:s});}})},trackPointerMove({context:r,scope:e,send:t,refs:n}){let o=n.get("parent");if(!o)return;qn(o,true);let i=e.getDoc();return ot(i,"pointermove",s=>{sv(r.get("intentPolygon"),{x:s.clientX,y:s.clientY})||(t({type:"POINTER_MOVED_AWAY_FROM_SUBMENU"}),qn(o,false));})},scrollToHighlightedItem({scope:r,computed:e}){let t=()=>{if(Iv()==="pointer")return;let i=r.getById(e("highlightedId")),s=zt(r);Vg(i,{rootEl:s,block:"nearest"});};return Ve(()=>{Av("virtual"),t();}),Og(()=>zt(r),{attributes:["aria-activedescendant"],callback:t})}},actions:{setAnchorPoint({context:r,event:e}){r.set("anchorPoint",t=>mo(t,e.point)?t:e.point);},setSubmenuPlacement({context:r,computed:e,refs:t}){if(!r.get("isSubmenu"))return;let n=e("isRtl")?"left-start":"right-start";t.set("positioningOverride",{placement:n,gutter:0});},reposition({context:r,scope:e,prop:t,event:n,refs:o}){let i=()=>Yu(e),s=n.point??r.get("anchorPoint"),a=s?()=>({width:0,height:0,...s}):void 0,l={...t("positioning"),...o.get("positioningOverride")},c=n.value??r.get("triggerValue");ic(()=>ss(e,c),i,{...l,defer:true,getAnchorRect:a,...n.options??{},listeners:false,onComplete(u){r.set("currentPlacement",u.placement);}});},setOptionState({event:r}){if(!r.option)return;let{checked:e,onCheckedChange:t,type:n}=r.option;n==="radio"?t?.(true):n==="checkbox"&&t?.(!e);},clickHighlightedItem({scope:r,computed:e,prop:t,context:n}){let o=r.getById(e("highlightedId"));if(!o||o.dataset.disabled)return;let i=n.get("highlightedValue");ug(o)?t("navigate")?.({value:i,node:o,href:o.href}):queueMicrotask(()=>o.click());},setIntentPolygon({context:r,scope:e,event:t}){let n=zt(e),o=r.get("currentPlacement");if(!n||!o)return;let i=n.getBoundingClientRect(),s=iv(i,o);if(!s)return;let l=is(o)==="right"?-5:5;r.set("intentPolygon",[{...t.point,x:t.point.x+l},...s]);},clearIntentPolygon({context:r}){r.set("intentPolygon",null);},clearAnchorPoint({context:r}){r.set("anchorPoint",null);},unlockParentOnOpen({refs:r,context:e,scope:t}){let n=r.get("parent");if(e.get("isSubmenu")){let o=cn(t);n?.send({type:"HIGHLIGHTED.SUGGEST",value:o});}qn(n,false);},unlockParentOnClose({refs:r,context:e}){cv(r.get("parent"),e.get("isSubmenu"));},setHighlightedItem({context:r,event:e}){let t=e.value||jn(e.target);r.set("highlightedValue",t);},clearHighlightedItem({context:r}){r.set("highlightedValue",null);},focusMenu({scope:r}){Ve(()=>{let e=zt(r);Vl({root:e,enabled:!mt(e,r.getActiveElement()),filter(n){return !n.role?.startsWith("menuitem")}})?.focus({preventScroll:true});});},highlightFirstItem({context:r,scope:e}){(zt(e)?queueMicrotask:Ve)(()=>{let n=Zb(e);n&&r.set("highlightedValue",jn(n));});},highlightLastItem({context:r,scope:e}){(zt(e)?queueMicrotask:Ve)(()=>{let n=Qb(e);n&&r.set("highlightedValue",jn(n));});},highlightNextItem({context:r,scope:e,event:t,prop:n}){let o=Jb(e,{loop:t.loop,value:r.get("highlightedValue"),loopFocus:n("loopFocus")});r.set("highlightedValue",jn(o));},highlightPrevItem({context:r,scope:e,event:t,prop:n}){let o=ev(e,{loop:t.loop,value:r.get("highlightedValue"),loopFocus:n("loopFocus")});r.set("highlightedValue",jn(o));},invokeOnSelect({context:r,prop:e,scope:t}){let n=r.get("highlightedValue");if(n==null)return;let o=jb(t,n);nv(o,n),e("onSelect")?.({value:n});},focusTrigger({scope:r,context:e,event:t}){e.get("isSubmenu")||e.get("anchorPoint")||t.restoreFocus===false||queueMicrotask(()=>{ss(r,e.get("triggerValue"))?.focus({preventScroll:true});});},highlightMatchedItem({scope:r,context:e,event:t,refs:n}){let o=tv(r,{key:t.key,value:e.get("highlightedValue"),typeaheadState:n.get("typeaheadState")});o&&e.set("highlightedValue",jn(o));},setParentMenu({refs:r,event:e,context:t}){r.set("parent",e.value),t.set("isSubmenu",true);},setChildMenu({refs:r,event:e}){let t=r.get("children");t[e.id]=e.value,r.set("children",t);},closeSiblingMenus({refs:r,event:e,scope:t}){let n=e.target;if(!Zu(n))return;let o=n?.getAttribute("data-uid"),i=r.get("children");for(let s in i){if(s===o)continue;let a=i[s],l=a.context.get("intentPolygon");l&&e.point&&lc(l,e.point)||(zt(t)?.focus({preventScroll:true}),a.send({type:"CLOSE"}));}},closeRootMenu({refs:r}){eh({parent:r.get("parent")});},openSubmenu({refs:r,scope:e,computed:t}){let o=e.getById(t("highlightedId"))?.getAttribute("data-uid"),i=r.get("children");(o?i[o]:null)?.send({type:"OPEN_AUTOFOCUS"});},focusParentMenu({refs:r}){r.get("parent")?.send({type:"FOCUS_MENU"});},setLastHighlightedItem({context:r,event:e}){r.set("lastHighlightedValue",jn(e.target));},suggestHighlightedItem({context:r,event:e}){let t=e.value;if(t){if(r.get("highlightedValue")!=null){r.set("lastHighlightedValue",t);return}r.set("highlightedValue",t);}},restoreHighlightedItem({context:r}){let e=r.get("lastHighlightedValue");r.set("lastHighlightedValue",null),e&&r.set("highlightedValue",e);},restoreParentHighlightedItem({refs:r}){r.get("parent")?.send({type:"HIGHLIGHTED.RESTORE"});},invokeOnOpen({prop:r}){r("onOpenChange")?.({open:true});},invokeOnClose({prop:r}){r("onOpenChange")?.({open:false});},releaseParentRoutingLock({refs:r,context:e}){e.get("isSubmenu")&&dv(r.get("parent"));},toggleVisibility({prop:r,event:e,send:t}){t({type:r("open")?"CONTROLLED.OPEN":"CONTROLLED.CLOSE",previousEvent:e});},setTriggerValue({context:r,event:e}){e.value!==void 0&&r.set("triggerValue",e.value);}}}});function Dv(r){return {machine:sh,props:{id:r.id??Kl("vela-menu"),ids:r.triggerId?{trigger:r.triggerId}:void 0,positioning:{placement:r.placement??"bottom-start",...r.getAnchorRect?{getAnchorRect:()=>r.getAnchorRect()}:{}},onSelect:e=>r.onSelect?.(e.value),onOpenChange:e=>r.onOpenChange?.(e.open)},connect:e=>th(e,Lo)}}var Ov="vela-ui-menu",Nv=` +`;function RL(r,e){let t=Al(e);for(let n in t)r.style.setProperty(n,t[n]);}function Zl(r,e){return r.closest(".vela-ui")??e??r}function rb(r,e){he(PL,AL,r.getRootNode()),r.classList.add("vela-ui"),e&&RL(r,e);}function ze(r,e=document){let t=e.createElement("span");t.className="vela-icon",t.setAttribute("aria-hidden","true");let n=io(r);return n&&(t.innerHTML=n),t}var DL="vela:surface-open",OL="vela:surface-close";function Vt(r,e,t,n=null){let o=r.ownerDocument.defaultView;o&&r.dispatchEvent(new o.CustomEvent(e?DL:OL,{bubbles:true,composed:true,detail:{kind:t,trigger:n}}));}var zu="data-closing";function ob(r){return r.flatMap(e=>e.getAnimations({subtree:true}))}function NL(r){return Number.isFinite(r.effect?.getComputedTiming().endTime??Number.POSITIVE_INFINITY)}function Kn(r,e,t={}){let n=Array.isArray(r)?r:[r];if(n.length===0||!n.every(p=>typeof p.getAnimations=="function"))return e(),null;let o=new Set(ob(n));for(let p of n)p.setAttribute(zu,"");let i=ob(n).filter(p=>!o.has(p)&&NL(p));if(i.length===0){for(let p of n)p.removeAttribute(zu);return e(),null}let s=[...n,...t.inert??[]],a=s.map(p=>p.inert);for(let p of s)p.inert=true;let l=false,c=p=>{if(!l){l=true,clearTimeout(d);for(let m of n)m.removeAttribute(zu);s.forEach((m,f)=>{m.inert=a[f];}),p&&e();}},d=setTimeout(()=>c(true),1e3),u=i.length,h=()=>{--u===0&&c(true);};for(let p of i)p.finished.then(h,h);return {cancel:()=>c(false),finish:()=>c(true)}}var Cn=(r,e=[])=>({parts:(...t)=>{if(FL(e))return Cn(r,t);throw new Error("createAnatomy().parts(...) should only be called once. Did you mean to use .extendWith(...) ?")},extendWith:(...t)=>Cn(r,[...e,...t]),omit:(...t)=>Cn(r,e.filter(n=>!t.includes(n))),rename:t=>Cn(t,e),keys:()=>e,build:()=>[...new Set(e)].reduce((t,n)=>Object.assign(t,{[n]:{selector:[`&[data-scope="${Ro(r)}"][data-part="${Ro(n)}"]`,`& [data-scope="${Ro(r)}"][data-part="${Ro(n)}"]`].join(", "),attrs:{"data-scope":Ro(r),"data-part":Ro(n)}}}),{})}),Ro=r=>r.replace(/([A-Z])([A-Z])/g,"$1-$2").replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[\s_]+/g,"-").toLowerCase(),FL=r=>r.length===0;var VL=Cn("menu").parts("arrow","arrowTip","content","contextTrigger","indicator","item","itemGroup","itemGroupLabel","itemIndicator","itemText","positioner","separator","trigger","triggerItem"),Qe=VL.build();var ab=["top","right","bottom","left"];var on=Math.min,Bt=Math.max,rs=Math.round,os=Math.floor,sn=r=>({x:r,y:r}),BL={left:"right",right:"left",bottom:"top",top:"bottom"};function Wu(r,e,t){return Bt(r,on(e,t))}function an(r,e){return typeof r=="function"?r(e):r}function Tn(r){return r.split("-")[0]}function Nr(r){return r.split("-")[1]}function Jl(r){return r==="x"?"y":"x"}function ec(r){return r==="y"?"height":"width"}function _t(r){let e=r[0];return e==="t"||e==="b"?"y":"x"}function tc(r){return Jl(_t(r))}function lb(r,e,t){t===void 0&&(t=false);let n=Nr(r),o=tc(r),i=ec(o),s=o==="x"?n===(t?"end":"start")?"right":"left":n==="start"?"bottom":"top";return e.reference[i]>e.floating[i]&&(s=ns(s)),[s,ns(s)]}function cb(r){let e=ns(r);return [Ql(r),e,Ql(e)]}function Ql(r){return r.includes("start")?r.replace("start","end"):r.replace("end","start")}var ib=["left","right"],sb=["right","left"],_L=["top","bottom"],HL=["bottom","top"];function zL(r,e,t){switch(r){case "top":case "bottom":return t?e?sb:ib:e?ib:sb;case "left":case "right":return e?_L:HL;default:return []}}function db(r,e,t,n){let o=Nr(r),i=zL(Tn(r),t==="start",n);return o&&(i=i.map(s=>s+"-"+o),e&&(i=i.concat(i.map(Ql)))),i}function ns(r){let e=Tn(r);return BL[e]+r.slice(e.length)}function WL(r){var e,t,n,o;return {top:(e=r.top)!=null?e:0,right:(t=r.right)!=null?t:0,bottom:(n=r.bottom)!=null?n:0,left:(o=r.left)!=null?o:0}}function Gu(r){return typeof r!="number"?WL(r):{top:r,right:r,bottom:r,left:r}}function Fr(r){let{x:e,y:t,width:n,height:o}=r;return {width:n,height:o,top:t,left:e,right:e+n,bottom:t+o,x:e,y:t}}function ub(r,e,t){let{reference:n,floating:o}=r,i=_t(e),s=tc(e),a=ec(s),l=Tn(e),c=i==="y",d=n.x+n.width/2-o.width/2,u=n.y+n.height/2-o.height/2,h=n[a]/2-o[a]/2,p;switch(l){case "top":p={x:d,y:n.y-o.height};break;case "bottom":p={x:d,y:n.y+n.height};break;case "right":p={x:n.x+n.width,y:u};break;case "left":p={x:n.x-o.width,y:u};break;default:p={x:n.x,y:n.y};}let m=Nr(e);return m&&(p[s]+=h*(m==="end"?1:-1)*(t&&c?-1:1)),p}async function mb(r,e){var t;e===void 0&&(e={});let{x:n,y:o,platform:i,rects:s,elements:a,strategy:l}=r,{boundary:c="clippingAncestors",rootBoundary:d="viewport",elementContext:u="floating",altBoundary:h=false,padding:p=0}=an(e,r),m=Gu(p),g=a[h?u==="floating"?"reference":"floating":u],b=Fr(await i.getClippingRect({element:(t=await(i.isElement==null?void 0:i.isElement(g)))==null||t?g:g.contextElement||await(i.getDocumentElement==null?void 0:i.getDocumentElement(a.floating)),boundary:c,rootBoundary:d,strategy:l})),y=u==="floating"?{x:n,y:o,width:s.floating.width,height:s.floating.height}:s.reference,w=await(i.getOffsetParent==null?void 0:i.getOffsetParent(a.floating)),S=await(i.isElement==null?void 0:i.isElement(w))&&await(i.getScale==null?void 0:i.getScale(w))||{x:1,y:1},M=Fr(i.convertOffsetParentRelativeRectToViewportRelativeRect?await i.convertOffsetParentRelativeRectToViewportRelativeRect({elements:a,rect:y,offsetParent:w,strategy:l}):y);return {top:(b.top-M.top+m.top)/S.y,bottom:(M.bottom-b.bottom+m.bottom)/S.y,left:(b.left-M.left+m.left)/S.x,right:(M.right-b.right+m.right)/S.x}}var GL=50,fb=async(r,e,t)=>{let{placement:n="bottom",strategy:o="absolute",middleware:i=[],platform:s}=t,a=s.detectOverflow?s:{...s,detectOverflow:mb},l=await(s.isRTL==null?void 0:s.isRTL(e)),c=await s.getElementRects({reference:r,floating:e,strategy:o}),{x:d,y:u}=ub(c,n,l),h=n,p=0,m={};for(let f=0;f({name:"arrow",options:r,async fn(e){let{x:t,y:n,placement:o,rects:i,platform:s,elements:a,middlewareData:l}=e,{element:c,padding:d=0}=an(r,e)||{};if(c==null)return {};let u=Gu(d),h={x:t,y:n},p=tc(o),m=ec(p),f=await s.getDimensions(c),g=p==="y",b=g?"top":"left",y=g?"bottom":"right",w=g?"clientHeight":"clientWidth",S=i.reference[m]+i.reference[p]-h[p]-i.floating[m],M=h[p]-i.reference[p],C=await(s.getOffsetParent==null?void 0:s.getOffsetParent(c)),L=C?C[w]:0;(!L||!await(s.isElement==null?void 0:s.isElement(C)))&&(L=a.floating[w]||i.floating[m]);let v=S/2-M/2,k=L/2-f[m]/2-1,x=on(u[b],k),E=on(u[y],k),I=L-f[m]-E,N=L/2-f[m]/2+v,V=Wu(x,N,I),Z=!l.arrow&&Nr(o)!=null&&N!==V&&i.reference[m]/2-(NV<=0)){var E,I;let V=(((E=i.flip)==null?void 0:E.index)||0)+1,Z=L[V];if(Z&&(!(u==="alignment"?y!==_t(Z):false)||x.every(At=>_t(At.placement)===y?At.overflows[0]>0:true)))return {data:{index:V,overflows:x},reset:{placement:Z}};let be=(I=x.filter(gn=>gn.overflows[0]<=0).sort((gn,At)=>gn.overflows[1]-At.overflows[1])[0])==null?void 0:I.placement;if(!be)switch(p){case "bestFit":{var N;let gn=(N=x.filter(At=>{if(C){let Fn=_t(At.placement);return Fn===y||Fn==="y"}return true}).map(At=>[At.placement,At.overflows.filter(Fn=>Fn>0).reduce((Fn,dC)=>Fn+dC,0)]).sort((At,Fn)=>At[1]-Fn[1])[0])==null?void 0:N[0];gn&&(be=gn);break}case "initialPlacement":be=a;break}if(o!==be)return {reset:{placement:be}}}return {}}}};function hb(r,e){return {top:r.top-e.height,right:r.right-e.width,bottom:r.bottom-e.height,left:r.left-e.width}}function pb(r){return ab.some(e=>r[e]>=0)}var vb=function(r){return r===void 0&&(r={}),{name:"hide",options:r,async fn(e){let{rects:t,platform:n}=e,{strategy:o="referenceHidden",...i}=an(r,e);switch(o){case "referenceHidden":{let s=await n.detectOverflow(e,{...i,elementContext:"reference"}),a=hb(s,t.reference);return {data:{referenceHiddenOffsets:a,referenceHidden:pb(a)}}}case "escaped":{let s=await n.detectOverflow(e,{...i,altBoundary:true}),a=hb(s,t.floating);return {data:{escapedOffsets:a,escaped:pb(a)}}}default:return {}}}}};var yb=new Set(["left","top"]);async function $L(r,e){let{placement:t,platform:n,elements:o}=r,i=await(n.isRTL==null?void 0:n.isRTL(o.floating)),s=Tn(t),a=Nr(t),l=_t(t)==="y",c=yb.has(s)?-1:1,d=i&&l?-1:1,u=an(e,r),{mainAxis:h,crossAxis:p,alignmentAxis:m}=typeof u=="number"?{mainAxis:u,crossAxis:0,alignmentAxis:null}:{mainAxis:u.mainAxis||0,crossAxis:u.crossAxis||0,alignmentAxis:u.alignmentAxis};return a&&typeof m=="number"&&(p=a==="end"?m*-1:m),l?{x:p*d,y:h*c}:{x:h*c,y:p*d}}var wb=function(r){return r===void 0&&(r=0),{name:"offset",options:r,async fn(e){var t,n;let{x:o,y:i,placement:s,middlewareData:a}=e,l=await $L(e,r);return s===((t=a.offset)==null?void 0:t.placement)&&(n=a.arrow)!=null&&n.alignmentOffset?{}:{x:o+l.x,y:i+l.y,data:{...l,placement:s}}}}},xb=function(r){return r===void 0&&(r={}),{name:"shift",options:r,async fn(e){let{x:t,y:n,placement:o,platform:i}=e,{mainAxis:s=true,crossAxis:a=false,limiter:l={fn:y=>{let{x:w,y:S}=y;return {x:w,y:S}}},...c}=an(r,e),d={x:t,y:n},u=await i.detectOverflow(e,c),h=_t(o),p=Jl(h),m=d[p],f=d[h],g=(y,w)=>Wu(w+u[y==="y"?"top":"left"],w,w-u[y==="y"?"bottom":"right"]);s&&(m=g(p,m)),a&&(f=g(h,f));let b=l.fn({...e,[p]:m,[h]:f});return {...b,data:{x:b.x-t,y:b.y-n,enabled:{[p]:s,[h]:a}}}}}},Sb=function(r){return r===void 0&&(r={}),{options:r,fn(e){var t,n;let{x:o,y:i,placement:s,rects:a,middlewareData:l}=e,{offset:c=0,mainAxis:d=true,crossAxis:u=true}=an(r,e),h={x:o,y:i},p=_t(s),m=Jl(p),f=h[m],g=h[p],b=an(c,e),y=typeof b=="number"?{mainAxis:b,crossAxis:0}:{mainAxis:(t=b.mainAxis)!=null?t:0,crossAxis:(n=b.crossAxis)!=null?n:0};if(d){let M=m==="y"?"height":"width",C=a.reference[m]-a.floating[M]+y.mainAxis,L=a.reference[m]+a.reference[M]-y.mainAxis;fL&&(f=L);}if(u){var w,S;let M=m==="y"?"width":"height",C=yb.has(Tn(s)),L=a.reference[p]-a.floating[M]+(C&&((w=l.offset)==null?void 0:w[p])||0)+(C?0:y.crossAxis),v=a.reference[p]+a.reference[M]+(C?0:((S=l.offset)==null?void 0:S[p])||0)-(C?y.crossAxis:0);gv&&(g=v);}return {[m]:f,[p]:g}}}},Cb=function(r){return r===void 0&&(r={}),{name:"size",options:r,async fn(e){let{placement:t,rects:n,platform:o,elements:i}=e,{apply:s=()=>{},...a}=an(r,e),l=await o.detectOverflow(e,a),c=Tn(t),d=Nr(t),u=_t(t)==="y",{width:h,height:p}=n.floating,m,f;c==="top"||c==="bottom"?(m=c,f=d===(await(o.isRTL==null?void 0:o.isRTL(i.floating))?"start":"end")?"left":"right"):(f=c,m=d==="end"?"top":"bottom");let g=p-l.top-l.bottom,b=h-l.left-l.right,y=on(p-l[m],g),w=on(h-l[f],b),S=e.middlewareData.shift,M=!S,C=y,L=w;S!=null&&S.enabled.x&&(L=b),S!=null&&S.enabled.y&&(C=g),M&&!d&&(u?L=h-2*Bt(l.left,l.right):C=p-2*Bt(l.top,l.bottom)),await s({...e,availableWidth:L,availableHeight:C});let v=await o.getDimensions(i.floating);return h!==v.width||p!==v.height?{reset:{rects:true}}:{}}}};function nc(){return typeof window<"u"}function Br(r){return kb(r)?(r.nodeName||"").toLowerCase():"#document"}function it(r){var e;return (r==null||(e=r.ownerDocument)==null?void 0:e.defaultView)||window}function ln(r){var e;return (e=(kb(r)?r.ownerDocument:r.document)||window.document)==null?void 0:e.documentElement}function kb(r){return nc()?r instanceof Node||r instanceof it(r).Node:false}function Ht(r){return nc()?r instanceof Element||r instanceof it(r).Element:false}function kn(r){return nc()?r instanceof HTMLElement||r instanceof it(r).HTMLElement:false}function Tb(r){return !nc()||typeof ShadowRoot>"u"?false:r instanceof ShadowRoot||r instanceof it(r).ShadowRoot}function is(r){let{overflow:e,overflowX:t,overflowY:n,display:o}=zt(r);return /auto|scroll|overlay|hidden|clip/.test(e+n+t)&&o!=="inline"&&o!=="contents"}function Lb(r){return /^(table|td|th)$/.test(Br(r))}function ss(r){try{if(r.matches(":popover-open"))return !0}catch{}try{return r.matches(":modal")}catch{return false}}var UL=/transform|translate|scale|rotate|perspective|filter/,YL=/paint|layout|strict|content/,Vr=r=>!!r&&r!=="none",$u;function rc(r){let e=Ht(r)?zt(r):r;return Vr(e.transform)||Vr(e.translate)||Vr(e.scale)||Vr(e.rotate)||Vr(e.perspective)||!oc()&&(Vr(e.backdropFilter)||Vr(e.filter))||UL.test(e.willChange||"")||YL.test(e.contain||"")}function Mb(r){let e=Xn(r);for(;kn(e)&&!Oo(e);){if(rc(e))return e;if(ss(e))return null;e=Xn(e);}return null}function oc(){return $u==null&&($u=typeof CSS<"u"&&CSS.supports&&CSS.supports("-webkit-backdrop-filter","none")),$u}function Oo(r){return /^(html|body|#document)$/.test(Br(r))}function zt(r){return it(r).getComputedStyle(r)}function as(r){return Ht(r)?{scrollLeft:r.scrollLeft,scrollTop:r.scrollTop}:{scrollLeft:r.scrollX,scrollTop:r.scrollY}}function Xn(r){if(Br(r)==="html")return r;let e=r.assignedSlot||r.parentNode||Tb(r)&&r.host||ln(r);return Tb(e)?e.host:e}function Eb(r){let e=Xn(r);return Oo(e)?(r.ownerDocument||r).body:kn(e)&&is(e)?e:Eb(e)}function Do(r,e,t){var n;e===void 0&&(e=[]),t===void 0&&(t=true);let o=Eb(r),i=o===((n=r.ownerDocument)==null?void 0:n.body),s=it(o);if(i){let a=ic(s);return e.concat(s,s.visualViewport||[],is(o)?o:[],a&&t?Do(a):[])}else return e.concat(o,Do(o,[],t))}function ic(r){return r.parent&&Object.getPrototypeOf(r.parent)?r.frameElement:null}function Ab(r){let e=zt(r),t=parseFloat(e.width)||0,n=parseFloat(e.height)||0,o=kn(r),i=o?r.offsetWidth:t,s=o?r.offsetHeight:n,a=rs(t)!==i||rs(n)!==s;return a&&(t=i,n=s),{width:t,height:n,$:a}}function Yu(r){return Ht(r)?r:r.contextElement}function No(r){let e=Yu(r);if(!kn(e))return sn(1);let t=e.getBoundingClientRect(),{width:n,height:o,$:i}=Ab(e),s=(i?rs(t.width):t.width)/n,a=(i?rs(t.height):t.height)/o;return (!s||!Number.isFinite(s))&&(s=1),(!a||!Number.isFinite(a))&&(a=1),{x:s,y:a}}var KL=sn(0);function Rb(r){let e=it(r);return !oc()||!e.visualViewport?KL:{x:e.visualViewport.offsetLeft,y:e.visualViewport.offsetTop}}function XL(r,e,t){return e===void 0&&(e=false),!!t&&e&&t===it(r)}function _r(r,e,t,n){e===void 0&&(e=false),t===void 0&&(t=false);let o=r.getBoundingClientRect(),i=Yu(r),s=sn(1);e&&(n?Ht(n)&&(s=No(n)):s=No(r));let a=XL(i,t,n)?Rb(i):sn(0),l=(o.left+a.x)/s.x,c=(o.top+a.y)/s.y,d=o.width/s.x,u=o.height/s.y;if(i&&n){let h=it(i),p=Ht(n)?it(n):n,m=h,f=ic(m);for(;f&&p!==m;){let g=No(f),b=f.getBoundingClientRect(),y=zt(f),w=b.left+(f.clientLeft+parseFloat(y.paddingLeft))*g.x,S=b.top+(f.clientTop+parseFloat(y.paddingTop))*g.y;l*=g.x,c*=g.y,d*=g.x,u*=g.y,l+=w,c+=S,m=it(f),f=ic(m);}}return Fr({width:d,height:u,x:l,y:c})}function sc(r,e){let t=as(r).scrollLeft;return e?e.left+t:_r(ln(r)).left+t}function Db(r,e){let t=r.getBoundingClientRect(),n=t.left+e.scrollLeft-sc(r,t),o=t.top+e.scrollTop;return {x:n,y:o}}function jL(r){let{elements:e,rect:t,offsetParent:n,strategy:o}=r,i=o==="fixed",s=ln(n),a=e?ss(e.floating):false;if(n===s||a&&i)return t;let l={scrollLeft:0,scrollTop:0},c=sn(1),d=sn(0),u=kn(n);if((u||!i)&&((Br(n)!=="body"||is(s))&&(l=as(n)),u)){let p=_r(n);c=No(n),d.x=p.x+n.clientLeft,d.y=p.y+n.clientTop;}let h=s&&!u&&!i?Db(s,l):sn(0);return {width:t.width*c.x,height:t.height*c.y,x:t.x*c.x-l.scrollLeft*c.x+d.x+h.x,y:t.y*c.y-l.scrollTop*c.y+d.y+h.y}}function qL(r){return r.getClientRects?Array.from(r.getClientRects()):[]}function ZL(r){let e=as(r),t=r.ownerDocument.body,n=Bt(r.scrollWidth,r.clientWidth,t.scrollWidth,t.clientWidth),o=Bt(r.scrollHeight,r.clientHeight,t.scrollHeight,t.clientHeight),i=-e.scrollLeft+sc(r),s=-e.scrollTop;return zt(t).direction==="rtl"&&(i+=Bt(r.clientWidth,t.clientWidth)-n),{width:n,height:o,x:i,y:s}}var QL=25;function JL(r,e,t){t===void 0&&(t="viewport");let n=t==="layoutViewport",o=it(r),i=ln(r),s=o.visualViewport,a=i.clientWidth,l=i.clientHeight,c=0,d=0;if(s){let h=!oc()||e==="fixed";n?h||(c=-s.offsetLeft,d=-s.offsetTop):(a=s.width,l=s.height,h&&(c=s.offsetLeft,d=s.offsetTop));}if(sc(i)<=0){let h=i.ownerDocument,p=h.body,m=getComputedStyle(p),f=h.compatMode==="CSS1Compat"&&parseFloat(m.marginLeft)+parseFloat(m.marginRight)||0,g=Math.abs(i.clientWidth-p.clientWidth-f),b=getComputedStyle(i).scrollbarGutter==="stable both-edges"?g/2:g;b<=QL&&(a-=b);}return {width:a,height:l,x:c,y:d}}function eM(r,e){let t=_r(r,true,e==="fixed"),n=t.top+r.clientTop,o=t.left+r.clientLeft,i=No(r),s=r.clientWidth*i.x,a=r.clientHeight*i.y,l=o*i.x,c=n*i.y;return {width:s,height:a,x:l,y:c}}function Pb(r,e,t){let n;if(e==="viewport"||e==="layoutViewport")n=JL(r,t,e);else if(e==="document")n=ZL(ln(r));else if(Ht(e))n=eM(e,t);else {let o=Rb(r);n={x:e.x-o.x,y:e.y-o.y,width:e.width,height:e.height};}return Fr(n)}function tM(r,e){let t=e.get(r);if(t)return t;let n=Do(r,[],false).filter(a=>Ht(a)&&Br(a)!=="body"),o=null,i=zt(r).position==="fixed",s=i?Xn(r):r;for(;Ht(s)&&!Oo(s);){let a=zt(s),l=rc(s),c=o?o.position:i?"fixed":"";!l&&(c==="fixed"||c==="absolute"&&a.position==="static")?n=n.filter(u=>u!==s):o=a,s=Xn(s);}return e.set(r,n),n}function nM(r){let{element:e,boundary:t,rootBoundary:n,strategy:o}=r,s=[...t==="clippingAncestors"?ss(e)?[]:tM(e,this._c):[].concat(t),n],a=Pb(e,s[0],o),l=a.top,c=a.right,d=a.bottom,u=a.left;for(let h=1;h{a(false,1e-7);},1e3);}L=false;}try{n=new IntersectionObserver(v,{...C,root:i.ownerDocument});}catch{n=new IntersectionObserver(v,C);}n.observe(r);}let l=it(r),c=()=>a(t);return l.addEventListener("resize",c),a(true),()=>{l.removeEventListener("resize",c),s();}}function Fb(r,e,t,n){n===void 0&&(n={});let{ancestorScroll:o=true,ancestorResize:i=true,elementResize:s=typeof ResizeObserver=="function",layoutShift:a=typeof IntersectionObserver=="function",animationFrame:l=false}=n,c=Yu(r),d=o||i?[...c?Do(c):[],...e?Do(e):[]]:[];d.forEach(b=>{o&&b.addEventListener("scroll",t),i&&b.addEventListener("resize",t);});let u=c&&a?lM(c,t,i):null,h=-1,p=null;s&&(p=new ResizeObserver(b=>{let[y]=b;y&&y.target===c&&p&&e&&(p.unobserve(e),cancelAnimationFrame(h),h=requestAnimationFrame(()=>{var w;(w=p)==null||w.observe(e);})),t();}),c&&!l&&p.observe(c),e&&p.observe(e));let m,f=l?_r(r):null;l&&g();function g(){let b=_r(r);f&&!Nb(f,b)&&t(),f=b,m=requestAnimationFrame(g);}return t(),()=>{var b;d.forEach(y=>{o&&y.removeEventListener("scroll",t),i&&y.removeEventListener("resize",t);}),u?.(),(b=p)==null||b.disconnect(),p=null,l&&cancelAnimationFrame(m);}}var Vb=wb;var Bb=xb,_b=bb,Hb=Cb,zb=vb,Wb=gb;var Gb=Sb,$b=(r,e,t)=>{let n=new Map,o=t??{},i={...aM,...o.platform,_c:n};return fb(r,e,{...o,platform:i})};function Ub(r=0,e=0,t=0,n=0){if(typeof DOMRect=="function")return new DOMRect(r,e,t,n);let o={x:r,y:e,width:t,height:n,top:e,right:r+t,bottom:e+n,left:r};return {...o,toJSON:()=>o}}function cM(r){if(!r)return Ub();let{x:e,y:t,width:n,height:o}=r;return Ub(e,t,n,o)}function Yb(r,e){return {contextElement:me(r)?r:r?.contextElement,getBoundingClientRect:()=>{let t=r,n=e?.(t);return n||!t?cM(n):t.getBoundingClientRect()}}}var ls=r=>({variable:r,reference:`var(${r})`}),cn={arrowSize:ls("--arrow-size"),arrowSizeHalf:ls("--arrow-size-half"),arrowBg:ls("--arrow-background"),transformOrigin:ls("--transform-origin"),arrowOffset:ls("--arrow-offset")},dM=r=>r==="top"||r==="bottom"?"y":"x";function Kb(r,e){return {name:"transformOrigin",fn(t){let{elements:n,middlewareData:o,placement:i,rects:s,y:a}=t,l=i.split("-")[0],c=dM(l),d=o.arrow?.x||0,u=o.arrow?.y||0,h=e?.clientWidth||0,p=e?.clientHeight||0,m=d+h/2,f=u+p/2,g=Math.abs(o.shift?.y||0),b=s.reference.height/2,y=p/2,w=r.offset?.mainAxis??r.gutter,S=typeof w=="number"?w+y:w??y,M=g>S,C={top:`${m}px calc(100% + ${S}px)`,bottom:`${m}px ${-S}px`,left:`calc(100% + ${S}px) ${f}px`,right:`${-S}px ${f}px`}[l],L=`${m}px ${s.reference.y+b-a}px`,v=!!r.overlap&&c==="y"&&M;return n.floating.style.setProperty(cn.transformOrigin.variable,v?L:C),{data:{transformOrigin:v?L:C}}}}}var Xb={name:"rects",fn({rects:r}){return {data:r}}},jb=r=>{if(r)return {name:"shiftArrow",fn({placement:e,middlewareData:t}){if(!t.arrow)return {};let{x:n,y:o}=t.arrow,i=e.split("-")[0];return Object.assign(r.style,{left:n!=null?`${n}px`:"",top:o!=null?`${o}px`:"",[i]:`calc(100% + ${cn.arrowOffset.reference})`}),{}}}};function qb(r){let[e,t]=r.split("-");return {side:e,align:t,hasAlign:t!=null}}function cs(r){return r.split("-")[0]}var uM={strategy:"absolute",placement:"bottom",listeners:true,restoreStyles:false,gutter:8,flip:true,slide:true,overlap:false,sameWidth:false,fitViewport:false,overflowPadding:8,arrowPadding:4};function Zb(r,e){let t=r.devicePixelRatio||1;return Math.round(e*t)/t}function Fo(r,e){return r!=null&&Math.abs(r-e)<.5}function ac(r){return typeof r=="function"?r():r==="clipping-ancestors"?"clippingAncestors":r}function hM(r,e,t){let n=r||e.createElement("div");return Wb({element:n,padding:t.arrowPadding})}function pM(r,e){if(!Qf(e.offset??e.gutter))return Vb(({placement:t})=>{let n=(r?.clientHeight||0)/2,o=e.offset?.mainAxis??e.gutter,i=typeof o=="number"?o+n:o??n,{hasAlign:s}=qb(t),a=s?void 0:e.shift,l=e.offset?.crossAxis??a;return $n({crossAxis:l,mainAxis:i,alignmentAxis:e.shift})})}function mM(r){if(r.flip)return _b(()=>{let e=ac(r.boundary);return {...e?{boundary:e}:void 0,padding:r.overflowPadding,fallbackPlacements:r.flip===true?void 0:r.flip}})}function fM(r){if(!(!r.slide&&!r.overlap))return Bb(()=>{let e=ac(r.boundary);return {...e?{boundary:e}:void 0,mainAxis:r.slide,crossAxis:r.overlap,padding:r.overflowPadding,limiter:Gb()}})}function gM(r){if(r.sizeMiddleware===false&&!r.sameWidth&&!r.fitViewport)return;let e,t,n,o;return Hb(()=>{let i=ac(r.boundary);return {padding:r.overflowPadding,...i?{boundary:i}:void 0,apply({elements:s,rects:a,availableHeight:l,availableWidth:c}){let d=s.floating,u=Math.round(a.reference.width),h=Math.round(a.reference.height);c=Math.floor(c),l=Math.floor(l),Fo(e,u)||(d.style.setProperty("--reference-width",`${u}px`),e=u),Fo(t,h)||(d.style.setProperty("--reference-height",`${h}px`),t=h),Fo(n,c)||(d.style.setProperty("--available-width",`${c}px`),n=c),Fo(o,l)||(d.style.setProperty("--available-height",`${l}px`),o=l);}}})}function bM(r){if(r.hideWhenDetached)return zb(()=>({strategy:"referenceHidden",boundary:ac(r.boundary)??"clippingAncestors"}))}function vM(r){return r?r===true?{ancestorResize:true,ancestorScroll:true,elementResize:true,layoutShift:true}:r:{}}var yM=["transform","visibility","pointer-events","--x","--y","--z-index","--reference-width","--reference-height","--available-width","--available-height","--transform-origin"],wM=["top","right","bottom","left"];function Qb(r,e){if(!r)return gu;let t=new Map(e.map(n=>[n,r.style.getPropertyValue(n)]));return ()=>{t.forEach((n,o)=>{n?r.style.setProperty(o,n):r.style.removeProperty(o);}),r.style.length===0&&r.removeAttribute("style");}}function Jb(r){return r==null?null:me(r)?r:typeof r=="object"&&r&&"contextElement"in r&&r.contextElement?r.contextElement:r}function xM(r,e,t={}){let n=()=>(typeof e=="function"?e():e)??null,o=()=>{let x=typeof r=="function"?r():r;return t.getAnchorElement?.()??x},i=()=>{let x=o();return !x&&!t.getAnchorRect?null:Yb(x,t.getAnchorRect)},s=Object.assign({},uM,t),a=[],l=null,c,d;function u(x){c?.(),d?.(),l=x,c=s.restoreStyles?Qb(x,yM):void 0;let E=x.querySelector("[data-part=arrow]");d=s.restoreStyles?Qb(E,wM):void 0,a=[pM(E,s),mM(s),fM(s),hM(E,x.ownerDocument,s),jb(E),Kb({gutter:s.gutter,offset:s.offset,overlap:s.overlap},E),gM(s),bM(s),Xb];}let{placement:h,strategy:p,onComplete:m,onPositioned:f}=s,g,b,y=false,w,S,M=gu,C=vM(s.listeners);function L(){if(!s.listeners)return;let x=o(),E=i(),I=n();if(!E||!I)return;(Jb(x)!==Jb(w)||I!==S)&&(M(),w=x,S=I,M=Fb(E,I,k,C));}async function v(){L();let x=n();if(!x)return;x!==l&&(u(x),y=false);let E=i();if(!E)return;let I=await $b(E,x,{placement:h,middleware:a,strategy:p});m?.(I);let N=Ie(x),V=Zb(N,I.x),Z=Zb(N,I.y);if(Fo(g,V)||(x.style.setProperty("--x",`${V}px`),g=V),Fo(b,Z)||(x.style.setProperty("--y",`${Z}px`),b=Z),s.hideWhenDetached&&(I.middlewareData.hide?.referenceHidden?(x.style.setProperty("visibility","hidden"),x.style.setProperty("pointer-events","none")):(x.style.removeProperty("visibility"),x.style.removeProperty("pointer-events"))),!y){let be=x.firstElementChild;be&&(x.style.setProperty("--z-index",To(be).zIndex),y=true);}}async function k(){t.updatePosition?(await t.updatePosition({updatePosition:v,floatingElement:n()}),f?.({placed:true})):await v();}return k(),()=>{M(),d?.(),c?.(),f?.({placed:false});}}function lc(r,e,t={}){let{defer:n,...o}=t,i=n?Ve:a=>a(),s=[];return s.push(i(()=>{s.push(xM(r,e,o));})),()=>{s.forEach(a=>a?.());}}var SM={bottom:"rotate(45deg)",left:"rotate(135deg)",top:"rotate(225deg)",right:"rotate(315deg)"};function Ku(r={}){let{placement:e,sameWidth:t,fitViewport:n,strategy:o="absolute"}=r;return {arrow:{position:"absolute",width:cn.arrowSize.reference,height:cn.arrowSize.reference,[cn.arrowSizeHalf.variable]:`calc(${cn.arrowSize.reference} / 2)`,[cn.arrowOffset.variable]:`calc(${cn.arrowSizeHalf.reference} * -1)`},arrowTip:{transform:e?SM[e.split("-")[0]]:void 0,background:cn.arrowBg.reference,top:"0",left:"0",width:"100%",height:"100%",position:"absolute",zIndex:"inherit"},floating:{position:o,isolation:"isolate",minWidth:t?void 0:"max-content",width:t?"var(--reference-width)":void 0,maxWidth:n?"var(--available-width)":void 0,maxHeight:n?"var(--available-height)":void 0,pointerEvents:e?void 0:"none",top:"0px",left:"0px",transform:e?"translate3d(var(--x), var(--y), 0)":"translate3d(0, -100vh, 0)",zIndex:"var(--z-index)"}}}var dn=(r,e)=>{let t=r.ids?.trigger;return t!=null?pt(t)?t(e):t:e?`menu:${r.id}:trigger:${e}`:`menu:${r.id}:trigger`},cc=(r,e)=>{let t=r.ids?.contextTrigger;return t!=null?pt(t)?t(e):t:e?`menu:${r.id}:ctx-trigger:${e}`:`menu:${r.id}:ctx-trigger`},jn=r=>r.ids?.content??`menu:${r.id}:content`,ev=r=>r.ids?.arrow??`menu:${r.id}:arrow`,Xu=r=>r.ids?.positioner??`menu:${r.id}:popper`,tv=(r,e)=>r.ids?.group?.(e)??`menu:${r.id}:group:${e}`,Hr=(r,e)=>`${r.id}/${e}`,qn=r=>r?.dataset.value??null,ju=(r,e)=>r.ids?.groupLabel?.(e)??`menu:${r.id}:group-label:${e}`,Wt=r=>r.getById(jn(r)),qu=r=>r.getById(Xu(r)),Zu=r=>r.getById(dn(r)),nv=(r,e)=>e?r.getById(Hr(r,e)):null;var rv=r=>r.getById(cc(r)),Qu=r=>Po(r.getRootNode(),`[data-scope="menu"][data-part="trigger"][data-ownedby="${r.id}"]`),Ju=r=>Po(r.getRootNode(),`[data-scope="menu"][data-part="context-trigger"][data-ownedby="${r.id}"]`),ds=(r,e)=>e==null?Zu(r)??Qu(r)[0]:r.getById(dn(r,e)),us=r=>{let t=`[role^="menuitem"][data-ownedby=${CSS.escape(jn(r))}]:not([data-disabled])`;return Po(Wt(r),t)},ov=r=>Yf(us(r)),iv=r=>Kf(us(r)),eh=(r,e)=>e?r.id===e||r.dataset.value===e:false,sv=(r,e)=>{let t=us(r),n=t.findIndex(o=>eh(o,e.value));return jf(t,n,{loop:e.loop??e.loopFocus})},av=(r,e)=>{let t=us(r),n=t.findIndex(o=>eh(o,e.value));return qf(t,n,{loop:e.loop??e.loopFocus})},lv=(r,e)=>{let t=us(r),n=t.find(o=>eh(o,e.value));return Gl(t,{state:e.typeaheadState,key:e.key,activeId:n?.id??null})},hs=r=>me(r)&&(r.dataset.disabled===""||r.hasAttribute("disabled")),th=r=>!!r?.getAttribute("role")?.startsWith("menuitem")&&!!r?.hasAttribute("data-controls");var dc="menu:select";function cv(r,e){if(!r)return;let t=Ie(r),n=new t.CustomEvent(dc,{detail:{value:e}});r.dispatchEvent(n);}function CM(r){let e=jn(r);return Wt(r)??r.getDoc().getElementById(e)}function nh(r,e){if(!me(r))return false;for(let t in e){let n=e[t],o=CM(n.scope);if(o&&mt(o,r))return true;let i=n.refs.get("children");if(Object.keys(i).length>0&&nh(r,i))return true}return false}var ps=(r,e)=>({x:r,y:e});function dv(r){let{x:e,y:t,width:n,height:o}=r,i=e+n/2,s=t+o/2;return {x:e,y:t,width:n,height:o,minX:e,minY:t,maxX:e+n,maxY:t+o,midX:i,midY:s,center:ps(i,s)}}function uv(r){let e=ps(r.minX,r.minY),t=ps(r.maxX,r.minY),n=ps(r.maxX,r.maxY),o=ps(r.minX,r.maxY);return {top:e,right:t,bottom:n,left:o}}function hv(r,e){let t=dv(r),{top:n,right:o,left:i,bottom:s}=uv(t),[a]=e.split("-");return {top:[i,n,o,s],right:[n,o,s,i],bottom:[n,i,s,o],left:[o,n,i,s]}[a]}function uc(r,e){let{x:t,y:n}=e,o=false;for(let i=0,s=r.length-1;in!=d>n&&t<(c-a)*(n-l)/(d-l)+a&&(o=!o);}return o}function oh(r){let e=r.parent;for(;e&&e.context.get("isSubmenu");)e=e.refs.get("parent");e?.send({type:"CLOSE"});}function pv(r,e){return r?uc(r,e):false}function mv(r,e,t){let n=Object.keys(r).length>0;if(!e)return null;if(!n)return Hr(t,e);for(let o in r){let i=r[o],s=dn(i.scope);if(s===e)return s}return Hr(t,e)}function Zn(r,e){r&&(r.refs.set("pointerRoutingLocked",e),r.context.set("pointerRoutingMode",e?"locked":"interactive"));}function fv(r){let e=r.context.get("highlightedValue");if(!e)return false;let t=r.refs.get("children");for(let n in t){let o=t[n];if(o.state.hasTag("open")&&dn(o.scope)===e)return true}return false}function gv(r,e){r&&(r.refs.get("pointerRoutingLocked")||e&&fv(r)||Zn(r,false));}function bv(r){r&&(fv(r)||Zn(r,false));}function ih(r,e){let{context:t,send:n,state:o,computed:i,prop:s,scope:a}=r,l=o.hasTag("open"),c=t.get("isSubmenu"),d=i("isTypingAhead"),u=s("composite"),h=t.get("currentPlacement"),p=h?cs(h):void 0,m=t.get("anchorPoint"),f=t.get("highlightedValue"),g=t.get("triggerValue"),b=Ku({...s("positioning"),placement:h});function y(C){return {id:Hr(a,C.value),disabled:!!C.disabled,highlighted:f===C.value}}function w(C){let L=C.valueText??C.value;return {...C,id:C.value,valueText:L}}function S(C){return {...y(w(C)),checked:!!C.checked}}function M(C){let{closeOnSelect:L,valueText:v,value:k}=C,x=y(C),E=Hr(a,k);return e.element({...Qe.item.attrs,id:E,role:"menuitem","aria-disabled":Su(x.disabled),"data-disabled":St(x.disabled),"data-ownedby":jn(a),"data-highlighted":St(x.highlighted),"data-value":k,"data-valuetext":v,onDragStart(I){I.currentTarget.matches("a[href]")&&I.preventDefault();},onPointerMove(I){if(x.disabled||I.pointerType!=="mouse")return;let N=I.currentTarget;if(x.highlighted)return;let V=Lo(I);n({type:"ITEM_POINTERMOVE",id:E,target:N,closeOnSelect:L,point:V});},onPointerLeave(I){if(x.disabled||I.pointerType!=="mouse"||!r.event.previous()?.type.includes("POINTER"))return;let V=I.currentTarget;n({type:"ITEM_POINTERLEAVE",id:E,target:V,closeOnSelect:L});},onPointerDown(I){if(x.disabled)return;let N=I.currentTarget;n({type:"ITEM_POINTERDOWN",target:N,id:E,closeOnSelect:L});},onClick(I){if(Au(I)||Iu(I)||x.disabled)return;let N=I.currentTarget;n({type:"ITEM_CLICK",target:N,id:E,closeOnSelect:L});}})}return {highlightedValue:f,open:l,setOpen(C){o.hasTag("open")!==C&&n({type:C?"OPEN":"CLOSE"});},triggerValue:g,setTriggerValue(C){n({type:"TRIGGER_VALUE.SET",value:C});},setHighlightedValue(C){n({type:"HIGHLIGHTED.SET",value:C});},setParent(C){n({type:"PARENT.SET",value:C,id:C.prop("id")});},setChild(C){n({type:"CHILD.SET",value:C,id:C.prop("id")});},reposition(C={}){n({type:"POSITIONING.SET",options:C});},addItemListener(C){let L=a.getById(C.id);if(!L)return;let v=()=>C.onSelect?.();return L.addEventListener(dc,v),()=>L.removeEventListener(dc,v)},getContextTriggerProps(C={}){let{value:L}=C,v=L==null?false:g===L,k=cc(a,L);return e.element({...Qe.contextTrigger.attrs,dir:s("dir"),id:k,"data-ownedby":a.id,"data-value":L,"data-current":St(v),"data-state":l?"open":"closed",onPointerDown(x){if(x.pointerType==="mouse")return;let E=Lo(x);n({type:"CONTEXT_MENU_START",point:E,value:L});},onPointerCancel(x){x.pointerType!=="mouse"&&n({type:"CONTEXT_MENU_CANCEL"});},onPointerMove(x){x.pointerType!=="mouse"&&n({type:"CONTEXT_MENU_CANCEL"});},onPointerUp(x){x.pointerType!=="mouse"&&n({type:"CONTEXT_MENU_CANCEL"});},onContextMenu(x){let E=Lo(x),I=l&&L!=null&&!v;n({type:I?"TRIGGER_VALUE.SET":"CONTEXT_MENU",point:E,value:L}),x.preventDefault();},style:{WebkitTouchCallout:"none",WebkitUserSelect:"none",userSelect:"none"}})},getTriggerItemProps(C){let L=C.getTriggerProps();return ng(M({value:L.id}),L)},getTriggerProps(C={}){let{value:L}=C,v=L==null?false:g===L,k=dn(a,L);return e.button({...c?Qe.triggerItem.attrs:Qe.trigger.attrs,"data-placement":h,"data-side":p,type:"button",dir:s("dir"),id:k,...L!=null&&{"data-ownedby":a.id,"data-value":L,"data-current":St(v)},"data-uid":s("id"),"aria-haspopup":u?"menu":"dialog","aria-controls":jn(a),"data-controls":jn(a),"aria-expanded":L==null?l:l&&v,"data-state":l?"open":"closed",onPointerMove(x){if(x.pointerType!=="mouse"||hs(x.currentTarget)||!c)return;let I=Lo(x);n({type:"TRIGGER_POINTERMOVE",target:x.currentTarget,point:I});},onPointerLeave(x){if(hs(x.currentTarget)||x.pointerType!=="mouse"||!c)return;Zn(r.refs.get("parent"),true);let E=Lo(x);n({type:"TRIGGER_POINTERLEAVE",target:x.currentTarget,point:E});},onPointerDown(x){hs(x.currentTarget)||Bl(x)||x.preventDefault();},onClick(x){if(x.defaultPrevented||hs(x.currentTarget))return;let E=l&&L!=null&&!v;n({type:E?"TRIGGER_VALUE.SET":"TRIGGER_CLICK",target:x.currentTarget,value:L});},onBlur(){n({type:"TRIGGER_BLUR"});},onFocus(){n({type:"TRIGGER_FOCUS"});},onKeyDown(x){if(x.defaultPrevented)return;let E={ArrowDown(){n({type:"ARROW_DOWN",value:L});},ArrowUp(){n({type:"ARROW_UP",value:L});},Enter(){n({type:"ARROW_DOWN",src:"enter",value:L});},Space(){n({type:"ARROW_DOWN",src:"space",value:L});}},I=Ru(x,{orientation:"vertical",dir:s("dir")}),N=E[I];N&&(x.preventDefault(),N(x));}})},getIndicatorProps(){return e.element({...Qe.indicator.attrs,dir:s("dir"),"data-state":l?"open":"closed"})},getPositionerProps(){return e.element({...Qe.positioner.attrs,dir:s("dir"),id:Xu(a),style:b.floating})},getArrowProps(){return e.element({id:ev(a),...Qe.arrow.attrs,dir:s("dir"),style:b.arrow})},getArrowTipProps(){return e.element({...Qe.arrowTip.attrs,dir:s("dir"),style:b.arrowTip})},getContentProps(){return e.element({...Qe.content.attrs,id:jn(a),"aria-label":s("aria-label"),hidden:!l,"data-state":l?"open":"closed",role:u?"menu":"dialog",tabIndex:0,dir:s("dir"),"aria-activedescendant":i("highlightedId")||void 0,"aria-labelledby":m?cc(a,g??void 0):dn(a,g??void 0),"data-placement":h,"data-side":p,onPointerEnter(C){C.pointerType==="mouse"&&n({type:"MENU_POINTERENTER"});},onKeyDown(C){if(C.defaultPrevented||!mt(C.currentTarget,He(C)))return;let L=He(C);if(!(L?.closest("[role=menu]")===C.currentTarget||L===C.currentTarget))return;if(C.key==="Tab"&&!Fg(C)){C.preventDefault();return}let k={ArrowDown(){n({type:"ARROW_DOWN"});},ArrowUp(){n({type:"ARROW_UP"});},ArrowLeft(){n({type:"ARROW_LEFT"});},ArrowRight(){n({type:"ARROW_RIGHT"});},Enter(){n({type:"ENTER"});},Space(I){d?n({type:"TYPEAHEAD",key:I.key}):k.Enter?.(I);},Home(){n({type:"HOME"});},End(){n({type:"END"});}},x=Ru(C,{dir:s("dir")}),E=k[x];if(E){E(C),C.stopPropagation(),C.preventDefault();return}s("typeahead")&&Pg(C)&&(Ag(C)||Co(L)||(n({type:"TYPEAHEAD",key:C.key}),C.preventDefault()));}})},getSeparatorProps(){return e.element({...Qe.separator.attrs,role:"separator",dir:s("dir"),"aria-orientation":"horizontal"})},getItemState:y,getItemProps:M,getOptionItemState:S,getOptionItemProps(C){let{type:L,disabled:v,closeOnSelect:k}=C,x=w(C),E=S(C);return {...M(x),...e.element({"data-type":L,...Qe.item.attrs,dir:s("dir"),"data-value":x.value,role:`menuitem${L}`,"aria-checked":!!E.checked,"data-state":E.checked?"checked":"unchecked",onClick(I){if(v||Au(I)||Iu(I))return;let N=I.currentTarget;n({type:"ITEM_CLICK",target:N,option:x,closeOnSelect:k});}})}},getItemIndicatorProps(C){let L=S(fu(C)),v=L.checked?"checked":"unchecked";return e.element({...Qe.itemIndicator.attrs,dir:s("dir"),"data-disabled":St(L.disabled),"data-highlighted":St(L.highlighted),"data-state":$i(C,"checked")?v:void 0,hidden:$i(C,"checked")?!L.checked:void 0})},getItemTextProps(C){let L=S(fu(C)),v=L.checked?"checked":"unchecked";return e.element({...Qe.itemText.attrs,dir:s("dir"),"data-disabled":St(L.disabled),"data-highlighted":St(L.highlighted),"data-state":$i(C,"checked")?v:void 0})},getItemGroupLabelProps(C){return e.element({...Qe.itemGroupLabel.attrs,id:ju(a,C.htmlFor),dir:s("dir")})},getItemGroupProps(C){return e.element({id:tv(a,C.id),...Qe.itemGroup.attrs,dir:s("dir"),"aria-labelledby":ju(a,C.id),role:"group"})}}}function vv(r){let e={each(t){for(let n=0;n{try{i.document.addEventListener(t,n,o);}catch{}}),()=>{try{e.removeEventListener(t,n,o);}catch{}}},removeEventListener(t,n,o){e.each(i=>{try{i.document.removeEventListener(t,n,o);}catch{}});}};return e}function yv(r){let e=r.frameElement!=null?r.parent:null;return {addEventListener:(t,n,o)=>{try{e?.addEventListener(t,n,o);}catch{}return ()=>{try{e?.removeEventListener(t,n,o);}catch{}}},removeEventListener:(t,n,o)=>{try{e?.removeEventListener(t,n,o);}catch{}}}}var wv="pointerdown.outside",xv="focus.outside";function TM(r){for(let e of r)if(me(e)&&Ct(e))return true;return false}var Tv=r=>"clientY"in r;function kM(r,e){if(!Tv(e)||!r)return false;let t=r.getBoundingClientRect();return t.width===0||t.height===0?false:t.top<=e.clientY&&e.clientY<=t.top+t.height&&t.left<=e.clientX&&e.clientX<=t.left+t.width}function LM(r,e){return r.y<=e.y&&e.y<=r.y+r.height&&r.x<=e.x&&e.x<=r.x+r.width}function Sv(r,e){if(!e||!Tv(r))return false;let t=e.scrollHeight>e.clientHeight,n=t&&r.clientX>e.offsetLeft+e.clientWidth,o=e.scrollWidth>e.clientWidth,i=o&&r.clientY>e.offsetTop+e.clientHeight,s={x:e.offsetLeft,y:e.offsetTop,width:e.clientWidth+(t?16:0),height:e.clientHeight+(o?16:0)},a={x:r.clientX,y:r.clientY};return LM(s,a)?n||i:false}function MM(r,e){let{exclude:t,onFocusOutside:n,onPointerDownOutside:o,onInteractOutside:i,defer:s,followControlledElements:a=true}=e;if(!r)return;let l=Oe(r),c=Ie(r),d=vv(c),u=yv(c);function h(S,M){if(!me(M)||!M.isConnected||mt(r,M)||kM(r,S)||a&&Vl(r,M))return false;let C=l.querySelector(`[aria-controls="${r.id}"]`);if(C){let v=zl(C);if(Sv(S,v))return false}let L=zl(r);return Sv(S,L)?false:!t?.(M)}let p=new Set,m=Rr(r?.getRootNode()),f=false;function g(S){f=true;let M=()=>{f=false;};l.addEventListener("pointerup",M,{once:true}),c.addEventListener("pointerup",M,{once:true});function C(L){let v=s&&!Pu()?Ve:E=>E(),k=L??S,x=k?.composedPath?.()??[k?.target];v(()=>{let E=m?x[0]:He(S);if(!(!r||!h(S,E))){if(o||i){let I=Gn(o,i);r.addEventListener(wv,I,{once:true});}Cv(r,wv,{bubbles:false,cancelable:true,detail:{originalEvent:k,contextmenu:Bl(k),focusable:TM(x),target:E}});}});}S.pointerType==="touch"?(p.forEach(L=>L()),p.add(ot(l,"click",C,{once:true})),p.add(u.addEventListener("click",C,{once:true})),p.add(d.addEventListener("click",C,{once:true}))):C();}let b=new Set,y=setTimeout(()=>{b.add(ot(l,"pointerdown",g,true)),b.add(u.addEventListener("pointerdown",g,true)),b.add(d.addEventListener("pointerdown",g,true));},0);function w(S){if(f)return;(s?Ve:C=>C())(()=>{let C=S?.composedPath?.()??[S?.target],L=m?C[0]:He(S);if(!(!r||!h(S,L))){if(n||i){let v=Gn(n,i);r.addEventListener(xv,v,{once:true});}Cv(r,xv,{bubbles:false,cancelable:true,detail:{originalEvent:S,contextmenu:false,focusable:Ct(L),target:L}});}});}return Pu()||(b.add(ot(l,"focusin",w,true)),b.add(u.addEventListener("focusin",w,true)),b.add(d.addEventListener("focusin",w,true))),()=>{clearTimeout(y),p.forEach(S=>S()),b.forEach(S=>S());}}function kv(r,e){let{defer:t}=e,n=t?Ve:i=>i(),o=[];return o.push(n(()=>{let i=typeof r=="function"?r():r;o.push(MM(i,e));})),()=>{o.forEach(i=>i?.());}}function Cv(r,e,t){let n=r.ownerDocument.defaultView||window,o=new n.CustomEvent(e,t);return r.dispatchEvent(o)}function Lv(r,e){let t=n=>{n.key==="Escape"&&(n.isComposing||e?.(n));};return ot(Oe(r),"keydown",t,{capture:true})}var Mv="layer:request-dismiss",Je={layers:[],branches:[],recentlyRemoved:new Set,count(){return this.layers.length},pointerBlockingLayers(){return this.layers.filter(r=>r.pointerBlocking)},topMostPointerBlockingLayer(){return [...this.pointerBlockingLayers()].slice(-1)[0]},hasPointerBlockingLayer(){return this.pointerBlockingLayers().length>0},isBelowPointerBlockingLayer(r){let e=this.indexOf(r),t=this.topMostPointerBlockingLayer()?this.indexOf(this.topMostPointerBlockingLayer()?.node):-1;return ee.type===r)},getNestedLayersByType(r,e){let t=this.indexOf(r);return t===-1?[]:this.layers.slice(t+1).filter(n=>n.type===e)},getParentLayerOfType(r,e){let t=this.indexOf(r);if(!(t<=0))return this.layers.slice(0,t).reverse().find(n=>n.type===e)},countNestedLayersOfType(r,e){return this.getNestedLayersByType(r,e).length},isInNestedLayer(r,e){return !!(this.getNestedLayers(r).some(n=>mt(n.node,e))||this.recentlyRemoved.size>0)},isInBranch(r){return Array.from(this.branches).some(e=>mt(e,r))},add(r){let e=this.indexOf(r.node);e!==-1&&this.layers.splice(e,1),this.layers.push(r),this.syncLayers();},addBranch(r){this.branches.push(r);},remove(r){let e=this.indexOf(r);if(e<0)return;this.layers[e].styleTargets?.forEach(n=>{let o=n();o&&EM(o);}),this.recentlyRemoved.add(r),Bg(()=>this.recentlyRemoved.delete(r)),eJe.dismiss(o.node,r)),this.layers.splice(e,1),this.syncLayers();},removeBranch(r){let e=this.branches.indexOf(r);e>=0&&this.branches.splice(e,1);},syncLayers(){this.layers.forEach((r,e)=>{Ev(r,e,r.node),r.styleTargets?.forEach(t=>{let n=t();if(!n||n===r.node)return;Ev(r,e,n);let{zIndex:o}=To(r.node);n.style.setProperty("--z-index",o);});});},indexOf(r){return this.layers.findIndex(e=>e.node===r)},dismiss(r,e){let t=this.indexOf(r);if(t===-1)return;let n=this.layers[t];IM(r,Mv,o=>{n.requestDismiss?.(o),o.defaultPrevented||n?.dismiss();}),PM(r,Mv,{originalLayer:r,targetLayer:e,originalIndex:t,targetIndex:e?this.indexOf(e):-1}),this.syncLayers();},clear(){this.remove(this.layers[0].node);}};function Ev(r,e,t){t.style.setProperty("--layer-index",`${e}`),t.removeAttribute("data-nested"),t.removeAttribute("data-has-nested"),Je.getParentLayerOfType(r.node,r.type)&&t.setAttribute("data-nested",r.type);let o=Je.countNestedLayersOfType(r.node,r.type);o>0&&t.setAttribute("data-has-nested",r.type),t.style.setProperty("--nested-layer-count",`${o}`);}function EM(r){r.style.removeProperty("--layer-index"),r.style.removeProperty("--nested-layer-count"),r.style.removeProperty("--z-index"),r.removeAttribute("data-nested"),r.removeAttribute("data-has-nested");}function PM(r,e,t){let n=r.ownerDocument.defaultView||window,o=new n.CustomEvent(e,{cancelable:true,bubbles:true,detail:t});return r.dispatchEvent(o)}function IM(r,e,t){r.addEventListener(e,t,{once:true});}var sh=new WeakMap,ms=new WeakMap;function AM(r){return Je.isBelowPointerBlockingLayer(r)?"none":"auto"}function Pv(r){let e=AM(r);r.style.pointerEvents!==e&&(r.style.pointerEvents=e);}function RM(r){if(ms.has(r))return;let e=Ie(r);if(typeof e.MutationObserver>"u")return;let t=new e.MutationObserver(()=>{ms.has(r)&&Pv(r);});t.observe(r,{attributes:true,attributeFilter:["style"]}),ms.set(r,t);}function ah(){Je.layers.forEach(({node:r})=>{Pv(r),RM(r);});}function Iv(r){let e=ms.get(r);e&&(e.disconnect(),ms.delete(r)),r.style.pointerEvents="";}function Av(r,e){let t=Oe(r),n=[];return Je.hasPointerBlockingLayer()&&!t.body.hasAttribute("data-inert")&&(sh.set(t.body,t.body.style.pointerEvents),queueMicrotask(()=>{let o=t.body;o&&(o.style.pointerEvents="none",o.setAttribute("data-inert",""));})),e?.forEach(o=>{let[i,s]=Yg(()=>{let a=o();return me(a)?a:null},{timeout:1e3});i.then(a=>n.push(Ji(a,{pointerEvents:"auto"}))),n.push(s);}),()=>{Je.hasPointerBlockingLayer()||(queueMicrotask(()=>{let o=t.body;if(!o)return;let i=sh.get(o);i!==void 0&&(o.style.pointerEvents=i,sh.delete(o)),o.removeAttribute("data-inert"),o.style.length===0&&o.removeAttribute("style");}),n.forEach(o=>o()));}}function DM(r,e){let{warnOnMissingNode:t=true}=e;if(t&&!r){wo("[@zag-js/dismissable] node is `null` or `undefined`");return}if(!r)return;let{onDismiss:n,onRequestDismiss:o,pointerBlocking:i,exclude:s,debug:a,type:l="dialog",layerStyleTargets:c}=e,d={dismiss:n,node:r,type:l,pointerBlocking:i,requestDismiss:o,styleTargets:c};Je.add(d),ah();function u(g){let b=He(g.detail.originalEvent);Je.isBelowPointerBlockingLayer(r)||Je.isInBranch(b)||(e.onPointerDownOutside?.(g),e.onInteractOutside?.(g),!g.defaultPrevented&&(a&&console.log("onPointerDownOutside:",g.detail.originalEvent),n?.()));}function h(g){let b=He(g.detail.originalEvent);Je.isInBranch(b)||(e.onFocusOutside?.(g),e.onInteractOutside?.(g),!g.defaultPrevented&&(a&&console.log("onFocusOutside:",g.detail.originalEvent),n?.()));}function p(g){Je.isTopMost(r)&&(e.onEscapeKeyDown?.(g),!g.defaultPrevented&&n&&(g.preventDefault(),n()));}function m(g){if(!r)return false;let b=typeof s=="function"?s():s,y=Array.isArray(b)?b:[b],w=e.persistentElements?.map(S=>S()).filter(me);return w&&y.push(...w),y.some(S=>mt(S,g))||Je.isInNestedLayer(r,g)}let f=[i?Av(r,e.persistentElements):void 0,Lv(r,p),kv(r,{exclude:m,onFocusOutside:h,onPointerDownOutside:u,defer:e.defer})];return ()=>{Je.remove(r),ah(),Iv(r),f.forEach(g=>g?.());}}function hc(r,e){let{defer:t}=e,n=t?Ve:i=>i(),o=[];return o.push(n(()=>{let i=pt(r)?r():r;o.push(DM(i,e));})),()=>{o.forEach(i=>i?.());}}function OM(r){return !(r.metaKey||!ko()&&r.altKey||r.ctrlKey||r.key==="Control"||r.key==="Shift"||r.key==="Meta")}var NM=new Set(["checkbox","radio","range","color","file","image","button","submit","reset"]);function FM(r,e,t){let n=t?He(t):null,o=Oe(n),i=Ie(n),s=rn(o);return r=r||s instanceof i.HTMLInputElement&&!NM.has(s?.type)||s instanceof i.HTMLTextAreaElement||s instanceof i.HTMLElement&&s.isContentEditable,!(r&&e==="keyboard"&&t instanceof i.KeyboardEvent&&!Reflect.has(VM,t.key))}var Ln=null,lh=new Set,pc=new Map,zr=false,ch=false,Dv=false,VM={Tab:true,Escape:true};function fc(r,e){for(let t of lh)t(r,e);}function mc(r){zr=true,OM(r)&&(Ln="keyboard",fc("keyboard",r));}function Tt(r){Ln="pointer",(r.type==="mousedown"||r.type==="pointerdown")&&(zr=true,fc("pointer",r));}function Ov(r){Ig(r)&&(zr=true,Ln="virtual");}function Nv(r){let e=He(r);e===Ie(e)||e===Oe(e)||Dv||!r.isTrusted||(!zr&&!ch&&(Ln="virtual",fc("virtual",r)),zr=false,ch=false);}function Fv(){(zr=false,ch=true);}function BM(r){if(typeof window>"u"||pc.get(Ie(r)))return;let e=Ie(r),t=Oe(r),n=e.HTMLElement.prototype.focus;function o(){zr=true,n.apply(this,arguments);}try{Object.defineProperty(e.HTMLElement.prototype,"focus",{configurable:!0,value:o});}catch{}t.addEventListener("keydown",mc,true),t.addEventListener("keyup",mc,true),t.addEventListener("click",Ov,true),e.addEventListener("focus",Nv,true),e.addEventListener("blur",Fv,false),typeof e.PointerEvent<"u"?(t.addEventListener("pointerdown",Tt,true),t.addEventListener("pointermove",Tt,true),t.addEventListener("pointerup",Tt,true)):(t.addEventListener("mousedown",Tt,true),t.addEventListener("mousemove",Tt,true),t.addEventListener("mouseup",Tt,true)),e.addEventListener("beforeunload",()=>{_M(r);},{once:true}),pc.set(e,{focus:n});}var _M=(r,e)=>{let t=Ie(r),n=Oe(r);let o=pc.get(t);if(o){try{Object.defineProperty(t.HTMLElement.prototype,"focus",{configurable:!0,value:o.focus});}catch{}n.removeEventListener("keydown",mc,true),n.removeEventListener("keyup",mc,true),n.removeEventListener("click",Ov,true),t.removeEventListener("focus",Nv,true),t.removeEventListener("blur",Fv,false),typeof t.PointerEvent<"u"?(n.removeEventListener("pointerdown",Tt,true),n.removeEventListener("pointermove",Tt,true),n.removeEventListener("pointerup",Tt,true)):(n.removeEventListener("mousedown",Tt,true),n.removeEventListener("mousemove",Tt,true),n.removeEventListener("mouseup",Tt,true)),pc.delete(t);}};function Vv(){return Ln}function Bv(r){Ln=r,fc(r,null);}function Rv(){return Ln==="keyboard"||Ln==="virtual"}function _v(r={}){let{isTextInput:e,autoFocus:t,onChange:n,root:o}=r;BM(o),n?.({isFocusVisible:t||Rv(),modality:Ln});let i=(s,a)=>{FM(!!e,s,a)&&n?.({isFocusVisible:Rv(),modality:s});};return lh.add(i),()=>{lh.delete(i);}}var{not:kt,and:Vo,or:HM}=hg(),dh=Ol({props({props:r}){return {closeOnSelect:true,typeahead:true,composite:true,loopFocus:false,navigate(e){zg(e.node);},...r,positioning:{placement:"bottom-start",gutter:8,...r.positioning}}},initialState({prop:r}){return r("open")||r("defaultOpen")?"open":"idle"},context({bindable:r,prop:e,scope:t}){return {highlightedValue:r(()=>({defaultValue:e("defaultHighlightedValue")||null,value:e("highlightedValue"),onChange(n){e("onHighlightChange")?.({highlightedValue:n});}})),lastHighlightedValue:r(()=>({defaultValue:null})),currentPlacement:r(()=>({defaultValue:void 0})),intentPolygon:r(()=>({defaultValue:null})),anchorPoint:r(()=>({defaultValue:null,hash(n){return `x: ${n?.x}, y: ${n?.y}`}})),isSubmenu:r(()=>({defaultValue:false})),triggerValue:r(()=>({defaultValue:e("defaultTriggerValue")??null,value:e("triggerValue"),onChange(n){let o=e("onTriggerValueChange");if(!o)return;let i=ds(t,n);o({value:n,triggerElement:i});}})),pointerRoutingMode:r(()=>({defaultValue:"interactive"}))}},refs(){return {parent:null,children:{},pointerRoutingLocked:false,typeaheadState:{...Gl.defaultOptions},positioningOverride:{}}},computed:{isRtl:({prop:r})=>r("dir")==="rtl",isTypingAhead:({refs:r})=>r.get("typeaheadState").keysSoFar!=="",highlightedId:({context:r,scope:e,refs:t})=>mv(t.get("children"),r.get("highlightedValue"),e)},watch({track:r,action:e,context:t,prop:n}){r([()=>t.get("isSubmenu")],()=>{e(["setSubmenuPlacement"]);}),r([()=>t.hash("anchorPoint")],()=>{t.get("anchorPoint")&&e(["reposition"]);}),r([()=>n("open")],()=>{e(["toggleVisibility"]);});},on:{"TRIGGER_VALUE.SET":{actions:["setTriggerValue","setAnchorPoint","reposition","focusMenu"]},"PARENT.SET":{actions:["setParentMenu"]},"CHILD.SET":{actions:["setChildMenu"]},OPEN:[{guard:"isOpenControlled",actions:["setTriggerValue","invokeOnOpen"]},{target:"open",actions:["setTriggerValue","invokeOnOpen"]}],OPEN_AUTOFOCUS:[{guard:"isOpenControlled",actions:["setTriggerValue","invokeOnOpen"]},{target:"open",actions:["setTriggerValue","highlightFirstItem","invokeOnOpen"]}],CLOSE:[{guard:"isOpenControlled",actions:["invokeOnClose","releaseParentRoutingLock"]},{target:"closed",actions:["invokeOnClose","releaseParentRoutingLock","focusTrigger"]}],"HIGHLIGHTED.RESTORE":{actions:["restoreHighlightedItem"]},"HIGHLIGHTED.SET":{actions:["setHighlightedItem"]},"HIGHLIGHTED.SUGGEST":{actions:["suggestHighlightedItem"]}},states:{idle:{tags:["closed"],on:{"CONTROLLED.OPEN":{target:"open"},"CONTROLLED.CLOSE":{target:"closed"},CONTEXT_MENU_START:{target:"opening:contextmenu",actions:["setAnchorPoint","setTriggerValue"]},CONTEXT_MENU:[{guard:"isOpenControlled",actions:["setAnchorPoint","setTriggerValue","invokeOnOpen"]},{target:"open",actions:["setAnchorPoint","setTriggerValue","invokeOnOpen"]}],TRIGGER_CLICK:[{guard:"isOpenControlled",actions:["invokeOnOpen","setTriggerValue"]},{target:"open",actions:["invokeOnOpen","setTriggerValue"]}],TRIGGER_FOCUS:{guard:kt("isSubmenu"),target:"closed"},TRIGGER_POINTERMOVE:{guard:"isSubmenu",target:"opening"}}},"opening:contextmenu":{tags:["closed"],effects:["waitForLongPress"],on:{"CONTROLLED.OPEN":{target:"open",actions:["reposition"]},"CONTROLLED.CLOSE":{target:"closed",actions:["focusTrigger"]},CONTEXT_MENU_CANCEL:[{guard:"isOpenControlled",actions:["invokeOnClose","releaseParentRoutingLock"]},{target:"closed",actions:["invokeOnClose","releaseParentRoutingLock","focusTrigger"]}],"LONG_PRESS.OPEN":[{guard:"isOpenControlled",actions:["setTriggerValue","invokeOnOpen"]},{target:"open",actions:["setTriggerValue","invokeOnOpen","reposition"]}]}},opening:{tags:["closed"],effects:["waitForOpenDelay"],on:{"CONTROLLED.OPEN":{target:"open"},"CONTROLLED.CLOSE":{target:"closed",actions:["focusTrigger"]},BLUR:[{guard:"isOpenControlled",actions:["invokeOnClose","releaseParentRoutingLock"]},{target:"closed",actions:["invokeOnClose","releaseParentRoutingLock","focusTrigger"]}],TRIGGER_POINTERLEAVE:[{guard:"isOpenControlled",actions:["invokeOnClose","releaseParentRoutingLock"]},{target:"closed",actions:["invokeOnClose","releaseParentRoutingLock","focusTrigger"]}],"DELAY.OPEN":[{guard:"isOpenControlled",actions:["invokeOnOpen"]},{target:"open",actions:["invokeOnOpen"]}]}},closing:{tags:["open"],effects:["trackPointerMove","trackInteractOutside","waitForCloseDelay"],on:{"CONTROLLED.OPEN":{target:"open"},"CONTROLLED.CLOSE":{target:"closed",actions:["focusParentMenu","restoreParentHighlightedItem"]},MENU_POINTERENTER:{target:"open",actions:["clearIntentPolygon"]},POINTER_MOVED_AWAY_FROM_SUBMENU:[{guard:"isOpenControlled",actions:["invokeOnClose","releaseParentRoutingLock"]},{target:"closed",actions:["focusParentMenu","restoreParentHighlightedItem"]}],"DELAY.CLOSE":[{guard:"isOpenControlled",actions:["invokeOnClose","releaseParentRoutingLock"]},{target:"closed",actions:["focusParentMenu","restoreParentHighlightedItem","invokeOnClose","releaseParentRoutingLock"]}]}},closed:{tags:["closed"],entry:["clearHighlightedItem","unlockParentOnClose","clearAnchorPoint"],on:{"CONTROLLED.OPEN":[{guard:HM("isOpenAutoFocusEvent","isArrowDownEvent"),target:"open",actions:["highlightFirstItem"]},{guard:"isArrowUpEvent",target:"open",actions:["highlightLastItem"]},{target:"open"}],CONTEXT_MENU_START:{target:"opening:contextmenu",actions:["setAnchorPoint","setTriggerValue"]},CONTEXT_MENU:[{guard:"isOpenControlled",actions:["setAnchorPoint","setTriggerValue","invokeOnOpen"]},{target:"open",actions:["setAnchorPoint","setTriggerValue","invokeOnOpen"]}],TRIGGER_CLICK:[{guard:"isOpenControlled",actions:["invokeOnOpen","setTriggerValue"]},{target:"open",actions:["invokeOnOpen","setTriggerValue"]}],TRIGGER_POINTERMOVE:{guard:"isTriggerItem",target:"opening"},TRIGGER_BLUR:{target:"idle"},ARROW_DOWN:[{guard:"isOpenControlled",actions:["setTriggerValue","invokeOnOpen"]},{target:"open",actions:["setTriggerValue","highlightFirstItem","invokeOnOpen"]}],ARROW_UP:[{guard:"isOpenControlled",actions:["setTriggerValue","invokeOnOpen"]},{target:"open",actions:["setTriggerValue","highlightLastItem","invokeOnOpen"]}]}},open:{tags:["open"],effects:["trackInteractOutside","trackFocusVisible","trackPositioning","scrollToHighlightedItem"],entry:["focusMenu","unlockParentOnOpen"],on:{"CONTROLLED.CLOSE":[{target:"closed",guard:"isArrowLeftEvent",actions:["focusParentMenu"]},{target:"closed",actions:["focusTrigger"]}],TRIGGER_CLICK:[{guard:Vo(kt("isTriggerItem"),"isOpenControlled"),actions:["invokeOnClose","releaseParentRoutingLock"]},{guard:kt("isTriggerItem"),target:"closed",actions:["invokeOnClose","releaseParentRoutingLock","focusTrigger"]}],CONTEXT_MENU:{actions:["setAnchorPoint","setTriggerValue","focusMenu"]},ARROW_UP:{actions:["highlightPrevItem","focusMenu"]},ARROW_DOWN:{actions:["highlightNextItem","focusMenu"]},ARROW_LEFT:[{guard:Vo("isSubmenu","isOpenControlled"),actions:["invokeOnClose","releaseParentRoutingLock"]},{guard:"isSubmenu",target:"closed",actions:["focusParentMenu","invokeOnClose","releaseParentRoutingLock"]}],HOME:{actions:["highlightFirstItem","focusMenu"]},END:{actions:["highlightLastItem","focusMenu"]},ARROW_RIGHT:{guard:"isTriggerItemHighlighted",actions:["openSubmenu"]},ENTER:[{guard:"isTriggerItemHighlighted",actions:["openSubmenu"]},{actions:["clickHighlightedItem"]}],ITEM_POINTERMOVE:[{guard:kt("isPointerRoutingLocked"),actions:["setHighlightedItem","focusMenu","closeSiblingMenus"]},{actions:["setLastHighlightedItem","closeSiblingMenus"]}],ITEM_POINTERLEAVE:{guard:Vo(kt("isPointerRoutingLocked"),kt("isTriggerItem")),actions:["clearHighlightedItem"]},ITEM_CLICK:[{guard:Vo(kt("isTriggerItemHighlighted"),kt("isHighlightedItemEditable"),"closeOnSelect","isOpenControlled"),actions:["invokeOnSelect","setOptionState","closeRootMenu","invokeOnClose","releaseParentRoutingLock"]},{guard:Vo(kt("isTriggerItemHighlighted"),kt("isHighlightedItemEditable"),"closeOnSelect"),target:"closed",actions:["invokeOnSelect","setOptionState","closeRootMenu","invokeOnClose","releaseParentRoutingLock","focusTrigger"]},{guard:Vo(kt("isTriggerItemHighlighted"),kt("isHighlightedItemEditable")),actions:["invokeOnSelect","setOptionState"]},{actions:["setHighlightedItem"]}],TRIGGER_POINTERMOVE:{guard:"isTriggerItem",actions:["setIntentPolygon"]},TRIGGER_POINTERLEAVE:{target:"closing",actions:["setIntentPolygon"]},ITEM_POINTERDOWN:{actions:["setHighlightedItem"]},TYPEAHEAD:{actions:["highlightMatchedItem"]},FOCUS_MENU:{actions:["focusMenu"]},"POSITIONING.SET":{actions:["reposition"]}}}},implementations:{guards:{closeOnSelect:({prop:r,event:e})=>!!(e?.closeOnSelect??r("closeOnSelect")),isTriggerItem:({event:r})=>th(r.target),isTriggerItemHighlighted:({event:r,scope:e,computed:t})=>!!(r.target??e.getById(t("highlightedId")))?.hasAttribute("data-controls"),isSubmenu:({context:r})=>r.get("isSubmenu"),isPointerRoutingLocked:({refs:r})=>r.get("pointerRoutingLocked"),isHighlightedItemEditable:({scope:r,computed:e})=>Co(r.getById(e("highlightedId"))),isOpenControlled:({prop:r})=>r("open")!==void 0,isArrowLeftEvent:({event:r})=>r.previousEvent?.type==="ARROW_LEFT",isArrowUpEvent:({event:r})=>r.previousEvent?.type==="ARROW_UP",isArrowDownEvent:({event:r})=>r.previousEvent?.type==="ARROW_DOWN",isOpenAutoFocusEvent:({event:r})=>r.previousEvent?.type==="OPEN_AUTOFOCUS"},effects:{waitForOpenDelay({send:r}){let e=setTimeout(()=>{r({type:"DELAY.OPEN"});},200);return ()=>clearTimeout(e)},waitForCloseDelay({send:r}){let e=setTimeout(()=>{r({type:"DELAY.CLOSE"});},100);return ()=>clearTimeout(e)},waitForLongPress({send:r}){let e=setTimeout(()=>{r({type:"LONG_PRESS.OPEN"});},700);return ()=>clearTimeout(e)},trackFocusVisible({scope:r}){return _v({root:r.getRootNode?.()})},trackPositioning({context:r,prop:e,scope:t,refs:n}){if(rv(t)||Ju(t).length>0)return;let i={...e("positioning"),...n.get("positioningOverride")};return r.set("currentPlacement",i.placement),lc(()=>ds(t,r.get("triggerValue")),()=>qu(t),{...i,defer:true,onComplete(l){r.set("currentPlacement",l.placement);}})},trackInteractOutside({refs:r,scope:e,prop:t,context:n,send:o}){let i=()=>Wt(e),s=true,a=l=>Ju(e).some(c=>mt(c,l));return hc(i,{type:"menu",defer:true,exclude:[Zu(e),...Qu(e)].filter(Boolean),onInteractOutside:t("onInteractOutside"),onRequestDismiss:t("onRequestDismiss"),onFocusOutside(l){t("onFocusOutside")?.(l);let c=He(l.detail.originalEvent);if(a(c)){l.preventDefault();return}if(nh(c,r.get("children"))){l.preventDefault();return}},onEscapeKeyDown(l){t("onEscapeKeyDown")?.(l),n.get("isSubmenu")&&l.preventDefault(),oh({parent:r.get("parent")});},onPointerDownOutside(l){t("onPointerDownOutside")?.(l);let c=He(l.detail.originalEvent);if(a(c)&&l.detail.contextmenu){l.preventDefault();return}s=!l.detail.focusable;},onDismiss(){o({type:"CLOSE",src:"interact-outside",restoreFocus:s});}})},trackPointerMove({context:r,scope:e,send:t,refs:n}){let o=n.get("parent");if(!o)return;Zn(o,true);let i=e.getDoc();return ot(i,"pointermove",s=>{pv(r.get("intentPolygon"),{x:s.clientX,y:s.clientY})||(t({type:"POINTER_MOVED_AWAY_FROM_SUBMENU"}),Zn(o,false));})},scrollToHighlightedItem({scope:r,computed:e}){let t=()=>{if(Vv()==="pointer")return;let i=r.getById(e("highlightedId")),s=Wt(r);Gg(i,{rootEl:s,block:"nearest"});};return Ve(()=>{Bv("virtual"),t();}),Hg(()=>Wt(r),{attributes:["aria-activedescendant"],callback:t})}},actions:{setAnchorPoint({context:r,event:e}){r.set("anchorPoint",t=>vo(t,e.point)?t:e.point);},setSubmenuPlacement({context:r,computed:e,refs:t}){if(!r.get("isSubmenu"))return;let n=e("isRtl")?"left-start":"right-start";t.set("positioningOverride",{placement:n,gutter:0});},reposition({context:r,scope:e,prop:t,event:n,refs:o}){let i=()=>qu(e),s=n.point??r.get("anchorPoint"),a=s?()=>({width:0,height:0,...s}):void 0,l={...t("positioning"),...o.get("positioningOverride")},c=n.value??r.get("triggerValue");lc(()=>ds(e,c),i,{...l,defer:true,getAnchorRect:a,...n.options??{},listeners:false,onComplete(u){r.set("currentPlacement",u.placement);}});},setOptionState({event:r}){if(!r.option)return;let{checked:e,onCheckedChange:t,type:n}=r.option;n==="radio"?t?.(true):n==="checkbox"&&t?.(!e);},clickHighlightedItem({scope:r,computed:e,prop:t,context:n}){let o=r.getById(e("highlightedId"));if(!o||o.dataset.disabled)return;let i=n.get("highlightedValue");bg(o)?t("navigate")?.({value:i,node:o,href:o.href}):queueMicrotask(()=>o.click());},setIntentPolygon({context:r,scope:e,event:t}){let n=Wt(e),o=r.get("currentPlacement");if(!n||!o)return;let i=n.getBoundingClientRect(),s=hv(i,o);if(!s)return;let l=cs(o)==="right"?-5:5;r.set("intentPolygon",[{...t.point,x:t.point.x+l},...s]);},clearIntentPolygon({context:r}){r.set("intentPolygon",null);},clearAnchorPoint({context:r}){r.set("anchorPoint",null);},unlockParentOnOpen({refs:r,context:e,scope:t}){let n=r.get("parent");if(e.get("isSubmenu")){let o=dn(t);n?.send({type:"HIGHLIGHTED.SUGGEST",value:o});}Zn(n,false);},unlockParentOnClose({refs:r,context:e}){gv(r.get("parent"),e.get("isSubmenu"));},setHighlightedItem({context:r,event:e}){let t=e.value||qn(e.target);r.set("highlightedValue",t);},clearHighlightedItem({context:r}){r.set("highlightedValue",null);},focusMenu({scope:r}){Ve(()=>{let e=Wt(r);Hl({root:e,enabled:!mt(e,r.getActiveElement()),filter(n){return !n.role?.startsWith("menuitem")}})?.focus({preventScroll:true});});},highlightFirstItem({context:r,scope:e}){(Wt(e)?queueMicrotask:Ve)(()=>{let n=ov(e);n&&r.set("highlightedValue",qn(n));});},highlightLastItem({context:r,scope:e}){(Wt(e)?queueMicrotask:Ve)(()=>{let n=iv(e);n&&r.set("highlightedValue",qn(n));});},highlightNextItem({context:r,scope:e,event:t,prop:n}){let o=sv(e,{loop:t.loop,value:r.get("highlightedValue"),loopFocus:n("loopFocus")});r.set("highlightedValue",qn(o));},highlightPrevItem({context:r,scope:e,event:t,prop:n}){let o=av(e,{loop:t.loop,value:r.get("highlightedValue"),loopFocus:n("loopFocus")});r.set("highlightedValue",qn(o));},invokeOnSelect({context:r,prop:e,scope:t}){let n=r.get("highlightedValue");if(n==null)return;let o=nv(t,n);cv(o,n),e("onSelect")?.({value:n});},focusTrigger({scope:r,context:e,event:t}){e.get("isSubmenu")||e.get("anchorPoint")||t.restoreFocus===false||queueMicrotask(()=>{ds(r,e.get("triggerValue"))?.focus({preventScroll:true});});},highlightMatchedItem({scope:r,context:e,event:t,refs:n}){let o=lv(r,{key:t.key,value:e.get("highlightedValue"),typeaheadState:n.get("typeaheadState")});o&&e.set("highlightedValue",qn(o));},setParentMenu({refs:r,event:e,context:t}){r.set("parent",e.value),t.set("isSubmenu",true);},setChildMenu({refs:r,event:e}){let t=r.get("children");t[e.id]=e.value,r.set("children",t);},closeSiblingMenus({refs:r,event:e,scope:t}){let n=e.target;if(!th(n))return;let o=n?.getAttribute("data-uid"),i=r.get("children");for(let s in i){if(s===o)continue;let a=i[s],l=a.context.get("intentPolygon");l&&e.point&&uc(l,e.point)||(Wt(t)?.focus({preventScroll:true}),a.send({type:"CLOSE"}));}},closeRootMenu({refs:r}){oh({parent:r.get("parent")});},openSubmenu({refs:r,scope:e,computed:t}){let o=e.getById(t("highlightedId"))?.getAttribute("data-uid"),i=r.get("children");(o?i[o]:null)?.send({type:"OPEN_AUTOFOCUS"});},focusParentMenu({refs:r}){r.get("parent")?.send({type:"FOCUS_MENU"});},setLastHighlightedItem({context:r,event:e}){r.set("lastHighlightedValue",qn(e.target));},suggestHighlightedItem({context:r,event:e}){let t=e.value;if(t){if(r.get("highlightedValue")!=null){r.set("lastHighlightedValue",t);return}r.set("highlightedValue",t);}},restoreHighlightedItem({context:r}){let e=r.get("lastHighlightedValue");r.set("lastHighlightedValue",null),e&&r.set("highlightedValue",e);},restoreParentHighlightedItem({refs:r}){r.get("parent")?.send({type:"HIGHLIGHTED.RESTORE"});},invokeOnOpen({prop:r}){r("onOpenChange")?.({open:true});},invokeOnClose({prop:r}){r("onOpenChange")?.({open:false});},releaseParentRoutingLock({refs:r,context:e}){e.get("isSubmenu")&&bv(r.get("parent"));},toggleVisibility({prop:r,event:e,send:t}){t({type:r("open")?"CONTROLLED.OPEN":"CONTROLLED.CLOSE",previousEvent:e});},setTriggerValue({context:r,event:e}){e.value!==void 0&&r.set("triggerValue",e.value);}}}});function Hv(r){return {machine:dh,props:{id:r.id??ql("vela-menu"),ids:r.triggerId?{trigger:r.triggerId}:void 0,positioning:{placement:r.placement??"bottom-start",...r.getAnchorRect?{getAnchorRect:()=>r.getAnchorRect()}:{}},onSelect:e=>r.onSelect?.(e.value),onOpenChange:e=>r.onOpenChange?.(e.open)},connect:e=>ih(e,Io)}}var zv="vela-ui-menu",Wv=` .vela-menu { /* The list is a
    : without this, block rows (the separator) paint a ::marker dot. */ list-style: none; @@ -83,6 +83,35 @@ ${CL} color: var(--vela-fg-bright); } .vela-menu-item[data-checkmark] { color: var(--vela-fg-bright); } +/* Badge mode (iconBadges): the row icon sits in a rounded tile and the row grows to fit + it. An icon-less row of the same level keeps an invisible slot, so labels align. */ +.vela-menu[data-badges] > .vela-menu-item { padding: 5px 10px 5px 6px; } +.vela-menu-item .vela-menu-badge { + width: 24px; + height: 24px; + padding: 3px; + flex: none; + box-sizing: border-box; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: var(--vela-radius-md); + background: var(--vela-hover); + border: 1px solid var(--vela-border); + color: var(--vela-fg-muted); + transition: background var(--vela-dur-fast) var(--vela-ease), border-color var(--vela-dur-fast) var(--vela-ease), color var(--vela-dur-fast) var(--vela-ease); +} +.vela-menu-item .vela-menu-badge:empty { background: transparent; border-color: transparent; } +.vela-menu-item .vela-menu-badge .vela-icon { color: inherit; } +.vela-menu-item[data-highlighted] .vela-menu-badge:not(:empty) { color: var(--vela-fg-bright); } +/* The selected tile inverts: a bright fill under the surface-colored glyph. After the + hover rule, so a selected row keeps its tile while highlighted. */ +.vela-menu-item[data-checked] .vela-menu-badge:not(:empty), +.vela-menu-item[data-checkmark] .vela-menu-badge:not(:empty) { + background: color-mix(in srgb, var(--vela-fg-bright) 83%, var(--vela-surface)); + border-color: color-mix(in srgb, var(--vela-fg-bright) 40%, transparent); + color: var(--vela-surface); +} /* Switch rows (boolean settings in a dropdown): a right-aligned toggle pill \u2014 the same control language as the settings dialog's toggles. */ .vela-menu-switch { @@ -138,7 +167,7 @@ ${CL} color: var(--vela-fg-faint); } .vela-menu-item[data-state='open'] { background: var(--vela-hover); } -`;var ah=class r{constructor(e,t){this.items=[];this.subs=new Map;this.pinnedAnchor=null;this.doc=e,this.host=t.host,this.onSelect=t.onSelect,this.onFavorite=t.onFavorite,this.checkmarks=t.checkmarks===true,this.positioner=e.createElement("div"),this.positioner.className="vela-ui-layer",this.list=e.createElement("ul"),this.list.className="vela-menu",t.minWidth&&(this.list.style.minWidth=t.minWidth),this.positioner.appendChild(this.list),this.host.appendChild(this.positioner);let n=t.trigger;this.ctrl=Dv({items:[],id:t.id,placement:t.placement,onSelect:o=>this.onSelect(o),getAnchorRect:()=>this.pinnedAnchor,onOpenChange:o=>{if(o&&n){let i=n.getBoundingClientRect();this.pinnedAnchor={x:i.x,y:i.y,width:i.width,height:i.height};}else this.pinnedAnchor=null;t.onOpenChange?.(o);},triggerId:t.triggerId}),this.mid=String(this.ctrl.props.id),t.triggerId&&n&&(n.id=t.triggerId),this.handle=Yl(this.ctrl.machine,this.ctrl.props,o=>{let i=this.ctrl.connect(o);n&&ft(n,i.getTriggerProps(),this.mid),ft(this.positioner,i.getPositionerProps(),this.mid),ft(this.list,i.getContentProps(),this.mid),this.project(i);});}get api(){return this.ctrl.connect(this.handle.service)}setItems(e){this.items=e;for(let n of this.subs.values())n.destroy();this.subs.clear(),this.build();let t=this.api;for(let n of this.subs.values())t.setChild(n.handle.service),n.api.setParent(this.handle.service);this.handle.flush(),this.subs.size>0&&queueMicrotask(()=>this.handle.flush());}destroy(){for(let e of this.subs.values())e.destroy();this.subs.clear(),this.handle.stop(),this.positioner.remove();}byId(e){return this.items.find(t=>t.id===e)}project(e){for(let t of this.list.children){let n=t.dataset.veiId;if(!n)continue;let o=this.subs.get(n);if(o){ft(t,e.getTriggerItemProps(o.api),this.mid);continue}let i=this.byId(n);ft(t,e.getItemProps({value:n,disabled:i?.disabled,closeOnSelect:i?.toggle?false:void 0}),this.mid);}}build(){let e=this.doc;this.list.replaceChildren();let t=this.checkmarks&&this.items.some(n=>!(n.submenu&&n.submenu.length>0)&&!n.toggle&&n.checked!==void 0);for(let n of this.items){if(n.separatorBefore){let a=e.createElement("li");a.className="vela-menu-sep",a.setAttribute("role","separator"),this.list.appendChild(a);}let o=n.submenu!==void 0&&n.submenu.length>0,i=e.createElement("li");if(i.className="vela-menu-item",i.dataset.veiId=n.id,n.toggle&&(i.dataset.toggle="1"),t){let a=e.createElement("span");a.className="vela-menu-mark",!o&&!n.toggle&&n.checked&&(a.appendChild(Ue("check",e)),i.dataset.checkmark="1"),i.appendChild(a);}else !o&&!n.toggle&&n.checked&&(i.dataset.checked="1");n.icon&&i.appendChild(Ue(n.icon,e));let s=e.createElement("span");if(s.className="vela-menu-label",s.textContent=n.label,i.appendChild(s),n.hint){let a=e.createElement("span");a.className="vela-menu-hint",a.textContent=n.hint,i.appendChild(a);}if(n.favorite!==void 0&&this.onFavorite){let a=n.favorite,l=Ue(a?"star-filled":"star",e);l.classList.add("vela-menu-star"),a&&l.classList.add("vela-fav"),l.removeAttribute("aria-hidden"),l.setAttribute("role","button"),l.setAttribute("aria-label",a?"Remove from favorites":"Add to favorites"),l.setAttribute("aria-pressed",a?"true":"false");for(let c of ["pointerdown","pointerup","mousedown","mouseup"])l.addEventListener(c,d=>d.stopPropagation());l.addEventListener("click",c=>{c.stopPropagation(),c.preventDefault(),this.onFavorite?.(n.id,!a);}),i.appendChild(l);}if(n.toggle){let a=e.createElement("span");a.className="vela-menu-switch"+(n.checked?" on":""),a.setAttribute("aria-hidden","true"),i.appendChild(a);}if(o){i.dataset.branch="1";let a=Ue("chevron-right",e);a.classList.add("vela-menu-arrow"),i.appendChild(a);let l=new r(e,{host:this.host,placement:"right-start",onSelect:this.onSelect,onFavorite:this.onFavorite,checkmarks:this.checkmarks,id:`${this.mid}--${n.id}`});l.setItems(n.submenu??[]),this.subs.set(n.id,l);}this.list.appendChild(i);}}},Oo=class{constructor(e){let t=e.trigger??e.host??document.body,n=t.ownerDocument;he(Ov,Nv,n);let o=Xl(e.host??t,n.body);this.root=new ah(n,{host:o,placement:e.placement,onSelect:i=>e.onSelect?.(i),onOpenChange:e.onOpenChange,trigger:e.trigger,triggerId:e.triggerId,id:e.id,minWidth:e.minWidth,onFavorite:e.onFavorite,checkmarks:e.checkmarks}),this.root.setItems(e.items);}get api(){return this.root.api}open(){this.api.setOpen(true);}openAt(e,t){let n=this.api;n.setOpen(true),n.reposition({getAnchorRect:()=>({x:e,y:t,width:0,height:0})});}close(){this.api.setOpen(false);}setItems(e){this.root.setItems(e);}destroy(){this.root.destroy();}};function Fv(r,e){return {left:r.left+e,top:r.top+e,right:r.right-e,bottom:r.bottom-e,width:r.width-e*2,height:r.height-e*2}}function Vv(r,e,t){return {left:t,top:t,right:r-t,bottom:e-t,width:r-t*2,height:e-t*2}}function Bv(r,e){let t=Math.max(r.left,e.left),n=Math.max(r.top,e.top),o=Math.min(r.right,e.right),i=Math.min(r.bottom,e.bottom);return {left:t,top:n,right:o,bottom:i,width:o-t,height:i-n}}function _v(r){let e=r.align==="end"?r.trigger.right-r.pop.width:r.align==="center"?r.trigger.left+r.trigger.width/2-r.pop.width/2:r.trigger.left,t=r.trigger.bottom+r.gap,n=r.trigger.top-r.pop.height-r.gap,o=t+r.pop.height<=r.clamp.bottom,i=n>=r.clamp.top,s=t;return !o&&(i||r.trigger.top-r.clamp.top>r.clamp.bottom-r.trigger.bottom)&&(s=Math.max(r.clamp.top,n)),e+r.pop.width>r.clamp.right&&(e=r.clamp.right-r.pop.width),er.clamp.bottom&&(s=r.clamp.bottom-r.pop.height),sthis.onSelect(o),getAnchorRect:()=>this.pinnedAnchor,onOpenChange:o=>{if(o&&n){let i=n.getBoundingClientRect();this.pinnedAnchor={x:i.x,y:i.y,width:i.width,height:i.height};}else this.pinnedAnchor=null;t.onOpenChange?.(o);},triggerId:t.triggerId}),this.mid=String(this.ctrl.props.id),t.triggerId&&n&&(n.id=t.triggerId),this.handle=jl(this.ctrl.machine,this.ctrl.props,o=>{let i=this.ctrl.connect(o),s=this.shown&&!i.open;s&&this.announce(false),i.open&&this.exit&&(this.exit.cancel(),this.exit=null),n&&ft(n,i.getTriggerProps(),this.mid),ft(this.positioner,i.getPositionerProps(),this.mid),ft(this.list,i.getContentProps(),this.mid),this.project(i),s&&this.holdExit(),i.open&&!this.shown&&this.announce(true);});}holdExit(){this.list.hidden=false,this.exit=Kn(this.list,()=>{this.exit=null,this.shown||(this.list.hidden=true);});}get api(){return this.ctrl.connect(this.handle.service)}announce(e){this.shown=e,Vt(this.list,e,"menu",this.opener);}setItems(e){this.items=e;for(let n of this.subs.values())n.destroy();this.subs.clear(),this.build();let t=this.api;for(let n of this.subs.values())t.setChild(n.handle.service),n.api.setParent(this.handle.service);this.handle.flush(),this.subs.size>0&&queueMicrotask(()=>this.handle.flush());}destroy(){for(let e of this.subs.values())e.destroy();this.subs.clear(),this.exit?.finish(),this.handle.stop(),this.shown&&this.announce(false),this.positioner.remove();}byId(e){return this.items.find(t=>t.id===e)}project(e){for(let t of this.list.children){let n=t.dataset.veiId;if(!n)continue;let o=this.subs.get(n);if(o){ft(t,e.getTriggerItemProps(o.api),this.mid);continue}let i=this.byId(n);ft(t,e.getItemProps({value:n,disabled:i?.disabled,closeOnSelect:i?.toggle?false:void 0}),this.mid);}}build(){let e=this.doc;this.list.replaceChildren();let t=this.checkmarks&&this.items.some(i=>!(i.submenu&&i.submenu.length>0)&&!i.toggle&&i.checked!==void 0),n=this.items.some(i=>!!i.icon),o=this.iconBadges&&n;o?this.list.dataset.badges="1":delete this.list.dataset.badges;for(let i of this.items){if(i.separatorBefore){let c=e.createElement("li");c.className="vela-menu-sep",c.setAttribute("role","separator"),this.list.appendChild(c);}let s=i.submenu!==void 0&&i.submenu.length>0,a=e.createElement("li");if(a.className="vela-menu-item",a.dataset.veiId=i.id,i.toggle&&(a.dataset.toggle="1"),t){let c=e.createElement("span");c.className="vela-menu-mark",!s&&!i.toggle&&i.checked&&(c.appendChild(ze("check",e)),a.dataset.checkmark="1"),a.appendChild(c);}else !s&&!i.toggle&&i.checked&&(a.dataset.checked="1");if(o){let c=e.createElement("span");c.className="vela-menu-badge",i.icon&&c.appendChild(ze(i.icon,e)),a.appendChild(c);}else i.icon?a.appendChild(ze(i.icon,e)):n&&a.appendChild(ze("",e));let l=e.createElement("span");if(l.className="vela-menu-label",l.textContent=i.label,a.appendChild(l),i.hint){let c=e.createElement("span");c.className="vela-menu-hint",c.textContent=i.hint,a.appendChild(c);}if(i.favorite!==void 0&&this.onFavorite){let c=i.favorite,d=ze(c?"star-filled":"star",e);d.classList.add("vela-menu-star"),c&&d.classList.add("vela-fav"),d.removeAttribute("aria-hidden"),d.setAttribute("role","button"),d.setAttribute("aria-label",c?"Remove from favorites":"Add to favorites"),d.setAttribute("aria-pressed",c?"true":"false");for(let u of ["pointerdown","pointerup","mousedown","mouseup"])d.addEventListener(u,h=>h.stopPropagation());d.addEventListener("click",u=>{u.stopPropagation(),u.preventDefault(),this.onFavorite?.(i.id,!c);}),a.appendChild(d);}if(i.toggle){let c=e.createElement("span");c.className="vela-menu-switch"+(i.checked?" on":""),c.setAttribute("aria-hidden","true"),a.appendChild(c);}if(s){a.dataset.branch="1";let c=ze("chevron-right",e);c.classList.add("vela-menu-arrow"),a.appendChild(c);let d=new r(e,{host:this.host,placement:"right-start",opener:a,onSelect:this.onSelect,onFavorite:this.onFavorite,checkmarks:this.checkmarks,iconBadges:this.iconBadges,id:`${this.mid}--${i.id}`});d.setItems(i.submenu??[]),this.subs.set(i.id,d);}this.list.appendChild(a);}}},Bo=class{constructor(e){let t=e.trigger??e.host??document.body,n=t.ownerDocument;he(zv,Wv,n);let o=Zl(e.host??t,n.body);this.root=new uh(n,{host:o,placement:e.placement,onSelect:i=>e.onSelect?.(i),onOpenChange:e.onOpenChange,trigger:e.trigger,triggerId:e.triggerId,id:e.id,minWidth:e.minWidth,onFavorite:e.onFavorite,checkmarks:e.checkmarks,iconBadges:e.iconBadges}),this.root.setItems(e.items);}get api(){return this.root.api}open(){this.api.setOpen(true);}openAt(e,t){let n=this.api;n.setOpen(true),n.reposition({getAnchorRect:()=>({x:e,y:t,width:0,height:0})});}close(){this.api.setOpen(false);}setItems(e){this.root.setItems(e);}destroy(){this.root.destroy();}};function Gv(r,e){return {left:r.left+e,top:r.top+e,right:r.right-e,bottom:r.bottom-e,width:r.width-e*2,height:r.height-e*2}}function $v(r,e,t){return {left:t,top:t,right:r-t,bottom:e-t,width:r-t*2,height:e-t*2}}function Uv(r,e){let t=Math.max(r.left,e.left),n=Math.max(r.top,e.top),o=Math.min(r.right,e.right),i=Math.min(r.bottom,e.bottom);return {left:t,top:n,right:o,bottom:i,width:o-t,height:i-n}}function Yv(r){let e=r.align==="end"?r.trigger.right-r.pop.width:r.align==="center"?r.trigger.left+r.trigger.width/2-r.pop.width/2:r.trigger.left,t=r.trigger.bottom+r.gap,n=r.trigger.top-r.pop.height-r.gap,o=t+r.pop.height<=r.clamp.bottom,i=n>=r.clamp.top,s=t;return !o&&(i||r.trigger.top-r.clamp.top>r.clamp.bottom-r.trigger.bottom)&&(s=Math.max(r.clamp.top,n)),e+r.pop.width>r.clamp.right&&(e=r.clamp.right-r.pop.width),er.clamp.bottom&&(s=r.clamp.bottom-r.pop.height),sn.stopPropagation()),e.content instanceof Node?this.el.appendChild(e.content):typeof e.content=="function"&&e.content(this.el);}get open(){return this.shown}get position(){return this.ctrl.position}get align(){return this.ctrl.align}show(){if(this.shown){this.place();return}Ln&&Ln!==this&&Ln.hide(),this.leaveTimer!==null&&(clearTimeout(this.leaveTimer),this.leaveTimer=null),Zg(this.el,this.inheritsTokens?void 0:this.theme),this.fadeMs>0&&(this.el.style.transition=`opacity ${this.fadeMs}ms ease`,this.el.style.opacity="0",this.el.style.pointerEvents=""),this.host.appendChild(this.el),this.shown=true,Ln=this,this.place(),this.fadeMs>0&&(this.el.style.opacity="1");let e=o=>{let i=o.target;this.el.contains(i)||this.trigger.contains(i)||(AM(o),this.hide());},t=o=>{o.key==="Escape"&&(o.preventDefault(),o.stopPropagation(),this.hide());},n=()=>this.place();setTimeout(()=>document.addEventListener("pointerdown",e,true),0),document.addEventListener("keydown",t,true),window.addEventListener("resize",n,true),document.addEventListener("scroll",n,true),this.onOutside=e,this.onKey=t,this.onReflow=n;}hide(){this.shown&&(this.onOutside&&document.removeEventListener("pointerdown",this.onOutside,true),this.onKey&&document.removeEventListener("keydown",this.onKey,true),this.onReflow&&(window.removeEventListener("resize",this.onReflow,true),document.removeEventListener("scroll",this.onReflow,true)),this.onOutside=null,this.onKey=null,this.onReflow=null,this.fadeMs>0?(this.el.style.opacity="0",this.el.style.pointerEvents="none",this.leaveTimer=setTimeout(()=>{this.leaveTimer=null,this.el.remove();},this.fadeMs)):this.el.remove(),this.shown=false,Ln===this&&(Ln=null),this.ctrl.onClose?.());}toggle(){this.shown?this.hide():this.show();}destroy(){this.hide();}reposition(){this.shown&&this.place();}clampRect(){let e=Vv(window.innerWidth,window.innerHeight,this.ctrl.viewportInset),t=this.readBoundary();if(!t)return e;let n=Fv(t,this.ctrl.boundaryInset);return Bv(e,n)}readBoundary(){let e=this.boundary;if(e==="viewport")return null;let t=typeof e=="function"?e():e.getBoundingClientRect();return t?Gv(t):null}place(){let e=this.trigger.getBoundingClientRect();this.ctrl.matchWidth&&(this.el.style.minWidth=`${Math.round(Math.max(this.el.offsetWidth,e.width))}px`);let t=this.ctrl.position==="absolute"?this.host.getBoundingClientRect():{left:0,top:0},n=_v({trigger:Gv(e),pop:{width:this.el.offsetWidth,height:this.el.offsetHeight},gap:this.ctrl.gap,align:this.ctrl.align,clamp:this.clampRect(),originX:t.left,originY:t.top});this.el.style.left=`${n.left}px`,this.el.style.top=`${n.top}px`;}};function Uv(r){return r.close!==false}function Yv(r){let e=[];for(let t of r){if(t.type==="text"){e.push({type:"text",text:t.text});continue}let n=e[e.length-1];n&&n.type==="buttons"?n.buttons.push(t):e.push({type:"buttons",buttons:[t]});}return e}var us="vela-ui-callout-bubble",hs=` +`;var Mn=null,gc=new Set;function Me(){Mn?.hide();}function un(){return Mn!==null}function En(){return Mn?.trigger??null}var Zv="__velaPopoverDismiss";function WM(r){r[Zv]=true;}function Wr(r){return r[Zv]===true}function qv(r){return {left:r.left,top:r.top,right:r.right,bottom:r.bottom,width:r.width,height:r.height}}var qe=class{constructor(e){this.onOutside=null;this.onKey=null;this.onReflow=null;this.shown=false;this.leaveTimer=null;this.exit=null;let t=e.trigger.ownerDocument;he(Xv,jv,t),this.trigger=e.trigger,this.host=e.host??Zl(e.trigger,t.body),this.inheritsTokens=!e.host&&this.host!==t.body,this.ctrl=Kv(e),this.boundary=e.boundary??"viewport",this.theme=e.theme,this.fadeMs=Math.max(0,e.fadeMs??0),this.el=t.createElement("div"),this.el.className="vela-popover vela-ui-layer"+(e.className?` ${e.className}`:""),this.el.dataset.position=this.ctrl.position,e.zIndex!==void 0&&(this.el.style.zIndex=String(e.zIndex)),this.el.addEventListener("pointerdown",n=>n.stopPropagation()),e.content instanceof Node?this.el.appendChild(e.content):typeof e.content=="function"&&e.content(this.el);}get open(){return this.shown}get position(){return this.ctrl.position}get align(){return this.ctrl.align}show(){if(this.shown){this.place();return}Mn&&Mn!==this&&Mn.hide(),this.leaveTimer!==null&&(clearTimeout(this.leaveTimer),this.leaveTimer=null),this.exit?.cancel(),this.exit=null,gc.delete(this);for(let o of [...gc])o.trigger===this.trigger&&o.exit?.finish();rb(this.el,this.inheritsTokens?void 0:this.theme),this.fadeMs>0&&(this.el.style.transition=`opacity ${this.fadeMs}ms ease`,this.el.style.opacity="0",this.el.style.pointerEvents=""),this.host.appendChild(this.el),this.shown=true,Mn=this,this.place(),this.fadeMs>0&&(this.el.style.opacity="1");let e=o=>{let i=o.target;this.el.contains(i)||this.trigger.contains(i)||(WM(o),this.hide());},t=o=>{o.key==="Escape"&&(o.preventDefault(),o.stopPropagation(),this.hide());},n=()=>this.place();setTimeout(()=>{this.onOutside===e&&document.addEventListener("pointerdown",e,true);},0),document.addEventListener("keydown",t,true),window.addEventListener("resize",n,true),document.addEventListener("scroll",n,true),this.onOutside=e,this.onKey=t,this.onReflow=n,Vt(this.el,true,"popover",this.trigger);}hide(){this.shown&&(this.shown=false,Vt(this.el,false,"popover",this.trigger),this.onOutside&&document.removeEventListener("pointerdown",this.onOutside,true),this.onKey&&document.removeEventListener("keydown",this.onKey,true),this.onReflow&&(window.removeEventListener("resize",this.onReflow,true),document.removeEventListener("scroll",this.onReflow,true)),this.onOutside=null,this.onKey=null,this.onReflow=null,this.fadeMs>0?(this.el.style.opacity="0",this.el.style.pointerEvents="none",this.leaveTimer=setTimeout(()=>{this.leaveTimer=null,this.el.remove();},this.fadeMs)):(this.exit=Kn(this.el,()=>{this.exit=null,gc.delete(this),this.el.remove();}),this.exit&&gc.add(this)),Mn===this&&(Mn=null),this.ctrl.onClose?.());}toggle(){this.shown?this.hide():this.show();}destroy(){this.hide(),this.exit?.finish();}reposition(){this.shown&&this.place();}clampRect(){let e=$v(window.innerWidth,window.innerHeight,this.ctrl.viewportInset),t=this.readBoundary();if(!t)return e;let n=Gv(t,this.ctrl.boundaryInset);return Uv(e,n)}readBoundary(){let e=this.boundary;if(e==="viewport")return null;let t=typeof e=="function"?e():e.getBoundingClientRect();return t?qv(t):null}place(){let e=this.trigger.getBoundingClientRect();this.ctrl.matchWidth&&(this.el.style.minWidth=`${Math.round(Math.max(this.el.offsetWidth,e.width))}px`);let t=this.ctrl.position==="absolute"?this.host.getBoundingClientRect():{left:0,top:0},n=Yv({trigger:qv(e),pop:{width:this.el.offsetWidth,height:this.el.offsetHeight},gap:this.ctrl.gap,align:this.ctrl.align,clamp:this.clampRect(),originX:t.left,originY:t.top});this.el.style.left=`${n.left}px`,this.el.style.top=`${n.top}px`;}};function Qv(r){return r.close!==false}function Jv(r){let e=[];for(let t of r){if(t.type==="text"){e.push({type:"text",text:t.text});continue}let n=e[e.length-1];n&&n.type==="buttons"?n.buttons.push(t):e.push({type:"buttons",buttons:[t]});}return e}var fs="vela-ui-callout-bubble",gs=` .vela-callout { display: inline-grid; place-items: center; @@ -197,7 +226,7 @@ ${CL} .vela-callout-btn:hover { background: var(--vela-hover); color: var(--vela-fg-bright); border-color: var(--vela-fg-muted); } .vela-callout-btn-primary { border-color: var(--vela-selected-bg); background: var(--vela-selected-bg); color: var(--vela-selected-fg); } .vela-callout-btn-primary:hover { background: var(--vela-selected-bg); color: var(--vela-selected-fg); opacity: 0.85; border-color: var(--vela-selected-bg); } -`;var ps=class{constructor(e){this.pop=null;this.spec={icon:e.icon,background:e.background,label:e.label},e.color!==void 0&&(this.spec.color=e.color),e.panel!==void 0&&(this.spec.panel=e.panel),this.size=e.size??16,this.host=e.host,this.theme=e.theme,this.boundary=e.boundary;let t=(e.host??document.body).ownerDocument;he(us,hs,t),this.el=t.createElement("span"),this.el.className="vela-callout",this.el.style.width=`${this.size}px`,this.el.style.height=`${this.size}px`,this.el.addEventListener("click",n=>{this.spec.panel&&(n.stopPropagation(),this.toggle());}),this.el.addEventListener("dblclick",n=>{this.spec.panel&&n.stopPropagation();}),this.el.addEventListener("keydown",n=>{!this.spec.panel||n.key!=="Enter"&&n.key!==" "||(n.preventDefault(),this.toggle());}),this.dress();}set(e){this.spec={...this.spec,...e},"panel"in e&&this.pop?.hide(),this.dress();}get open(){return this.pop?.open??false}hidePanel(){this.pop?.hide();}destroy(){this.pop?.destroy(),this.pop=null,this.el.remove();}dress(){let e=this.spec.panel!==void 0;this.el.style.background=this.spec.background,this.el.style.color=this.spec.color??"",this.el.innerHTML=Re(this.spec.icon,this.size-4),this.el.setAttribute("aria-label",this.spec.label),e?(this.el.setAttribute("role","button"),this.el.tabIndex=0):(this.el.removeAttribute("role"),this.el.removeAttribute("tabindex"));}toggle(){if(this.pop?.open){this.pop.hide();return}let e=this.spec.panel;e&&(this.pop?.destroy(),this.pop=new qe({trigger:this.el,gap:6,content:t=>this.buildPanel(t,e),...this.host?{host:this.host}:{},...this.theme?{theme:this.theme()}:{},...this.boundary?{boundary:this.boundary}:{}}),this.pop.show());}buildPanel(e,t){let n=e.ownerDocument,o=n.createElement("div");if(o.className="vela-callout-panel",t.title){let i=n.createElement("div");i.className="vela-callout-title",i.textContent=t.title,o.appendChild(i);}for(let i of Yv(t.items)){if(i.type==="text"){let a=n.createElement("div");a.className="vela-callout-text",a.textContent=i.text,o.appendChild(a);continue}let s=n.createElement("div");s.className="vela-callout-actions";for(let a of i.buttons){let l=n.createElement("button");l.type="button",l.className="vela-callout-btn"+(a.primary?" vela-callout-btn-primary":""),l.textContent=a.label,l.addEventListener("click",()=>{a.run(),Uv(a)&&this.pop?.hide();}),s.appendChild(l);}o.appendChild(s);}e.appendChild(o);}};function ms(r,e){return r?(Array.isArray(r)?r:[r]).every(n=>n.anyOf?n.anyOf.some(o=>o===e[n.key]):e[n.key]===n.equals):true}function Kv(r,e){let t={};for(let n of r){let o=e[n.key];o!==void 0&&JSON.stringify(o)!==JSON.stringify(n.defval)&&(t[n.key]=o);}return Object.keys(t).length>0?t:void 0}function Xv(r){let e=r.options,t=r.value??e[0]?.value??"",n=r.size??"md";return {options:e,get value(){return t},size:n,fill:r.fill??n!=="sm",disabled:r.disabled??false,setValue(o){t=o;},labelOf(o){return e.find(i=>i.value===o)?.label??o},pick(o){t=o;let i=e.find(s=>s.value===o)?.label??o;return r.onChange?.(o,i),{value:o,label:i}}}}var jv="vela-ui-select-3",qv=` +`;var bs=class{constructor(e){this.pop=null;this.spec={icon:e.icon,background:e.background,label:e.label},e.color!==void 0&&(this.spec.color=e.color),e.panel!==void 0&&(this.spec.panel=e.panel),this.size=e.size??16,this.host=e.host,this.theme=e.theme,this.boundary=e.boundary;let t=(e.host??document.body).ownerDocument;he(fs,gs,t),this.el=t.createElement("span"),this.el.className="vela-callout",this.el.style.width=`${this.size}px`,this.el.style.height=`${this.size}px`,this.el.addEventListener("click",n=>{this.spec.panel&&(n.stopPropagation(),this.toggle());}),this.el.addEventListener("dblclick",n=>{this.spec.panel&&n.stopPropagation();}),this.el.addEventListener("keydown",n=>{!this.spec.panel||n.key!=="Enter"&&n.key!==" "||(n.preventDefault(),this.toggle());}),this.dress();}set(e){this.spec={...this.spec,...e},"panel"in e&&this.pop?.hide(),this.dress();}get open(){return this.pop?.open??false}hidePanel(){this.pop?.hide();}destroy(){this.pop?.destroy(),this.pop=null,this.el.remove();}dress(){let e=this.spec.panel!==void 0;this.el.style.background=this.spec.background,this.el.style.color=this.spec.color??"",this.el.innerHTML=Re(this.spec.icon,this.size-4),this.el.setAttribute("aria-label",this.spec.label),e?(this.el.setAttribute("role","button"),this.el.tabIndex=0):(this.el.removeAttribute("role"),this.el.removeAttribute("tabindex"));}toggle(){if(this.pop?.open){this.pop.hide();return}let e=this.spec.panel;e&&(this.pop?.destroy(),this.pop=new qe({trigger:this.el,gap:6,content:t=>this.buildPanel(t,e),...this.host?{host:this.host}:{},...this.theme?{theme:this.theme()}:{},...this.boundary?{boundary:this.boundary}:{}}),this.pop.show());}buildPanel(e,t){let n=e.ownerDocument,o=n.createElement("div");if(o.className="vela-callout-panel",t.title){let i=n.createElement("div");i.className="vela-callout-title",i.textContent=t.title,o.appendChild(i);}for(let i of Jv(t.items)){if(i.type==="text"){let a=n.createElement("div");a.className="vela-callout-text",a.textContent=i.text,o.appendChild(a);continue}let s=n.createElement("div");s.className="vela-callout-actions";for(let a of i.buttons){let l=n.createElement("button");l.type="button",l.className="vela-callout-btn"+(a.primary?" vela-callout-btn-primary":""),l.textContent=a.label,l.addEventListener("click",()=>{a.run(),Qv(a)&&this.pop?.hide();}),s.appendChild(l);}o.appendChild(s);}e.appendChild(o);}};function vs(r,e){return r?(Array.isArray(r)?r:[r]).every(n=>n.anyOf?n.anyOf.some(o=>o===e[n.key]):e[n.key]===n.equals):true}function ey(r,e){let t={};for(let n of r){let o=e[n.key];o!==void 0&&JSON.stringify(o)!==JSON.stringify(n.defval)&&(t[n.key]=o);}return Object.keys(t).length>0?t:void 0}function ty(r){let e=r.options,t=r.value??e[0]?.value??"",n=r.size??"md";return {options:e,get value(){return t},size:n,fill:r.fill??n!=="sm",disabled:r.disabled??false,setValue(o){t=o;},labelOf(o){return e.find(i=>i.value===o)?.label??o},pick(o){t=o;let i=e.find(s=>s.value===o)?.label??o;return r.onChange?.(o,i),{value:o,label:i}}}}var ny="vela-ui-select-3",ry=` .vela-select { position: relative; display: inline-block; min-width: 0; } .vela-select[data-fill] { width: 100%; } /* Closed trigger matches NumberInput / TextField (100px). Long labels ellipsis; @@ -292,7 +321,7 @@ ${CL} .vela-select-item:hover { background: var(--vela-hover); } .vela-select-item[data-checked] { background: var(--vela-hover-strong); color: var(--vela-fg-bright); } .vela-select-item[data-checked]:hover { background: var(--vela-hover-strong); } -`;function Qv(r){he(jv,qv,r);}function Zv(r,e){let t=r.clientHeight,n=r.scrollHeight;if(n<=t){e.style.height="0";return}let o=Math.max(20,t/n*t),i=r.scrollTop/(n-t)*(t-o);e.style.height=`${Math.round(o)}px`,e.style.transform=`translateY(${Math.round(i)}px`;}function Jv(r,e,t,n){r.replaceChildren();let o=r.ownerDocument.createElement("div");o.className="vela-select-items";for(let i of e){let s=r.ownerDocument.createElement("button");s.type="button",s.className="vela-select-item",s.textContent=i.label,i.value===t&&(s.dataset.checked="1"),s.addEventListener("click",a=>{a.stopPropagation(),n(i.value,i.label);}),o.appendChild(s);}r.appendChild(o);}function ey(r){let e=r.querySelector(".vela-select-items");if(e){if(e.scrollHeight>240){r.classList.add("is-scroll");let t=r.ownerDocument.createElement("div");t.className="vela-select-rail";let n=r.ownerDocument.createElement("div");n.className="vela-select-thumb",t.appendChild(n),r.appendChild(t),e.addEventListener("scroll",()=>Zv(e,n)),Zv(e,n);}r.querySelector(".vela-select-item[data-checked]")?.scrollIntoView({block:"nearest"}),e.dispatchEvent(new Event("scroll"));}}function pc(r,e,t,n,o={}){return Mn()===r?(Me(),null):ty(r,e,t,n,o)}function ty(r,e,t,n,o={}){Qv(r.ownerDocument),Me();let i=new qe({trigger:r,theme:o.theme,matchWidth:o.matchWidth??true,boundary:o.boundary,boundaryInset:o.boundaryInset,gap:o.gap??4,align:o.align??"start",host:o.host,position:o.position,zIndex:o.zIndex,className:"vela-select-list",onClose:o.onClose,content:s=>{o.size&&(s.dataset.size=o.size),Jv(s,e,t,(a,l)=>{i.hide(),n(a,l);});}});return i.show(),ey(i.el),i.reposition(),i}var fs=class{constructor(e){this.list=null;let t=e.list?.host?.ownerDocument??document;Qv(t),this.ctrl=Xv(e),this.listOpts={...e.list,theme:e.theme??e.list?.theme,size:this.ctrl.size};let n=t.createElement("div");n.className="vela-select",n.dataset.size=this.ctrl.size,this.ctrl.fill&&(n.dataset.fill="");let o=t.createElement("button");o.type="button",e.id&&(o.id=e.id),o.className="vela-select-trigger",this.ctrl.disabled&&(o.disabled=true);let i=t.createElement("span");i.className="vela-select-label",i.textContent=this.ctrl.labelOf(this.ctrl.value);let s=t.createElement("span");if(s.className="vela-select-chevron",s.appendChild(Ue("chevron-down",t)),o.append(i,s),n.appendChild(o),this.ctrl.size==="sm"){let a=t.createElement("div");a.className="vela-select-sizer",a.setAttribute("aria-hidden","true");for(let l of this.ctrl.options){let c=t.createElement("span");c.textContent=l.label,a.appendChild(c);}n.appendChild(a);}o.addEventListener("pointerdown",a=>{a.preventDefault(),o.focus({preventScroll:true});}),o.addEventListener("click",a=>{a.stopPropagation(),this.toggle();}),this.el=n,this.trigger=o,this.labelEl=i;}get value(){return this.ctrl.value}setValue(e){this.ctrl.setValue(e),this.labelEl.textContent=this.ctrl.labelOf(e);}toggle(){this.list=pc(this.trigger,this.ctrl.options,this.ctrl.value,(e,t)=>{this.ctrl.pick(e),this.labelEl.textContent=t,this.list=null;},{...this.listOpts,onClose:()=>{this.list=null,this.listOpts.onClose?.();}});}destroy(){this.list?.hide(),this.list=null;}};var RM=Cn("dialog").parts("trigger","backdrop","positioner","content","title","description","closeTrigger"),Zn=RM.build();var lh=r=>r.ids?.positioner??`dialog:${r.id}:positioner`,ch=r=>r.ids?.backdrop??`dialog:${r.id}:backdrop`,mc=r=>r.ids?.content??`dialog:${r.id}:content`,fc=(r,e)=>{let t=r.ids?.trigger;return t!=null?pt(t)?t(e):t:e?`dialog:${r.id}:trigger:${e}`:`dialog:${r.id}:trigger`},gc=r=>r.ids?.title??`dialog:${r.id}:title`,bc=r=>r.ids?.description??`dialog:${r.id}:description`,dh=r=>r.ids?.closeTrigger??`dialog:${r.id}:close`,gs=r=>r.getById(mc(r)),ny=r=>r.getById(lh(r)),ry=r=>r.getById(ch(r)),uh=r=>r.getById(fc(r)),oy=r=>r.getById(gc(r)),iy=r=>r.getById(bc(r)),sy=r=>r.getById(dh(r)),vc=r=>ko(r.getRootNode(),`[data-scope="dialog"][data-part="trigger"][data-ownedby="${r.id}"]`),hh=(r,e)=>e==null?uh(r)??vc(r)[0]:r.getById(fc(r,e));function ph(r,e){let{state:t,send:n,context:o,prop:i,scope:s}=r,a=i("aria-label"),l=t.matches("open"),c=o.get("triggerValue");return {open:l,setOpen(d){t.matches("open")!==d&&n({type:d?"OPEN":"CLOSE"});},triggerValue:c,setTriggerValue(d){n({type:"TRIGGER_VALUE.SET",value:d});},getTriggerProps(d={}){let{value:u}=d,h=u==null?false:c===u;return e.button({...Zn.trigger.attrs,dir:i("dir"),id:fc(s,u),"data-ownedby":s.id,"data-value":u,"aria-haspopup":"dialog",type:"button","aria-expanded":u==null?l:l&&h,"data-state":l?"open":"closed","aria-controls":mc(s),"data-current":Ct(h),onClick(p){if(p.defaultPrevented)return;let m=l&&u!=null&&!h;n({type:m?"TRIGGER_VALUE.SET":"TOGGLE",value:u});}})},getBackdropProps(){return e.element({...Zn.backdrop.attrs,dir:i("dir"),hidden:!l,id:ch(s),"data-state":l?"open":"closed"})},getPositionerProps(){return e.element({...Zn.positioner.attrs,dir:i("dir"),id:lh(s),style:$n({pointerEvents:!l||!i("modal")?"none":void 0})})},getContentProps(){let d=o.get("rendered");return e.element({...Zn.content.attrs,dir:i("dir"),role:i("role"),hidden:!l,id:mc(s),tabIndex:-1,"data-state":l?"open":"closed","aria-modal":i("modal"),"aria-label":a||void 0,"aria-labelledby":a||!d.title?void 0:gc(s),"aria-describedby":d.description?bc(s):void 0,style:$n({pointerEvents:i("modal")?void 0:"auto"})})},getTitleProps(){return e.element({...Zn.title.attrs,dir:i("dir"),id:gc(s)})},getDescriptionProps(){return e.element({...Zn.description.attrs,dir:i("dir"),id:bc(s)})},getCloseTriggerProps(){return e.button({...Zn.closeTrigger.attrs,dir:i("dir"),id:dh(s),type:"button",onClick(d){d.defaultPrevented||(d.stopPropagation(),n({type:"CLOSE"}));}})}}}var No=new WeakMap,yc=new WeakMap,wc={},mh=0,ly=r=>r&&(r.host||ly(r.parentNode)),DM=(r,e)=>e.map(t=>{if(r.contains(t))return t;let n=ly(t);return n&&r.contains(n)?n:(console.error("[zag-js > ariaHidden] target",t,"in not contained inside",r,". Doing nothing"),null)}).filter(t=>!!t),OM=new Set(["script","output","status","next-route-announcer"]),NM=r=>OM.has(r.localName)||r.role==="status"||r.hasAttribute("aria-live")?true:r.matches("[data-live-announcer]"),cy=(r,e)=>{let{parentNode:t,markerName:n,controlAttribute:o,explicitBooleanValue:i,followControlledElements:s=true}=e,a=DM(t,Array.isArray(r)?r:[r]);wc[n]||(wc[n]=new WeakMap);let l=wc[n],c=[],d=new Set,u=new Set(a),h=m=>{!m||d.has(m)||(d.add(m),h(m.parentNode));};a.forEach(m=>{h(m),s&&me(m)&&Su(m,f=>{h(f);});});let p=m=>{!m||u.has(m)||Array.prototype.forEach.call(m.children,f=>{if(d.has(f))p(f);else try{if(NM(f))return;let g=f.getAttribute(o),b=i?g==="true":g!==null&&g!=="false",y=(No.get(f)||0)+1,w=(l.get(f)||0)+1;No.set(f,y),l.set(f,w),c.push(f),y===1&&b&&yc.set(f,!0),w===1&&f.setAttribute(n,""),b||f.setAttribute(o,i?"true":"");}catch(g){console.error("[zag-js > ariaHidden] cannot operate on ",f,g);}});};return p(t),d.clear(),mh++,()=>{c.forEach(m=>{let f=No.get(m)-1,g=l.get(m)-1;No.set(m,f),l.set(m,g),f||(yc.has(m)||m.removeAttribute(o),yc.delete(m)),g||m.removeAttribute(n);}),mh--,mh||(No=new WeakMap,No=new WeakMap,yc=new WeakMap,wc={});}};var FM=r=>(Array.isArray(r)?r[0]:r).ownerDocument.body,dy=(r,e=FM(r),t="data-aria-hidden",n=true)=>{if(e)return cy(r,{parentNode:e,markerName:t,controlAttribute:"aria-hidden",explicitBooleanValue:true,followControlledElements:n})};var VM=r=>{let e=requestAnimationFrame(()=>r());return ()=>cancelAnimationFrame(e)};function uy(r,e={}){let{defer:t=true}=e,n=t?VM:i=>i(),o=[];return o.push(n(()=>{let s=(typeof r=="function"?r():r).filter(Boolean);s.length!==0&&o.push(dy(s));})),()=>{o.forEach(i=>i?.());}}var BM=Object.defineProperty,_M=(r,e,t)=>e in r?BM(r,e,{enumerable:true,configurable:true,writable:true,value:t}):r[e]=t,ke=(r,e,t)=>_M(r,typeof e!="symbol"?e+"":e,t);var hy={activateTrap(r,e){if(r.length>0){let n=r[r.length-1];n!==e&&n.pause();}let t=r.indexOf(e);t===-1||r.splice(t,1),r.push(e);},deactivateTrap(r,e){let t=r.indexOf(e);t!==-1&&r.splice(t,1),r.length>0&&r[r.length-1].unpause();}},HM=[],my=class{constructor(r,e){ke(this,"trapStack"),ke(this,"config"),ke(this,"doc"),ke(this,"state",{containers:[],containerGroups:[],tabbableGroups:[],nodeFocusedBeforeActivation:null,mostRecentlyFocusedNode:null,active:false,paused:false,delayInitialFocusTimer:void 0,recentNavEvent:void 0}),ke(this,"portalContainers",new Set),ke(this,"listenerCleanups",[]),ke(this,"handleFocus",n=>{let o=_e(n),i=this.findContainerIndex(o,n)>=0;if(i||Ki(o))i&&(this.state.mostRecentlyFocusedNode=o);else {n.stopImmediatePropagation();let s,a=true;if(this.state.mostRecentlyFocusedNode)if(To(this.state.mostRecentlyFocusedNode)>0){let l=this.findContainerIndex(this.state.mostRecentlyFocusedNode),{tabbableNodes:c}=this.state.containerGroups[l];if(c.length>0){let d=c.findIndex(u=>u===this.state.mostRecentlyFocusedNode);d>=0&&(this.config.isKeyForward(this.state.recentNavEvent)?d+1=0&&(s=c[d-1],a=false));}}else this.state.containerGroups.some(l=>l.tabbableNodes.some(c=>To(c)>0))||(a=false);else a=false;a&&(s=this.findNextNavNode({target:this.state.mostRecentlyFocusedNode,isBackward:this.config.isKeyBackward(this.state.recentNavEvent)})),s?this.tryFocus(s):this.tryFocus(this.state.mostRecentlyFocusedNode||this.getInitialFocusNode());}this.state.recentNavEvent=void 0;}),ke(this,"handlePointerDown",n=>{let o=_e(n);if(!(this.findContainerIndex(o,n)>=0)){if(bs(this.config.clickOutsideDeactivates,n)){this.deactivate({returnFocus:this.config.returnFocusOnDeactivate});return}bs(this.config.allowOutsideClick,n)||n.preventDefault();}}),ke(this,"handleClick",n=>{let o=_e(n);this.findContainerIndex(o,n)>=0||bs(this.config.clickOutsideDeactivates,n)||bs(this.config.allowOutsideClick,n)||(n.preventDefault(),n.stopImmediatePropagation());}),ke(this,"handleTabKey",n=>{if(this.config.isKeyForward(n)||this.config.isKeyBackward(n)){this.state.recentNavEvent=n;let o=this.config.isKeyBackward(n),i=this.findNextNavNode({event:n,isBackward:o});if(!i)return;fh(n)&&n.preventDefault(),this.tryFocus(i);}}),ke(this,"handleEscapeKey",n=>{GM(n)&&bs(this.config.escapeDeactivates,n)!==false&&(n.preventDefault(),this.deactivate());}),ke(this,"_mutationObserver"),ke(this,"setupMutationObserver",()=>{let n=this.doc.defaultView||window;this._mutationObserver=new n.MutationObserver(o=>{o.some(a=>Array.from(a.removedNodes).some(c=>c===this.state.mostRecentlyFocusedNode))&&this.tryFocus(this.getInitialFocusNode()),o.some(a=>a.type==="attributes"&&(a.attributeName==="aria-controls"||a.attributeName==="aria-expanded")?true:a.type==="childList"&&a.addedNodes.length>0?Array.from(a.addedNodes).some(l=>{if(l.nodeType!==Node.ELEMENT_NODE)return false;let c=l;return gg(c)?true:c.id&&!this.state.containers.some(d=>d.contains(c))?bg(c):false}):false)&&this.state.active&&!this.state.paused&&(this.updateTabbableNodes(),this.updatePortalContainers());});}),ke(this,"updateObservedNodes",()=>{this._mutationObserver?.disconnect(),this.state.active&&!this.state.paused&&(this.state.containers.map(n=>{this._mutationObserver?.observe(n,{subtree:true,childList:true,attributes:true,attributeFilter:["aria-controls","aria-expanded"]});}),this.portalContainers.forEach(n=>{this.observePortalContainer(n);}));}),ke(this,"getInitialFocusNode",()=>{let n=this.getNodeForOption("initialFocus",{hasFallback:true});if(n===false)return false;if(n===void 0||n&&!St(n)){let o=nn(this.doc);if(o&&this.findContainerIndex(o)>=0)n=o;else {let i=this.state.tabbableGroups[0];n=i&&i.firstTabbableNode||this.getNodeForOption("fallbackFocus");}}else n===null&&(n=this.getNodeForOption("fallbackFocus"));if(!n)throw new Error("Your focus-trap needs to have at least one focusable element");if(n.isConnected||(n=this.getNodeForOption("fallbackFocus")),!n||!n.isConnected)throw new Error("Your focus-trap needs to have at least one focusable element");return n}),ke(this,"tryFocus",n=>{if(n!==false&&n!==nn(this.doc)){if(!n||!n.focus){this.tryFocus(this.getInitialFocusNode());return}n.focus({preventScroll:!!this.config.preventScroll}),this.state.mostRecentlyFocusedNode=n,$M(n)&&n.select();}}),ke(this,"deactivate",n=>{if(!this.state.active)return this;let o={onDeactivate:this.config.onDeactivate,onPostDeactivate:this.config.onPostDeactivate,checkCanReturnFocus:this.config.checkCanReturnFocus,...n};clearTimeout(this.state.delayInitialFocusTimer),this.state.delayInitialFocusTimer=void 0,this.removeListeners(),this.state.active=false,this.state.paused=false,this.updateObservedNodes(),hy.deactivateTrap(this.trapStack,this),this.portalContainers.clear();let i=this.getOption(o,"onDeactivate"),s=this.getOption(o,"onPostDeactivate"),a=this.getOption(o,"checkCanReturnFocus"),l=this.getOption(o,"returnFocus","returnFocusOnDeactivate");i?.();let c=()=>{py(()=>{if(l){let d=this.getReturnFocusNode(this.state.nodeFocusedBeforeActivation);this.tryFocus(d);}s?.();});};if(l&&a){let d=this.getReturnFocusNode(this.state.nodeFocusedBeforeActivation);return a(d).then(c,c),this}return c(),this}),ke(this,"pause",n=>{if(this.state.paused||!this.state.active)return this;let o=this.getOption(n,"onPause"),i=this.getOption(n,"onPostPause");return this.state.paused=true,o?.(),this.removeListeners(),this.updateObservedNodes(),i?.(),this}),ke(this,"unpause",n=>{if(!this.state.paused||!this.state.active)return this;let o=this.getOption(n,"onUnpause"),i=this.getOption(n,"onPostUnpause");return this.state.paused=false,o?.(),this.updateTabbableNodes(),this.addListeners(),this.updateObservedNodes(),i?.(),this}),ke(this,"updateContainerElements",n=>(this.state.containers=Array.isArray(n)?n.filter(Boolean):[n].filter(Boolean),this.state.active&&this.updateTabbableNodes(),this.updateObservedNodes(),this)),ke(this,"getReturnFocusNode",n=>{let o=this.getNodeForOption("setReturnFocus",{params:[n]});return o||(o===false?false:n)}),ke(this,"getOption",(n,o,i)=>n&&n[o]!==void 0?n[o]:this.config[i||o]),ke(this,"getNodeForOption",(n,{hasFallback:o=false,params:i=[]}={})=>{let s=this.config[n];if(typeof s=="function"&&(s=s(...i)),s===true&&(s=void 0),!s){if(s===void 0||s===false)return s;throw new Error(`\`${n}\` was specified but was not a node, or did not return a node`)}let a=s;if(typeof s=="string"){try{a=this.doc.querySelector(s);}catch(l){throw new Error(`\`${n}\` appears to be an invalid selector; error="${l.message}"`)}if(!a&&!o)throw new Error(`\`${n}\` as selector refers to no known node`)}return a}),ke(this,"findNextNavNode",n=>{let{event:o,isBackward:i=false}=n,s=n.target||_e(o);this.updateTabbableNodes();let a=null;if(this.state.tabbableGroups.length>0){let l=this.findContainerIndex(s,o),c=l>=0?this.state.containerGroups[l]:void 0;if(l<0)i?a=this.state.tabbableGroups[this.state.tabbableGroups.length-1].lastTabbableNode:a=this.state.tabbableGroups[0].firstTabbableNode;else if(i){let d=this.state.tabbableGroups.findIndex(({firstTabbableNode:u})=>s===u);if(d<0&&(c?.container===s||St(s)&&!Yn(s)&&!c?.nextTabbableNode(s,false))&&(d=l),d>=0){let u=d===0?this.state.tabbableGroups.length-1:d-1,h=this.state.tabbableGroups[u];a=To(s)>=0?h.lastTabbableNode:h.lastDomTabbableNode;}else fh(o)||(a=c?.nextTabbableNode(s,false));}else {let d=this.state.tabbableGroups.findIndex(({lastTabbableNode:u})=>s===u);if(d<0&&(c?.container===s||St(s)&&!Yn(s)&&!c?.nextTabbableNode(s))&&(d=l),d>=0){let u=d===this.state.tabbableGroups.length-1?0:d+1,h=this.state.tabbableGroups[u];a=To(s)>=0?h.firstTabbableNode:h.firstDomTabbableNode;}else fh(o)||(a=c?.nextTabbableNode(s));}}else a=this.getNodeForOption("fallbackFocus");return a}),this.trapStack=e.trapStack||HM;let t={returnFocusOnDeactivate:true,escapeDeactivates:true,delayInitialFocus:true,followControlledElements:true,isKeyForward:zM,isKeyBackward:WM,...e};this.doc=t.document||Oe(Array.isArray(r)?r[0]:r),this.config=t,this.updateContainerElements(r),this.setupMutationObserver();}addPortalContainer(r){let e=r.parentElement;e&&!this.portalContainers.has(e)&&(this.portalContainers.add(e),this.state.active&&!this.state.paused&&this.observePortalContainer(e));}observePortalContainer(r){this._mutationObserver?.observe(r,{subtree:true,childList:true,attributes:true,attributeFilter:["aria-controls","aria-expanded"]});}updatePortalContainers(){this.config.followControlledElements&&this.state.containers.forEach(r=>{fg(r).forEach(t=>{this.addPortalContainer(t);});});}get active(){return this.state.active}get paused(){return this.state.paused}findContainerIndex(r,e){let t=typeof e?.composedPath=="function"?e.composedPath():void 0;return this.state.containerGroups.findIndex(({container:n,tabbableNodes:o})=>n.contains(r)||t?.includes(n)||o.find(i=>i===r)||this.isControlledElement(n,r))}isControlledElement(r,e){return this.config.followControlledElements?Ol(r,e):false}updateTabbableNodes(){if(this.state.containerGroups=this.state.containers.map(r=>{let e=So(r,{getShadowRoot:this.config.getShadowRoot}),t=Iu(r,{getShadowRoot:this.config.getShadowRoot}),n=e[0],o=e[e.length-1],i=n,s=o,a=false;for(let c=0;c0){a=true;break}function l(c,d=true){let u=e.indexOf(c);if(u>=0)return e[u+(d?1:-1)];let h=t.indexOf(c);if(!(h<0)){if(d){for(let p=h+1;p=0;p--)if(Yn(t[p]))return t[p]}}return {container:r,tabbableNodes:e,focusableNodes:t,posTabIndexesFound:a,firstTabbableNode:n,lastTabbableNode:o,firstDomTabbableNode:i,lastDomTabbableNode:s,nextTabbableNode:l}}),this.state.tabbableGroups=this.state.containerGroups.filter(r=>r.tabbableNodes.length>0),this.state.tabbableGroups.length<=0&&!this.getNodeForOption("fallbackFocus"))throw new Error("Your focus-trap must have at least one container with at least one tabbable node in it at all times");if(this.state.containerGroups.find(r=>r.posTabIndexesFound)&&this.state.containerGroups.length>1)throw new Error("At least one node with a positive tabindex was found in one of your focus-trap's multiple containers. Positive tabindexes are only supported in single-container focus-traps.")}addListeners(){if(this.state.active)return hy.activateTrap(this.trapStack,this),this.state.delayInitialFocusTimer=this.config.delayInitialFocus?py(()=>{this.tryFocus(this.getInitialFocusNode());}):this.tryFocus(this.getInitialFocusNode()),this.listenerCleanups.push(ot(this.doc,"focusin",this.handleFocus,true),ot(this.doc,"mousedown",this.handlePointerDown,{capture:true,passive:false}),ot(this.doc,"touchstart",this.handlePointerDown,{capture:true,passive:false}),ot(this.doc,"click",this.handleClick,{capture:true,passive:false}),ot(this.doc,"keydown",this.handleTabKey,{capture:true,passive:false}),ot(this.doc,"keydown",this.handleEscapeKey)),this}removeListeners(){if(this.state.active)return this.listenerCleanups.forEach(r=>r()),this.listenerCleanups=[],this}activate(r){if(this.state.active)return this;let e=this.getOption(r,"onActivate"),t=this.getOption(r,"onPostActivate"),n=this.getOption(r,"checkCanFocusTrap");n||this.updateTabbableNodes(),this.state.active=true,this.state.paused=false,this.state.nodeFocusedBeforeActivation=nn(this.doc),e?.();let o=()=>{n&&this.updateTabbableNodes(),this.addListeners(),this.updateObservedNodes(),t?.();};return n?(n(this.state.containers.concat()).then(o,o),this):(o(),this)}},gh=r=>r?.type==="keydown",fh=r=>gh(r)&&r?.key==="Tab",zM=r=>gh(r)&&r.key==="Tab"&&!r?.shiftKey,WM=r=>gh(r)&&r.key==="Tab"&&r?.shiftKey,bs=(r,...e)=>typeof r=="function"?r(...e):r,GM=r=>!r.isComposing&&r.key==="Escape",py=r=>setTimeout(r,0),$M=r=>r.localName==="input"&&"select"in r&&typeof r.select=="function";function fy(r,e={}){let t,n=Ve(()=>{let i=(Array.isArray(r)?r:[r]).map(a=>typeof a=="function"?a():a).filter(a=>a!=null);if(i.length===0)return;let s=i[0];t=new my(i,{escapeDeactivates:false,allowOutsideClick:true,preventScroll:true,returnFocusOnDeactivate:true,delayInitialFocus:false,fallbackFocus:s,...e,document:Oe(s)});try{t.activate();}catch{}});return function(){t?.deactivate(),n();}}var gy="data-scroll-lock",bh=new WeakMap;function UM(r){let e=r.getBoundingClientRect().left;return Math.round(e)+r.scrollLeft?"paddingLeft":"paddingRight"}function by(r){let t=wo(r)?.scrollbarGutter;return t==="stable"||t?.startsWith("stable ")===true}function YM(r){let e=r.defaultView??window,{documentElement:t,body:n}=r,o=by(t)||by(n),i=e.innerWidth-t.clientWidth;n.setAttribute(gy,"");let s=()=>_g(t,"--scrollbar-width",`${i}px`),a=UM(t),l=()=>{let u={overflow:"hidden"};return !o&&i>0&&(u[a]=`${i}px`),ji(n,u)},c=()=>{let{scrollX:u,scrollY:h,visualViewport:p}=e,m=p?.offsetLeft??0,f=p?.offsetTop??0,g={position:"fixed",overflow:"hidden",top:`${-(h-Math.floor(f))}px`,left:`${-(u-Math.floor(m))}px`,right:"0"};!o&&i>0&&(g[a]=`${i}px`);let b=ji(n,g);return ()=>{b?.(),e.scrollTo({left:u,top:h,behavior:"instant"});}},d=[s(),yg()?c():l()];return ()=>{d.forEach(u=>u?.()),n.removeAttribute(gy);}}function vy(r){let e=r??document,t=bh.get(e);t||(t={count:0,cleanup:YM(e)},bh.set(e,t)),t.count++;let n=t,o=false;return ()=>{o||(o=true,n.count--,n.count===0&&(n.cleanup(),bh.delete(e)));}}var vh=Al({props({props:r,scope:e}){let t=r.role==="alertdialog",n=t?()=>sy(e):void 0,o=typeof r.modal=="boolean"?r.modal:true;return {role:"dialog",modal:o,trapFocus:o,preventScroll:o,closeOnInteractOutside:o&&!t,closeOnEscape:true,restoreFocus:true,initialFocusEl:n,...r}},initialState({prop:r}){return r("open")||r("defaultOpen")?"open":"closed"},context({bindable:r,prop:e,scope:t}){return {rendered:r(()=>({defaultValue:{title:true,description:true}})),triggerValue:r(()=>({defaultValue:e("defaultTriggerValue")??null,value:e("triggerValue"),onChange(n){let o=e("onTriggerValueChange");if(!o)return;let i=hh(t,n);o({value:n,triggerElement:i});}}))}},watch({track:r,action:e,prop:t}){r([()=>t("open")],()=>{e(["toggleVisibility"]);});},states:{open:{entry:["checkRenderedElements","setInitialFocus"],effects:["trackDismissableElement","trapFocus","preventScroll","hideContentBelow"],on:{"CONTROLLED.CLOSE":{target:"closed"},CLOSE:[{guard:"isOpenControlled",actions:["invokeOnClose"]},{target:"closed",actions:["invokeOnClose"]}],TOGGLE:[{guard:"isOpenControlled",actions:["invokeOnClose"]},{target:"closed",actions:["invokeOnClose"]}],"TRIGGER_VALUE.SET":{actions:["setTriggerValue"]}}},closed:{on:{"CONTROLLED.OPEN":{target:"open"},OPEN:[{guard:"isOpenControlled",actions:["invokeOnOpen","setTriggerValue"]},{target:"open",actions:["invokeOnOpen","setTriggerValue"]}],TOGGLE:[{guard:"isOpenControlled",actions:["invokeOnOpen","setTriggerValue"]},{target:"open",actions:["invokeOnOpen","setTriggerValue"]}],"TRIGGER_VALUE.SET":{actions:["setTriggerValue"]}}}},implementations:{guards:{isOpenControlled:({prop:r})=>r("open")!=null},effects:{trackDismissableElement({scope:r,send:e,prop:t}){return cc(()=>gs(r),{type:"dialog",defer:true,pointerBlocking:t("modal"),layerStyleTargets:[()=>ry(r),()=>ny(r)],exclude:[uh(r),...vc(r)].filter(Boolean),onInteractOutside(o){t("onInteractOutside")?.(o),t("closeOnInteractOutside")||o.preventDefault();},persistentElements:t("persistentElements"),onFocusOutside:t("onFocusOutside"),onPointerDownOutside:t("onPointerDownOutside"),onRequestDismiss:t("onRequestDismiss"),onEscapeKeyDown(o){t("onEscapeKeyDown")?.(o),t("closeOnEscape")||o.preventDefault();},onDismiss(){e({type:"CLOSE",src:"interact-outside"});}})},preventScroll({scope:r,prop:e}){if(e("preventScroll"))return vy(r.getDoc())},trapFocus({scope:r,prop:e,context:t}){return e("trapFocus")?fy(()=>gs(r),{preventScroll:true,returnFocusOnDeactivate:!!e("restoreFocus"),initialFocus:e("initialFocusEl"),setReturnFocus:o=>{let i=e("finalFocusEl")?.();if(i)return i;let s=t.get("triggerValue");if(s){let l=hh(r,s);if(l)return l}let a=vc(r)[0];return a||o},getShadowRoot:true}):void 0},hideContentBelow({scope:r,prop:e}){return e("modal")?uy(()=>[gs(r)],{defer:true}):void 0}},actions:{setInitialFocus({prop:r,scope:e}){r("trapFocus")||Ve(()=>{Vl({root:gs(e),getInitialEl:r("initialFocusEl")})?.focus({preventScroll:true});});},checkRenderedElements({context:r,scope:e}){Ve(()=>{r.set("rendered",{title:!!oy(e),description:!!iy(e)});});},invokeOnClose({prop:r}){r("onOpenChange")?.({open:false});},invokeOnOpen({prop:r}){r("onOpenChange")?.({open:true});},setTriggerValue({context:r,event:e}){e.value!==void 0&&r.set("triggerValue",e.value);},toggleVisibility({prop:r,send:e,event:t}){e({type:r("open")?"CONTROLLED.OPEN":"CONTROLLED.CLOSE",previousEvent:t});}}}});function yy(r={}){return {machine:vh,props:{id:Kl("vela-dialog"),modal:r.modal??true,closeOnEscape:r.closeOnEscape??true,closeOnInteractOutside:r.closeOnInteractOutside??false,initialFocusEl:r.initialFocusEl,onOpenChange:e=>r.onOpenChange?.(e.open)},connect:e=>ph(e,Lo)}}var wy="vela-ui-dialog-5",xy=` +`;function iy(r){he(ny,ry,r);}function oy(r,e){let t=r.clientHeight,n=r.scrollHeight;if(n<=t){e.style.height="0";return}let o=Math.max(20,t/n*t),i=r.scrollTop/(n-t)*(t-o);e.style.height=`${Math.round(o)}px`,e.style.transform=`translateY(${Math.round(i)}px`;}function sy(r,e,t,n){r.replaceChildren();let o=r.ownerDocument.createElement("div");o.className="vela-select-items";for(let i of e){let s=r.ownerDocument.createElement("button");s.type="button",s.className="vela-select-item",s.textContent=i.label,i.value===t&&(s.dataset.checked="1"),s.addEventListener("click",a=>{a.stopPropagation(),n(i.value,i.label);}),o.appendChild(s);}r.appendChild(o);}function ay(r){let e=r.querySelector(".vela-select-items");if(e){if(e.scrollHeight>240){r.classList.add("is-scroll");let t=r.ownerDocument.createElement("div");t.className="vela-select-rail";let n=r.ownerDocument.createElement("div");n.className="vela-select-thumb",t.appendChild(n),r.appendChild(t),e.addEventListener("scroll",()=>oy(e,n)),oy(e,n);}r.querySelector(".vela-select-item[data-checked]")?.scrollIntoView({block:"nearest"}),e.dispatchEvent(new Event("scroll"));}}function bc(r,e,t,n,o={}){return En()===r?(Me(),null):ly(r,e,t,n,o)}function ly(r,e,t,n,o={}){iy(r.ownerDocument),Me();let i=new qe({trigger:r,theme:o.theme,matchWidth:o.matchWidth??true,boundary:o.boundary,boundaryInset:o.boundaryInset,gap:o.gap??4,align:o.align??"start",host:o.host,position:o.position,zIndex:o.zIndex,className:"vela-select-list",onClose:o.onClose,content:s=>{o.size&&(s.dataset.size=o.size),sy(s,e,t,(a,l)=>{i.hide(),n(a,l);});}});return i.show(),ay(i.el),i.reposition(),i}var ys=class{constructor(e){this.list=null;let t=e.list?.host?.ownerDocument??document;iy(t),this.ctrl=ty(e),this.listOpts={...e.list,theme:e.theme??e.list?.theme,size:this.ctrl.size};let n=t.createElement("div");n.className="vela-select",n.dataset.size=this.ctrl.size,this.ctrl.fill&&(n.dataset.fill="");let o=t.createElement("button");o.type="button",e.id&&(o.id=e.id),o.className="vela-select-trigger",this.ctrl.disabled&&(o.disabled=true);let i=t.createElement("span");i.className="vela-select-label",i.textContent=this.ctrl.labelOf(this.ctrl.value);let s=t.createElement("span");if(s.className="vela-select-chevron",s.appendChild(ze("chevron-down",t)),o.append(i,s),n.appendChild(o),this.ctrl.size==="sm"){let a=t.createElement("div");a.className="vela-select-sizer",a.setAttribute("aria-hidden","true");for(let l of this.ctrl.options){let c=t.createElement("span");c.textContent=l.label,a.appendChild(c);}n.appendChild(a);}o.addEventListener("pointerdown",a=>{a.preventDefault(),o.focus({preventScroll:true});}),o.addEventListener("click",a=>{a.stopPropagation(),this.toggle();}),this.el=n,this.trigger=o,this.labelEl=i;}get value(){return this.ctrl.value}setValue(e){this.ctrl.setValue(e),this.labelEl.textContent=this.ctrl.labelOf(e);}toggle(){this.list=bc(this.trigger,this.ctrl.options,this.ctrl.value,(e,t)=>{this.ctrl.pick(e),this.labelEl.textContent=t,this.list=null;},{...this.listOpts,onClose:()=>{this.list=null,this.listOpts.onClose?.();}});}destroy(){this.list?.hide(),this.list=null;}};var GM=Cn("dialog").parts("trigger","backdrop","positioner","content","title","description","closeTrigger"),Qn=GM.build();var hh=r=>r.ids?.positioner??`dialog:${r.id}:positioner`,ph=r=>r.ids?.backdrop??`dialog:${r.id}:backdrop`,vc=r=>r.ids?.content??`dialog:${r.id}:content`,yc=(r,e)=>{let t=r.ids?.trigger;return t!=null?pt(t)?t(e):t:e?`dialog:${r.id}:trigger:${e}`:`dialog:${r.id}:trigger`},wc=r=>r.ids?.title??`dialog:${r.id}:title`,xc=r=>r.ids?.description??`dialog:${r.id}:description`,mh=r=>r.ids?.closeTrigger??`dialog:${r.id}:close`,ws=r=>r.getById(vc(r)),cy=r=>r.getById(hh(r)),dy=r=>r.getById(ph(r)),fh=r=>r.getById(yc(r)),uy=r=>r.getById(wc(r)),hy=r=>r.getById(xc(r)),py=r=>r.getById(mh(r)),Sc=r=>Po(r.getRootNode(),`[data-scope="dialog"][data-part="trigger"][data-ownedby="${r.id}"]`),gh=(r,e)=>e==null?fh(r)??Sc(r)[0]:r.getById(yc(r,e));function bh(r,e){let{state:t,send:n,context:o,prop:i,scope:s}=r,a=i("aria-label"),l=t.matches("open"),c=o.get("triggerValue");return {open:l,setOpen(d){t.matches("open")!==d&&n({type:d?"OPEN":"CLOSE"});},triggerValue:c,setTriggerValue(d){n({type:"TRIGGER_VALUE.SET",value:d});},getTriggerProps(d={}){let{value:u}=d,h=u==null?false:c===u;return e.button({...Qn.trigger.attrs,dir:i("dir"),id:yc(s,u),"data-ownedby":s.id,"data-value":u,"aria-haspopup":"dialog",type:"button","aria-expanded":u==null?l:l&&h,"data-state":l?"open":"closed","aria-controls":vc(s),"data-current":St(h),onClick(p){if(p.defaultPrevented)return;let m=l&&u!=null&&!h;n({type:m?"TRIGGER_VALUE.SET":"TOGGLE",value:u});}})},getBackdropProps(){return e.element({...Qn.backdrop.attrs,dir:i("dir"),hidden:!l,id:ph(s),"data-state":l?"open":"closed"})},getPositionerProps(){return e.element({...Qn.positioner.attrs,dir:i("dir"),id:hh(s),style:$n({pointerEvents:!l||!i("modal")?"none":void 0})})},getContentProps(){let d=o.get("rendered");return e.element({...Qn.content.attrs,dir:i("dir"),role:i("role"),hidden:!l,id:vc(s),tabIndex:-1,"data-state":l?"open":"closed","aria-modal":i("modal"),"aria-label":a||void 0,"aria-labelledby":a||!d.title?void 0:wc(s),"aria-describedby":d.description?xc(s):void 0,style:$n({pointerEvents:i("modal")?void 0:"auto"})})},getTitleProps(){return e.element({...Qn.title.attrs,dir:i("dir"),id:wc(s)})},getDescriptionProps(){return e.element({...Qn.description.attrs,dir:i("dir"),id:xc(s)})},getCloseTriggerProps(){return e.button({...Qn.closeTrigger.attrs,dir:i("dir"),id:mh(s),type:"button",onClick(d){d.defaultPrevented||(d.stopPropagation(),n({type:"CLOSE"}));}})}}}var _o=new WeakMap,Cc=new WeakMap,Tc={},vh=0,fy=r=>r&&(r.host||fy(r.parentNode)),$M=(r,e)=>e.map(t=>{if(r.contains(t))return t;let n=fy(t);return n&&r.contains(n)?n:(console.error("[zag-js > ariaHidden] target",t,"in not contained inside",r,". Doing nothing"),null)}).filter(t=>!!t),UM=new Set(["script","output","status","next-route-announcer"]),YM=r=>UM.has(r.localName)||r.role==="status"||r.hasAttribute("aria-live")?true:r.matches("[data-live-announcer]"),gy=(r,e)=>{let{parentNode:t,markerName:n,controlAttribute:o,explicitBooleanValue:i,followControlledElements:s=true}=e,a=$M(t,Array.isArray(r)?r:[r]);Tc[n]||(Tc[n]=new WeakMap);let l=Tc[n],c=[],d=new Set,u=new Set(a),h=m=>{!m||d.has(m)||(d.add(m),h(m.parentNode));};a.forEach(m=>{h(m),s&&me(m)&&Lu(m,f=>{h(f);});});let p=m=>{!m||u.has(m)||Array.prototype.forEach.call(m.children,f=>{if(d.has(f))p(f);else try{if(YM(f))return;let g=f.getAttribute(o),b=i?g==="true":g!==null&&g!=="false",y=(_o.get(f)||0)+1,w=(l.get(f)||0)+1;_o.set(f,y),l.set(f,w),c.push(f),y===1&&b&&Cc.set(f,!0),w===1&&f.setAttribute(n,""),b||f.setAttribute(o,i?"true":"");}catch(g){console.error("[zag-js > ariaHidden] cannot operate on ",f,g);}});};return p(t),d.clear(),vh++,()=>{c.forEach(m=>{let f=_o.get(m)-1,g=l.get(m)-1;_o.set(m,f),l.set(m,g),f||(Cc.has(m)||m.removeAttribute(o),Cc.delete(m)),g||m.removeAttribute(n);}),vh--,vh||(_o=new WeakMap,_o=new WeakMap,Cc=new WeakMap,Tc={});}};var KM=r=>(Array.isArray(r)?r[0]:r).ownerDocument.body,by=(r,e=KM(r),t="data-aria-hidden",n=true)=>{if(e)return gy(r,{parentNode:e,markerName:t,controlAttribute:"aria-hidden",explicitBooleanValue:true,followControlledElements:n})};var XM=r=>{let e=requestAnimationFrame(()=>r());return ()=>cancelAnimationFrame(e)};function vy(r,e={}){let{defer:t=true}=e,n=t?XM:i=>i(),o=[];return o.push(n(()=>{let s=(typeof r=="function"?r():r).filter(Boolean);s.length!==0&&o.push(by(s));})),()=>{o.forEach(i=>i?.());}}var jM=Object.defineProperty,qM=(r,e,t)=>e in r?jM(r,e,{enumerable:true,configurable:true,writable:true,value:t}):r[e]=t,ke=(r,e,t)=>qM(r,typeof e!="symbol"?e+"":e,t);var yy={activateTrap(r,e){if(r.length>0){let n=r[r.length-1];n!==e&&n.pause();}let t=r.indexOf(e);t===-1||r.splice(t,1),r.push(e);},deactivateTrap(r,e){let t=r.indexOf(e);t!==-1&&r.splice(t,1),r.length>0&&r[r.length-1].unpause();}},ZM=[],xy=class{constructor(r,e){ke(this,"trapStack"),ke(this,"config"),ke(this,"doc"),ke(this,"state",{containers:[],containerGroups:[],tabbableGroups:[],nodeFocusedBeforeActivation:null,mostRecentlyFocusedNode:null,active:false,paused:false,delayInitialFocusTimer:void 0,recentNavEvent:void 0}),ke(this,"portalContainers",new Set),ke(this,"listenerCleanups",[]),ke(this,"handleFocus",n=>{let o=He(n),i=this.findContainerIndex(o,n)>=0;if(i||Zi(o))i&&(this.state.mostRecentlyFocusedNode=o);else {n.stopImmediatePropagation();let s,a=true;if(this.state.mostRecentlyFocusedNode)if(Eo(this.state.mostRecentlyFocusedNode)>0){let l=this.findContainerIndex(this.state.mostRecentlyFocusedNode),{tabbableNodes:c}=this.state.containerGroups[l];if(c.length>0){let d=c.findIndex(u=>u===this.state.mostRecentlyFocusedNode);d>=0&&(this.config.isKeyForward(this.state.recentNavEvent)?d+1=0&&(s=c[d-1],a=false));}}else this.state.containerGroups.some(l=>l.tabbableNodes.some(c=>Eo(c)>0))||(a=false);else a=false;a&&(s=this.findNextNavNode({target:this.state.mostRecentlyFocusedNode,isBackward:this.config.isKeyBackward(this.state.recentNavEvent)})),s?this.tryFocus(s):this.tryFocus(this.state.mostRecentlyFocusedNode||this.getInitialFocusNode());}this.state.recentNavEvent=void 0;}),ke(this,"handlePointerDown",n=>{let o=He(n);if(!(this.findContainerIndex(o,n)>=0)){if(xs(this.config.clickOutsideDeactivates,n)){this.deactivate({returnFocus:this.config.returnFocusOnDeactivate});return}xs(this.config.allowOutsideClick,n)||n.preventDefault();}}),ke(this,"handleClick",n=>{let o=He(n);this.findContainerIndex(o,n)>=0||xs(this.config.clickOutsideDeactivates,n)||xs(this.config.allowOutsideClick,n)||(n.preventDefault(),n.stopImmediatePropagation());}),ke(this,"handleTabKey",n=>{if(this.config.isKeyForward(n)||this.config.isKeyBackward(n)){this.state.recentNavEvent=n;let o=this.config.isKeyBackward(n),i=this.findNextNavNode({event:n,isBackward:o});if(!i)return;yh(n)&&n.preventDefault(),this.tryFocus(i);}}),ke(this,"handleEscapeKey",n=>{eE(n)&&xs(this.config.escapeDeactivates,n)!==false&&(n.preventDefault(),this.deactivate());}),ke(this,"_mutationObserver"),ke(this,"setupMutationObserver",()=>{let n=this.doc.defaultView||window;this._mutationObserver=new n.MutationObserver(o=>{o.some(a=>Array.from(a.removedNodes).some(c=>c===this.state.mostRecentlyFocusedNode))&&this.tryFocus(this.getInitialFocusNode()),o.some(a=>a.type==="attributes"&&(a.attributeName==="aria-controls"||a.attributeName==="aria-expanded")?true:a.type==="childList"&&a.addedNodes.length>0?Array.from(a.addedNodes).some(l=>{if(l.nodeType!==Node.ELEMENT_NODE)return false;let c=l;return Sg(c)?true:c.id&&!this.state.containers.some(d=>d.contains(c))?Cg(c):false}):false)&&this.state.active&&!this.state.paused&&(this.updateTabbableNodes(),this.updatePortalContainers());});}),ke(this,"updateObservedNodes",()=>{this._mutationObserver?.disconnect(),this.state.active&&!this.state.paused&&(this.state.containers.map(n=>{this._mutationObserver?.observe(n,{subtree:true,childList:true,attributes:true,attributeFilter:["aria-controls","aria-expanded"]});}),this.portalContainers.forEach(n=>{this.observePortalContainer(n);}));}),ke(this,"getInitialFocusNode",()=>{let n=this.getNodeForOption("initialFocus",{hasFallback:true});if(n===false)return false;if(n===void 0||n&&!Ct(n)){let o=rn(this.doc);if(o&&this.findContainerIndex(o)>=0)n=o;else {let i=this.state.tabbableGroups[0];n=i&&i.firstTabbableNode||this.getNodeForOption("fallbackFocus");}}else n===null&&(n=this.getNodeForOption("fallbackFocus"));if(!n)throw new Error("Your focus-trap needs to have at least one focusable element");if(n.isConnected||(n=this.getNodeForOption("fallbackFocus")),!n||!n.isConnected)throw new Error("Your focus-trap needs to have at least one focusable element");return n}),ke(this,"tryFocus",n=>{if(n!==false&&n!==rn(this.doc)){if(!n||!n.focus){this.tryFocus(this.getInitialFocusNode());return}n.focus({preventScroll:!!this.config.preventScroll}),this.state.mostRecentlyFocusedNode=n,tE(n)&&n.select();}}),ke(this,"deactivate",n=>{if(!this.state.active)return this;let o={onDeactivate:this.config.onDeactivate,onPostDeactivate:this.config.onPostDeactivate,checkCanReturnFocus:this.config.checkCanReturnFocus,...n};clearTimeout(this.state.delayInitialFocusTimer),this.state.delayInitialFocusTimer=void 0,this.removeListeners(),this.state.active=false,this.state.paused=false,this.updateObservedNodes(),yy.deactivateTrap(this.trapStack,this),this.portalContainers.clear();let i=this.getOption(o,"onDeactivate"),s=this.getOption(o,"onPostDeactivate"),a=this.getOption(o,"checkCanReturnFocus"),l=this.getOption(o,"returnFocus","returnFocusOnDeactivate");i?.();let c=()=>{wy(()=>{if(l){let d=this.getReturnFocusNode(this.state.nodeFocusedBeforeActivation);this.tryFocus(d);}s?.();});};if(l&&a){let d=this.getReturnFocusNode(this.state.nodeFocusedBeforeActivation);return a(d).then(c,c),this}return c(),this}),ke(this,"pause",n=>{if(this.state.paused||!this.state.active)return this;let o=this.getOption(n,"onPause"),i=this.getOption(n,"onPostPause");return this.state.paused=true,o?.(),this.removeListeners(),this.updateObservedNodes(),i?.(),this}),ke(this,"unpause",n=>{if(!this.state.paused||!this.state.active)return this;let o=this.getOption(n,"onUnpause"),i=this.getOption(n,"onPostUnpause");return this.state.paused=false,o?.(),this.updateTabbableNodes(),this.addListeners(),this.updateObservedNodes(),i?.(),this}),ke(this,"updateContainerElements",n=>(this.state.containers=Array.isArray(n)?n.filter(Boolean):[n].filter(Boolean),this.state.active&&this.updateTabbableNodes(),this.updateObservedNodes(),this)),ke(this,"getReturnFocusNode",n=>{let o=this.getNodeForOption("setReturnFocus",{params:[n]});return o||(o===false?false:n)}),ke(this,"getOption",(n,o,i)=>n&&n[o]!==void 0?n[o]:this.config[i||o]),ke(this,"getNodeForOption",(n,{hasFallback:o=false,params:i=[]}={})=>{let s=this.config[n];if(typeof s=="function"&&(s=s(...i)),s===true&&(s=void 0),!s){if(s===void 0||s===false)return s;throw new Error(`\`${n}\` was specified but was not a node, or did not return a node`)}let a=s;if(typeof s=="string"){try{a=this.doc.querySelector(s);}catch(l){throw new Error(`\`${n}\` appears to be an invalid selector; error="${l.message}"`)}if(!a&&!o)throw new Error(`\`${n}\` as selector refers to no known node`)}return a}),ke(this,"findNextNavNode",n=>{let{event:o,isBackward:i=false}=n,s=n.target||He(o);this.updateTabbableNodes();let a=null;if(this.state.tabbableGroups.length>0){let l=this.findContainerIndex(s,o),c=l>=0?this.state.containerGroups[l]:void 0;if(l<0)i?a=this.state.tabbableGroups[this.state.tabbableGroups.length-1].lastTabbableNode:a=this.state.tabbableGroups[0].firstTabbableNode;else if(i){let d=this.state.tabbableGroups.findIndex(({firstTabbableNode:u})=>s===u);if(d<0&&(c?.container===s||Ct(s)&&!Yn(s)&&!c?.nextTabbableNode(s,false))&&(d=l),d>=0){let u=d===0?this.state.tabbableGroups.length-1:d-1,h=this.state.tabbableGroups[u];a=Eo(s)>=0?h.lastTabbableNode:h.lastDomTabbableNode;}else yh(o)||(a=c?.nextTabbableNode(s,false));}else {let d=this.state.tabbableGroups.findIndex(({lastTabbableNode:u})=>s===u);if(d<0&&(c?.container===s||Ct(s)&&!Yn(s)&&!c?.nextTabbableNode(s))&&(d=l),d>=0){let u=d===this.state.tabbableGroups.length-1?0:d+1,h=this.state.tabbableGroups[u];a=Eo(s)>=0?h.firstTabbableNode:h.firstDomTabbableNode;}else yh(o)||(a=c?.nextTabbableNode(s));}}else a=this.getNodeForOption("fallbackFocus");return a}),this.trapStack=e.trapStack||ZM;let t={returnFocusOnDeactivate:true,escapeDeactivates:true,delayInitialFocus:true,followControlledElements:true,isKeyForward:QM,isKeyBackward:JM,...e};this.doc=t.document||Oe(Array.isArray(r)?r[0]:r),this.config=t,this.updateContainerElements(r),this.setupMutationObserver();}addPortalContainer(r){let e=r.parentElement;e&&!this.portalContainers.has(e)&&(this.portalContainers.add(e),this.state.active&&!this.state.paused&&this.observePortalContainer(e));}observePortalContainer(r){this._mutationObserver?.observe(r,{subtree:true,childList:true,attributes:true,attributeFilter:["aria-controls","aria-expanded"]});}updatePortalContainers(){this.config.followControlledElements&&this.state.containers.forEach(r=>{xg(r).forEach(t=>{this.addPortalContainer(t);});});}get active(){return this.state.active}get paused(){return this.state.paused}findContainerIndex(r,e){let t=typeof e?.composedPath=="function"?e.composedPath():void 0;return this.state.containerGroups.findIndex(({container:n,tabbableNodes:o})=>n.contains(r)||t?.includes(n)||o.find(i=>i===r)||this.isControlledElement(n,r))}isControlledElement(r,e){return this.config.followControlledElements?Vl(r,e):false}updateTabbableNodes(){if(this.state.containerGroups=this.state.containers.map(r=>{let e=Mo(r,{getShadowRoot:this.config.getShadowRoot}),t=Du(r,{getShadowRoot:this.config.getShadowRoot}),n=e[0],o=e[e.length-1],i=n,s=o,a=false;for(let c=0;c0){a=true;break}function l(c,d=true){let u=e.indexOf(c);if(u>=0)return e[u+(d?1:-1)];let h=t.indexOf(c);if(!(h<0)){if(d){for(let p=h+1;p=0;p--)if(Yn(t[p]))return t[p]}}return {container:r,tabbableNodes:e,focusableNodes:t,posTabIndexesFound:a,firstTabbableNode:n,lastTabbableNode:o,firstDomTabbableNode:i,lastDomTabbableNode:s,nextTabbableNode:l}}),this.state.tabbableGroups=this.state.containerGroups.filter(r=>r.tabbableNodes.length>0),this.state.tabbableGroups.length<=0&&!this.getNodeForOption("fallbackFocus"))throw new Error("Your focus-trap must have at least one container with at least one tabbable node in it at all times");if(this.state.containerGroups.find(r=>r.posTabIndexesFound)&&this.state.containerGroups.length>1)throw new Error("At least one node with a positive tabindex was found in one of your focus-trap's multiple containers. Positive tabindexes are only supported in single-container focus-traps.")}addListeners(){if(this.state.active)return yy.activateTrap(this.trapStack,this),this.state.delayInitialFocusTimer=this.config.delayInitialFocus?wy(()=>{this.tryFocus(this.getInitialFocusNode());}):this.tryFocus(this.getInitialFocusNode()),this.listenerCleanups.push(ot(this.doc,"focusin",this.handleFocus,true),ot(this.doc,"mousedown",this.handlePointerDown,{capture:true,passive:false}),ot(this.doc,"touchstart",this.handlePointerDown,{capture:true,passive:false}),ot(this.doc,"click",this.handleClick,{capture:true,passive:false}),ot(this.doc,"keydown",this.handleTabKey,{capture:true,passive:false}),ot(this.doc,"keydown",this.handleEscapeKey)),this}removeListeners(){if(this.state.active)return this.listenerCleanups.forEach(r=>r()),this.listenerCleanups=[],this}activate(r){if(this.state.active)return this;let e=this.getOption(r,"onActivate"),t=this.getOption(r,"onPostActivate"),n=this.getOption(r,"checkCanFocusTrap");n||this.updateTabbableNodes(),this.state.active=true,this.state.paused=false,this.state.nodeFocusedBeforeActivation=rn(this.doc),e?.();let o=()=>{n&&this.updateTabbableNodes(),this.addListeners(),this.updateObservedNodes(),t?.();};return n?(n(this.state.containers.concat()).then(o,o),this):(o(),this)}},wh=r=>r?.type==="keydown",yh=r=>wh(r)&&r?.key==="Tab",QM=r=>wh(r)&&r.key==="Tab"&&!r?.shiftKey,JM=r=>wh(r)&&r.key==="Tab"&&r?.shiftKey,xs=(r,...e)=>typeof r=="function"?r(...e):r,eE=r=>!r.isComposing&&r.key==="Escape",wy=r=>setTimeout(r,0),tE=r=>r.localName==="input"&&"select"in r&&typeof r.select=="function";function Sy(r,e={}){let t,n=Ve(()=>{let i=(Array.isArray(r)?r:[r]).map(a=>typeof a=="function"?a():a).filter(a=>a!=null);if(i.length===0)return;let s=i[0];t=new xy(i,{escapeDeactivates:false,allowOutsideClick:true,preventScroll:true,returnFocusOnDeactivate:true,delayInitialFocus:false,fallbackFocus:s,...e,document:Oe(s)});try{t.activate();}catch{}});return function(){t?.deactivate(),n();}}var Cy="data-scroll-lock",xh=new WeakMap;function nE(r){let e=r.getBoundingClientRect().left;return Math.round(e)+r.scrollLeft?"paddingLeft":"paddingRight"}function Ty(r){let t=To(r)?.scrollbarGutter;return t==="stable"||t?.startsWith("stable ")===true}function rE(r){let e=r.defaultView??window,{documentElement:t,body:n}=r,o=Ty(t)||Ty(n),i=e.innerWidth-t.clientWidth;n.setAttribute(Cy,"");let s=()=>Ug(t,"--scrollbar-width",`${i}px`),a=nE(t),l=()=>{let u={overflow:"hidden"};return !o&&i>0&&(u[a]=`${i}px`),Ji(n,u)},c=()=>{let{scrollX:u,scrollY:h,visualViewport:p}=e,m=p?.offsetLeft??0,f=p?.offsetTop??0,g={position:"fixed",overflow:"hidden",top:`${-(h-Math.floor(f))}px`,left:`${-(u-Math.floor(m))}px`,right:"0"};!o&&i>0&&(g[a]=`${i}px`);let b=Ji(n,g);return ()=>{b?.(),e.scrollTo({left:u,top:h,behavior:"instant"});}},d=[s(),kg()?c():l()];return ()=>{d.forEach(u=>u?.()),n.removeAttribute(Cy);}}function ky(r){let e=r??document,t=xh.get(e);t||(t={count:0,cleanup:rE(e)},xh.set(e,t)),t.count++;let n=t,o=false;return ()=>{o||(o=true,n.count--,n.count===0&&(n.cleanup(),xh.delete(e)));}}var Sh=Ol({props({props:r,scope:e}){let t=r.role==="alertdialog",n=t?()=>py(e):void 0,o=typeof r.modal=="boolean"?r.modal:true;return {role:"dialog",modal:o,trapFocus:o,preventScroll:o,closeOnInteractOutside:o&&!t,closeOnEscape:true,restoreFocus:true,initialFocusEl:n,...r}},initialState({prop:r}){return r("open")||r("defaultOpen")?"open":"closed"},context({bindable:r,prop:e,scope:t}){return {rendered:r(()=>({defaultValue:{title:true,description:true}})),triggerValue:r(()=>({defaultValue:e("defaultTriggerValue")??null,value:e("triggerValue"),onChange(n){let o=e("onTriggerValueChange");if(!o)return;let i=gh(t,n);o({value:n,triggerElement:i});}}))}},watch({track:r,action:e,prop:t}){r([()=>t("open")],()=>{e(["toggleVisibility"]);});},states:{open:{entry:["checkRenderedElements","setInitialFocus"],effects:["trackDismissableElement","trapFocus","preventScroll","hideContentBelow"],on:{"CONTROLLED.CLOSE":{target:"closed"},CLOSE:[{guard:"isOpenControlled",actions:["invokeOnClose"]},{target:"closed",actions:["invokeOnClose"]}],TOGGLE:[{guard:"isOpenControlled",actions:["invokeOnClose"]},{target:"closed",actions:["invokeOnClose"]}],"TRIGGER_VALUE.SET":{actions:["setTriggerValue"]}}},closed:{on:{"CONTROLLED.OPEN":{target:"open"},OPEN:[{guard:"isOpenControlled",actions:["invokeOnOpen","setTriggerValue"]},{target:"open",actions:["invokeOnOpen","setTriggerValue"]}],TOGGLE:[{guard:"isOpenControlled",actions:["invokeOnOpen","setTriggerValue"]},{target:"open",actions:["invokeOnOpen","setTriggerValue"]}],"TRIGGER_VALUE.SET":{actions:["setTriggerValue"]}}}},implementations:{guards:{isOpenControlled:({prop:r})=>r("open")!=null},effects:{trackDismissableElement({scope:r,send:e,prop:t}){return hc(()=>ws(r),{type:"dialog",defer:true,pointerBlocking:t("modal"),layerStyleTargets:[()=>dy(r),()=>cy(r)],exclude:[fh(r),...Sc(r)].filter(Boolean),onInteractOutside(o){t("onInteractOutside")?.(o),t("closeOnInteractOutside")||o.preventDefault();},persistentElements:t("persistentElements"),onFocusOutside:t("onFocusOutside"),onPointerDownOutside:t("onPointerDownOutside"),onRequestDismiss:t("onRequestDismiss"),onEscapeKeyDown(o){t("onEscapeKeyDown")?.(o),t("closeOnEscape")||o.preventDefault();},onDismiss(){e({type:"CLOSE",src:"interact-outside"});}})},preventScroll({scope:r,prop:e}){if(e("preventScroll"))return ky(r.getDoc())},trapFocus({scope:r,prop:e,context:t}){return e("trapFocus")?Sy(()=>ws(r),{preventScroll:true,returnFocusOnDeactivate:!!e("restoreFocus"),initialFocus:e("initialFocusEl"),setReturnFocus:o=>{let i=e("finalFocusEl")?.();if(i)return i;let s=t.get("triggerValue");if(s){let l=gh(r,s);if(l)return l}let a=Sc(r)[0];return a||o},getShadowRoot:true}):void 0},hideContentBelow({scope:r,prop:e}){return e("modal")?vy(()=>[ws(r)],{defer:true}):void 0}},actions:{setInitialFocus({prop:r,scope:e}){r("trapFocus")||Ve(()=>{Hl({root:ws(e),getInitialEl:r("initialFocusEl")})?.focus({preventScroll:true});});},checkRenderedElements({context:r,scope:e}){Ve(()=>{r.set("rendered",{title:!!uy(e),description:!!hy(e)});});},invokeOnClose({prop:r}){r("onOpenChange")?.({open:false});},invokeOnOpen({prop:r}){r("onOpenChange")?.({open:true});},setTriggerValue({context:r,event:e}){e.value!==void 0&&r.set("triggerValue",e.value);},toggleVisibility({prop:r,send:e,event:t}){e({type:r("open")?"CONTROLLED.OPEN":"CONTROLLED.CLOSE",previousEvent:t});}}}});function Ly(r={}){return {machine:Sh,props:{id:ql("vela-dialog"),modal:r.modal??true,closeOnEscape:r.closeOnEscape??true,closeOnInteractOutside:r.closeOnInteractOutside??false,initialFocusEl:r.initialFocusEl,onOpenChange:e=>r.onOpenChange?.(e.open)},connect:e=>bh(e,Io)}}var My="vela-ui-dialog-5",Ey=` .vela-dialog-backdrop { position: fixed; inset: 0; @@ -403,11 +432,11 @@ ${CL} .vela-dialog-btn:hover { background: var(--vela-hover); color: var(--vela-fg-bright); border-color: var(--vela-fg-muted); } .vela-dialog-btn-primary { border-color: var(--vela-selected-bg); background: var(--vela-selected-bg); color: var(--vela-selected-fg); } .vela-dialog-btn-primary:hover { background: var(--vela-selected-bg); color: var(--vela-selected-fg); opacity: 0.85; border-color: var(--vela-selected-bg); } -${Ir(".vela-dialog-body")} +${Or(".vela-dialog-body")} /* Scrollers NESTED in a dialog (a flush body's grid, a tab pane) get the same thin overlay bars \u2014 the two-class selectors below stay overridable by more specific per-dialog sheets. */ -${Ir(".vela-dialog *")} +${Or(".vela-dialog *")} /* \u2500\u2500 mobile chrome: dialogs fill the shell \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 Inside a shell in the mobile size class ([data-layout='mobile'] on the widget root, which is position:relative) every kit dialog presents fullscreen: desktop cards are @@ -431,7 +460,7 @@ ${Ir(".vela-dialog *")} } [data-layout='mobile'] .vela-dialog-close { width: 40px; height: 40px; } [data-layout='mobile'] .vela-dialog-body { padding-bottom: calc(var(--vela-space-4) + env(safe-area-inset-bottom, 0px)); } -`;var En=class{constructor(e={}){let t=(e.host??document.body).ownerDocument;he(wy,xy,t);let n=e.host??t.body;if(this.backdrop=t.createElement("div"),this.backdrop.className="vela-dialog-backdrop vela-ui-layer",e.dimBackdrop!==true&&this.backdrop.classList.add("vela-dialog-backdrop--clear"),this.positioner=t.createElement("div"),this.positioner.className="vela-dialog-positioner vela-ui-layer",e.contained&&(this.backdrop.dataset.contained="",this.positioner.dataset.contained=""),this.positioner.dataset.align=e.align??"top",this.panel=t.createElement("div"),this.panel.className="vela-dialog",e.className)for(let l of e.className.split(/\s+/))l&&this.panel.classList.add(l);this.panel.tabIndex=-1,this.panel.addEventListener("keydown",l=>{l.key!=="Escape"&&l.stopPropagation();});let o=t.createElement("div");if(o.className="vela-dialog-header",e.draggable){o.style.cursor="move";let l=0,c=0,d=0,u=0,h=false;o.addEventListener("pointerdown",p=>{p.target.closest(".vela-dialog-close")||(h=true,l=p.clientX-d,c=p.clientY-u,o.setPointerCapture(p.pointerId));}),o.addEventListener("pointermove",p=>{h&&(d=p.clientX-l,u=p.clientY-c,this.panel.style.transform=`translate(${d}px, ${u}px)`);}),o.addEventListener("pointerup",()=>h=false);}e.headerStart&&o.appendChild(e.headerStart);let i=t.createElement("div");i.className="vela-dialog-title",i.textContent=e.title??"",this.titleEl=i;let s=t.createElement("button");if(s.className="vela-dialog-close",s.appendChild(Ue("close",t)),o.append(i,s),this.body=t.createElement("div"),this.body.className="vela-dialog-body",e.flush&&(this.body.dataset.flush=""),e.content instanceof Node?this.body.appendChild(e.content):typeof e.content=="function"&&e.content(this.body),this.panel.append(o,this.body),e.footer){let l=t.createElement("div");l.className="vela-dialog-footer",e.footer instanceof Node?l.appendChild(e.footer):e.footer(l),this.panel.appendChild(l),this.footer=l;}else this.footer=null;if(this.positioner.appendChild(this.panel),n.append(this.backdrop,this.positioner),e.closeOnBackdrop){let l=c=>{if(!(c.target!==this.backdrop&&c.target!==this.positioner)){if(dn()||Br(c)){Me();return}this.hide();}};this.backdrop.addEventListener("pointerdown",l),this.positioner.addEventListener("pointerdown",l);}this.ctrl=yy({...e,initialFocusEl:()=>this.positioner.closest('[data-layout="mobile"]')?this.panel:e.initialFocusEl?.()??null});let a=String(this.ctrl.props.id);this.handle=Yl(this.ctrl.machine,this.ctrl.props,l=>{let c=this.ctrl.connect(l);ft(this.backdrop,c.getBackdropProps(),a),ft(this.positioner,c.getPositionerProps(),a),ft(this.panel,c.getContentProps(),a),ft(i,c.getTitleProps(),a),ft(s,c.getCloseTriggerProps(),a),this.backdrop.style.display=c.open?"":"none",this.positioner.style.display=c.open?"":"none";});}get open(){return this.ctrl.connect(this.handle.service).open}show(){this.ctrl.connect(this.handle.service).setOpen(true);}hide(){this.ctrl.connect(this.handle.service).setOpen(false);}contains(e){return e==null?false:this.panel.contains(e)||this.backdrop.contains(e)||this.positioner.contains(e)?true:(e instanceof Element?e:e.parentElement)?.closest(".vela-popover, .vela-menu")!=null}destroy(){this.open&&this.hide(),this.handle.stop(),this.backdrop.remove(),this.positioner.remove();}};var XM=["January","February","March","April","May","June","July","August","September","October","November","December"],jM=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],Cy=["Su","Mo","Tu","We","Th","Fr","Sa"];function Fo(r){return `${r.getFullYear()}-${String(r.getMonth()+1).padStart(2,"0")}-${String(r.getDate()).padStart(2,"0")}`}function xc(r){let e=/^(\d{4})-(\d{1,2})-(\d{1,2})$/.exec(r.trim());if(!e)return null;let t=Number(e[1]),n=Number(e[2]),o=Number(e[3]),i=new Date(t,n-1,o);return i.getFullYear()!==t||i.getMonth()!==n-1||i.getDate()!==o?null:Fo(i)}function yh(r){let e=r?xc(r):null;if(!e)return null;let[t,n,o]=e.split("-").map(Number);return new Date(t,n-1,o)}function wh(r={}){let e=r.today??new Date,t=yh(r.value),n=t?.getFullYear()??e.getFullYear(),o=t?.getMonth()??e.getMonth(),i="date",s=()=>Math.floor(n/10)*10;return {get panel(){return i},get year(){return n},get month(){return o},get value(){return t?Fo(t):null},header(){return {month:XM[o]??"",monthVisible:i==="date",year:i==="year"?`${s()}-${s()+9}`:String(n),yearDisabled:i==="year"}},navLabels(){return i==="date"?{prev:"Previous month",next:"Next month"}:i==="month"?{prev:"Previous year",next:"Next year"}:{prev:"Previous decade",next:"Next decade"}},cells(){let a=[];if(i==="date"){let c=new Date(n,o,1).getDay(),d=new Date(n,o+1,0).getDate(),u=Fo(e),h=t?Fo(t):"";for(let p=0;pl+9});return a},step(a){i==="date"?(o+=a,o<0&&(o=11,n-=1),o>11&&(o=0,n+=1)):n+=i==="month"?a:a*10;},showMonths(){i="month";},showYears(){i="year";},choose(a){return a.blank?null:i==="date"?(t=yh(String(a.value)),t?Fo(t):null):i==="month"?(o=Number(a.value),i="date",null):(n=Number(a.value),i="month",null)},setValue(a){t=yh(a),t&&(n=t.getFullYear(),o=t.getMonth()),i="date";}}}var Sy="vela-date-picker-styles",Ty=` +`;var Pn=class{constructor(e={}){this.opener=null;this.wasOpen=false;this.exit=null;this.destroyed=false;let t=(e.host??document.body).ownerDocument;he(My,Ey,t);let n=e.host??t.body;if(this.backdrop=t.createElement("div"),this.backdrop.className="vela-dialog-backdrop vela-ui-layer",e.dimBackdrop!==true&&this.backdrop.classList.add("vela-dialog-backdrop--clear"),this.positioner=t.createElement("div"),this.positioner.className="vela-dialog-positioner vela-ui-layer",e.contained&&(this.backdrop.dataset.contained="",this.positioner.dataset.contained=""),this.positioner.dataset.align=e.align??"top",this.panel=t.createElement("div"),this.panel.className="vela-dialog",e.className)for(let l of e.className.split(/\s+/))l&&this.panel.classList.add(l);this.panel.tabIndex=-1,this.panel.addEventListener("keydown",l=>{l.key!=="Escape"&&l.stopPropagation();});let o=t.createElement("div");if(o.className="vela-dialog-header",e.draggable){o.style.cursor="move";let l=0,c=0,d=0,u=0,h=false;o.addEventListener("pointerdown",p=>{p.target.closest(".vela-dialog-close")||(h=true,l=p.clientX-d,c=p.clientY-u,o.setPointerCapture(p.pointerId));}),o.addEventListener("pointermove",p=>{h&&(d=p.clientX-l,u=p.clientY-c,this.panel.style.transform=`translate(${d}px, ${u}px)`);}),o.addEventListener("pointerup",()=>h=false);}e.headerStart&&o.appendChild(e.headerStart);let i=t.createElement("div");i.className="vela-dialog-title",i.textContent=e.title??"",this.titleEl=i;let s=t.createElement("button");if(s.className="vela-dialog-close",s.appendChild(ze("close",t)),o.append(i,s),this.body=t.createElement("div"),this.body.className="vela-dialog-body",e.flush&&(this.body.dataset.flush=""),e.content instanceof Node?this.body.appendChild(e.content):typeof e.content=="function"&&e.content(this.body),this.panel.append(o,this.body),e.footer){let l=t.createElement("div");l.className="vela-dialog-footer",e.footer instanceof Node?l.appendChild(e.footer):e.footer(l),this.panel.appendChild(l),this.footer=l;}else this.footer=null;if(this.positioner.appendChild(this.panel),n.append(this.backdrop,this.positioner),e.closeOnBackdrop){let l=c=>{if(!(c.target!==this.backdrop&&c.target!==this.positioner)){if(un()||Wr(c)){Me();return}this.hide();}};this.backdrop.addEventListener("pointerdown",l),this.positioner.addEventListener("pointerdown",l);}this.ctrl=Ly({...e,initialFocusEl:()=>this.positioner.closest('[data-layout="mobile"]')?this.panel:e.initialFocusEl?.()??null});let a=String(this.ctrl.props.id);this.handle=jl(this.ctrl.machine,this.ctrl.props,l=>{let c=this.ctrl.connect(l),d=this.wasOpen&&!c.open;d&&this.announce(false),ft(this.backdrop,c.getBackdropProps(),a),ft(this.positioner,c.getPositionerProps(),a),ft(this.panel,c.getContentProps(),a),ft(i,c.getTitleProps(),a),ft(s,c.getCloseTriggerProps(),a),c.open?(this.exit?.cancel(),this.exit=null,this.setShown(true)):d?this.holdExit():this.exit||this.setShown(false),c.open&&!this.wasOpen&&this.announce(true),this.wasOpen&&!c.open&&this.restoreOpener(),this.wasOpen=c.open;});}setShown(e){this.backdrop.style.display=e?"":"none",this.positioner.style.display=e?"":"none";}holdExit(){let e=[this.panel,this.backdrop];for(let t of e)t.hidden=false;this.exit=Kn(e,()=>{if(this.exit=null,this.destroyed)this.detach();else if(!this.open){for(let t of e)t.hidden=true;this.setShown(false);}},{inert:[this.positioner]});}detach(){this.backdrop.remove(),this.positioner.remove();}restoreOpener(){let e=this.opener;this.opener=null,e?.isConnected&&e.focus({preventScroll:true});}announce(e){let t=this.opener===this.panel.ownerDocument.body?null:this.opener;Vt(this.panel,e,"dialog",t);}get open(){return this.ctrl.connect(this.handle.service).open}show(){this.opener=this.panel.ownerDocument.activeElement,this.ctrl.connect(this.handle.service).setOpen(true);}hide(){this.ctrl.connect(this.handle.service).setOpen(false);}contains(e){return e==null?false:this.panel.contains(e)||this.backdrop.contains(e)||this.positioner.contains(e)?true:(e instanceof Element?e:e.parentElement)?.closest(".vela-popover, .vela-menu")!=null}destroy(){this.wasOpen&&!this.open&&this.handle.flush(),this.open&&this.hide(),this.handle.stop(),this.destroyed=true,this.wasOpen&&(this.wasOpen=false,this.announce(false)),this.restoreOpener(),this.exit||this.detach();}};var iE=["January","February","March","April","May","June","July","August","September","October","November","December"],sE=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],Py=["Su","Mo","Tu","We","Th","Fr","Sa"];function Ho(r){return `${r.getFullYear()}-${String(r.getMonth()+1).padStart(2,"0")}-${String(r.getDate()).padStart(2,"0")}`}function kc(r){let e=/^(\d{4})-(\d{1,2})-(\d{1,2})$/.exec(r.trim());if(!e)return null;let t=Number(e[1]),n=Number(e[2]),o=Number(e[3]),i=new Date(t,n-1,o);return i.getFullYear()!==t||i.getMonth()!==n-1||i.getDate()!==o?null:Ho(i)}function Ch(r){let e=r?kc(r):null;if(!e)return null;let[t,n,o]=e.split("-").map(Number);return new Date(t,n-1,o)}function Th(r={}){let e=r.today??new Date,t=Ch(r.value),n=t?.getFullYear()??e.getFullYear(),o=t?.getMonth()??e.getMonth(),i="date",s=()=>Math.floor(n/10)*10;return {get panel(){return i},get year(){return n},get month(){return o},get value(){return t?Ho(t):null},header(){return {month:iE[o]??"",monthVisible:i==="date",year:i==="year"?`${s()}-${s()+9}`:String(n),yearDisabled:i==="year"}},navLabels(){return i==="date"?{prev:"Previous month",next:"Next month"}:i==="month"?{prev:"Previous year",next:"Next year"}:{prev:"Previous decade",next:"Next decade"}},cells(){let a=[];if(i==="date"){let c=new Date(n,o,1).getDay(),d=new Date(n,o+1,0).getDate(),u=Ho(e),h=t?Ho(t):"";for(let p=0;pl+9});return a},step(a){i==="date"?(o+=a,o<0&&(o=11,n-=1),o>11&&(o=0,n+=1)):n+=i==="month"?a:a*10;},showMonths(){i="month";},showYears(){i="year";},choose(a){return a.blank?null:i==="date"?(t=Ch(String(a.value)),t?Ho(t):null):i==="month"?(o=Number(a.value),i="date",null):(n=Number(a.value),i="month",null)},setValue(a){t=Ch(a),t&&(n=t.getFullYear(),o=t.getMonth()),i="date";}}}var Iy="vela-date-picker-styles",Ay=` .vela-date-picker{color:var(--vela-fg);font:14px var(--vela-font);user-select:none;} .vela-date-picker [hidden]{display:none !important;} .vela-date-picker-head{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px;} @@ -455,7 +484,7 @@ ${Ir(".vela-dialog *")} .vela-date-picker-cell[data-checked]{background:var(--vela-hover-strong);color:var(--vela-fg-bright);} .vela-date-picker-cell[data-today]:not([data-checked]){box-shadow:inset 0 0 0 1px var(--vela-border-strong);} .vela-date-picker-cell[data-outside]{opacity:0.45;} -`;var vs=class{constructor(e={}){this.opts=e;let t=document;he(Sy,Ty,t),this.ctrl=wh(e);let n=a=>{let l=t.createElement("button");return l.type="button",l.className=a,l};this.prev=n("vela-date-picker-nav"),this.prev.append(Ue("chevron-left",t)),this.next=n("vela-date-picker-nav"),this.next.append(Ue("chevron-right",t)),this.monthBtn=n("vela-date-picker-switch"),this.monthBtn.setAttribute("aria-label","Choose month"),this.yearBtn=n("vela-date-picker-switch"),this.yearBtn.setAttribute("aria-label","Choose year");let o=t.createElement("div");o.className="vela-date-picker-title",o.append(this.monthBtn,this.yearBtn);let i=t.createElement("div");i.className="vela-date-picker-head",i.append(this.prev,o,this.next),this.week=t.createElement("div"),this.week.className="vela-date-picker-week";for(let a of Cy){let l=t.createElement("span");l.textContent=a,this.week.appendChild(l);}this.grid=t.createElement("div");let s=(a,l)=>a.addEventListener("click",c=>{c.stopPropagation(),l(),this.paint();});s(this.prev,()=>this.ctrl.step(-1)),s(this.next,()=>this.ctrl.step(1)),s(this.monthBtn,()=>this.ctrl.showMonths()),s(this.yearBtn,()=>this.ctrl.showYears()),this.el=t.createElement("div"),this.el.className="vela-date-picker",this.el.append(i,this.week,this.grid),this.paint();}get value(){return this.ctrl.value}setValue(e){this.ctrl.setValue(e),this.paint();}paint(){let e=this.el.ownerDocument,t=this.ctrl.header();this.monthBtn.hidden=!t.monthVisible,this.monthBtn.textContent=t.month,this.yearBtn.textContent=t.year,this.yearBtn.disabled=t.yearDisabled;let n=this.ctrl.navLabels();this.prev.setAttribute("aria-label",n.prev),this.next.setAttribute("aria-label",n.next);let o=this.ctrl.panel==="date";this.week.hidden=!o,this.grid.className=o?"vela-date-picker-grid":"vela-date-picker-cells",this.grid.replaceChildren(...this.ctrl.cells().map(i=>this.cellEl(e,i,o)));}cellEl(e,t,n){if(t.blank){let i=e.createElement("span");return i.className="vela-date-picker-blank",i}let o=e.createElement("button");return o.type="button",o.className=n?"vela-date-picker-day":"vela-date-picker-cell",o.textContent=t.label,t.checked&&(o.dataset.checked="1"),t.today&&(o.dataset.today="1"),t.outside&&(o.dataset.outside="1"),o.addEventListener("click",i=>{i.stopPropagation();let s=this.ctrl.choose(t);s?this.opts.onPick?.(s):this.paint();}),o}};function ky(r={}){let e=r.checked??false,t=r.disabled??false;return {get checked(){return e},disabled:t,size:r.size??"md",tone:r.tone??"bright",setChecked(n){e=n;},toggle(){return t||(e=!e,r.onChange?.(e)),e}}}var Ly="vela-ui-switch",My=` +`;var Ss=class{constructor(e={}){this.opts=e;let t=document;he(Iy,Ay,t),this.ctrl=Th(e);let n=a=>{let l=t.createElement("button");return l.type="button",l.className=a,l};this.prev=n("vela-date-picker-nav"),this.prev.append(ze("chevron-left",t)),this.next=n("vela-date-picker-nav"),this.next.append(ze("chevron-right",t)),this.monthBtn=n("vela-date-picker-switch"),this.monthBtn.setAttribute("aria-label","Choose month"),this.yearBtn=n("vela-date-picker-switch"),this.yearBtn.setAttribute("aria-label","Choose year");let o=t.createElement("div");o.className="vela-date-picker-title",o.append(this.monthBtn,this.yearBtn);let i=t.createElement("div");i.className="vela-date-picker-head",i.append(this.prev,o,this.next),this.week=t.createElement("div"),this.week.className="vela-date-picker-week";for(let a of Py){let l=t.createElement("span");l.textContent=a,this.week.appendChild(l);}this.grid=t.createElement("div");let s=(a,l)=>a.addEventListener("click",c=>{c.stopPropagation(),l(),this.paint();});s(this.prev,()=>this.ctrl.step(-1)),s(this.next,()=>this.ctrl.step(1)),s(this.monthBtn,()=>this.ctrl.showMonths()),s(this.yearBtn,()=>this.ctrl.showYears()),this.el=t.createElement("div"),this.el.className="vela-date-picker",this.el.append(i,this.week,this.grid),this.paint();}get value(){return this.ctrl.value}setValue(e){this.ctrl.setValue(e),this.paint();}paint(){let e=this.el.ownerDocument,t=this.ctrl.header();this.monthBtn.hidden=!t.monthVisible,this.monthBtn.textContent=t.month,this.yearBtn.textContent=t.year,this.yearBtn.disabled=t.yearDisabled;let n=this.ctrl.navLabels();this.prev.setAttribute("aria-label",n.prev),this.next.setAttribute("aria-label",n.next);let o=this.ctrl.panel==="date";this.week.hidden=!o,this.grid.className=o?"vela-date-picker-grid":"vela-date-picker-cells",this.grid.replaceChildren(...this.ctrl.cells().map(i=>this.cellEl(e,i,o)));}cellEl(e,t,n){if(t.blank){let i=e.createElement("span");return i.className="vela-date-picker-blank",i}let o=e.createElement("button");return o.type="button",o.className=n?"vela-date-picker-day":"vela-date-picker-cell",o.textContent=t.label,t.checked&&(o.dataset.checked="1"),t.today&&(o.dataset.today="1"),t.outside&&(o.dataset.outside="1"),o.addEventListener("click",i=>{i.stopPropagation();let s=this.ctrl.choose(t);s?this.opts.onPick?.(s):this.paint();}),o}};function Ry(r={}){let e=r.checked??false,t=r.disabled??false;return {get checked(){return e},disabled:t,size:r.size??"md",tone:r.tone??"bright",setChecked(n){e=n;},toggle(){return t||(e=!e,r.onChange?.(e)),e}}}var Dy="vela-ui-switch",Oy=` .vela-switch { width: 20px; height: 20px; @@ -493,7 +522,7 @@ ${Ir(".vela-dialog *")} color: var(--vela-selected-fg); } .vela-switch[disabled] { opacity: 0.4; cursor: default; } -`;var _r=class{constructor(e={}){he(Ly,My,document),this.ctrl=ky(e);let t=document.createElement("button");t.type="button",e.id&&(t.id=e.id),t.className="vela-switch",t.dataset.size=this.ctrl.size,t.dataset.tone=this.ctrl.tone,t.setAttribute("role","switch"),this.ctrl.disabled&&(t.disabled=true),t.appendChild(Ue("check",t.ownerDocument)),this.el=t,this.paint(),t.addEventListener("pointerdown",n=>{n.preventDefault(),t.focus({preventScroll:true});}),t.addEventListener("click",()=>{this.ctrl.toggle(),this.paint();});}get checked(){return this.ctrl.checked}setChecked(e){this.ctrl.setChecked(e),this.paint();}paint(){let e=this.ctrl.checked;this.el.setAttribute("aria-checked",e?"true":"false"),e?this.el.dataset.checked="":delete this.el.dataset.checked;}};function qM(r,e){let t=r;return e.min!==void 0&&(t=Math.max(e.min,t)),e.max!==void 0&&(t=Math.min(e.max,t)),e.integer&&(t=Math.round(t)),t}function Ey(r){let e=String(r),t=e.search(/[eE]/);if(t>=0){let n=e.slice(0,t).split(".")[1]?.length??0;return Math.max(0,Math.min(20,n-Number(e.slice(t+1))))}return e.split(".")[1]?.length??0}function xh(r,e,t){let n=Math.min(20,Math.max(Ey(e),Ey(t)));return Number(r.toFixed(n))}function Py(r){let e=r.value,t=r.integer??false,n=r.commit??"blur",o=r.clamp??n==="blur",i=r.step??(t?1:.1),s=r.onChange,a=c=>o?qM(c,{min:r.min,max:r.max,integer:t}):c,l=c=>{if(!Number.isFinite(c))return null;let d=a(c);return d!==e&&(e=d,s?.(d)),d};return {get value(){return e},min:r.min,max:r.max,step:i,integer:t,size:r.size??"md",commit:n,steppers:r.steppers??n==="blur",clamp:o,disabled:r.disabled??false,apply:l,sync(c){let d=Number.isFinite(c)?a(c):e;return e=d,d},nudge(c){return l(xh(e+c*i,e,i))}}}var Iy="vela-ui-number-3",Ay=` +`;var Gr=class{constructor(e={}){he(Dy,Oy,document),this.ctrl=Ry(e);let t=document.createElement("button");t.type="button",e.id&&(t.id=e.id),t.className="vela-switch",t.dataset.size=this.ctrl.size,t.dataset.tone=this.ctrl.tone,t.setAttribute("role","switch"),this.ctrl.disabled&&(t.disabled=true),t.appendChild(ze("check",t.ownerDocument)),this.el=t,this.paint(),t.addEventListener("pointerdown",n=>{n.preventDefault(),t.focus({preventScroll:true});}),t.addEventListener("click",()=>{this.ctrl.toggle(),this.paint();});}get checked(){return this.ctrl.checked}setChecked(e){this.ctrl.setChecked(e),this.paint();}paint(){let e=this.ctrl.checked;this.el.setAttribute("aria-checked",e?"true":"false"),e?this.el.dataset.checked="":delete this.el.dataset.checked;}};function aE(r,e){let t=r;return e.min!==void 0&&(t=Math.max(e.min,t)),e.max!==void 0&&(t=Math.min(e.max,t)),e.integer&&(t=Math.round(t)),t}function Ny(r){let e=String(r),t=e.search(/[eE]/);if(t>=0){let n=e.slice(0,t).split(".")[1]?.length??0;return Math.max(0,Math.min(20,n-Number(e.slice(t+1))))}return e.split(".")[1]?.length??0}function kh(r,e,t){let n=Math.min(20,Math.max(Ny(e),Ny(t)));return Number(r.toFixed(n))}function Fy(r){let e=r.value,t=r.integer??false,n=r.commit??"blur",o=r.clamp??n==="blur",i=r.step??(t?1:.1),s=r.onChange,a=c=>o?aE(c,{min:r.min,max:r.max,integer:t}):c,l=c=>{if(!Number.isFinite(c))return null;let d=a(c);return d!==e&&(e=d,s?.(d)),d};return {get value(){return e},min:r.min,max:r.max,step:i,integer:t,size:r.size??"md",commit:n,steppers:r.steppers??n==="blur",clamp:o,disabled:r.disabled??false,apply:l,sync(c){let d=Number.isFinite(c)?a(c):e;return e=d,d},nudge(c){return l(kh(e+c*i,e,i))}}}var Vy="vela-ui-number-3",By=` .vela-num { position: relative; display: inline-block; min-width: 0; } .vela-num[data-fill] { width: 100%; } .vela-num:not([data-fill]) { width: 100px; flex: none; justify-self: start; } @@ -564,7 +593,7 @@ ${Ir(".vela-dialog *")} } .vela-num-step button:hover { background: var(--vela-hover); color: var(--vela-fg-bright); } .vela-num-step .vela-icon, .vela-num-step svg { width: 12px; height: 12px; display: block; } -`;var Hr=class{constructor(e){let t=document;he(Iy,Ay,t),this.ctrl=Py(e),this.placeholderMode=e.placeholder!==void 0,this.emptyValue=e.emptyValue??e.value,this.last=String(e.value);let n=t.createElement("div");n.className="vela-num",n.dataset.size=this.ctrl.size,(e.fill??this.ctrl.size!=="sm")&&(n.dataset.fill=""),e.compact&&(n.dataset.compact=""),this.ctrl.steppers&&(n.dataset.steppers="");let o=t.createElement("input");o.type="number",e.id&&(o.id=e.id),e.title&&(o.title=e.title),e.min!==void 0&&(o.min=String(e.min)),e.max!==void 0&&(o.max=String(e.max)),o.step=String(this.ctrl.step),this.ctrl.disabled&&(o.disabled=true),this.placeholderMode?(o.placeholder=e.placeholder??"",o.value=e.value!==this.emptyValue?String(e.value):""):o.value=String(e.value);let i=s=>{let a=this.ctrl.apply(s);if(a===null){o.value=this.placeholderMode&&this.ctrl.value===this.emptyValue?"":this.last;return}this.last=String(a),this.placeholderMode&&a===this.emptyValue?o.value="":o.value=String(a);};this.placeholderMode?o.addEventListener("change",()=>{let s=o.value.trim()===""?this.emptyValue:Number(o.value);i(Number.isFinite(s)?s:this.emptyValue);}):this.ctrl.commit==="live"?o.addEventListener("input",()=>{let s=Number(o.value);Number.isFinite(s)&&this.ctrl.apply(s);}):(o.addEventListener("blur",()=>i(Number(o.value))),o.addEventListener("keydown",s=>{s.key==="Enter"&&(s.preventDefault(),o.blur());})),n.appendChild(o),this.ctrl.steppers&&n.appendChild(this.buildSteppers(t,s=>{let a=Number(o.value),l=Number.isFinite(a)?a:this.ctrl.value;i(xh(l+s*this.ctrl.step,l,this.ctrl.step));})),this.el=n,this.input=o;}get value(){return this.ctrl.value}setValue(e){let t=this.ctrl.sync(e);this.last=String(t),this.placeholderMode&&t===this.emptyValue?this.input.value="":this.input.value=String(t);}buildSteppers(e,t){let n=e.createElement("div");n.className="vela-num-step";let o=(i,s,a)=>{let l=e.createElement("button");l.type="button",l.tabIndex=-1,l.setAttribute("aria-label",a),l.appendChild(Ue(s,e));let c=0,d=()=>t(i),u=()=>{c&&(window.clearTimeout(c),c=0);};return l.addEventListener("pointerdown",h=>{h.preventDefault(),h.stopPropagation(),d(),c=window.setTimeout(function p(){d(),c=window.setTimeout(p,60);},400);}),l.addEventListener("pointerup",u),l.addEventListener("pointerleave",u),l.addEventListener("pointercancel",u),l};return n.append(o(1,"chevron-up","Increase"),o(-1,"chevron-down","Decrease")),n}};function Ry(r={}){let e=r.value??"",t=r.size??"md";return {get value(){return e},size:t,fill:r.fill??t!=="sm",disabled:r.disabled??false,commit(n){return n===e?null:(e=n,r.onChange?.(n),n)},sync(n){e=n;}}}var Dy="vela-ui-text-2",Oy=` +`;var $r=class{constructor(e){let t=document;he(Vy,By,t),this.ctrl=Fy(e),this.placeholderMode=e.placeholder!==void 0,this.emptyValue=e.emptyValue??e.value,this.last=String(e.value);let n=t.createElement("div");n.className="vela-num",n.dataset.size=this.ctrl.size,(e.fill??this.ctrl.size!=="sm")&&(n.dataset.fill=""),e.compact&&(n.dataset.compact=""),this.ctrl.steppers&&(n.dataset.steppers="");let o=t.createElement("input");o.type="number",e.id&&(o.id=e.id),e.title&&(o.title=e.title),e.min!==void 0&&(o.min=String(e.min)),e.max!==void 0&&(o.max=String(e.max)),o.step=String(this.ctrl.step),this.ctrl.disabled&&(o.disabled=true),this.placeholderMode?(o.placeholder=e.placeholder??"",o.value=e.value!==this.emptyValue?String(e.value):""):o.value=String(e.value);let i=s=>{let a=this.ctrl.apply(s);if(a===null){o.value=this.placeholderMode&&this.ctrl.value===this.emptyValue?"":this.last;return}this.last=String(a),this.placeholderMode&&a===this.emptyValue?o.value="":o.value=String(a);};this.placeholderMode?o.addEventListener("change",()=>{let s=o.value.trim()===""?this.emptyValue:Number(o.value);i(Number.isFinite(s)?s:this.emptyValue);}):this.ctrl.commit==="live"?o.addEventListener("input",()=>{let s=Number(o.value);Number.isFinite(s)&&this.ctrl.apply(s);}):(o.addEventListener("blur",()=>i(Number(o.value))),o.addEventListener("keydown",s=>{s.key==="Enter"&&(s.preventDefault(),o.blur());})),n.appendChild(o),this.ctrl.steppers&&n.appendChild(this.buildSteppers(t,s=>{let a=Number(o.value),l=Number.isFinite(a)?a:this.ctrl.value;i(kh(l+s*this.ctrl.step,l,this.ctrl.step));})),this.el=n,this.input=o;}get value(){return this.ctrl.value}setValue(e){let t=this.ctrl.sync(e);this.last=String(t),this.placeholderMode&&t===this.emptyValue?this.input.value="":this.input.value=String(t);}buildSteppers(e,t){let n=e.createElement("div");n.className="vela-num-step";let o=(i,s,a)=>{let l=e.createElement("button");l.type="button",l.tabIndex=-1,l.setAttribute("aria-label",a),l.appendChild(ze(s,e));let c=0,d=()=>t(i),u=()=>{c&&(window.clearTimeout(c),c=0);};return l.addEventListener("pointerdown",h=>{h.preventDefault(),h.stopPropagation(),d(),c=window.setTimeout(function p(){d(),c=window.setTimeout(p,60);},400);}),l.addEventListener("pointerup",u),l.addEventListener("pointerleave",u),l.addEventListener("pointercancel",u),l};return n.append(o(1,"chevron-up","Increase"),o(-1,"chevron-down","Decrease")),n}};function _y(r={}){let e=r.value??"",t=r.size??"md";return {get value(){return e},size:t,fill:r.fill??t!=="sm",disabled:r.disabled??false,commit(n){return n===e?null:(e=n,r.onChange?.(n),n)},sync(n){e=n;}}}var Hy="vela-ui-text-2",zy=` .vela-text { display: inline-block; min-width: 0; @@ -600,7 +629,7 @@ ${Ir(".vela-dialog *")} color: var(--vela-fg); font-size: 13px; } -`;var ys=class{constructor(e={}){let t=document;he(Dy,Oy,t),this.ctrl=Ry(e);let n=t.createElement("div");n.className="vela-text",n.dataset.size=this.ctrl.size,this.ctrl.fill&&(n.dataset.fill="");let o=t.createElement("input");o.type="text",o.size=1,e.id&&(o.id=e.id),o.value=this.ctrl.value,o.className="vela-text-field",this.ctrl.disabled&&(o.disabled=true),o.addEventListener("blur",()=>{this.ctrl.commit(o.value);}),o.addEventListener("keydown",i=>{i.key==="Enter"&&(i.preventDefault(),o.blur());}),n.appendChild(o),this.el=n,this.input=o;}get value(){return this.ctrl.value}setValue(e){this.ctrl.sync(e),this.input.value=e;}};function Ny(r={}){let e=r.value??"";return {get value(){return e},size:r.size??"md",rows:r.rows??3,disabled:r.disabled??false,commit(t){return t===e?null:(e=t,r.onChange?.(t),t)},sync(t){e=t;}}}var Fy="vela-ui-textarea",Vy=` +`;var Cs=class{constructor(e={}){let t=document;he(Hy,zy,t),this.ctrl=_y(e);let n=t.createElement("div");n.className="vela-text",n.dataset.size=this.ctrl.size,this.ctrl.fill&&(n.dataset.fill="");let o=t.createElement("input");o.type="text",o.size=1,e.id&&(o.id=e.id),o.value=this.ctrl.value,o.className="vela-text-field",this.ctrl.disabled&&(o.disabled=true),o.addEventListener("blur",()=>{this.ctrl.commit(o.value);}),o.addEventListener("keydown",i=>{i.key==="Enter"&&(i.preventDefault(),o.blur());}),n.appendChild(o),this.el=n,this.input=o;}get value(){return this.ctrl.value}setValue(e){this.ctrl.sync(e),this.input.value=e;}};function Wy(r={}){let e=r.value??"";return {get value(){return e},size:r.size??"md",rows:r.rows??3,disabled:r.disabled??false,commit(t){return t===e?null:(e=t,r.onChange?.(t),t)},sync(t){e=t;}}}var Gy="vela-ui-textarea",$y=` .vela-textarea { display: block; width: 100%; min-width: 0; } .vela-textarea-field { display: block; @@ -632,14 +661,14 @@ ${Ir(".vela-dialog *")} padding: 6px 9px; line-height: 18px; } -`;var zr=class{constructor(e={}){let t=document;he(Fy,Vy,t),this.ctrl=Ny(e),this.autoGrow=e.autoGrow===true,this.maxLines=e.maxLines??4;let n=t.createElement("div");n.className="vela-textarea",n.dataset.size=this.ctrl.size,this.autoGrow&&(n.dataset.autogrow="");let o=t.createElement("textarea");o.className="vela-textarea-field",e.id&&(o.id=e.id),e.placeholder&&(o.placeholder=e.placeholder),o.rows=this.ctrl.rows,o.value=this.ctrl.value,this.ctrl.disabled&&(o.disabled=true),o.addEventListener("blur",()=>{this.ctrl.commit(o.value);}),this.autoGrow&&o.addEventListener("input",()=>this.grow()),n.appendChild(o),this.el=n,this.input=o,this.autoGrow&&this.grow();}get value(){return this.ctrl.value}setValue(e){this.ctrl.sync(e),this.input.value=e,this.autoGrow&&this.grow();}grow(){let e=this.input,t=parseFloat(getComputedStyle(e).lineHeight)||18,n=e.clientHeight-(e.offsetHeight?t*(e.rows||1):0),o=t*this.maxLines+(Number.isFinite(n)&&n>0?n:12);e.style.height="auto",e.style.height=`${Math.min(e.scrollHeight,o)}px`,e.style.overflowY=e.scrollHeight>o?"auto":"hidden";}};function Qn(r){let e=String(r??"").trim(),t=/^#([0-9a-f]{6})([0-9a-f]{2})?$/i.exec(e);if(t)return {hex6:`#${t[1].toLowerCase()}`,alpha:t[2]?parseInt(t[2],16)/255:1};if(t=/^#([0-9a-f]{3})$/i.exec(e),t){let o=t[1].toLowerCase();return {hex6:`#${o[0]}${o[0]}${o[1]}${o[1]}${o[2]}${o[2]}`,alpha:1}}let n=/^rgba?\(([^)]+)\)/i.exec(e);if(n){let o=n[1].split(",").map(a=>a.trim()),i=a=>Math.max(0,Math.min(255,Math.round(a))).toString(16).padStart(2,"0"),s=o[3]!=null?Math.max(0,Math.min(1,parseFloat(o[3]))):1;return {hex6:`#${i(parseInt(o[0]??"0",10))}${i(parseInt(o[1]??"0",10))}${i(parseInt(o[2]??"0",10))}`,alpha:s}}return {hex6:eo,alpha:1}}function Cc(r,e){let t=Math.max(0,Math.min(1,e));return t>=.999?r:`${r}${Math.round(t*255).toString(16).padStart(2,"0")}`}function Sh(r,e,t){let n=h=>{let p=parseInt(Qn(h).hex6.slice(1),16);return [p>>16&255,p>>8&255,p&255]},[o,i,s]=n(r),[a,l,c]=n(e),d=Math.max(0,Math.min(1,t)),u=h=>Math.round(h).toString(16).padStart(2,"0");return `#${u(o*d+a*(1-d))}${u(i*d+l*(1-d))}${u(s*d+c*(1-d))}`}function Ch(r,e,t){let n=e/100,o=t/100,i=c=>(c+r/30)%12,s=n*Math.min(o,1-o),a=c=>o-s*Math.max(-1,Math.min(i(c)-3,Math.min(9-i(c),1))),l=c=>Math.round(c*255).toString(16).padStart(2,"0");return `#${l(a(0))}${l(a(8))}${l(a(4))}`}function Th(){let r=[100,90,80,68,56,45,35,25,14,0].map(n=>Ch(0,0,n)),e=[4,28,50,96,140,174,200,224,270,322];return [r,...[[82,56],[58,84],[62,74],[66,62],[70,50],[64,39],[54,29]].map(([n,o])=>e.map(i=>Ch(i,n,o)))]}function Sc(r){return `repeating-conic-gradient(#9aa0a6 0% 25%, #d3d6da 0% 50%) 0 0 / ${r}px ${r}px`}var By="vela-ui-color",_y=` +`;var Ur=class{constructor(e={}){let t=document;he(Gy,$y,t),this.ctrl=Wy(e),this.autoGrow=e.autoGrow===true,this.maxLines=e.maxLines??4;let n=t.createElement("div");n.className="vela-textarea",n.dataset.size=this.ctrl.size,this.autoGrow&&(n.dataset.autogrow="");let o=t.createElement("textarea");o.className="vela-textarea-field",e.id&&(o.id=e.id),e.placeholder&&(o.placeholder=e.placeholder),o.rows=this.ctrl.rows,o.value=this.ctrl.value,this.ctrl.disabled&&(o.disabled=true),o.addEventListener("blur",()=>{this.ctrl.commit(o.value);}),this.autoGrow&&o.addEventListener("input",()=>this.grow()),n.appendChild(o),this.el=n,this.input=o,this.autoGrow&&this.grow();}get value(){return this.ctrl.value}setValue(e){this.ctrl.sync(e),this.input.value=e,this.autoGrow&&this.grow();}grow(){let e=this.input,t=parseFloat(getComputedStyle(e).lineHeight)||18,n=e.clientHeight-(e.offsetHeight?t*(e.rows||1):0),o=t*this.maxLines+(Number.isFinite(n)&&n>0?n:12);e.style.height="auto",e.style.height=`${Math.min(e.scrollHeight,o)}px`,e.style.overflowY=e.scrollHeight>o?"auto":"hidden";}};function Jn(r){let e=String(r??"").trim(),t=/^#([0-9a-f]{6})([0-9a-f]{2})?$/i.exec(e);if(t)return {hex6:`#${t[1].toLowerCase()}`,alpha:t[2]?parseInt(t[2],16)/255:1};if(t=/^#([0-9a-f]{3})$/i.exec(e),t){let o=t[1].toLowerCase();return {hex6:`#${o[0]}${o[0]}${o[1]}${o[1]}${o[2]}${o[2]}`,alpha:1}}let n=/^rgba?\(([^)]+)\)/i.exec(e);if(n){let o=n[1].split(",").map(a=>a.trim()),i=a=>Math.max(0,Math.min(255,Math.round(a))).toString(16).padStart(2,"0"),s=o[3]!=null?Math.max(0,Math.min(1,parseFloat(o[3]))):1;return {hex6:`#${i(parseInt(o[0]??"0",10))}${i(parseInt(o[1]??"0",10))}${i(parseInt(o[2]??"0",10))}`,alpha:s}}return {hex6:oo,alpha:1}}function Lc(r,e){let t=Math.max(0,Math.min(1,e));return t>=.999?r:`${r}${Math.round(t*255).toString(16).padStart(2,"0")}`}function Mh(r,e,t){let n=h=>{let p=parseInt(Jn(h).hex6.slice(1),16);return [p>>16&255,p>>8&255,p&255]},[o,i,s]=n(r),[a,l,c]=n(e),d=Math.max(0,Math.min(1,t)),u=h=>Math.round(h).toString(16).padStart(2,"0");return `#${u(o*d+a*(1-d))}${u(i*d+l*(1-d))}${u(s*d+c*(1-d))}`}function Lh(r,e,t){let n=e/100,o=t/100,i=c=>(c+r/30)%12,s=n*Math.min(o,1-o),a=c=>o-s*Math.max(-1,Math.min(i(c)-3,Math.min(9-i(c),1))),l=c=>Math.round(c*255).toString(16).padStart(2,"0");return `#${l(a(0))}${l(a(8))}${l(a(4))}`}function Eh(){let r=[100,90,80,68,56,45,35,25,14,0].map(n=>Lh(0,0,n)),e=[4,28,50,96,140,174,200,224,270,322];return [r,...[[82,56],[58,84],[62,74],[66,62],[70,50],[64,39],[54,29]].map(([n,o])=>e.map(i=>Lh(i,n,o)))]}function Mc(r){return `repeating-conic-gradient(#9aa0a6 0% 25%, #d3d6da 0% 50%) 0 0 / ${r}px ${r}px`}var Uy="vela-ui-color",Yy=` .vela-color-field{width:24px;height:24px;padding:2px;border:1px solid var(--vela-border);border-radius:0;background:var(--vela-surface-sunken);cursor:pointer;display:inline-flex;flex:none;} .vela-color-field:hover{border-color:var(--vela-fg-muted);} .vela-color-field-swatch{display:block;width:100%;height:100%;border-radius:0;box-shadow:inset 0 0 0 1px rgba(0,0,0,0.25);} .vela-color-field-circle{width:26px;height:26px;padding:3px;border:1px solid var(--vela-border-strong);border-radius:4px;background:transparent;overflow:hidden;} .vela-color-field-circle .vela-color-field-swatch{border-radius:2px;box-shadow:none;} .vela-color-field-pop{background:var(--vela-surface-overlay);border:1px solid var(--vela-border);border-radius:var(--vela-radius-lg);box-shadow:var(--vela-shadow);padding:10px;} -`;var ZM=Th(),QM=Sc(10),JM=Sc(8),Vo=[nt,O,D,U,A];function eE(r){let e=Vo.findIndex(t=>t.toLowerCase()===r.toLowerCase());e>=0&&Vo.splice(e,1),Vo.unshift(r),Vo.length>10&&(Vo.length=10);}function ws(r,e,t,n={}){let o=n.commit??"live",i=Qn(r),s=i.hex6,a=i.alpha,l=document.createElement("div");l.style.cssText="display:flex;flex-direction:column;gap:9px;width:236px;";let c=document.createElement("div");c.style.cssText="display:grid;grid-template-columns:repeat(10,1fr);gap:4px;";let d=[];for(let V of ZM)for(let Z of V){let be=document.createElement("button");be.type="button",be.dataset.c=Z,be.style.cssText=`width:100%;aspect-ratio:1;border-radius:4px;border:none;cursor:pointer;background:${Z};padding:0;`,be.addEventListener("click",fn=>{fn.stopPropagation(),N(Z);}),c.appendChild(be),d.push(be);}let u=()=>{for(let V of d){let Z=(V.dataset.c??"").toLowerCase()===s.toLowerCase();V.style.outline=Z?`2px solid ${e.textColor}`:"none",V.style.outlineOffset="2px",V.style.zIndex=Z?"1":"",V.style.position=Z?"relative":"";}},h=document.createElement("div");h.style.cssText="display:flex;align-items:center;gap:5px;flex-wrap:wrap;border-top:1px solid var(--vela-border);padding-top:9px;";let p=document.createElement("div");p.style.cssText="display:contents;";let m=document.createElement("label");m.style.cssText=`width:17px;height:17px;border-radius:var(--vela-radius-sm);border:1px dashed var(--vela-border-strong);cursor:pointer;display:flex;align-items:center;justify-content:center;color:${e.textColor};font:14px ${e.fontFamily};position:relative;`,m.textContent="+";let f=document.createElement("input");f.type="color",f.value=s,f.style.cssText="position:absolute;inset:0;opacity:0;cursor:pointer;",f.addEventListener("input",()=>I(f.value)),f.addEventListener("change",()=>N(f.value,true)),m.appendChild(f),h.append(p,m);let g=()=>{p.replaceChildren();for(let V of Vo){let Z=document.createElement("button");Z.type="button",Z.style.cssText=`width:17px;height:17px;border-radius:var(--vela-radius-sm);border:1px solid var(--vela-border);cursor:pointer;background:${V};padding:0;`,Z.addEventListener("click",be=>{be.stopPropagation(),N(V);}),p.appendChild(Z);}},b=document.createElement("div");b.textContent="Opacity",b.style.cssText=`font:11px ${e.fontFamily};color:var(--vela-fg-muted);`;let y=document.createElement("div");y.style.cssText="display:flex;align-items:center;gap:10px;";let w=document.createElement("div");w.style.cssText="flex:1;position:relative;height:13px;border-radius:7px;cursor:pointer;";let C=document.createElement("div");C.style.cssText="position:absolute;top:50%;width:15px;height:15px;border-radius:50%;background:var(--vela-selected-bg);box-shadow:0 1px 3px rgba(0,0,0,0.55);transform:translate(-50%,-50%);pointer-events:none;",w.appendChild(C);let M=document.createElement("input");M.type="text",M.inputMode="numeric",M.title="Opacity (%)",M.style.cssText=`width:46px;box-sizing:border-box;text-align:center;font:var(--vela-font-size-md) ${e.fontFamily};color:var(--vela-fg);background:transparent;border:1px solid var(--vela-border);border-radius:5px;padding:3px 4px;outline:none;`,M.addEventListener("focus",()=>{M.style.borderColor="var(--vela-border-strong)",M.select();}),y.append(w,M);let S=()=>{w.style.background=`linear-gradient(to right, ${s}00, ${s}ff), ${QM}`,C.style.left=`${a*100}%`,M.value=`${Math.round(a*100)}%`;},L=()=>{M.style.borderColor="var(--vela-border)";let V=parseFloat(M.value.replace("%",""));if(Number.isFinite(V)){let Z=Math.max(0,Math.min(100,V))/100;if(Math.round(Z*100)!==Math.round(a*100)){a=Z,S(),E();return}}S();};M.addEventListener("change",L),M.addEventListener("blur",()=>{M.style.borderColor="var(--vela-border)",S();}),M.addEventListener("keydown",V=>{V.key!=="Escape"&&(V.stopPropagation(),V.key==="Enter"&&(V.preventDefault(),L(),M.blur()));});let v=false,k=V=>{let Z=w.getBoundingClientRect();a=Math.max(0,Math.min(1,(V-Z.left)/Z.width)),S(),o==="live"&&E();},x=()=>{v&&(v=false,o==="release"&&E());};w.addEventListener("pointerdown",V=>{V.stopPropagation(),v=true,w.setPointerCapture(V.pointerId),k(V.clientX);}),w.addEventListener("pointermove",V=>{v&&k(V.clientX);}),w.addEventListener("pointerup",x),w.addEventListener("pointercancel",x);function E(){t(Cc(s,a));}function I(V){s=Qn(V).hex6,u(),S(),E();}function N(V,Z=false){I(V),eE(s),f.value=s,Z&&g();}return g(),u(),S(),l.append(c,h,b,y),l}function kh(r,e,t,n){return new Tc({theme:r,getVal:e,onVal:t,shape:n?.shape,id:n?.id,popover:n?.popover,commit:n?.commit}).el}var Tc=class{constructor(e){he(By,_y,document),this.theme=e.theme,this.getVal=e.getVal,this.onVal=e.onVal,this.popoverOpts=e.popover,this.commit=e.commit;let t=document.createElement("button");t.type="button",e.id&&(t.id=e.id),t.className=e.shape==="circle"?"vela-color-field vela-color-field-circle":"vela-color-field";let n=document.createElement("span");n.className="vela-color-field-swatch",t.appendChild(n),this.el=t,this.swatch=n,this.paint(),t.addEventListener("vela-sync",()=>this.paint()),t.addEventListener("pointerdown",o=>{o.preventDefault(),t.focus({preventScroll:true});}),t.addEventListener("click",o=>{o.stopPropagation(),this.toggle();});}paint(){let e=this.getVal();this.swatch.style.background=`linear-gradient(${e}, ${e}), ${JM}`;}toggle(){if(Mn()===this.el){Me();return}new qe({trigger:this.el,theme:this.theme,align:this.popoverOpts?.align??"end",gap:this.popoverOpts?.gap??6,host:this.popoverOpts?.host,position:this.popoverOpts?.position,boundary:this.popoverOpts?.boundary,zIndex:this.popoverOpts?.zIndex,className:"vela-color-field-pop",content:ws(this.getVal(),this.theme,t=>{this.onVal(t),this.paint();},{commit:this.commit})}).show();}};function Hy(r){let e=r.value;return {options:r.options,get value(){return e},setValue(t){e=t;},optionOf(t){return r.options.find(n=>n.value===t)},pick(t){return e=t,r.onChange?.(t),t}}}var tE=[1,2,3,4,5];function nE(r){return ``}function zy(){return tE.map(r=>({value:r,label:`${r}px`,glyph:nE(r)}))}var Wy="vela-ui-glyph-select",Gy=` +`;var lE=Eh(),cE=Mc(10),dE=Mc(8),zo=[nt,O,D,Y,A];function uE(r){let e=zo.findIndex(t=>t.toLowerCase()===r.toLowerCase());e>=0&&zo.splice(e,1),zo.unshift(r),zo.length>10&&(zo.length=10);}function Ts(r,e,t,n={}){let o=n.commit??"live",i=Jn(r),s=i.hex6,a=i.alpha,l=document.createElement("div");l.style.cssText="display:flex;flex-direction:column;gap:9px;width:236px;";let c=document.createElement("div");c.style.cssText="display:grid;grid-template-columns:repeat(10,1fr);gap:4px;";let d=[];for(let V of lE)for(let Z of V){let be=document.createElement("button");be.type="button",be.dataset.c=Z,be.style.cssText=`width:100%;aspect-ratio:1;border-radius:4px;border:none;cursor:pointer;background:${Z};padding:0;`,be.addEventListener("click",gn=>{gn.stopPropagation(),N(Z);}),c.appendChild(be),d.push(be);}let u=()=>{for(let V of d){let Z=(V.dataset.c??"").toLowerCase()===s.toLowerCase();V.style.outline=Z?`2px solid ${e.textColor}`:"none",V.style.outlineOffset="2px",V.style.zIndex=Z?"1":"",V.style.position=Z?"relative":"";}},h=document.createElement("div");h.style.cssText="display:flex;align-items:center;gap:5px;flex-wrap:wrap;border-top:1px solid var(--vela-border);padding-top:9px;";let p=document.createElement("div");p.style.cssText="display:contents;";let m=document.createElement("label");m.style.cssText=`width:17px;height:17px;border-radius:var(--vela-radius-sm);border:1px dashed var(--vela-border-strong);cursor:pointer;display:flex;align-items:center;justify-content:center;color:${e.textColor};font:14px ${e.fontFamily};position:relative;`,m.textContent="+";let f=document.createElement("input");f.type="color",f.value=s,f.style.cssText="position:absolute;inset:0;opacity:0;cursor:pointer;",f.addEventListener("input",()=>I(f.value)),f.addEventListener("change",()=>N(f.value,true)),m.appendChild(f),h.append(p,m);let g=()=>{p.replaceChildren();for(let V of zo){let Z=document.createElement("button");Z.type="button",Z.style.cssText=`width:17px;height:17px;border-radius:var(--vela-radius-sm);border:1px solid var(--vela-border);cursor:pointer;background:${V};padding:0;`,Z.addEventListener("click",be=>{be.stopPropagation(),N(V);}),p.appendChild(Z);}},b=document.createElement("div");b.textContent="Opacity",b.style.cssText=`font:11px ${e.fontFamily};color:var(--vela-fg-muted);`;let y=document.createElement("div");y.style.cssText="display:flex;align-items:center;gap:10px;";let w=document.createElement("div");w.style.cssText="flex:1;position:relative;height:13px;border-radius:7px;cursor:pointer;";let S=document.createElement("div");S.style.cssText="position:absolute;top:50%;width:15px;height:15px;border-radius:50%;background:var(--vela-selected-bg);box-shadow:0 1px 3px rgba(0,0,0,0.55);transform:translate(-50%,-50%);pointer-events:none;",w.appendChild(S);let M=document.createElement("input");M.type="text",M.inputMode="numeric",M.title="Opacity (%)",M.style.cssText=`width:46px;box-sizing:border-box;text-align:center;font:var(--vela-font-size-md) ${e.fontFamily};color:var(--vela-fg);background:transparent;border:1px solid var(--vela-border);border-radius:5px;padding:3px 4px;outline:none;`,M.addEventListener("focus",()=>{M.style.borderColor="var(--vela-border-strong)",M.select();}),y.append(w,M);let C=()=>{w.style.background=`linear-gradient(to right, ${s}00, ${s}ff), ${cE}`,S.style.left=`${a*100}%`,M.value=`${Math.round(a*100)}%`;},L=()=>{M.style.borderColor="var(--vela-border)";let V=parseFloat(M.value.replace("%",""));if(Number.isFinite(V)){let Z=Math.max(0,Math.min(100,V))/100;if(Math.round(Z*100)!==Math.round(a*100)){a=Z,C(),E();return}}C();};M.addEventListener("change",L),M.addEventListener("blur",()=>{M.style.borderColor="var(--vela-border)",C();}),M.addEventListener("keydown",V=>{V.key!=="Escape"&&(V.stopPropagation(),V.key==="Enter"&&(V.preventDefault(),L(),M.blur()));});let v=false,k=V=>{let Z=w.getBoundingClientRect();a=Math.max(0,Math.min(1,(V-Z.left)/Z.width)),C(),o==="live"&&E();},x=()=>{v&&(v=false,o==="release"&&E());};w.addEventListener("pointerdown",V=>{V.stopPropagation(),v=true,w.setPointerCapture(V.pointerId),k(V.clientX);}),w.addEventListener("pointermove",V=>{v&&k(V.clientX);}),w.addEventListener("pointerup",x),w.addEventListener("pointercancel",x);function E(){t(Lc(s,a));}function I(V){s=Jn(V).hex6,u(),C(),E();}function N(V,Z=false){I(V),uE(s),f.value=s,Z&&g();}return g(),u(),C(),l.append(c,h,b,y),l}function Ph(r,e,t,n){return new Ec({theme:r,getVal:e,onVal:t,shape:n?.shape,id:n?.id,popover:n?.popover,commit:n?.commit}).el}var Ec=class{constructor(e){he(Uy,Yy,document),this.theme=e.theme,this.getVal=e.getVal,this.onVal=e.onVal,this.popoverOpts=e.popover,this.commit=e.commit;let t=document.createElement("button");t.type="button",e.id&&(t.id=e.id),t.className=e.shape==="circle"?"vela-color-field vela-color-field-circle":"vela-color-field";let n=document.createElement("span");n.className="vela-color-field-swatch",t.appendChild(n),this.el=t,this.swatch=n,this.paint(),t.addEventListener("vela-sync",()=>this.paint()),t.addEventListener("pointerdown",o=>{o.preventDefault(),t.focus({preventScroll:true});}),t.addEventListener("click",o=>{o.stopPropagation(),this.toggle();});}paint(){let e=this.getVal();this.swatch.style.background=`linear-gradient(${e}, ${e}), ${dE}`;}toggle(){if(En()===this.el){Me();return}new qe({trigger:this.el,theme:this.theme,align:this.popoverOpts?.align??"end",gap:this.popoverOpts?.gap??6,host:this.popoverOpts?.host,position:this.popoverOpts?.position,boundary:this.popoverOpts?.boundary,zIndex:this.popoverOpts?.zIndex,className:"vela-color-field-pop",content:Ts(this.getVal(),this.theme,t=>{this.onVal(t),this.paint();},{commit:this.commit})}).show();}};function Ky(r){let e=r.value;return {options:r.options,get value(){return e},setValue(t){e=t;},optionOf(t){return r.options.find(n=>n.value===t)},pick(t){return e=t,r.onChange?.(t),t}}}var hE=[1,2,3,4,5];function pE(r){return ``}function Xy(){return hE.map(r=>({value:r,label:`${r}px`,glyph:pE(r)}))}var jy="vela-ui-glyph-select",qy=` .vela-glyph-select { height: 34px; padding: 0 26px 0 8px; @@ -700,7 +729,7 @@ ${Ir(".vela-dialog *")} } .vela-glyph-select-item:hover { background: var(--vela-hover); } .vela-glyph-select-item[data-active='1'] { background: var(--vela-hover-strong); color: var(--vela-fg-bright); } -`;var kc=class{constructor(e){he(Wy,Gy,document),this.ctrl=Hy(e),this.theme=e.theme,this.get=e.get??(()=>this.ctrl.value);let t=document.createElement("button");t.type="button",t.className="vela-glyph-select",e.title&&(t.title=e.title),this.el=t,this.paint(),t.addEventListener("pointerdown",n=>{n.preventDefault(),t.focus({preventScroll:true});}),t.addEventListener("click",n=>{n.stopPropagation(),this.toggle();}),t.addEventListener("vela-sync",()=>{this.ctrl.setValue(this.get()),this.paint();});}setValue(e){this.ctrl.setValue(e),this.paint();}paint(){let e=this.get(),t=this.ctrl.optionOf(e),n=document.createElement("span");n.style.display="flex",n.innerHTML=t?.glyph??"";let o=document.createElement("span");o.className="vela-glyph-select-caret",o.appendChild(Ue("chevron-down",this.el.ownerDocument)),this.el.replaceChildren(n,o);}toggle(){if(Mn()===this.el){Me();return}let e=this.get(),t=new qe({trigger:this.el,theme:this.theme,align:"end",gap:6,className:"vela-glyph-select-pop",content:n=>{n.style.font=`var(--vela-font-size-md) ${this.theme.fontFamily}`;for(let o of this.ctrl.options){let i=document.createElement("button");i.type="button",i.className="vela-glyph-select-item",i.dataset.active=o.value===e?"1":"0",i.innerHTML=`${o.glyph}${o.label}`,i.addEventListener("click",s=>{s.stopPropagation(),t.hide(),this.ctrl.pick(o.value),this.paint();}),n.appendChild(i);}}});t.show();}};function Lh(r,e,t){return new kc({theme:r,options:zy(),value:e(),get:e,onChange:t}).el}function Lc(){Me();}function xs(r,e){return r==="inputs"?e?"minmax(0,1fr) auto":"max-content 1fr":e?"minmax(0,1fr) max-content":"max-content max-content"}var $y="vela-ui-field",Uy=` +`;var Pc=class{constructor(e){he(jy,qy,document),this.ctrl=Ky(e),this.theme=e.theme,this.get=e.get??(()=>this.ctrl.value);let t=document.createElement("button");t.type="button",t.className="vela-glyph-select",e.title&&(t.title=e.title),this.el=t,this.paint(),t.addEventListener("pointerdown",n=>{n.preventDefault(),t.focus({preventScroll:true});}),t.addEventListener("click",n=>{n.stopPropagation(),this.toggle();}),t.addEventListener("vela-sync",()=>{this.ctrl.setValue(this.get()),this.paint();});}setValue(e){this.ctrl.setValue(e),this.paint();}paint(){let e=this.get(),t=this.ctrl.optionOf(e),n=document.createElement("span");n.style.display="flex",n.innerHTML=t?.glyph??"";let o=document.createElement("span");o.className="vela-glyph-select-caret",o.appendChild(ze("chevron-down",this.el.ownerDocument)),this.el.replaceChildren(n,o);}toggle(){if(En()===this.el){Me();return}let e=this.get(),t=new qe({trigger:this.el,theme:this.theme,align:"end",gap:6,className:"vela-glyph-select-pop",content:n=>{n.style.font=`var(--vela-font-size-md) ${this.theme.fontFamily}`;for(let o of this.ctrl.options){let i=document.createElement("button");i.type="button",i.className="vela-glyph-select-item",i.dataset.active=o.value===e?"1":"0",i.innerHTML=`${o.glyph}${o.label}`,i.addEventListener("click",s=>{s.stopPropagation(),t.hide(),this.ctrl.pick(o.value),this.paint();}),n.appendChild(i);}}});t.show();}};function Ih(r,e,t){return new Pc({theme:r,options:Xy(),value:e(),get:e,onChange:t}).el}function Ic(){Me();}function ks(r,e){return r==="inputs"?e?"minmax(0,1fr) auto":"max-content 1fr":e?"minmax(0,1fr) max-content":"max-content max-content"}var Zy="vela-ui-field",Qy=` .vela-field-grid { display: grid; align-items: center; @@ -753,31 +782,31 @@ ${Ir(".vela-dialog *")} .vela-field-section[data-variant='inputs'][data-first] { padding-top: 4px; } .vela-field-sep { grid-column: 1 / -1; height: 14px; } .vela-field-dim { opacity: 0.4 !important; pointer-events: none !important; } -`;function Pc(r=document){he($y,Uy,r);}function Ss(r={}){Pc();let e=document.createElement("div");e.className="vela-field-grid";let t=r.variant??"inputs";return e.dataset.variant=t,r.mobile&&(e.dataset.mobile=""),e.style.gridTemplateColumns=xs(t,r.mobile===true),e}function Pn(r,e={}){Pc();let t=document.createElement("div");return t.className="vela-field-section",e.variant&&(t.dataset.variant=e.variant),e.first&&(t.dataset.first=""),t.textContent=r,t}function Eh(){Pc();let r=document.createElement("div");return r.className="vela-field-sep",r}function Cs(r,e){let t=document.createElement("span");t.className="vela-field-label",e.size&&(t.dataset.size=e.size),t.textContent=r;let n=e.id;return n&&(t.id=`${n}--title`,queueMicrotask(()=>{t.ownerDocument.getElementById(n)?.setAttribute("aria-labelledby",t.id);})),t}function Yy(r){return r?Array.isArray(r)?r:[r]:[]}function Ec(r,e){if(e)for(let t of e.split(/\s+/))t&&r.classList.add(t);}function Mh(r,e){for(let t of r)t.dataset.sdSelfGated!=="1"&&t.classList.toggle("vela-field-dim",!e);}function He(r){Pc();let e=r.labelSize;if(r.inline){let i=document.createElement("div");i.className="vela-field-span vela-field-inline";for(let s of r.inline){let a=document.createElement("div");if(a.className="vela-field-inline-item",s.toggleFirst&&(a.style.flexDirection="row-reverse"),s.label&&a.appendChild(Cs(s.label,{id:s.id,size:e})),s.fit)a.appendChild(s.control);else {let l=document.createElement("div");l.style.width="100px",l.appendChild(s.control),a.appendChild(l);}i.appendChild(a);}return r.info&&i.appendChild(r.info),Ec(i,r.className),i}if(r.bool){let i=document.createElement("div");i.className="vela-field-span vela-field-bool";let s=new _r({id:r.toggle?.id??r.id,checked:r.toggle?.checked??false,size:"md",tone:"bright",onChange:a=>r.toggle?.onChange(a)});if(i.append(s.el,Cs(r.label,{id:r.toggle?.id??r.id,size:e})),r.info&&i.appendChild(r.info),r.toggle?.get){let a=r.toggle.get;i.addEventListener("vela-sync",()=>{s.setChecked(a());});}return Ec(i,r.className),i}if(r.stacked){let i=document.createElement("div");i.className="vela-field-span vela-field-stacked";let s=document.createElement("div");s.className="vela-field-stacked-head",s.appendChild(Cs(r.label,{id:r.id,size:e})),r.info&&s.appendChild(r.info),i.appendChild(s);for(let a of Yy(r.control))i.appendChild(a);return Ec(i,r.className),i}let t=document.createElement("div");t.className="vela-field-row";let n=Yy(r.control);if(r.toggle){let i=document.createElement("div");i.className="vela-field-toggle-label";let s=new _r({id:r.toggle.id??r.id,checked:r.toggle.checked,size:"md",tone:"bright",onChange:a=>{r.toggle.onChange(a),n.length>0&&Mh(n,a);}});if(i.append(s.el,Cs(r.label,{id:r.toggle.id??r.id,size:e})),t.appendChild(i),n.length>0&&Mh(n,r.toggle.checked),r.toggle.get){let a=r.toggle.get;t.addEventListener("vela-sync",()=>{let l=a();s.setChecked(l),n.length>0&&Mh(n,l);});}}else t.appendChild(Cs(r.label,{id:r.id,size:e}));let o=document.createElement("div");if(o.className="vela-field-cell",r.controlWidth!=null&&n.length===1&&!r.fit){let i=document.createElement("div");i.style.width=`${r.controlWidth}px`,i.appendChild(n[0]),o.appendChild(i);}else for(let i of n)o.appendChild(i);return r.info&&o.appendChild(r.info),t.appendChild(o),Ec(t,r.className),t}function de(r){if(r.kind==="number"){let t=new Hr({id:r.id,value:r.value,min:r.min,max:r.max,step:r.step,integer:r.integer,size:"md",fill:r.fill,compact:r.compact,commit:r.commit,steppers:r.steppers,clamp:r.clamp,placeholder:r.placeholder,emptyValue:r.emptyValue,title:r.title,onChange:r.onChange});if(r.sync){let n=r.sync;t.el.addEventListener("vela-sync",()=>{t.setValue(n());});}return {el:t.el,setValue:n=>t.setValue(Number(n))}}if(r.kind==="select"){let t=new fs({id:r.id,options:r.options,value:r.value,size:"md",fill:r.fill,theme:r.theme,list:r.list,onChange:r.onChange});if(r.title&&(t.el.title=r.title),r.sync){let n=r.sync;t.el.addEventListener("vela-sync",()=>{t.setValue(n());});}return {el:t.el,setValue:n=>t.setValue(String(n))}}if(r.kind==="switch"){let t=new _r({id:r.id,checked:r.checked,size:"md",tone:"bright",onChange:r.onChange});if(r.sync){let n=r.sync;t.el.addEventListener("vela-sync",()=>{t.setChecked(n());});}return {el:t.el,setValue:n=>t.setChecked(!!n)}}if(r.kind==="color"){let t=kh(r.theme,r.get,r.onChange,{shape:"circle",id:r.id,popover:r.popover,commit:r.commit});return r.title&&(t.title=r.title),{el:t}}if(r.kind==="text"){let t=new ys({id:r.id,value:r.value,size:"md",fill:r.fill,onChange:r.onChange});if(r.placeholder&&(t.input.placeholder=r.placeholder),r.sync){let n=r.sync;t.el.addEventListener("vela-sync",()=>{t.setValue(n());});}return {el:t.el,setValue:n=>t.setValue(String(n))}}if(r.kind==="textarea"){let t=new zr({id:r.id,value:r.value,rows:r.rows,autoGrow:r.autoGrow,maxLines:r.maxLines,placeholder:r.placeholder,onChange:r.onChange});if(r.sync){let n=r.sync;t.el.addEventListener("vela-sync",()=>{t.setValue(n());});}return {el:t.el,setValue:n=>t.setValue(String(n))}}let e=Lh(r.theme,r.get,r.onChange);return r.title&&(e.title=r.title),{el:e}}var Ky="Properties";function Ic(r,e){return e.prop?r.propValues:r.values}var rE=["close","open","high","low","hl2","hlc3","ohlc4","volume"],Dc=class{constructor(e){this.host=e;this.dialog=null;this.backdrop=null;this.uiDialog=null;this.openId=null;this.row=null;this.snapshot=null;this.propSnapshot=null;this.dialogTips=[];this.refreshVisibility=null;this.choicePop=null;this.calendarPop=null;this.calendarAnchor=null;this.onDialogKey=e=>{if(e.key==="Escape"){if(e.preventDefault(),dn()){Me();return}this.close();}};}isOpen(){return this.dialog!==null}open(e){if(this.close(),e.inputs.length===0&&e.props.length===0)return;this.row=e,this.openId=e.id,this.snapshot={...e.values},this.propSnapshot={...e.propValues},Oc();let t=this.host.theme(),n="var(--vela-border)",o="var(--vela-fg-bright)",i=this.host.dialogHost()??this.host.container,s=new En({host:i,title:e.title,modal:false,contained:true,align:"center",draggable:!this.host.mobile(),flush:true,className:"vela-dialog--form vela-ind-dialog",closeOnEscape:false,footer:g=>{g.append(this.resetAction(),this.dialogButton("Cancel",false,()=>this.revertAndClose()),this.dialogButton("Ok",true,()=>this.close()));},onOpenChange:g=>{!g&&this.uiDialog===s&&this.close();}});Be(s.panel,t),s.panel.style.colorScheme=this.isDarkTheme()?"dark":"light",this.dialogTips.push(tn(s.panel.querySelector(".vela-dialog-close"),{host:this.host.container,theme:()=>this.host.theme(),text:()=>"Close"}));let a=iE(e.inputs);if(e.props.length>0){let g=e.props.map(y=>{let w={...y,prop:true};return delete w.tab,w}),b=a.find(y=>y.name===Ky);b?b.inputs.push(...g):a.push({name:Ky,inputs:g});}let l=document.createElement("div");l.style.cssText=`display:flex;gap:12px;padding:0 20px;border-bottom:1px solid ${n};flex:0 0 auto;`;let c=[],d=[],u=[],h=0,p=g=>{h=g;for(let b=0;b1?"cursor:pointer;":""}`,y.addEventListener("click",()=>p(g)),l.appendChild(y),c.push(y),d.push(this.buildTabBody(b.inputs,e,u)),b.inputs.every(w=>w.when)&&u.push({el:y,visible:w=>b.inputs.some(C=>ms(C.when,w))});}s.body.appendChild(l);for(let g of d)s.body.appendChild(g);p(0);let m=()=>{let g=sE(e);for(let b of u)b.el.style.display=b.visible(g)?"":"none";if(c[h]?.style.display==="none"){let b=c.findIndex(y=>y.style.display!=="none");b>=0&&p(b);}};this.refreshVisibility=m,m();let f=g=>{if(!(g.target!==s.backdrop&&g.target!==s.positioner)){if(dn()||Br(g)){Me();return}this.close(),this.host.onBackdropClose();}};s.backdrop.addEventListener("pointerdown",f),s.positioner.addEventListener("pointerdown",f),this.uiDialog=s,this.dialog=s.panel,this.backdrop=s.backdrop,s.show(),document.addEventListener("keydown",this.onDialogKey);}buildTabBody(e,t,n){let o=document.createElement("div");o.style.cssText=oE(this.host.mobile());for(let i of aE(e)){let s=document.createElement("div");s.style.cssText="display:contents;";let a=null;i.name&&(a=Pn(i.name,{variant:"inputs",first:o.childElementCount===0}),s.appendChild(a));for(let l of i.rows){let c=this.buildInputRow(s,l,t);l.some(d=>d.when)&&n.push({el:c,visible:d=>jy(l,d)});}if(a&&i.rows.every(l=>l.every(c=>c.when))){let l=i.rows;n.push({el:a,visible:c=>l.some(d=>jy(d,c))});}o.appendChild(s);}return o}close(){document.removeEventListener("keydown",this.onDialogKey),Me(),this.refreshVisibility=null,this.choicePop=null,this.calendarPop=null,this.calendarAnchor=null;for(let t of this.dialogTips.splice(0))t();let e=this.uiDialog;this.uiDialog=null,this.backdrop=null,this.dialog=null,this.openId=null,this.row=null,this.snapshot=null,this.propSnapshot=null,e?.destroy();}revertAndClose(){let e=this.row,t=this.snapshot;if(e&&t)for(let o of e.inputs){let i=t[o.key],s=i!==void 0?i:o.defval;e.values[o.key]!==s&&(e.values[o.key]=s,this.host.onChange?.({indicatorId:e.id,key:o.key,value:s}));}let n=this.propSnapshot;if(e&&n)for(let o of e.props){let i=n[o.key],s=i!==void 0?i:o.defval;e.propValues[o.key]!==s&&(e.propValues[o.key]=s,this.host.onChange?.({indicatorId:e.id,key:o.key,value:s,kind:"prop"}));}this.close();}resetAction(){let e=this.dialogButton("Reset defaults",false,()=>this.resetToDefaults());return e.style.marginRight="auto",e}resetToDefaults(){let e=this.row;if(!e)return;let t=this.snapshot,n=this.propSnapshot;for(let o of e.inputs)e.values[o.key]!==o.defval&&(e.values[o.key]=o.defval,this.host.onChange?.({indicatorId:e.id,key:o.key,value:o.defval}));for(let o of e.props)e.propValues[o.key]!==o.defval&&(e.propValues[o.key]=o.defval,this.host.onChange?.({indicatorId:e.id,key:o.key,value:o.defval,kind:"prop"}));this.open(e),t&&(this.snapshot=t),n&&(this.propSnapshot=n);}commit(e,t,n){Ic(e,t)[t.key]=n,this.host.onChange?.({indicatorId:e.id,key:t.key,value:n,...t.prop?{kind:"prop"}:{}}),this.refreshVisibility?.();}buildInputRow(e,t,n){let o=d=>`vela-inp-${n.id}-${d.key}`,i=d=>(e.appendChild(d),d);if(t.length>1)return i(He({label:"",inline:t.map(d=>({label:Ac(d)||void 0,id:o(d),control:this.buildControl(n,d,o(d)),toggleFirst:d.type==="bool",fit:d.type==="color"||d.type==="bool"})),info:[...t].reverse().find(d=>d.tooltip)?.tooltip?this.infoButton([...t].reverse().find(d=>d.tooltip).tooltip):void 0}));let s=t[0],a=o(s),l=s.tooltip?this.infoButton(s.tooltip):void 0;if(s.type==="bool"){let d=!!(Ic(n,s)[s.key]??s.defval);return i(He({label:Ac(s),id:a,bool:true,info:l,toggle:{id:a,checked:d,onChange:u=>this.commit(n,s,u)}}))}if(s.type==="text_area")return i(He({label:Ac(s),id:a,stacked:true,info:l,control:this.buildControl(n,s,a)}));let c=s.type==="color"||s.type==="session"||s.type==="time";return i(He({label:Ac(s),id:a,fit:c,controlWidth:c?void 0:100,info:l,control:this.buildControl(n,s,a)}))}buildControl(e,t,n){let o=Ic(e,t)[t.key]??t.defval,i=s=>this.commit(e,t,s);return t.type==="bool"?de({kind:"switch",id:n,checked:!!o,onChange:s=>i(s)}).el:t.options&&t.options.length>0?this.select(n,t.options.map(String),String(o),i):t.type==="source"?this.select(n,rE,String(o),i):t.type==="color"?de({kind:"color",id:n,theme:this.host.theme(),get:()=>String(Ic(e,t)[t.key]??t.defval),onChange:s=>i(s),commit:"release"}).el:t.type==="symbol"?this.buildSymbol(n,String(o),i):t.type==="timeframe"?this.selectPairs(n,dE,String(o),i):t.type==="session"?this.buildSession(n,String(o),i):t.type==="time"?this.buildTime(n,Number(o)||0,i):t.type==="text_area"?de({kind:"textarea",id:n,value:String(o),onChange:s=>i(s)}).el:t.type==="int"||t.type==="float"||t.type==="price"?de({kind:"number",id:n,value:Number(o),min:t.min,max:t.max,step:t.step??(t.type==="int"?1:.1),integer:t.type==="int",commit:"blur",onChange:s=>i(s)}).el:this.buildTextField(n,String(o),i)}buildTextField(e,t,n){return de({kind:"text",id:e,value:t,onChange:n}).el}infoButton(e){let{el:t,dispose:n}=Pl(e,{host:this.host.container,theme:()=>this.host.theme(),size:18});return this.dialogTips.push(n),t}select(e,t,n,o){return this.selectPairs(e,t.map(i=>({value:i,label:i})),n,o)}selectPairs(e,t,n,o){return de({kind:"select",id:e,options:t,value:n,theme:this.host.theme(),list:this.listPopover(),onChange:o}).el}buildSession(e,t,n){let[o,i]=pE(t),s=document.createElement("div");s.style.cssText="display:flex;align-items:center;gap:6px;";let a=o,l=i,c=()=>n(mE(a,l));return s.append(this.timeCombobox(e,a,86,d=>{a=d,c();}),this.timeCombobox(`${e}-end`,l,86,d=>{l=d,c();})),s}buildTime(e,t,n){let o=fE(t),i=document.createElement("div");i.style.cssText="display:flex;align-items:center;gap:6px;";let s=o.date,a=o.time,l=()=>{if(!s)return;let u=Date.parse(`${s}T${a}:00`);Number.isFinite(u)&&n(u);},c=this.dateField(e,s,u=>{s=u,l();}),d=this.timeCombobox(`${e}-time`,a,86,u=>{a=u,l();});return i.append(c,d),i}timeCombobox(e,t,n,o){let i=document.createElement("div");i.className="vela-ind-combo",i.style.cssText=`position:relative;width:${n}px;`;let s=document.createElement("input");s.type="text",s.id=e,s.value=t,s.autocomplete="off",s.spellcheck=false,s.style.cssText=`${this.ctrlStyle()}padding-right:26px;`;let a=document.createElement("button");a.type="button",a.tabIndex=-1,a.className="vela-ind-combo-chevron",a.setAttribute("aria-label","Open time list"),a.innerHTML=cE;let l=t,c=()=>{let p=hE(s.value);if(!p){s.value=l;return}s.value=p,p!==l&&(l=p,o(p));};s.addEventListener("blur",()=>{dn()||c();});let d=p=>{l=p,s.value=p,o(p);},u=()=>{this.choicePop=pc(i,uE,l,d,{...this.listPopover(),onClose:()=>{this.choicePop=null;}});};s.addEventListener("keydown",p=>{p.key==="Enter"&&(p.preventDefault(),c(),s.blur()),p.key==="ArrowDown"&&(p.preventDefault(),u());});let h=p=>{p.preventDefault(),p.stopPropagation(),u();};return s.addEventListener("click",h),a.addEventListener("mousedown",p=>p.preventDefault()),a.addEventListener("click",h),i.append(s,a),i}dateField(e,t,n){let o=document.createElement("div");o.className="vela-ind-combo",o.style.cssText="position:relative;width:128px;";let i=document.createElement("input");i.type="text",i.id=e,i.value=t,i.autocomplete="off",i.spellcheck=false,i.style.cssText=`${this.ctrlStyle()}padding-right:26px;`;let s=document.createElement("button");s.type="button",s.tabIndex=-1,s.className="vela-ind-combo-chevron",s.setAttribute("aria-label","Open calendar"),s.innerHTML=lE;let a=t,l=()=>{let u=xc(i.value);if(!u){i.value=a;return}i.value=u,u!==a&&(a=u,n(u));};i.addEventListener("blur",()=>{dn()||l();});let c=u=>{a=u,i.value=u,n(u);};i.addEventListener("keydown",u=>{u.key==="Enter"&&(u.preventDefault(),l(),i.blur()),u.key==="ArrowDown"&&(u.preventDefault(),this.openCalendar(o,a,c));});let d=u=>{if(u.preventDefault(),u.stopPropagation(),Mn()===o){Me();return}this.openCalendar(o,a,c);};return i.addEventListener("click",d),s.addEventListener("mousedown",u=>u.preventDefault()),s.addEventListener("click",d),o.append(i,s),o}listPopover(){return {theme:this.host.theme(),matchWidth:true,boundary:this.dialog??"viewport",boundaryInset:8,gap:4}}openCalendar(e,t,n){let o=new qe({trigger:e,theme:this.host.theme(),className:"vela-ind-cal",boundary:this.dialog??"viewport",boundaryInset:8,gap:4,onClose:()=>{this.calendarPop=null,this.calendarAnchor=null;},content:i=>{let s=new vs({value:t,onPick:a=>{o.hide(),n(a);}});i.append(s.el);}});this.calendarPop=o,this.calendarAnchor=e,o.show();}buildSymbol(e,t,n){let o=this.host.symbolPicker();if(!o)return this.buildTextField(e,t,n);let i=t,s=document.createElement("button");s.type="button",s.id=e,s.style.cssText=`${this.ctrlStyle()}display:flex;align-items:center;cursor:pointer;text-align:left;`;let a=document.createElement("span");return a.textContent=i||"Select symbol\u2026",a.style.cssText="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;",s.append(a),s.addEventListener("click",()=>o(i,l=>{l&&(i=l,a.textContent=l,n(l));})),s}ctrlStyle(){return "width:100%;box-sizing:border-box;height:34px;background:transparent;border:1px solid var(--vela-border-strong);color:var(--vela-fg-bright);border-radius:6px;padding:0 8px;font-size:14px;font-family:inherit;outline:none;"}isDarkTheme(){return bt(this.host.theme().background)}dialogButton(e,t,n){let o=document.createElement("button");return o.type="button",o.textContent=e,o.className=t?"vela-dialog-btn vela-dialog-btn-primary":"vela-dialog-btn",o.addEventListener("click",n),o}};function Ac(r){let e=r.title;return e.length>0?e.charAt(0).toUpperCase()+e.slice(1):""}var Xy=16;function oE(r){return `padding:16px 20px;overflow-y:auto;overflow-x:hidden;overflow-anchor:none;flex:1 1 auto;display:grid;grid-template-columns:${xs("inputs",r)};align-items:center;align-content:start;column-gap:${Xy}px;row-gap:${Xy}px;`}var Rc="Inputs";function iE(r){let e=new Map;for(let n of r){let o=n.tab&&n.tab.length>0?n.tab:Rc;e.has(o)||e.set(o,[]),e.get(o).push(n);}let t=[...e.keys()];return t.includes(Rc)&&(t.splice(t.indexOf(Rc),1),t.unshift(Rc)),t.map(n=>({name:n,inputs:e.get(n)}))}function jy(r,e){return r.some(t=>ms(t.when,e))}function sE(r){let e={};for(let t of r.inputs)e[t.key]=r.values[t.key]??t.defval;return e}function aE(r){let e=[],t=new Map;for(let n of r){let o=n.group&&n.group.length>0?n.group:null;t.has(o)||(t.set(o,[]),e.push(o)),t.get(o).push(n);}return e.map(n=>{let o=t.get(n),i=[],s=new Map;for(let a of o){let l=a.inline&&a.inline.length>0?a.inline:null;l&&s.has(l)?i[s.get(l)].push(a):(l&&s.set(l,i.length),i.push([a]));}return {name:n,rows:i}})}var lE=Re("calendar",14),cE=Re("clock",14),qy="vela-ind-dialog-styles",Zy="30",Qy=16;function Oc(){if(typeof document>"u")return;let r=document.getElementById(qy);if(r?.dataset.rev===Zy)return;let e=r??document.createElement("style");e.id=qy,e.dataset.rev=Zy,e.textContent=` -.vela-ind-combo input{${jg}} +`;function Dc(r=document){he(Zy,Qy,r);}function Ms(r={}){Dc();let e=document.createElement("div");e.className="vela-field-grid";let t=r.variant??"inputs";return e.dataset.variant=t,r.mobile&&(e.dataset.mobile=""),e.style.gridTemplateColumns=ks(t,r.mobile===true),e}function In(r,e={}){Dc();let t=document.createElement("div");return t.className="vela-field-section",e.variant&&(t.dataset.variant=e.variant),e.first&&(t.dataset.first=""),t.textContent=r,t}function Rh(){Dc();let r=document.createElement("div");return r.className="vela-field-sep",r}function Ls(r,e){let t=document.createElement("span");t.className="vela-field-label",e.size&&(t.dataset.size=e.size),t.textContent=r;let n=e.id;return n&&(t.id=`${n}--title`,queueMicrotask(()=>{t.ownerDocument.getElementById(n)?.setAttribute("aria-labelledby",t.id);})),t}function Jy(r){return r?Array.isArray(r)?r:[r]:[]}function Rc(r,e){if(e)for(let t of e.split(/\s+/))t&&r.classList.add(t);}function Ah(r,e){for(let t of r)t.dataset.sdSelfGated!=="1"&&t.classList.toggle("vela-field-dim",!e);}function Be(r){Dc();let e=r.labelSize;if(r.inline){let i=document.createElement("div");i.className="vela-field-span vela-field-inline";for(let s of r.inline){let a=document.createElement("div");if(a.className="vela-field-inline-item",s.toggleFirst&&(a.style.flexDirection="row-reverse"),s.label&&a.appendChild(Ls(s.label,{id:s.id,size:e})),s.fit)a.appendChild(s.control);else {let l=document.createElement("div");l.style.width="100px",l.appendChild(s.control),a.appendChild(l);}i.appendChild(a);}return r.info&&i.appendChild(r.info),Rc(i,r.className),i}if(r.bool){let i=document.createElement("div");i.className="vela-field-span vela-field-bool";let s=new Gr({id:r.toggle?.id??r.id,checked:r.toggle?.checked??false,size:"md",tone:"bright",onChange:a=>r.toggle?.onChange(a)});if(i.append(s.el,Ls(r.label,{id:r.toggle?.id??r.id,size:e})),r.info&&i.appendChild(r.info),r.toggle?.get){let a=r.toggle.get;i.addEventListener("vela-sync",()=>{s.setChecked(a());});}return Rc(i,r.className),i}if(r.stacked){let i=document.createElement("div");i.className="vela-field-span vela-field-stacked";let s=document.createElement("div");s.className="vela-field-stacked-head",s.appendChild(Ls(r.label,{id:r.id,size:e})),r.info&&s.appendChild(r.info),i.appendChild(s);for(let a of Jy(r.control))i.appendChild(a);return Rc(i,r.className),i}let t=document.createElement("div");t.className="vela-field-row";let n=Jy(r.control);if(r.toggle){let i=document.createElement("div");i.className="vela-field-toggle-label";let s=new Gr({id:r.toggle.id??r.id,checked:r.toggle.checked,size:"md",tone:"bright",onChange:a=>{r.toggle.onChange(a),n.length>0&&Ah(n,a);}});if(i.append(s.el,Ls(r.label,{id:r.toggle.id??r.id,size:e})),t.appendChild(i),n.length>0&&Ah(n,r.toggle.checked),r.toggle.get){let a=r.toggle.get;t.addEventListener("vela-sync",()=>{let l=a();s.setChecked(l),n.length>0&&Ah(n,l);});}}else t.appendChild(Ls(r.label,{id:r.id,size:e}));let o=document.createElement("div");if(o.className="vela-field-cell",r.controlWidth!=null&&n.length===1&&!r.fit){let i=document.createElement("div");i.style.width=`${r.controlWidth}px`,i.appendChild(n[0]),o.appendChild(i);}else for(let i of n)o.appendChild(i);return r.info&&o.appendChild(r.info),t.appendChild(o),Rc(t,r.className),t}function de(r){if(r.kind==="number"){let t=new $r({id:r.id,value:r.value,min:r.min,max:r.max,step:r.step,integer:r.integer,size:"md",fill:r.fill,compact:r.compact,commit:r.commit,steppers:r.steppers,clamp:r.clamp,placeholder:r.placeholder,emptyValue:r.emptyValue,title:r.title,onChange:r.onChange});if(r.sync){let n=r.sync;t.el.addEventListener("vela-sync",()=>{t.setValue(n());});}return {el:t.el,setValue:n=>t.setValue(Number(n))}}if(r.kind==="select"){let t=new ys({id:r.id,options:r.options,value:r.value,size:"md",fill:r.fill,theme:r.theme,list:r.list,onChange:r.onChange});if(r.title&&(t.el.title=r.title),r.sync){let n=r.sync;t.el.addEventListener("vela-sync",()=>{t.setValue(n());});}return {el:t.el,setValue:n=>t.setValue(String(n))}}if(r.kind==="switch"){let t=new Gr({id:r.id,checked:r.checked,size:"md",tone:"bright",onChange:r.onChange});if(r.sync){let n=r.sync;t.el.addEventListener("vela-sync",()=>{t.setChecked(n());});}return {el:t.el,setValue:n=>t.setChecked(!!n)}}if(r.kind==="color"){let t=Ph(r.theme,r.get,r.onChange,{shape:"circle",id:r.id,popover:r.popover,commit:r.commit});return r.title&&(t.title=r.title),{el:t}}if(r.kind==="text"){let t=new Cs({id:r.id,value:r.value,size:"md",fill:r.fill,onChange:r.onChange});if(r.placeholder&&(t.input.placeholder=r.placeholder),r.sync){let n=r.sync;t.el.addEventListener("vela-sync",()=>{t.setValue(n());});}return {el:t.el,setValue:n=>t.setValue(String(n))}}if(r.kind==="textarea"){let t=new Ur({id:r.id,value:r.value,rows:r.rows,autoGrow:r.autoGrow,maxLines:r.maxLines,placeholder:r.placeholder,onChange:r.onChange});if(r.sync){let n=r.sync;t.el.addEventListener("vela-sync",()=>{t.setValue(n());});}return {el:t.el,setValue:n=>t.setValue(String(n))}}let e=Ih(r.theme,r.get,r.onChange);return r.title&&(e.title=r.title),{el:e}}var ew="Properties";function Oc(r,e){return e.prop?r.propValues:r.values}var mE=["close","open","high","low","hl2","hlc3","ohlc4","volume"],Vc=class{constructor(e){this.host=e;this.dialog=null;this.backdrop=null;this.uiDialog=null;this.openId=null;this.row=null;this.snapshot=null;this.propSnapshot=null;this.dialogTips=[];this.refreshVisibility=null;this.choicePop=null;this.calendarPop=null;this.calendarAnchor=null;this.onDialogKey=e=>{if(e.key==="Escape"){if(e.preventDefault(),un()){Me();return}this.close();}};}isOpen(){return this.dialog!==null}open(e){if(this.close(),e.inputs.length===0&&e.props.length===0)return;this.row=e,this.openId=e.id,this.snapshot={...e.values},this.propSnapshot={...e.propValues},Bc();let t=this.host.theme(),n="var(--vela-border)",o="var(--vela-fg-bright)",i=this.host.dialogHost()??this.host.container,s=new Pn({host:i,title:e.title,modal:false,contained:true,align:"center",draggable:!this.host.mobile(),flush:true,className:"vela-dialog--form vela-ind-dialog",closeOnEscape:false,footer:g=>{g.append(this.resetAction(),this.dialogButton("Cancel",false,()=>this.revertAndClose()),this.dialogButton("Ok",true,()=>this.close()));},onOpenChange:g=>{!g&&this.uiDialog===s&&this.close();}});_e(s.panel,t),s.panel.style.colorScheme=this.isDarkTheme()?"dark":"light",this.dialogTips.push(nn(s.panel.querySelector(".vela-dialog-close"),{host:this.host.container,theme:()=>this.host.theme(),text:()=>"Close"}));let a=gE(e.inputs);if(e.props.length>0){let g=e.props.map(y=>{let w={...y,prop:true};return delete w.tab,w}),b=a.find(y=>y.name===ew);b?b.inputs.push(...g):a.push({name:ew,inputs:g});}let l=document.createElement("div");l.style.cssText=`display:flex;gap:12px;padding:0 20px;border-bottom:1px solid ${n};flex:0 0 auto;`;let c=[],d=[],u=[],h=0,p=g=>{h=g;for(let b=0;b1?"cursor:pointer;":""}`,y.addEventListener("click",()=>p(g)),l.appendChild(y),c.push(y),d.push(this.buildTabBody(b.inputs,e,u)),b.inputs.every(w=>w.when)&&u.push({el:y,visible:w=>b.inputs.some(S=>vs(S.when,w))});}s.body.appendChild(l);for(let g of d)s.body.appendChild(g);p(0);let m=()=>{let g=bE(e);for(let b of u)b.el.style.display=b.visible(g)?"":"none";if(c[h]?.style.display==="none"){let b=c.findIndex(y=>y.style.display!=="none");b>=0&&p(b);}};this.refreshVisibility=m,m();let f=g=>{if(!(g.target!==s.backdrop&&g.target!==s.positioner)){if(un()||Wr(g)){Me();return}this.close(),this.host.onBackdropClose();}};s.backdrop.addEventListener("pointerdown",f),s.positioner.addEventListener("pointerdown",f),this.uiDialog=s,this.dialog=s.panel,this.backdrop=s.backdrop,s.show(),document.addEventListener("keydown",this.onDialogKey);}buildTabBody(e,t,n){let o=document.createElement("div");o.style.cssText=fE(this.host.mobile());for(let i of vE(e)){let s=document.createElement("div");s.style.cssText="display:contents;";let a=null;i.name&&(a=In(i.name,{variant:"inputs",first:o.childElementCount===0}),s.appendChild(a));for(let l of i.rows){let c=this.buildInputRow(s,l,t);l.some(d=>d.when)&&n.push({el:c,visible:d=>nw(l,d)});}if(a&&i.rows.every(l=>l.every(c=>c.when))){let l=i.rows;n.push({el:a,visible:c=>l.some(d=>nw(d,c))});}o.appendChild(s);}return o}close(){document.removeEventListener("keydown",this.onDialogKey),Me(),this.refreshVisibility=null,this.choicePop=null,this.calendarPop=null,this.calendarAnchor=null;for(let t of this.dialogTips.splice(0))t();let e=this.uiDialog;this.uiDialog=null,this.backdrop=null,this.dialog=null,this.openId=null,this.row=null,this.snapshot=null,this.propSnapshot=null,e?.destroy();}revertAndClose(){let e=this.row,t=this.snapshot;if(e&&t)for(let o of e.inputs){let i=t[o.key],s=i!==void 0?i:o.defval;e.values[o.key]!==s&&(e.values[o.key]=s,this.host.onChange?.({indicatorId:e.id,key:o.key,value:s}));}let n=this.propSnapshot;if(e&&n)for(let o of e.props){let i=n[o.key],s=i!==void 0?i:o.defval;e.propValues[o.key]!==s&&(e.propValues[o.key]=s,this.host.onChange?.({indicatorId:e.id,key:o.key,value:s,kind:"prop"}));}this.close();}resetAction(){let e=this.dialogButton("Reset defaults",false,()=>this.resetToDefaults());return e.style.marginRight="auto",e}resetToDefaults(){let e=this.row;if(!e)return;let t=this.snapshot,n=this.propSnapshot;for(let o of e.inputs)e.values[o.key]!==o.defval&&(e.values[o.key]=o.defval,this.host.onChange?.({indicatorId:e.id,key:o.key,value:o.defval}));for(let o of e.props)e.propValues[o.key]!==o.defval&&(e.propValues[o.key]=o.defval,this.host.onChange?.({indicatorId:e.id,key:o.key,value:o.defval,kind:"prop"}));this.open(e),t&&(this.snapshot=t),n&&(this.propSnapshot=n);}commit(e,t,n){Oc(e,t)[t.key]=n,this.host.onChange?.({indicatorId:e.id,key:t.key,value:n,...t.prop?{kind:"prop"}:{}}),this.refreshVisibility?.();}buildInputRow(e,t,n){let o=d=>`vela-inp-${n.id}-${d.key}`,i=d=>(e.appendChild(d),d);if(t.length>1)return i(Be({label:"",inline:t.map(d=>({label:Nc(d)||void 0,id:o(d),control:this.buildControl(n,d,o(d)),toggleFirst:d.type==="bool",fit:d.type==="color"||d.type==="bool"})),info:[...t].reverse().find(d=>d.tooltip)?.tooltip?this.infoButton([...t].reverse().find(d=>d.tooltip).tooltip):void 0}));let s=t[0],a=o(s),l=s.tooltip?this.infoButton(s.tooltip):void 0;if(s.type==="bool"){let d=!!(Oc(n,s)[s.key]??s.defval);return i(Be({label:Nc(s),id:a,bool:true,info:l,toggle:{id:a,checked:d,onChange:u=>this.commit(n,s,u)}}))}if(s.type==="text_area")return i(Be({label:Nc(s),id:a,stacked:true,info:l,control:this.buildControl(n,s,a)}));let c=s.type==="color"||s.type==="session"||s.type==="time";return i(Be({label:Nc(s),id:a,fit:c,controlWidth:c?void 0:100,info:l,control:this.buildControl(n,s,a)}))}buildControl(e,t,n){let o=Oc(e,t)[t.key]??t.defval,i=s=>this.commit(e,t,s);return t.type==="bool"?de({kind:"switch",id:n,checked:!!o,onChange:s=>i(s)}).el:t.options&&t.options.length>0?this.select(n,t.options.map(String),String(o),i):t.type==="source"?this.select(n,mE,String(o),i):t.type==="color"?de({kind:"color",id:n,theme:this.host.theme(),get:()=>String(Oc(e,t)[t.key]??t.defval),onChange:s=>i(s),commit:"release"}).el:t.type==="symbol"?this.buildSymbol(n,String(o),i):t.type==="timeframe"?this.selectPairs(n,xE,String(o),i):t.type==="session"?this.buildSession(n,String(o),i):t.type==="time"?this.buildTime(n,Number(o)||0,i):t.type==="text_area"?de({kind:"textarea",id:n,value:String(o),onChange:s=>i(s)}).el:t.type==="int"||t.type==="float"||t.type==="price"?de({kind:"number",id:n,value:Number(o),min:t.min,max:t.max,step:t.step??(t.type==="int"?1:.1),integer:t.type==="int",commit:"blur",onChange:s=>i(s)}).el:this.buildTextField(n,String(o),i)}buildTextField(e,t,n){return de({kind:"text",id:e,value:t,onChange:n}).el}infoButton(e){let{el:t,dispose:n}=Rl(e,{host:this.host.container,theme:()=>this.host.theme(),size:18});return this.dialogTips.push(n),t}select(e,t,n,o){return this.selectPairs(e,t.map(i=>({value:i,label:i})),n,o)}selectPairs(e,t,n,o){return de({kind:"select",id:e,options:t,value:n,theme:this.host.theme(),list:this.listPopover(),onChange:o}).el}buildSession(e,t,n){let[o,i]=TE(t),s=document.createElement("div");s.style.cssText="display:flex;align-items:center;gap:6px;";let a=o,l=i,c=()=>n(kE(a,l));return s.append(this.timeCombobox(e,a,86,d=>{a=d,c();}),this.timeCombobox(`${e}-end`,l,86,d=>{l=d,c();})),s}buildTime(e,t,n){let o=LE(t),i=document.createElement("div");i.style.cssText="display:flex;align-items:center;gap:6px;";let s=o.date,a=o.time,l=()=>{if(!s)return;let u=Date.parse(`${s}T${a}:00`);Number.isFinite(u)&&n(u);},c=this.dateField(e,s,u=>{s=u,l();}),d=this.timeCombobox(`${e}-time`,a,86,u=>{a=u,l();});return i.append(c,d),i}timeCombobox(e,t,n,o){let i=document.createElement("div");i.className="vela-ind-combo",i.style.cssText=`position:relative;width:${n}px;`;let s=document.createElement("input");s.type="text",s.id=e,s.value=t,s.autocomplete="off",s.spellcheck=false,s.style.cssText=`${this.ctrlStyle()}padding-right:26px;`;let a=document.createElement("button");a.type="button",a.tabIndex=-1,a.className="vela-ind-combo-chevron",a.setAttribute("aria-label","Open time list"),a.innerHTML=wE;let l=t,c=()=>{let p=CE(s.value);if(!p){s.value=l;return}s.value=p,p!==l&&(l=p,o(p));};s.addEventListener("blur",()=>{un()||c();});let d=p=>{l=p,s.value=p,o(p);},u=()=>{this.choicePop=bc(i,SE,l,d,{...this.listPopover(),onClose:()=>{this.choicePop=null;}});};s.addEventListener("keydown",p=>{p.key==="Enter"&&(p.preventDefault(),c(),s.blur()),p.key==="ArrowDown"&&(p.preventDefault(),u());});let h=p=>{p.preventDefault(),p.stopPropagation(),u();};return s.addEventListener("click",h),a.addEventListener("mousedown",p=>p.preventDefault()),a.addEventListener("click",h),i.append(s,a),i}dateField(e,t,n){let o=document.createElement("div");o.className="vela-ind-combo",o.style.cssText="position:relative;width:128px;";let i=document.createElement("input");i.type="text",i.id=e,i.value=t,i.autocomplete="off",i.spellcheck=false,i.style.cssText=`${this.ctrlStyle()}padding-right:26px;`;let s=document.createElement("button");s.type="button",s.tabIndex=-1,s.className="vela-ind-combo-chevron",s.setAttribute("aria-label","Open calendar"),s.innerHTML=yE;let a=t,l=()=>{let u=kc(i.value);if(!u){i.value=a;return}i.value=u,u!==a&&(a=u,n(u));};i.addEventListener("blur",()=>{un()||l();});let c=u=>{a=u,i.value=u,n(u);};i.addEventListener("keydown",u=>{u.key==="Enter"&&(u.preventDefault(),l(),i.blur()),u.key==="ArrowDown"&&(u.preventDefault(),this.openCalendar(o,a,c));});let d=u=>{if(u.preventDefault(),u.stopPropagation(),En()===o){Me();return}this.openCalendar(o,a,c);};return i.addEventListener("click",d),s.addEventListener("mousedown",u=>u.preventDefault()),s.addEventListener("click",d),o.append(i,s),o}listPopover(){return {theme:this.host.theme(),matchWidth:true,boundary:this.dialog??"viewport",boundaryInset:8,gap:4}}openCalendar(e,t,n){let o=new qe({trigger:e,theme:this.host.theme(),className:"vela-ind-cal",boundary:this.dialog??"viewport",boundaryInset:8,gap:4,onClose:()=>{this.calendarPop=null,this.calendarAnchor=null;},content:i=>{let s=new Ss({value:t,onPick:a=>{o.hide(),n(a);}});i.append(s.el);}});this.calendarPop=o,this.calendarAnchor=e,o.show();}buildSymbol(e,t,n){let o=this.host.symbolPicker();if(!o)return this.buildTextField(e,t,n);let i=t,s=document.createElement("button");s.type="button",s.id=e,s.style.cssText=`${this.ctrlStyle()}display:flex;align-items:center;cursor:pointer;text-align:left;`;let a=document.createElement("span");return a.textContent=i||"Select symbol\u2026",a.style.cssText="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;",s.append(a),s.addEventListener("click",()=>o(i,l=>{l&&(i=l,a.textContent=l,n(l));})),s}ctrlStyle(){return "width:100%;box-sizing:border-box;height:34px;background:transparent;border:1px solid var(--vela-border-strong);color:var(--vela-fg-bright);border-radius:6px;padding:0 8px;font-size:14px;font-family:inherit;outline:none;"}isDarkTheme(){return bt(this.host.theme().background)}dialogButton(e,t,n){let o=document.createElement("button");return o.type="button",o.textContent=e,o.className=t?"vela-dialog-btn vela-dialog-btn-primary":"vela-dialog-btn",o.addEventListener("click",n),o}};function Nc(r){let e=r.title;return e.length>0?e.charAt(0).toUpperCase()+e.slice(1):""}var tw=16;function fE(r){return `padding:16px 20px;overflow-y:auto;overflow-x:hidden;overflow-anchor:none;flex:1 1 auto;display:grid;grid-template-columns:${ks("inputs",r)};align-items:center;align-content:start;column-gap:${tw}px;row-gap:${tw}px;`}var Fc="Inputs";function gE(r){let e=new Map;for(let n of r){let o=n.tab&&n.tab.length>0?n.tab:Fc;e.has(o)||e.set(o,[]),e.get(o).push(n);}let t=[...e.keys()];return t.includes(Fc)&&(t.splice(t.indexOf(Fc),1),t.unshift(Fc)),t.map(n=>({name:n,inputs:e.get(n)}))}function nw(r,e){return r.some(t=>vs(t.when,e))}function bE(r){let e={};for(let t of r.inputs)e[t.key]=r.values[t.key]??t.defval;return e}function vE(r){let e=[],t=new Map;for(let n of r){let o=n.group&&n.group.length>0?n.group:null;t.has(o)||(t.set(o,[]),e.push(o)),t.get(o).push(n);}return e.map(n=>{let o=t.get(n),i=[],s=new Map;for(let a of o){let l=a.inline&&a.inline.length>0?a.inline:null;l&&s.has(l)?i[s.get(l)].push(a):(l&&s.set(l,i.length),i.push([a]));}return {name:n,rows:i}})}var yE=Re("calendar",14),wE=Re("clock",14),rw="vela-ind-dialog-styles",ow="30",iw=16;function Bc(){if(typeof document>"u")return;let r=document.getElementById(rw);if(r?.dataset.rev===ow)return;let e=r??document.createElement("style");e.id=rw,e.dataset.rev=ow,e.textContent=` +.vela-ind-combo input{${tb}} .vela-ind-combo input:hover{border-color:var(--vela-fg-muted);} -.vela-ind-combo input:focus{${qg}} +.vela-ind-combo input:focus{${nb}} .vela-ind-combo-chevron{position:absolute;right:0;top:0;bottom:0;width:26px;border:none;background:transparent;color:inherit;opacity:0.55;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0;} .vela-ind-combo-chevron:hover{opacity:0.9;} .vela-ind-cal{background:var(--vela-bg);color:var(--vela-fg);border:none;border-radius:6px;box-shadow:var(--vela-shadow);font:14px var(--vela-font);padding:10px 12px;user-select:none;} -${Ir(".vela-dialog.vela-ind-dialog *",9)} +${Or(".vela-dialog.vela-ind-dialog *",9)} .vela-ind-tab{font-weight:600;font-size:13px;line-height:20px;transition:color var(--vela-dur-fast) ease,border-color var(--vela-dur-fast) ease;} .vela-ind-tab:not(.vela-ind-tab-active):hover{color:var(--vela-fg-bright);} .vela-ind-ctl,.vela-ind-close{background-color:transparent;color:inherit;transition:color var(--vela-dur-fast) ease,background-color var(--vela-dur-fast) ease;} -.vela-ind-ctl svg,.vela-ind-close svg{width:${Qy}px;height:${Qy}px;display:block;flex:none;stroke-width:1;} +.vela-ind-ctl svg,.vela-ind-close svg{width:${iw}px;height:${iw}px;display:block;flex:none;stroke-width:1;} .vela-ind-ctl:hover{background-color:var(--vela-hover-strong);} .vela-ind-close:hover{color:var(--vela-danger) !important;background-color:var(--vela-hover-strong);} .vela-ind-fold{transition:border-color var(--vela-dur-fast) ease,opacity var(--vela-dur-fast) ease;} -.vela-ind-fold:hover{border-color:var(--vela-border-strong);opacity:0.9;}`,r||document.head.appendChild(e);}var dE=[{value:"",label:"Chart"},{value:"1",label:"1 minute"},{value:"3",label:"3 minutes"},{value:"5",label:"5 minutes"},{value:"15",label:"15 minutes"},{value:"30",label:"30 minutes"},{value:"45",label:"45 minutes"},{value:"60",label:"1 hour"},{value:"120",label:"2 hours"},{value:"180",label:"3 hours"},{value:"240",label:"4 hours"},{value:"D",label:"1 day"},{value:"W",label:"1 week"},{value:"M",label:"1 month"}],uE=Array.from({length:48},(r,e)=>{let t=String(Math.floor(e/2)).padStart(2,"0"),n=e%2===0?"00":"30",o=`${t}:${n}`;return {value:o,label:o}});function hE(r){let e=r.trim(),t=/^(\d{1,2}):(\d{2})$/.exec(e)??/^(\d{2})(\d{2})$/.exec(e);if(!t)return null;let n=Number(t[1]),o=Number(t[2]);return n>23||o>59?null:`${String(n).padStart(2,"0")}:${String(o).padStart(2,"0")}`}function pE(r){let e=/^(\d{2})(\d{2})-(\d{2})(\d{2})$/.exec(r.trim());return e?[`${e[1]}:${e[2]}`,`${e[3]}:${e[4]}`]:["09:00","16:00"]}function mE(r,e){return `${r.replace(":","")}-${e.replace(":","")}`}function fE(r){if(!r)return {date:"",time:"09:30"};let e=r<1e12?r*1e3:r,t=new Date(e);if(Number.isNaN(t.getTime()))return {date:"",time:"09:30"};let n=`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}-${String(t.getDate()).padStart(2,"0")}`,o=Math.round((t.getHours()*60+t.getMinutes())/30)*30,i=String(Math.floor(o/60)%24).padStart(2,"0"),s=String(o%60).padStart(2,"0");return {date:n,time:`${i}:${s}`}}var gE="data-vela-pane-at-top",bE="@keyframes vela-ind-pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.3;transform:scale(.6)}}",In=16,Ih=18,rw=2,Jy=6,vE=6,Ph=8,ew=6,Ts=`cursor:pointer;display:inline-flex;align-items:center;justify-content:center;border:none;line-height:0;padding:0;width:${Ih}px;height:${Ih}px;border-radius:3px;box-sizing:border-box;flex:none;`,yE=Ih+rw*2,tw=Re("eye",In),wE=Re("eye-off",In),xE=Re("gear",In),CE=Re("close",In),SE=Re("chevron-up",In),TE=Re("chevron-down",In),kE=Re("objects",In);function nw(r,e){return !r&&e?"inline-flex":"none"}var Nc=class{constructor(e,t,n){this.container=e;this.theme=t;this.paneBoundsOf=n;this.legends=new Map;this.rows=new Map;this.selectedId=null;this.onChange=null;this.onRemove=null;this.onToggleVisible=null;this.symbolPicker=null;this.mobileLayout=false;this.moveApi=null;this.legendActions=null;this.legendCallouts=null;this.rowTips=new Map;this.extrasTips=new Map;this.calloutTips=new Map;this.moveMenu=null;this.moveTargets=[];this.moveMenuId=null;this.paneCollapse=new Map;this.legendFolded=false;this.titlesVisible=true;this.valuesVisible=true;this.rowMenu=null;this.rowMenuId=null;this.foldToggle=null;this.overviewAction=null;this.onDocClick=e=>{if(!this.selectedId)return;let t=e.target;if(t){for(let n of this.rows.values())if(n.el.contains(t))return}this.clearSelection();};this.dialogHost=null;e.style.position||(e.style.position="relative"),typeof document<"u"&&document.addEventListener("click",this.onDocClick),Oc(),this.inputsDialog=new Dc({container:e,theme:()=>this.theme,mobile:()=>this.mobileLayout,dialogHost:()=>this.dialogHost,symbolPicker:()=>this.symbolPicker,onChange:o=>this.onChange?.(o),onBackdropClose:()=>this.clearSelection()});}setDialogHost(e){this.dialogHost=e,e&&getComputedStyle(e).position==="static"&&(e.style.position="relative");}setLayoutMode(e){let t=e==="mobile";if(t!==this.mobileLayout&&(this.mobileLayout=t,this.overviewAction===null&&(this.legendFolded=t),this.syncFoldToggle(),this.inputsDialog.openId!==null)){let n=this.inputsDialog.openId;this.closeOpenDialog(),this.openDialog(n);}}setLegendOverviewAction(e){e!==this.overviewAction&&(this.overviewAction=e,this.legendFolded=e!==null?true:this.mobileLayout,this.syncFoldToggle());}openSettingsFor(e){this.rows.has(e)&&this.openDialog(e);}tip(e,t,n,o,i=false){let s=e.get(t)??[];s.push(tn(n,{host:this.container,theme:()=>this.theme,text:typeof o=="function"?o:()=>o,wrap:i})),e.set(t,s);}disposeTips(e,t){for(let n of e.get(t)??[])n();e.delete(t);}setOnChange(e){this.onChange=e;}setOnRemove(e){this.onRemove=e;}setOnToggleVisible(e){this.onToggleVisible=e;}setTheme(e){this.theme=e;for(let t of this.legends.values())Be(t,e);for(let t of this.rows.values())t.el.style.background=t.highlighted?e.background:this.idleRowFill(),t.el.style.color=e.textColor;this.foldToggle&&this.syncFoldToggle();}setSymbolPicker(e){this.symbolPicker=e;}setMoveApi(e){this.moveApi=e;}setLegendActions(e){this.legendActions=e;for(let t of this.rows.values())this.renderExtras(t.id,t.extrasEl);}renderExtras(e,t){this.disposeTips(this.extrasTips,e),t.replaceChildren();for(let n of this.legendActions?.(e)??[]){let o=document.createElement("button");o.type="button",o.setAttribute("aria-label",n.tooltip),this.tip(this.extrasTips,e,o,n.tooltip),o.innerHTML=Re(n.icon,In),o.className="vela-ind-ctl",o.dataset.legendAction=n.id,o.style.cssText=Ts,o.addEventListener("click",i=>{i.stopPropagation(),n.run();}),t.appendChild(o);}}setLegendCallouts(e){this.legendCallouts=e;for(let t of this.rows.values())this.renderCallouts(t);}renderCallouts(e){this.disposeTips(this.calloutTips,e.id);for(let n of e.callouts)n.destroy();e.callouts=[],e.calloutsEl.replaceChildren();let t=this.legendCallouts?.(e.id)??[];e.calloutsEl.style.display=nw(e.highlighted,t.length>0);for(let n of t){let o=new ps({icon:n.icon,background:n.background,...n.color!==void 0?{color:n.color}:{},label:n.tooltip,...n.content!==void 0?{panel:n.content}:{},host:this.container,theme:()=>this.theme});o.el.dataset.legendCallout=n.id,this.tip(this.calloutTips,e.id,o.el,n.tooltip),e.callouts.push(o),e.calloutsEl.appendChild(o.el);}}reposition(){for(let[e,t]of this.legends)this.positionLegend(t,e);}setTitlesVisible(e){this.titlesVisible!==e&&(this.titlesVisible=e,this.reposition());}setValuesVisible(e){this.valuesVisible=e;for(let t of this.rows.values())t.showValues=null,this.renderRowValues(t);}setPlotValues(e){for(let t of this.rows.values()){let n=e.get(t.id)??[],o=n.map(i=>`${i.value}|${i.color}`).join("\0");o!==t.plotValuesKey&&(t.plotValues=n,t.plotValuesKey=o,this.renderRowValues(t));}}rowValuesShown(e){return e.showValues??this.valuesVisible}renderRowValues(e){if(!this.rowValuesShown(e)||e.plotValues.length===0||e.highlighted){e.valuesEl.style.display="none",e.valuesEl.replaceChildren();return}e.valuesEl.style.display="inline-flex",e.valuesEl.replaceChildren();for(let t of e.plotValues){let n=document.createElement("span");n.textContent=t.value,n.style.color=t.color,e.valuesEl.appendChild(n);}}openMoveMenu(e,t){this.closeMoveMenu();let n=this.moveApi;if(!n)return;let i=this.rows.get(e)?.paneId??"price",s=n.panes(),a=[];for(let u of s)u.id!==i&&a.push({label:`Move to ${u.label}`,target:u.kind==="price"?"price":{pane:u.id}});i!=="price"&&[...this.rows.values()].filter(u=>u.paneId===i).length<=1||(i!=="price"&&a.push({label:"New pane above",target:{newPane:{before:i}}}),a.push({label:"New pane below",target:{newPane:{after:i}}})),this.moveTargets=a.map(u=>u.target),this.moveMenuId=e;let c=a.map((u,h)=>({id:String(h),label:u.label}));this.moveMenu?this.moveMenu.setItems(c):this.moveMenu=new Oo({host:this.container,items:c,placement:"bottom-start",onSelect:u=>{let h=this.moveTargets[Number(u)],p=this.moveMenuId;h&&p&&n.move(p,h);}});let d=t.getBoundingClientRect();this.moveMenu.openAt(d.left,d.bottom+4);}closeMoveMenu(){this.moveMenu?.close();}openRowMenu(e,t,n){this.closeRowMenu(),this.closeMoveMenu();let o=this.rows.get(e);if(!o)return;this.rowMenuId=e;let i=[{id:"values",label:"Indicator values",checked:this.rowValuesShown(o)}];this.rowMenu?this.rowMenu.setItems(i):this.rowMenu=new Oo({host:this.container,items:i,placement:"bottom-start",checkmarks:true,onSelect:s=>{if(s!=="values"||!this.rowMenuId)return;let a=this.rows.get(this.rowMenuId);a&&(a.showValues=!this.rowValuesShown(a),this.renderRowValues(a));}}),this.rowMenu.openAt(t,n);}closeRowMenu(){this.rowMenu?.close();}setPane(e,t){let n=this.rows.get(e);if(!n||n.paneId===t)return;let o=n.paneId;if(n.paneId=t,this.attach(this.legendFor(t),n.el,n.native),this.syncFoldToggle(),o!=="price"){let i=this.legends.get(o);i&&i.childElementCount===0&&(i.remove(),this.legends.delete(o));}}legendFor(e){let t=this.legends.get(e);return t||(t=document.createElement("div"),t.dataset.velaPane=e,t.style.cssText="position:absolute;left:10px;z-index:5;display:flex;flex-direction:column;align-items:flex-start;gap:0;pointer-events:none;font:12px -apple-system,Segoe UI,sans-serif;",Be(t,this.theme),this.positionLegend(t,e),this.container.appendChild(t),this.legends.set(e,t)),t}positionLegend(e,t){let n=this.paneBoundsOf?this.paneBoundsOf(t):{top:0,height:1/0};e.toggleAttribute(gE,n.top===0),e.style.display=n.height<4||!this.titlesVisible?"none":"flex";let o=this.paneCollapse.has(t),i=this.paneCollapse.get(t)??null;for(let a of this.rows.values())a.paneId===t&&(a.el.style.display=(o?a.id!==i:this.legendFolded)?"none":"flex");let s=n.top+8;if(o&&Number.isFinite(n.height)){let a=e.offsetHeight||20;s=n.top+Math.max(1,Math.round((n.height-a)/2));}e.style.top=`${s}px`;}setCollapsedPanes(e){this.paneCollapse=e;}syncFoldToggle(){let e=this.rows.size,t=this.overviewAction!==null||this.mobileLayout?1:2;if(e0&&(this.legendFolded=false),this.foldToggle&&(this.foldToggle.remove(),this.foldToggle=null,this.disposeTips(this.rowTips,"fold")),a&&e>0&&this.reposition();return}let n=this.foldToggle;n||(n=document.createElement("button"),n.type="button",n.className="vela-ind-fold",this.tip(this.rowTips,"fold",n,()=>this.overviewAction!==null?"Indicators":this.legendFolded?"Show indicator legend":"Hide indicator legend"),n.addEventListener("click",()=>{if(this.overviewAction!==null){this.overviewAction();return}this.legendFolded=!this.legendFolded,this.syncFoldToggle();}),this.foldToggle=n);let o=this.legendFolded;n.setAttribute("aria-label",this.overviewAction!==null?"Indicators":o?"Show indicator legend":"Hide indicator legend");let i=this.theme.textColor;n.style.cssText=`pointer-events:auto;display:inline-flex;align-items:center;gap:4px;background:${this.theme.background};color:${i};border:1px solid ${this.theme.borderColor};border-radius:4px;padding:2px 6px;margin-top:6px;cursor:pointer;font:inherit;line-height:0;`,n.replaceChildren();let s=document.createElement("span");if(s.style.cssText="display:inline-flex;align-items:center;line-height:0;opacity:0.7;",s.innerHTML=this.overviewAction!==null?kE:o?TE:SE,n.appendChild(s),o){let a=document.createElement("span");a.textContent=String(e),a.style.cssText=`font-weight:600;line-height:normal;font-size:12px;color:${i};`,n.appendChild(a);}this.legendFor("price").appendChild(n),this.reposition();}upsert(e,t,n,o,i="price",s={}){let a=this.rows.get(e);if(a){a.title=t,a.inputs=n,a.values={...o},a.props=s.props??[],a.propValues={...s.propValues??{}},a.titleEl.textContent=t,a.paneId!==i&&(a.paneId=i,this.attach(this.legendFor(i),a.el,a.native),this.syncFoldToggle());return}Oc();let l=document.createElement("div");l.style.cssText=`pointer-events:auto;display:flex;align-items:center;background:${this.idleRowFill()};border-radius:4px;padding:${rw}px ${Jy}px;margin-left:-${Jy}px;min-height:${yE}px;box-sizing:border-box;color:${this.theme.textColor};user-select:none;-webkit-user-select:none;`,l.addEventListener("mouseleave",()=>{this.selectedId!==e&&this.setRowHighlighted(e,false);}),l.addEventListener("click",w=>{w.button!==0||w.target.closest("button")||this.selectRow(e);}),l.addEventListener("dblclick",w=>{w.target.closest("button")||this.openDialog(e);}),l.addEventListener("mousedown",w=>{w.button===1&&w.preventDefault();}),l.addEventListener("auxclick",w=>{w.button===1&&(w.preventDefault(),this.onRemove?.(e));}),l.addEventListener("contextmenu",w=>{w.preventDefault(),w.stopPropagation(),this.openRowMenu(e,w.clientX,w.clientY);});let c=document.createElement("span");c.style.cssText="display:none;box-sizing:border-box;flex:none;";let d=document.createElement("span");d.style.cssText="white-space:nowrap;",d.addEventListener("mouseenter",()=>this.setRowHighlighted(e,true));let u=document.createElement("span");if(u.textContent=t,u.style.cssText="font-weight:600;",d.appendChild(u),s.beta){let w=document.createElement("sup");w.textContent="beta",w.style.cssText="font-size:8px;font-weight:700;opacity:0.7;margin-left:1px;letter-spacing:0.2px;",d.appendChild(w);}l.appendChild(d);let h=document.createElement("span");h.style.cssText=`display:none;align-items:center;gap:4px;flex:none;margin-left:${Ph}px;`,l.appendChild(h),l.appendChild(c);let p=document.createElement("span");p.style.cssText=`display:none;align-items:center;gap:5px;margin-left:${vE}px;white-space:nowrap;font-variant-numeric:tabular-nums;`,l.appendChild(p);let m=document.createElement("span");m.style.cssText=`display:none;align-items:center;gap:${ew}px;flex:none;margin-left:${ew}px;`;let f=null;if(this.onToggleVisible){let w=document.createElement("button");w.type="button",w.setAttribute("aria-label","Hide"),this.tip(this.rowTips,e,w,()=>this.rows.get(e)?.hidden?"Show":"Hide"),w.innerHTML=tw,w.className="vela-ind-ctl",w.style.cssText=Ts,w.addEventListener("click",()=>{let C=this.rows.get(e);this.onToggleVisible?.(e,!!C?.hidden);}),m.appendChild(w),f=w;}if(n.length>0||(s.props??[]).length>0){let w=document.createElement("button");w.type="button",w.setAttribute("aria-label","Settings"),this.tip(this.rowTips,e,w,"Settings"),w.innerHTML=xE,w.className="vela-ind-ctl",w.style.cssText=Ts,w.addEventListener("click",()=>this.openDialog(e)),m.appendChild(w);}if(this.moveApi){let w=document.createElement("button");w.type="button",w.setAttribute("aria-label","Move to pane"),this.tip(this.rowTips,e,w,"Move to pane"),w.innerHTML=Re("move",In),w.className="vela-ind-ctl",w.style.cssText=Ts,w.addEventListener("click",C=>{C.stopPropagation(),this.openMoveMenu(e,w);}),m.appendChild(w);}let g=document.createElement("span");g.style.cssText="display:contents;",this.renderExtras(e,g),m.appendChild(g);let b=document.createElement("button");b.type="button",b.setAttribute("aria-label","Remove indicator"),this.tip(this.rowTips,e,b,"Remove indicator"),b.innerHTML=CE,b.className="vela-ind-close",b.style.cssText=Ts,b.addEventListener("click",()=>this.onRemove?.(e)),m.appendChild(b),l.appendChild(m),this.attach(this.legendFor(i),l,!!s.native);let y={id:e,title:t,inputs:n,values:{...o},props:s.props??[],propValues:{...s.propValues??{}},el:l,titleEl:u,statusEl:c,valuesEl:p,plotValues:[],plotValuesKey:"",showValues:null,highlighted:false,paneId:i,hidden:false,eyeEl:f,controlsEl:m,extrasEl:g,calloutsEl:h,callouts:[],native:!!s.native};this.rows.set(e,y),this.renderCallouts(y),this.syncFoldToggle();}attach(e,t,n){n?e.prepend(t):e.appendChild(t);}setValues(e,t,n){let o=this.rows.get(e);o&&(o.values={...o.values,...t},n&&(o.propValues={...o.propValues,...n}));}setStatus(e,t){let n=this.rows.get(e);if(!n)return;let o=n.statusEl;if(o.replaceChildren(),t==="idle"){o.style.cssText="display:none;box-sizing:border-box;flex:none;";return}if(t==="loading"){o.style.cssText=`display:inline-flex;align-items:center;gap:3px;box-sizing:border-box;flex:none;margin-left:${Ph}px;line-height:0;transform:translateY(1px);`;for(let i=0;i<3;i+=1){let s=document.createElement("span");s.style.cssText="width:4px;height:4px;border-radius:50%;background:currentColor;opacity:0.15;flex:none;",s.animate?.([{opacity:.12},{opacity:.55}],{duration:800,iterations:1/0,direction:"alternate",easing:"ease-in-out",delay:-i*260}),o.appendChild(s);}return}this.ensureStatusKeyframes(),o.style.cssText=`display:inline-block;box-sizing:border-box;flex:none;width:8px;height:8px;border-radius:50%;margin-left:${Ph}px;transform:translateY(1px);background:${this.theme.upColor};animation:vela-ind-pulse 1.2s ease-in-out infinite;`;}ensureStatusKeyframes(){if(typeof document>"u"||document.getElementById("vela-ind-status-kf"))return;let e=document.createElement("style");e.id="vela-ind-status-kf",e.textContent=bE,document.head.appendChild(e);}setVisible(e,t){let n=this.rows.get(e);n&&(n.hidden=!t,n.el.style.opacity=t?"1":"0.5",n.eyeEl&&(n.eyeEl.innerHTML=t?tw:wE,n.eyeEl.setAttribute("aria-label",t?"Hide":"Show")),this.syncRowActions(n));}selectRow(e){this.selectedId!==e&&(this.clearSelection(),this.selectedId=e,this.setRowHighlighted(e,true));}setRowHighlighted(e,t){let n=this.rows.get(e);n&&(n.highlighted=t,this.renderRowValues(n),n.el.style.boxShadow=t?`inset 0 0 0 1px ${this.neutralBorder()}`:"none",n.el.style.background=t?this.theme.background:this.idleRowFill(),this.syncRowActions(n));}syncRowActions(e){let t=e.highlighted;if(e.controlsEl.style.display=t||e.hidden?"inline-flex":"none",t){e.el.appendChild(e.statusEl);for(let n of e.callouts)n.hidePanel();}else e.el.insertBefore(e.statusEl,e.valuesEl);e.calloutsEl.style.display=nw(t,e.callouts.length>0);for(let n of Array.from(e.controlsEl.children))if(!(!(n instanceof HTMLElement)||n===e.eyeEl)){if(n===e.extrasEl){n.style.display=t?"contents":"none";continue}n.style.display=t?"inline-flex":"none";}}clearSelection(){this.selectedId&&(this.setRowHighlighted(this.selectedId,false),this.selectedId=null);}remove(e){let t=this.rows.get(e);for(let n of t?.callouts??[])n.destroy();if(t?.el.remove(),this.rows.delete(e),this.disposeTips(this.rowTips,e),this.disposeTips(this.extrasTips,e),this.disposeTips(this.calloutTips,e),this.selectedId===e&&(this.selectedId=null),this.inputsDialog.openId===e&&this.inputsDialog.close(),this.syncFoldToggle(),t&&t.paneId!=="price"){let n=this.legends.get(t.paneId);n&&n.childElementCount===0&&(n.remove(),this.legends.delete(t.paneId));}}destroy(){this.inputsDialog.close(),this.moveMenu?.destroy(),this.moveMenu=null,this.rowMenu?.destroy(),this.rowMenu=null;for(let e of [...this.rowTips.keys()])this.disposeTips(this.rowTips,e);for(let e of [...this.extrasTips.keys()])this.disposeTips(this.extrasTips,e);for(let e of [...this.calloutTips.keys()])this.disposeTips(this.calloutTips,e);for(let e of this.rows.values())for(let t of e.callouts)t.destroy();for(let e of this.legends.values())e.remove();this.legends.clear(),this.rows.clear(),this.foldToggle=null,this.legendFolded=false,this.selectedId=null,typeof document<"u"&&document.removeEventListener("click",this.onDocClick);}isDialogOpen(){return this.inputsDialog.isOpen()}closeOpenDialog(){this.inputsDialog.close();}openDialog(e){let t=this.rows.get(e);t&&this.inputsDialog.open(t);}idleRowFill(){return J(this.theme.background,.6)}neutralBorder(){return "var(--vela-border)"}};var Bo={up:ee("chevron-up"),down:ee("chevron-down"),collapse:ee("pane-collapse"),expand:ee("pane-expand"),maximize:ee("maximize"),restore:ee("restore")},ow="vela-pane-controls",LE=12,iw="rgba(0,0,0,0.65)";function ME(){if(typeof document>"u"||document.getElementById(ow))return;let r=document.createElement("style");r.id=ow,r.textContent=` -.vela-pc-btn{display:inline-flex;align-items:center;justify-content:center;padding:0;border:none;border-radius:var(--vela-radius-sm);background:transparent;line-height:0;font-size:${LE}px;color:var(--vela-fg-muted);} +.vela-ind-fold:hover{border-color:var(--vela-border-strong);opacity:0.9;}`,r||document.head.appendChild(e);}var xE=[{value:"",label:"Chart"},{value:"1",label:"1 minute"},{value:"3",label:"3 minutes"},{value:"5",label:"5 minutes"},{value:"15",label:"15 minutes"},{value:"30",label:"30 minutes"},{value:"45",label:"45 minutes"},{value:"60",label:"1 hour"},{value:"120",label:"2 hours"},{value:"180",label:"3 hours"},{value:"240",label:"4 hours"},{value:"D",label:"1 day"},{value:"W",label:"1 week"},{value:"M",label:"1 month"}],SE=Array.from({length:48},(r,e)=>{let t=String(Math.floor(e/2)).padStart(2,"0"),n=e%2===0?"00":"30",o=`${t}:${n}`;return {value:o,label:o}});function CE(r){let e=r.trim(),t=/^(\d{1,2}):(\d{2})$/.exec(e)??/^(\d{2})(\d{2})$/.exec(e);if(!t)return null;let n=Number(t[1]),o=Number(t[2]);return n>23||o>59?null:`${String(n).padStart(2,"0")}:${String(o).padStart(2,"0")}`}function TE(r){let e=/^(\d{2})(\d{2})-(\d{2})(\d{2})$/.exec(r.trim());return e?[`${e[1]}:${e[2]}`,`${e[3]}:${e[4]}`]:["09:00","16:00"]}function kE(r,e){return `${r.replace(":","")}-${e.replace(":","")}`}function LE(r){if(!r)return {date:"",time:"09:30"};let e=r<1e12?r*1e3:r,t=new Date(e);if(Number.isNaN(t.getTime()))return {date:"",time:"09:30"};let n=`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}-${String(t.getDate()).padStart(2,"0")}`,o=Math.round((t.getHours()*60+t.getMinutes())/30)*30,i=String(Math.floor(o/60)%24).padStart(2,"0"),s=String(o%60).padStart(2,"0");return {date:n,time:`${i}:${s}`}}var ME="data-vela-pane-at-top",EE="@keyframes vela-ind-pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.3;transform:scale(.6)}}",An=16,Nh=18,dw=2,Dh=6,sw=10,PE=6,IE=6,AE=5,Oh=8,aw=6,Es=`cursor:pointer;display:inline-flex;align-items:center;justify-content:center;border:none;line-height:0;padding:0;width:${Nh}px;height:${Nh}px;border-radius:3px;box-sizing:border-box;flex:none;`,RE=Nh+dw*2,lw=Re("eye",An),DE=Re("eye-off",An),OE=Re("gear",An),NE=Re("close",An),FE=Re("chevron-up",An),VE=Re("chevron-down",An),BE=Re("objects",An);function cw(r,e){return !r&&e?"inline-flex":"none"}var _c=class{constructor(e,t,n){this.container=e;this.theme=t;this.paneBoundsOf=n;this.legends=new Map;this.rows=new Map;this.selectedId=null;this.onChange=null;this.onRemove=null;this.onToggleVisible=null;this.symbolPicker=null;this.mobileLayout=false;this.moveApi=null;this.legendActions=null;this.legendCallouts=null;this.rowTips=new Map;this.extrasTips=new Map;this.calloutTips=new Map;this.moveMenu=null;this.moveTargets=[];this.moveMenuId=null;this.paneCollapse=new Map;this.legendFolded=false;this.titlesVisible=true;this.valuesVisible=true;this.rowMenu=null;this.rowMenuId=null;this.foldToggle=null;this.overviewAction=null;this.onDocClick=e=>{if(!this.selectedId)return;let t=e.target;if(t){for(let n of this.rows.values())if(n.el.contains(t))return}this.clearSelection();};this.dialogHost=null;e.style.position||(e.style.position="relative"),typeof document<"u"&&document.addEventListener("click",this.onDocClick),Bc(),this.inputsDialog=new Vc({container:e,theme:()=>this.theme,mobile:()=>this.mobileLayout,dialogHost:()=>this.dialogHost,symbolPicker:()=>this.symbolPicker,onChange:o=>this.onChange?.(o),onBackdropClose:()=>this.clearSelection()});}setDialogHost(e){this.dialogHost=e,e&&getComputedStyle(e).position==="static"&&(e.style.position="relative");}setLayoutMode(e){let t=e==="mobile";if(t!==this.mobileLayout&&(this.mobileLayout=t,this.overviewAction===null&&(this.legendFolded=t),this.syncFoldToggle(),this.inputsDialog.openId!==null)){let n=this.inputsDialog.openId;this.closeOpenDialog(),this.openDialog(n);}}setLegendOverviewAction(e){e!==this.overviewAction&&(this.overviewAction=e,this.legendFolded=e!==null?true:this.mobileLayout,this.syncFoldToggle());}openSettingsFor(e){this.rows.has(e)&&this.openDialog(e);}tip(e,t,n,o,i=false){let s=e.get(t)??[];s.push(nn(n,{host:this.container,theme:()=>this.theme,text:typeof o=="function"?o:()=>o,wrap:i})),e.set(t,s);}disposeTips(e,t){for(let n of e.get(t)??[])n();e.delete(t);}setOnChange(e){this.onChange=e;}setOnRemove(e){this.onRemove=e;}setOnToggleVisible(e){this.onToggleVisible=e;}setTheme(e){this.theme=e;for(let t of this.legends.values())_e(t,e);for(let t of this.rows.values())t.el.style.background=t.highlighted?e.background:this.idleRowFill(),t.el.style.color=e.textColor;this.foldToggle&&this.syncFoldToggle();}setSymbolPicker(e){this.symbolPicker=e;}setMoveApi(e){this.moveApi=e;}setLegendActions(e){this.legendActions=e;for(let t of this.rows.values())this.renderExtras(t.id,t.extrasEl);}renderExtras(e,t){this.disposeTips(this.extrasTips,e),t.replaceChildren();for(let n of this.legendActions?.(e)??[]){let o=document.createElement("button");o.type="button",o.setAttribute("aria-label",n.tooltip),this.tip(this.extrasTips,e,o,n.tooltip),o.innerHTML=Re(n.icon,An),o.className="vela-ind-ctl",o.dataset.legendAction=n.id,o.style.cssText=Es,o.addEventListener("click",i=>{i.stopPropagation(),n.run();}),t.appendChild(o);}}setLegendCallouts(e){this.legendCallouts=e;for(let t of this.rows.values())this.renderCallouts(t);}renderCallouts(e){this.disposeTips(this.calloutTips,e.id);for(let n of e.callouts)n.destroy();e.callouts=[],e.calloutsEl.replaceChildren();let t=this.legendCallouts?.(e.id)??[];e.calloutsEl.style.display=cw(e.highlighted,t.length>0);for(let n of t){let o=new bs({icon:n.icon,background:n.background,...n.color!==void 0?{color:n.color}:{},label:n.tooltip,...n.content!==void 0?{panel:n.content}:{},host:this.container,theme:()=>this.theme});o.el.dataset.legendCallout=n.id,this.tip(this.calloutTips,e.id,o.el,n.tooltip),e.callouts.push(o),e.calloutsEl.appendChild(o.el);}}reposition(){for(let[e,t]of this.legends)this.positionLegend(t,e);}setTitlesVisible(e){this.titlesVisible!==e&&(this.titlesVisible=e,this.reposition());}setValuesVisible(e){this.valuesVisible=e;for(let t of this.rows.values())t.showValues=null,this.renderRowValues(t);}setPlotValues(e){for(let t of this.rows.values()){let n=e.get(t.id)??[],o=n.map(i=>`${i.value}|${i.color}`).join("\0");o!==t.plotValuesKey&&(t.plotValues=n,t.plotValuesKey=o,this.renderRowValues(t));}}rowValuesShown(e){return e.showValues??this.valuesVisible}renderRowValues(e){if(!this.rowValuesShown(e)||e.plotValues.length===0||e.highlighted){e.valuesEl.style.display="none",e.valuesEl.replaceChildren();return}e.valuesEl.style.display="block",e.valuesEl.replaceChildren(),e.plotValues.forEach((t,n)=>{let o=document.createElement("span");o.textContent=t.value,o.style.color=t.color,n>0&&(o.style.marginLeft=`${AE}px`),e.valuesEl.appendChild(o);});}openMoveMenu(e,t){this.closeMoveMenu();let n=this.moveApi;if(!n)return;let i=this.rows.get(e)?.paneId??"price",s=n.panes(),a=[];for(let u of s)u.id!==i&&a.push({label:`Move to ${u.label}`,target:u.kind==="price"?"price":{pane:u.id}});i!=="price"&&[...this.rows.values()].filter(u=>u.paneId===i).length<=1||(i!=="price"&&a.push({label:"New pane above",target:{newPane:{before:i}}}),a.push({label:"New pane below",target:{newPane:{after:i}}})),this.moveTargets=a.map(u=>u.target),this.moveMenuId=e;let c=a.map((u,h)=>({id:String(h),label:u.label}));this.moveMenu?this.moveMenu.setItems(c):this.moveMenu=new Bo({host:this.container,items:c,placement:"bottom-start",onSelect:u=>{let h=this.moveTargets[Number(u)],p=this.moveMenuId;h&&p&&n.move(p,h);}});let d=t.getBoundingClientRect();this.moveMenu.openAt(d.left,d.bottom+4);}closeMoveMenu(){this.moveMenu?.close();}openRowMenu(e,t,n){this.closeRowMenu(),this.closeMoveMenu();let o=this.rows.get(e);if(!o)return;this.rowMenuId=e;let i=[{id:"values",label:"Indicator values",checked:this.rowValuesShown(o)}];this.rowMenu?this.rowMenu.setItems(i):this.rowMenu=new Bo({host:this.container,items:i,placement:"bottom-start",checkmarks:true,onSelect:s=>{if(s!=="values"||!this.rowMenuId)return;let a=this.rows.get(this.rowMenuId);a&&(a.showValues=!this.rowValuesShown(a),this.renderRowValues(a));}}),this.rowMenu.openAt(t,n);}closeRowMenu(){this.rowMenu?.close();}setPane(e,t){let n=this.rows.get(e);if(!n||n.paneId===t)return;let o=n.paneId;if(n.paneId=t,this.attach(this.legendFor(t),n.el,n.native),this.syncFoldToggle(),o!=="price"){let i=this.legends.get(o);i&&i.childElementCount===0&&(i.remove(),this.legends.delete(o));}}legendFor(e){let t=this.legends.get(e);return t||(t=document.createElement("div"),t.dataset.velaPane=e,t.style.cssText=`position:absolute;left:${sw}px;z-index:5;display:flex;flex-direction:column;align-items:flex-start;gap:0;pointer-events:none;font:12px -apple-system,Segoe UI,sans-serif;`,_e(t,this.theme),this.positionLegend(t,e),this.container.appendChild(t),this.legends.set(e,t)),t}positionLegend(e,t){let n=this.paneBoundsOf?this.paneBoundsOf(t):{top:0,height:1/0};e.toggleAttribute(ME,n.top===0),e.style.display=n.height<4||!this.titlesVisible?"none":"flex",e.style.maxWidth=`calc(100% - ${(n.rightAxis??0)+sw+PE}px)`;let o=this.paneCollapse.has(t),i=this.paneCollapse.get(t)??null;for(let a of this.rows.values())a.paneId===t&&(a.el.style.display=(o?a.id!==i:this.legendFolded)?"none":"flex");let s=n.top+8;if(o&&Number.isFinite(n.height)){let a=e.offsetHeight||20;s=n.top+Math.max(1,Math.round((n.height-a)/2));}e.style.top=`${s}px`;}setCollapsedPanes(e){this.paneCollapse=e;}syncFoldToggle(){let e=this.rows.size,t=this.overviewAction!==null||this.mobileLayout?1:2;if(e0&&(this.legendFolded=false),this.foldToggle&&(this.foldToggle.remove(),this.foldToggle=null,this.disposeTips(this.rowTips,"fold")),a&&e>0&&this.reposition();return}let n=this.foldToggle;n||(n=document.createElement("button"),n.type="button",n.className="vela-ind-fold",this.tip(this.rowTips,"fold",n,()=>this.overviewAction!==null?"Indicators":this.legendFolded?"Show indicator legend":"Hide indicator legend"),n.addEventListener("click",()=>{if(this.overviewAction!==null){this.overviewAction();return}this.legendFolded=!this.legendFolded,this.syncFoldToggle();}),this.foldToggle=n);let o=this.legendFolded;n.setAttribute("aria-label",this.overviewAction!==null?"Indicators":o?"Show indicator legend":"Hide indicator legend");let i=this.theme.textColor;n.style.cssText=`pointer-events:auto;display:inline-flex;align-items:center;gap:4px;background:${this.theme.background};color:${i};border:1px solid ${this.theme.borderColor};border-radius:4px;padding:2px 6px;margin-top:6px;cursor:pointer;font:inherit;line-height:0;`,n.replaceChildren();let s=document.createElement("span");if(s.style.cssText="display:inline-flex;align-items:center;line-height:0;opacity:0.7;",s.innerHTML=this.overviewAction!==null?BE:o?VE:FE,n.appendChild(s),o){let a=document.createElement("span");a.textContent=String(e),a.style.cssText=`font-weight:600;line-height:normal;font-size:12px;color:${i};`,n.appendChild(a);}this.legendFor("price").appendChild(n),this.reposition();}upsert(e,t,n,o,i="price",s={}){let a=this.rows.get(e);if(a){a.title=t,a.inputs=n,a.values={...o},a.props=s.props??[],a.propValues={...s.propValues??{}},a.titleEl.textContent=t,a.paneId!==i&&(a.paneId=i,this.attach(this.legendFor(i),a.el,a.native),this.syncFoldToggle());return}Bc();let l=document.createElement("div");l.style.cssText=`pointer-events:auto;display:flex;align-items:center;background:${this.idleRowFill()};border-radius:4px;padding:${dw}px ${Dh}px;margin-left:-${Dh}px;max-width:calc(100% + ${Dh}px);min-height:${RE}px;box-sizing:border-box;color:${this.theme.textColor};user-select:none;-webkit-user-select:none;`,l.addEventListener("mouseleave",()=>{this.selectedId!==e&&this.setRowHighlighted(e,false);}),l.addEventListener("click",w=>{w.button!==0||w.target.closest("button")||this.selectRow(e);}),l.addEventListener("dblclick",w=>{w.target.closest("button")||this.openDialog(e);}),l.addEventListener("mousedown",w=>{w.button===1&&w.preventDefault();}),l.addEventListener("auxclick",w=>{w.button===1&&(w.preventDefault(),this.onRemove?.(e));}),l.addEventListener("contextmenu",w=>{w.preventDefault(),w.stopPropagation(),this.openRowMenu(e,w.clientX,w.clientY);});let c=document.createElement("span");c.style.cssText="display:none;box-sizing:border-box;flex:none;";let d=document.createElement("span");d.style.cssText="white-space:nowrap;min-width:0;overflow:hidden;text-overflow:ellipsis;",d.addEventListener("mouseenter",()=>this.setRowHighlighted(e,true));let u=document.createElement("span");if(u.textContent=t,u.style.cssText="font-weight:600;",d.appendChild(u),s.beta){let w=document.createElement("sup");w.textContent="beta",w.style.cssText="font-size:8px;font-weight:700;opacity:0.7;margin-left:1px;letter-spacing:0.2px;",d.appendChild(w);}l.appendChild(d);let h=document.createElement("span");h.style.cssText=`display:none;align-items:center;gap:4px;flex:none;margin-left:${Oh}px;`,l.appendChild(h),l.appendChild(c);let p=document.createElement("span");p.style.cssText=`display:none;flex:1 1 0%;min-width:0;overflow:hidden;text-overflow:ellipsis;margin-left:${IE}px;white-space:nowrap;font-variant-numeric:tabular-nums;`,l.appendChild(p);let m=document.createElement("span");m.style.cssText=`display:none;align-items:center;gap:${aw}px;flex:none;margin-left:${aw}px;`;let f=null;if(this.onToggleVisible){let w=document.createElement("button");w.type="button",w.setAttribute("aria-label","Hide"),this.tip(this.rowTips,e,w,()=>this.rows.get(e)?.hidden?"Show":"Hide"),w.innerHTML=lw,w.className="vela-ind-ctl",w.style.cssText=Es,w.addEventListener("click",()=>{let S=this.rows.get(e);this.onToggleVisible?.(e,!!S?.hidden);}),m.appendChild(w),f=w;}if(n.length>0||(s.props??[]).length>0){let w=document.createElement("button");w.type="button",w.setAttribute("aria-label","Settings"),this.tip(this.rowTips,e,w,"Settings"),w.innerHTML=OE,w.className="vela-ind-ctl",w.style.cssText=Es,w.addEventListener("click",()=>this.openDialog(e)),m.appendChild(w);}if(this.moveApi){let w=document.createElement("button");w.type="button",w.setAttribute("aria-label","Move to pane"),this.tip(this.rowTips,e,w,"Move to pane"),w.innerHTML=Re("move",An),w.className="vela-ind-ctl",w.style.cssText=Es,w.addEventListener("click",S=>{S.stopPropagation(),this.openMoveMenu(e,w);}),m.appendChild(w);}let g=document.createElement("span");g.style.cssText="display:contents;",this.renderExtras(e,g),m.appendChild(g);let b=document.createElement("button");b.type="button",b.setAttribute("aria-label","Remove indicator"),this.tip(this.rowTips,e,b,"Remove indicator"),b.innerHTML=NE,b.className="vela-ind-close",b.style.cssText=Es,b.addEventListener("click",()=>this.onRemove?.(e)),m.appendChild(b),l.appendChild(m),this.attach(this.legendFor(i),l,!!s.native);let y={id:e,title:t,inputs:n,values:{...o},props:s.props??[],propValues:{...s.propValues??{}},el:l,titleEl:u,statusEl:c,valuesEl:p,plotValues:[],plotValuesKey:"",showValues:null,highlighted:false,paneId:i,hidden:false,eyeEl:f,controlsEl:m,extrasEl:g,calloutsEl:h,callouts:[],native:!!s.native};this.rows.set(e,y),this.renderCallouts(y),this.syncFoldToggle();}attach(e,t,n){n?e.prepend(t):e.appendChild(t);}setValues(e,t,n){let o=this.rows.get(e);o&&(o.values={...o.values,...t},n&&(o.propValues={...o.propValues,...n}));}setStatus(e,t){let n=this.rows.get(e);if(!n)return;let o=n.statusEl;if(o.replaceChildren(),t==="idle"){o.style.cssText="display:none;box-sizing:border-box;flex:none;";return}if(t==="loading"){o.style.cssText=`display:inline-flex;align-items:center;gap:3px;box-sizing:border-box;flex:none;margin-left:${Oh}px;line-height:0;transform:translateY(1px);`;for(let i=0;i<3;i+=1){let s=document.createElement("span");s.style.cssText="width:4px;height:4px;border-radius:50%;background:currentColor;opacity:0.15;flex:none;",s.animate?.([{opacity:.12},{opacity:.55}],{duration:800,iterations:1/0,direction:"alternate",easing:"ease-in-out",delay:-i*260}),o.appendChild(s);}return}this.ensureStatusKeyframes(),o.style.cssText=`display:inline-block;box-sizing:border-box;flex:none;width:8px;height:8px;border-radius:50%;margin-left:${Oh}px;transform:translateY(1px);background:${this.theme.upColor};animation:vela-ind-pulse 1.2s ease-in-out infinite;`;}ensureStatusKeyframes(){if(typeof document>"u"||document.getElementById("vela-ind-status-kf"))return;let e=document.createElement("style");e.id="vela-ind-status-kf",e.textContent=EE,document.head.appendChild(e);}setVisible(e,t){let n=this.rows.get(e);n&&(n.hidden=!t,n.el.style.opacity=t?"1":"0.5",n.eyeEl&&(n.eyeEl.innerHTML=t?lw:DE,n.eyeEl.setAttribute("aria-label",t?"Hide":"Show")),this.syncRowActions(n));}selectRow(e){this.selectedId!==e&&(this.clearSelection(),this.selectedId=e,this.setRowHighlighted(e,true));}setRowHighlighted(e,t){let n=this.rows.get(e);n&&(n.highlighted=t,this.renderRowValues(n),n.el.style.boxShadow=t?`inset 0 0 0 1px ${this.neutralBorder()}`:"none",n.el.style.background=t?this.theme.background:this.idleRowFill(),this.syncRowActions(n));}syncRowActions(e){let t=e.highlighted;if(e.controlsEl.style.display=t||e.hidden?"inline-flex":"none",t){e.el.appendChild(e.statusEl);for(let n of e.callouts)n.hidePanel();}else e.el.insertBefore(e.statusEl,e.valuesEl);e.calloutsEl.style.display=cw(t,e.callouts.length>0);for(let n of Array.from(e.controlsEl.children))if(!(!(n instanceof HTMLElement)||n===e.eyeEl)){if(n===e.extrasEl){n.style.display=t?"contents":"none";continue}n.style.display=t?"inline-flex":"none";}}clearSelection(){this.selectedId&&(this.setRowHighlighted(this.selectedId,false),this.selectedId=null);}remove(e){let t=this.rows.get(e);for(let n of t?.callouts??[])n.destroy();if(t?.el.remove(),this.rows.delete(e),this.disposeTips(this.rowTips,e),this.disposeTips(this.extrasTips,e),this.disposeTips(this.calloutTips,e),this.selectedId===e&&(this.selectedId=null),this.inputsDialog.openId===e&&this.inputsDialog.close(),this.syncFoldToggle(),t&&t.paneId!=="price"){let n=this.legends.get(t.paneId);n&&n.childElementCount===0&&(n.remove(),this.legends.delete(t.paneId));}}destroy(){this.inputsDialog.close(),this.moveMenu?.destroy(),this.moveMenu=null,this.rowMenu?.destroy(),this.rowMenu=null;for(let e of [...this.rowTips.keys()])this.disposeTips(this.rowTips,e);for(let e of [...this.extrasTips.keys()])this.disposeTips(this.extrasTips,e);for(let e of [...this.calloutTips.keys()])this.disposeTips(this.calloutTips,e);for(let e of this.rows.values())for(let t of e.callouts)t.destroy();for(let e of this.legends.values())e.remove();this.legends.clear(),this.rows.clear(),this.foldToggle=null,this.legendFolded=false,this.selectedId=null,typeof document<"u"&&document.removeEventListener("click",this.onDocClick);}isDialogOpen(){return this.inputsDialog.isOpen()}closeOpenDialog(){this.inputsDialog.close();}openDialog(e){let t=this.rows.get(e);t&&this.inputsDialog.open(t);}idleRowFill(){return J(this.theme.background,.6)}neutralBorder(){return "var(--vela-border)"}};var Wo={up:ee("chevron-up"),down:ee("chevron-down"),collapse:ee("pane-collapse"),expand:ee("pane-expand"),maximize:ee("maximize"),restore:ee("restore")},uw="vela-pane-controls",_E=12,hw="rgba(0,0,0,0.65)";function HE(){if(typeof document>"u"||document.getElementById(uw))return;let r=document.createElement("style");r.id=uw,r.textContent=` +.vela-pc-btn{display:inline-flex;align-items:center;justify-content:center;padding:0;border:none;border-radius:var(--vela-radius-sm);background:transparent;line-height:0;font-size:${_E}px;color:var(--vela-fg-muted);} .vela-pc-btn svg{display:block;} .vela-pc-btn:not(:disabled):hover{opacity:1 !important;background:var(--vela-active);color:var(--vela-fg-bright);} .vela-pc-on,.vela-pc-on:not(:disabled):hover{background:var(--vela-selected-bg);color:var(--vela-selected-fg);} -`,document.head.appendChild(r);}var Fc=class{constructor(e,t,n){this.plot=e;this.theme=t;this.deps=n;this.clusters=new Map;this.hoverPaneId=null;this.suspended=false;this.onPlotMove=e=>{if(this.suspended)return;let t=this.plot.getBoundingClientRect(),n=e.clientY-t.top,o=null;for(let i of this.deps.panes())if(n>=i.top&&n<=i.top+i.height){o=i.id;break}this.setHoverPane(o);};this.onPlotLeave=()=>this.setHoverPane(null);ME(),this.root=document.createElement("div"),Object.assign(this.root.style,{position:"absolute",inset:"0",pointerEvents:"none",zIndex:"6"}),this.plot.appendChild(this.root),this.plot.addEventListener("pointermove",this.onPlotMove),this.plot.addEventListener("pointerleave",this.onPlotLeave),this.refresh();}setTheme(e){this.theme=e,this.refresh();}refresh(){let e=this.deps.panes(),t=new Set;for(let n of e){t.add(n.id);let o=this.clusters.get(n.id);o||(o=document.createElement("div"),Object.assign(o.style,{position:"absolute",display:"flex",gap:"2px",padding:"2px",borderRadius:"var(--vela-radius-md)",background:iw,pointerEvents:"auto"}),this.root.appendChild(o),this.clusters.set(n.id,o)),this.buildButtons(o,n);}for(let[n,o]of this.clusters)t.has(n)||(o.remove(),this.clusters.delete(n));this.reposition();}buildButtons(e,t){e.textContent="",t.kind==="study"&&(e.appendChild(this.button(Bo.up,"Move pane up",t.index<=1,()=>this.deps.onMove(t.id,"up"),{role:"up"})),e.appendChild(this.button(Bo.down,"Move pane down",t.index>=t.count-1,()=>this.deps.onMove(t.id,"down"),{role:"down"})),e.appendChild(this.button(t.collapsed?Bo.expand:Bo.collapse,t.collapsed?"Expand pane":"Collapse pane",false,()=>this.deps.onToggleCollapse(t.id),{role:"collapse",selected:t.collapsed}))),t.count>1&&e.appendChild(this.button(t.maximized?Bo.restore:Bo.maximize,t.maximized?"Restore pane":"Maximize pane",false,()=>this.deps.onToggleMaximize(t.id),{role:"maximize",selected:t.maximized}));}button(e,t,n,o,i){let s=document.createElement("button");s.type="button",s.title=t,s.innerHTML=e,s.disabled=n,s.dataset.role=i.role;let a=i.selected===true;return s.className=a?"vela-pc-btn vela-pc-on":"vela-pc-btn",Object.assign(s.style,{cursor:n?"default":"pointer",width:"20px",height:"20px",opacity:n?"0.3":"1"}),n||s.addEventListener("click",l=>{l.stopPropagation(),o();}),s}reposition(){let e=this.deps.rightAxis()+6,t=new Map(this.deps.panes().map(n=>[n.id,n]));for(let[n,o]of this.clusters){let i=t.get(n);if(!i){o.style.display="none";continue}let s=n===this.hoverPaneId,a=o.children.length>0,l=i.collapsed?"collapse":!this.suspended&&i.maximized?"maximize":null,c=a&&(s||l!=null)&&i.height>8;if(o.style.right=`${e}px`,o.style.top=i.collapsed?`${i.top+Math.max(1,Math.round((i.height-24)/2))}px`:`${i.top+4}px`,o.style.display=c?"flex":"none",!c)continue;let d=l!=null&&!s;o.style.background=d?"transparent":iw;for(let u of o.children){let h=u;h.style.display="inline-flex",h.style.visibility=d&&h.dataset.role!==l?"hidden":"visible";}}}setHoverPane(e){this.hoverPaneId!==e&&(this.hoverPaneId=e,this.reposition());}setSuspended(e){e!==this.suspended&&(this.suspended=e,e&&(this.hoverPaneId=null),this.reposition());}destroy(){this.plot.removeEventListener("pointermove",this.onPlotMove),this.plot.removeEventListener("pointerleave",this.onPlotLeave),this.root.remove(),this.clusters.clear();}};function sw(r,e){return e===0?r:r+64+(e-1)*56}var aw="vela-axis-scale-buttons",Ah=18,EE=4,PE=1,IE=64-PE,cw=8,dw=6,AE=Ah+cw+dw,lw=48;function RE(){if(typeof document>"u"||document.getElementById(aw))return;let r=document.createElement("style");r.id=aw,r.textContent=` +`,document.head.appendChild(r);}var Hc=class{constructor(e,t,n){this.plot=e;this.theme=t;this.deps=n;this.clusters=new Map;this.hoverPaneId=null;this.suspended=false;this.onPlotMove=e=>{if(this.suspended)return;let t=this.plot.getBoundingClientRect(),n=e.clientY-t.top,o=null;for(let i of this.deps.panes())if(n>=i.top&&n<=i.top+i.height){o=i.id;break}this.setHoverPane(o);};this.onPlotLeave=()=>this.setHoverPane(null);HE(),this.root=document.createElement("div"),Object.assign(this.root.style,{position:"absolute",inset:"0",pointerEvents:"none",zIndex:"6"}),this.plot.appendChild(this.root),this.plot.addEventListener("pointermove",this.onPlotMove),this.plot.addEventListener("pointerleave",this.onPlotLeave),this.refresh();}setTheme(e){this.theme=e,this.refresh();}refresh(){let e=this.deps.panes(),t=new Set;for(let n of e){t.add(n.id);let o=this.clusters.get(n.id);o||(o=document.createElement("div"),Object.assign(o.style,{position:"absolute",display:"flex",gap:"2px",padding:"2px",borderRadius:"var(--vela-radius-md)",background:hw,pointerEvents:"auto"}),this.root.appendChild(o),this.clusters.set(n.id,o)),this.buildButtons(o,n);}for(let[n,o]of this.clusters)t.has(n)||(o.remove(),this.clusters.delete(n));this.reposition();}buildButtons(e,t){e.textContent="",t.kind==="study"&&(e.appendChild(this.button(Wo.up,"Move pane up",t.index<=1,()=>this.deps.onMove(t.id,"up"),{role:"up"})),e.appendChild(this.button(Wo.down,"Move pane down",t.index>=t.count-1,()=>this.deps.onMove(t.id,"down"),{role:"down"})),e.appendChild(this.button(t.collapsed?Wo.expand:Wo.collapse,t.collapsed?"Expand pane":"Collapse pane",false,()=>this.deps.onToggleCollapse(t.id),{role:"collapse",selected:t.collapsed}))),t.count>1&&e.appendChild(this.button(t.maximized?Wo.restore:Wo.maximize,t.maximized?"Restore pane":"Maximize pane",false,()=>this.deps.onToggleMaximize(t.id),{role:"maximize",selected:t.maximized}));}button(e,t,n,o,i){let s=document.createElement("button");s.type="button",s.title=t,s.innerHTML=e,s.disabled=n,s.dataset.role=i.role;let a=i.selected===true;return s.className=a?"vela-pc-btn vela-pc-on":"vela-pc-btn",Object.assign(s.style,{cursor:n?"default":"pointer",width:"20px",height:"20px",opacity:n?"0.3":"1"}),n||s.addEventListener("click",l=>{l.stopPropagation(),o();}),s}reposition(){let e=this.deps.rightAxis()+6,t=new Map(this.deps.panes().map(n=>[n.id,n]));for(let[n,o]of this.clusters){let i=t.get(n);if(!i){o.style.display="none";continue}let s=n===this.hoverPaneId,a=o.children.length>0,l=i.collapsed?"collapse":!this.suspended&&i.maximized?"maximize":null,c=a&&(s||l!=null)&&i.height>8;if(o.style.right=`${e}px`,o.style.top=i.collapsed?`${i.top+Math.max(1,Math.round((i.height-24)/2))}px`:`${i.top+4}px`,o.style.display=c?"flex":"none",!c)continue;let d=l!=null&&!s;o.style.background=d?"transparent":hw;for(let u of o.children){let h=u;h.style.display="inline-flex",h.style.visibility=d&&h.dataset.role!==l?"hidden":"visible";}}}setHoverPane(e){this.hoverPaneId!==e&&(this.hoverPaneId=e,this.reposition());}setSuspended(e){e!==this.suspended&&(this.suspended=e,e&&(this.hoverPaneId=null),this.reposition());}destroy(){this.plot.removeEventListener("pointermove",this.onPlotMove),this.plot.removeEventListener("pointerleave",this.onPlotLeave),this.root.remove(),this.clusters.clear();}};function pw(r,e){return e===0?r:r+64+(e-1)*56}var mw="vela-axis-scale-buttons",Fh=18,zE=4,WE=1,GE=64-WE,gw=8,bw=6,$E=Fh+gw+bw,fw=48;function UE(){if(typeof document>"u"||document.getElementById(mw))return;let r=document.createElement("style");r.id=mw,r.textContent=` .vela-axis-btn{display:inline-flex;align-items:center;justify-content:center;padding:0;border:none;border-radius:var(--vela-radius-sm);background:transparent;cursor:pointer;font:600 10px/1 -apple-system,Segoe UI,sans-serif;color:var(--vela-fg-muted);} .vela-axis-btn:hover{background:var(--vela-active);color:var(--vela-fg-bright);} .vela-axis-on,.vela-axis-on:hover{background:var(--vela-selected-bg);color:var(--vela-selected-fg);} -`,document.head.appendChild(r);}var Vc=class{constructor(e,t,n){this.plot=e;this.theme=t;this.deps=n;this.tipDisposers=[];this.hoverPaneId=null;this.onPlotMove=e=>{if(e.pointerType!=="mouse")return;let t=this.plot.getBoundingClientRect(),n=e.clientX-t.left,o=t.width-this.deps.rightAxis(),i=null;if(n>=o&&n<=o+64){let s=e.clientY-t.top;for(let a of this.deps.panes())if(!(a.collapsed||a.height=a.top&&s<=a.top+a.height){i=a.id;break}}this.setHoverPane(i),i&&this.sync();};this.onPlotLeave=()=>this.setHoverPane(null);RE(),this.cluster=document.createElement("div"),Object.assign(this.cluster.style,{position:"absolute",display:"none",justifyContent:"center",alignItems:"center",gap:`${EE}px`,padding:`${cw}px 0 ${dw}px`,width:`${IE}px`,boxSizing:"border-box",zIndex:"6",pointerEvents:"auto"}),this.applyTheme(),this.autoBtn=this.button("A","Auto (fits data to screen)",()=>this.deps.onToggleAuto(this.hoverPaneId??"")),this.logBtn=this.button("L","Logarithmic scale",()=>this.deps.onToggleLog(this.hoverPaneId??"")),this.cluster.append(this.autoBtn,this.logBtn),this.plot.appendChild(this.cluster),this.plot.addEventListener("pointermove",this.onPlotMove),this.plot.addEventListener("pointerleave",this.onPlotLeave);}button(e,t,n){let o=document.createElement("button");return o.type="button",o.setAttribute("aria-label",t),o.textContent=e,o.className="vela-axis-btn",Object.assign(o.style,{width:`${Ah}px`,height:`${Ah}px`}),this.tipDisposers.push(tn(o,{host:this.plot,theme:()=>this.theme,text:()=>t,placement:"above"})),o.addEventListener("click",i=>{i.stopPropagation(),n(),this.sync();}),o}setTheme(e){this.theme=e,this.applyTheme();}applyTheme(){this.cluster.style.background=this.theme.background;}setHoverPane(e){this.hoverPaneId!==e&&(this.hoverPaneId=e,this.reposition());}reposition(){let e=this.hoverPaneId?this.deps.panes().find(t=>t.id===this.hoverPaneId):void 0;if(!e||e.collapsed||e.heightt.id===this.hoverPaneId);e&&(this.autoBtn.classList.toggle("vela-axis-on",e.auto),this.logBtn.classList.toggle("vela-axis-on",e.log));}destroy(){this.plot.removeEventListener("pointermove",this.onPlotMove),this.plot.removeEventListener("pointerleave",this.onPlotLeave);for(let e of this.tipDisposers)e();this.tipDisposers.length=0,this.cluster.remove();}};var uw={panes:true,paneManagement:true,fills:"native",bgcolor:"native",hline:"native",markers:true,barcolor:"native",perPointColor:true,drawings:true,userDrawings:true,drawingDepth:true,tables:true,trades:true,timelineMarks:true,inputsUI:true},Ls=null;function hw(){if(Ls!==null)return Ls;try{Ls=!!document.createElement("canvas").getContext("webgl2");}catch{Ls=false;}return Ls}function Ms(r){let e=Math.max(.5,Math.floor(r*.7)/2);return Math.max(1,Math.min(1.5,e))}function _o(r){return r<1?"aggregate":r<3?"wick":"full"}function un(r,e){return Math.round(r*e)/e}function Bc(r,e,t,n=1){let o=Math.max(1,Math.round(Ms(e)*t)),i=Math.round(r*t-o/2),s=Math.max(o,Math.round(Math.floor(e*.7*n)*t));(s-o)%2!==0&&(s+=1);let a=(s-o)/2;return {wickX:i/t,wickW:o/t,bodyX:(i-a)/t,bodyW:s/t,center:(i+o/2)/t}}function _c(r,e,t,n,o,i){let s=[],a=NaN,l=[],c=()=>{if(l.length===0)return;l.sort((u,h)=>u.lo-h.lo);let d=[];for(let u of l){let h;for(let p=d.length-1;p>=0;p-=1)if(d[p].color===u.color){h=d[p];break}h&&Math.abs(o(h.hi)-o(u.lo))<1?(h.hi=u.hi,u.lastIdx>h.lastIdx&&(h.lastIdx=u.lastIdx)):d.push(u);}d.sort((u,h)=>u.lastIdx-h.lastIdx);for(let u of d)s.push({x:a,hi:u.hi,lo:u.lo,color:u.color});l=[];};for(let d=e;d<=t;d+=1){let u=r[d];if(!u||u.high<=u.low)continue;let h=Math.round(n(d));h!==a&&(c(),a=h);let p=i(u),m=u.low,f=u.high;for(let g=l.length-1;g>=0;g-=1){let b=l[g];b.color!==p||b.lo>f||b.hif&&(f=b.hi),l.splice(g,1));}l.push({lo:m,hi:f,color:p,lastIdx:d});}return c(),s}var Oh=1,Ho=O,zo=D,An=.25,Rn=.05,DE=50,OE=J(U,.08),mw=J(nt,.08),NE=mw,Nh={top:10,bottom:10,right:10};function fw(){return {chartTypes:{},fontSize:11,margins:{...Nh},gridVert:{visible:true,color:null},gridHorz:{visible:true,color:null},borderColor:null,separatorColor:null,crosshair:{color:_m,width:1,style:"dashed",opacity:.4,labelBackground:Wm},candle:{bodyVisible:true,borderVisible:false,borderUpColor:null,borderDownColor:null,wickVisible:true,wickUpColor:null,wickDownColor:null},bars:{upColor:null,downColor:null},line:{color:ui,width:2},area:{lineColor:ui,width:2,topColor:J(ui,.28),bottomColor:J(ui,.02)},baseline:{topLineColor:null,bottomLineColor:null,topFillColor:null,topFillColor2:null,bottomFillColor:null,bottomFillColor2:null,width:2,baselineLevel:DE},sessions:{premarketColor:OE,postmarketColor:mw,extendedColor:NE}}}var FE=["solid","dashed","dotted"],gw=["candles","bars","line","area","baseline","heikinashi"];function Fh(r){for(let e of xt())if(e.id===r)return e.basePainting??"candles";return "candles"}function Wo(r){if(gw.includes(r))return false;for(let e of xt())if(e.id===r)return (e.basePainting??"candles")==="candles";return false}var VE=["candleUpColor","candleDownColor","candleBodyVisible","candleBorderVisible","candleBorderUpColor","candleBorderDownColor","candleWickVisible","candleWickUpColor","candleWickDownColor"];function Hc(r,e){if(!Wo(r))return null;let t=e[r]??{},n=i=>ie(i)?i:null,o=i=>Ee(i)?i:null;return {upColor:n(t.candleUpColor),downColor:n(t.candleDownColor),bodyVisible:o(t.candleBodyVisible),borderVisible:o(t.candleBorderVisible),borderUpColor:n(t.candleBorderUpColor),borderDownColor:n(t.candleBorderDownColor),wickVisible:o(t.candleWickVisible),wickUpColor:n(t.candleWickUpColor),wickDownColor:n(t.candleWickDownColor)}}function Go(r,e,t,n){return e?{up:e.upColor??t,down:e.downColor??n,candle:{bodyVisible:e.bodyVisible??r.bodyVisible,borderVisible:e.borderVisible??r.borderVisible,borderUpColor:e.borderUpColor??r.borderUpColor,borderDownColor:e.borderDownColor??r.borderDownColor,wickVisible:e.wickVisible??r.wickVisible,wickUpColor:e.wickUpColor??r.wickUpColor,wickDownColor:e.wickDownColor??r.wickDownColor}}:{up:t,down:n,candle:r}}function $o(){let r=[...gw];for(let e of xt())r.includes(e.id)||r.push(e.id);return r}function bw(r){if(!r||typeof r!="object")return null;let e=r,t={};Ee(e.vertical)&&(t.vertical=e.vertical),Ee(e.horizontal)&&(t.horizontal=e.horizontal),ie(e.color)&&(t.color=e.color),Ze(e.width)&&(t.width=Math.max(.5,Math.min(8,e.width))),vw(e.style)&&(t.style=e.style),Ze(e.opacity)&&(t.opacity=Dh(e.opacity));let n=e.shadeRight;return n&&typeof n=="object"&&ie(n.color)&&(t.shadeRight=Ze(n.opacity)?{color:n.color,opacity:Dh(n.opacity)}:{color:n.color}),Object.keys(t).length>0?t:null}function ie(r){return typeof r=="string"&&r.trim().length>0}function Ee(r){return typeof r=="boolean"}function Ze(r){return typeof r=="number"&&Number.isFinite(r)}function vw(r){return typeof r=="string"&&FE.includes(r)}function BE(r){return typeof r=="string"&&$o().includes(r)}function _E(r){return r==="price"||r==="percent"||r==="indexed"}function Le(r){return r&&typeof r=="object"?r:{}}function Dh(r){return r<0?0:r>1?1:r}function Rh(r){return r<1?1:r>10?10:r}function HE(r){return r<0?0:r>100?100:r}function zE(r){return r<.1?.1:r>10?10:r}function pw(r){return r<0?0:r>40?40:r}function WE(r){return Math.round(r<0?0:r>200?200:r)}function yw(r,e=r.series.style){let t={};for(let n of xt()){let o=n.settings;if(!o)continue;let i={},s=a=>{for(let l of a??[])for(let c of Li(l))i[c.key]=c.defval;};for(let a of o.instances??[])a.enableKey&&(i[a.enableKey]=false),s(a.rows);for(let a of o.subsections??[])a.enableKey&&(i[a.enableKey]=false),s(a.rows);o.instances||s(o.rows),t[n.id]=i;}for(let n of xt()){if(!Wo(n.id))continue;let o=t[n.id]??{};for(let i of VE)o[i]=null;t[n.id]=o;}for(let[n,o]of Object.entries(r.chartTypes))t[n]={...t[n]??{},...o};return {...r,chartTypes:t,series:{...r.series,style:e}}}function ww(r,e){let t=Le(e),n=Le(t.chartTypes),o={...r.chartTypes};for(let[E,I]of Object.entries(n))o[E]={...o[E]??{},...Le(I)};let i=Le(t.layout),s=Le(t.grid),a=Le(s.vertLines),l=Le(s.horzLines),c=Le(t.crosshair),d=Le(t.priceScale),u=Le(t.animations),h=Le(t.panes),p=Le(t.margins),m=Le(t.trades),f=Le(t.timeScale),g=Le(t.marks),b=Le(g.groups),y=Le(t.candles),w=Le(t.bars),C=Le(t.line),M=Le(t.area),S=Le(t.baseline),L=Le(t.series),v=Le(t.sessions),k=Le(t.stacking),x=Le(k.series);return {version:Oh,chartTypes:o,layout:{background:ie(i.background)?i.background:r.layout.background,textColor:ie(i.textColor)?i.textColor:r.layout.textColor,fontFamily:ie(i.fontFamily)?i.fontFamily:r.layout.fontFamily,fontSize:Ze(i.fontSize)?Math.max(6,Math.min(32,i.fontSize)):r.layout.fontSize},grid:{vertLines:{visible:Ee(a.visible)?a.visible:r.grid.vertLines.visible,color:ie(a.color)?a.color:r.grid.vertLines.color},horzLines:{visible:Ee(l.visible)?l.visible:r.grid.horzLines.visible,color:ie(l.color)?l.color:r.grid.horzLines.color}},crosshair:{color:ie(c.color)?c.color:r.crosshair.color,width:Ze(c.width)?Math.max(.5,Math.min(8,c.width)):r.crosshair.width,style:vw(c.style)?c.style:r.crosshair.style,opacity:Ze(c.opacity)?Dh(c.opacity):r.crosshair.opacity,labelBackground:ie(c.labelBackground)?c.labelBackground:r.crosshair.labelBackground},priceScale:{mode:_E(d.mode)?d.mode:r.priceScale.mode,log:Ee(d.log)?d.log:r.priceScale.log,invert:Ee(d.invert)?d.invert:r.priceScale.invert,borderColor:ie(d.borderColor)?d.borderColor:r.priceScale.borderColor,labelsVisible:Ee(d.labelsVisible)?d.labelsVisible:r.priceScale.labelsVisible,currentPriceLine:Ee(d.currentPriceLine)?d.currentPriceLine:r.priceScale.currentPriceLine,priceLabel:Ee(d.priceLabel)?d.priceLabel:r.priceScale.priceLabel,countdown:Ee(d.countdown)?d.countdown:r.priceScale.countdown,animateLastPrice:Ee(d.animateLastPrice)?d.animateLastPrice:r.priceScale.animateLastPrice},animations:{zoom:Ee(u.zoom)?u.zoom:r.animations.zoom,pan:Ee(u.pan)?u.pan:r.animations.pan,autoscale:Ee(u.autoscale)?u.autoscale:r.animations.autoscale,intro:Ee(u.intro)?u.intro:r.animations.intro},panes:{separatorColor:ie(h.separatorColor)?h.separatorColor:r.panes.separatorColor},margins:{top:Ze(p.top)?pw(p.top):r.margins.top,bottom:Ze(p.bottom)?pw(p.bottom):r.margins.bottom,right:Ze(p.right)?WE(p.right):r.margins.right},trades:{visible:Ee(m.visible)?m.visible:r.trades.visible,labels:Ee(m.labels)?m.labels:r.trades.labels,qty:Ee(m.qty)?m.qty:r.trades.qty,longColor:ie(m.longColor)?m.longColor:r.trades.longColor,shortColor:ie(m.shortColor)?m.shortColor:r.trades.shortColor,exitColor:ie(m.exitColor)?m.exitColor:r.trades.exitColor},timeScale:{timezone:typeof f.timezone=="string"&&f.timezone?f.timezone:r.timeScale.timezone},marks:{visible:Ee(g.visible)?g.visible:r.marks.visible,groups:{...r.marks.groups,...Object.fromEntries(Object.entries(b).filter(([,E])=>Ee(E)))}},candles:{upColor:ie(y.upColor)?y.upColor:r.candles.upColor,downColor:ie(y.downColor)?y.downColor:r.candles.downColor,bodyVisible:Ee(y.bodyVisible)?y.bodyVisible:r.candles.bodyVisible,borderVisible:Ee(y.borderVisible)?y.borderVisible:r.candles.borderVisible,borderUpColor:ie(y.borderUpColor)?y.borderUpColor:r.candles.borderUpColor,borderDownColor:ie(y.borderDownColor)?y.borderDownColor:r.candles.borderDownColor,wickVisible:Ee(y.wickVisible)?y.wickVisible:r.candles.wickVisible,wickUpColor:ie(y.wickUpColor)?y.wickUpColor:r.candles.wickUpColor,wickDownColor:ie(y.wickDownColor)?y.wickDownColor:r.candles.wickDownColor},bars:{upColor:ie(w.upColor)?w.upColor:r.bars.upColor,downColor:ie(w.downColor)?w.downColor:r.bars.downColor},line:{color:ie(C.color)?C.color:r.line.color,width:Ze(C.width)?Rh(C.width):r.line.width},area:{lineColor:ie(M.lineColor)?M.lineColor:r.area.lineColor,width:Ze(M.width)?Rh(M.width):r.area.width,topColor:ie(M.topColor)?M.topColor:r.area.topColor,bottomColor:ie(M.bottomColor)?M.bottomColor:r.area.bottomColor},baseline:{topLineColor:ie(S.topLineColor)?S.topLineColor:r.baseline.topLineColor,bottomLineColor:ie(S.bottomLineColor)?S.bottomLineColor:r.baseline.bottomLineColor,topFillColor:ie(S.topFillColor)?S.topFillColor:r.baseline.topFillColor,topFillColor2:ie(S.topFillColor2)?S.topFillColor2:r.baseline.topFillColor2,bottomFillColor:ie(S.bottomFillColor)?S.bottomFillColor:r.baseline.bottomFillColor,bottomFillColor2:ie(S.bottomFillColor2)?S.bottomFillColor2:r.baseline.bottomFillColor2,width:Ze(S.width)?Rh(S.width):r.baseline.width,baselineLevel:Ze(S.baselineLevel)?HE(S.baselineLevel):r.baseline.baselineLevel},series:{style:BE(L.style)?L.style:r.series.style,baseline:L.baseline===null?null:Ze(L.baseline)?L.baseline:r.series.baseline,spacing:Ze(L.spacing)?zE(L.spacing):r.series.spacing},sessions:{premarketColor:ie(v.premarketColor)?v.premarketColor:r.sessions.premarketColor,postmarketColor:ie(v.postmarketColor)?v.postmarketColor:r.sessions.postmarketColor,extendedColor:ie(v.extendedColor)?v.extendedColor:r.sessions.extendedColor},stacking:{candles:Ze(k.candles)?k.candles:r.stacking.candles,series:{...r.stacking.series,...Object.fromEntries(Object.entries(x).filter(([,E])=>Ze(E)))}}}}var Es=class{constructor(e=4096){this.n=0;this.alpha=1;this.buf=new Float32Array(e*8);}reset(){this.n=0;}get vertexCount(){return this.n/8}get view(){return this.buf.subarray(0,this.n)}ensure(e){let t=this.n+e*8;if(t<=this.buf.length)return;let n=this.buf.length||8;for(;n=GE&&(xw=Uo,Uo=new Map),e))}function Sw(r,e="#000000"){let[t,n,o,i]=se(r),s=t,a=n,l=o;if(i<1){let[h,p,m]=se(e);s=t*i+h*(1-i),a=n*i+p*(1-i),l=o*i+m*(1-i);}let c=.2126*Vh(s)+.7152*Vh(a)+.0722*Vh(l),d=(c+.05)/.05,u=1.05/(c+.05);return d>=u?"#000000":"#ffffff"}function Vh(r){return r<=.04045?r/12.92:Math.pow((r+.055)/1.055,2.4)}function $E(r){if(!Jn){let t=document.createElement("canvas");t.width=1,t.height=1,Jn=t.getContext("2d",{willReadFrequently:true});}if(!Jn)return Cw;Jn.clearRect(0,0,1,1),Jn.fillStyle="#000",Jn.fillStyle=r,Jn.fillRect(0,0,1,1);let e=Jn.getImageData(0,0,1,1).data;return [e[0]/255,e[1]/255,e[2]/255,e[3]/255]}var UE=`#version 300 es +`,document.head.appendChild(r);}var zc=class{constructor(e,t,n){this.plot=e;this.theme=t;this.deps=n;this.tipDisposers=[];this.hoverPaneId=null;this.onPlotMove=e=>{if(e.pointerType!=="mouse")return;let t=this.plot.getBoundingClientRect(),n=e.clientX-t.left,o=t.width-this.deps.rightAxis(),i=null;if(n>=o&&n<=o+64){let s=e.clientY-t.top;for(let a of this.deps.panes())if(!(a.collapsed||a.height=a.top&&s<=a.top+a.height){i=a.id;break}}this.setHoverPane(i),i&&this.sync();};this.onPlotLeave=()=>this.setHoverPane(null);UE(),this.cluster=document.createElement("div"),Object.assign(this.cluster.style,{position:"absolute",display:"none",justifyContent:"center",alignItems:"center",gap:`${zE}px`,padding:`${gw}px 0 ${bw}px`,width:`${GE}px`,boxSizing:"border-box",zIndex:"6",pointerEvents:"auto"}),this.applyTheme(),this.autoBtn=this.button("A","Auto (fits data to screen)",()=>this.deps.onToggleAuto(this.hoverPaneId??"")),this.logBtn=this.button("L","Logarithmic scale",()=>this.deps.onToggleLog(this.hoverPaneId??"")),this.cluster.append(this.autoBtn,this.logBtn),this.plot.appendChild(this.cluster),this.plot.addEventListener("pointermove",this.onPlotMove),this.plot.addEventListener("pointerleave",this.onPlotLeave);}button(e,t,n){let o=document.createElement("button");return o.type="button",o.setAttribute("aria-label",t),o.textContent=e,o.className="vela-axis-btn",Object.assign(o.style,{width:`${Fh}px`,height:`${Fh}px`}),this.tipDisposers.push(nn(o,{host:this.plot,theme:()=>this.theme,text:()=>t,placement:"above"})),o.addEventListener("click",i=>{i.stopPropagation(),n(),this.sync();}),o}setTheme(e){this.theme=e,this.applyTheme();}applyTheme(){this.cluster.style.background=this.theme.background;}setHoverPane(e){this.hoverPaneId!==e&&(this.hoverPaneId=e,this.reposition());}reposition(){let e=this.hoverPaneId?this.deps.panes().find(t=>t.id===this.hoverPaneId):void 0;if(!e||e.collapsed||e.heightt.id===this.hoverPaneId);e&&(this.autoBtn.classList.toggle("vela-axis-on",e.auto),this.logBtn.classList.toggle("vela-axis-on",e.log));}destroy(){this.plot.removeEventListener("pointermove",this.onPlotMove),this.plot.removeEventListener("pointerleave",this.onPlotLeave);for(let e of this.tipDisposers)e();this.tipDisposers.length=0,this.cluster.remove();}};var vw={panes:true,paneManagement:true,fills:"native",bgcolor:"native",hline:"native",markers:true,barcolor:"native",perPointColor:true,drawings:true,userDrawings:true,drawingDepth:true,tables:true,trades:true,timelineMarks:true,inputsUI:true},Is=null;function yw(){if(Is!==null)return Is;try{Is=!!document.createElement("canvas").getContext("webgl2");}catch{Is=false;}return Is}function As(r){let e=Math.max(.5,Math.floor(r*.7)/2);return Math.max(1,Math.min(1.5,e))}function Go(r){return r<1?"aggregate":r<3?"wick":"full"}function hn(r,e){return Math.round(r*e)/e}function Wc(r,e,t,n=1){let o=Math.max(1,Math.round(As(e)*t)),i=Math.round(r*t-o/2),s=Math.max(o,Math.round(Math.floor(e*.7*n)*t));(s-o)%2!==0&&(s+=1);let a=(s-o)/2;return {wickX:i/t,wickW:o/t,bodyX:(i-a)/t,bodyW:s/t,center:(i+o/2)/t}}function Gc(r,e,t,n,o,i){let s=[],a=NaN,l=[],c=()=>{if(l.length===0)return;l.sort((u,h)=>u.lo-h.lo);let d=[];for(let u of l){let h;for(let p=d.length-1;p>=0;p-=1)if(d[p].color===u.color){h=d[p];break}h&&Math.abs(o(h.hi)-o(u.lo))<1?(h.hi=u.hi,u.lastIdx>h.lastIdx&&(h.lastIdx=u.lastIdx)):d.push(u);}d.sort((u,h)=>u.lastIdx-h.lastIdx);for(let u of d)s.push({x:a,hi:u.hi,lo:u.lo,color:u.color});l=[];};for(let d=e;d<=t;d+=1){let u=r[d];if(!u||u.high<=u.low)continue;let h=Math.round(n(d));h!==a&&(c(),a=h);let p=i(u),m=u.low,f=u.high;for(let g=l.length-1;g>=0;g-=1){let b=l[g];b.color!==p||b.lo>f||b.hif&&(f=b.hi),l.splice(g,1));}l.push({lo:m,hi:f,color:p,lastIdx:d});}return c(),s}var _h=1,$o=O,Uo=D,Rn=.25,Dn=.05,YE=50,KE=J(Y,.08),xw=J(nt,.08),XE=xw,Hh={top:10,bottom:10,right:10};function Sw(){return {chartTypes:{},fontSize:11,margins:{...Hh},gridVert:{visible:true,color:null},gridHorz:{visible:true,color:null},borderColor:null,separatorColor:null,crosshair:{color:Um,width:1,style:"dashed",opacity:.4,labelBackground:Xm},candle:{bodyVisible:true,borderVisible:false,borderUpColor:null,borderDownColor:null,wickVisible:true,wickUpColor:null,wickDownColor:null},bars:{upColor:null,downColor:null},line:{color:fi,width:2},area:{lineColor:fi,width:2,topColor:J(fi,.28),bottomColor:J(fi,.02)},baseline:{topLineColor:null,bottomLineColor:null,topFillColor:null,topFillColor2:null,bottomFillColor:null,bottomFillColor2:null,width:2,baselineLevel:YE},sessions:{premarketColor:KE,postmarketColor:xw,extendedColor:XE}}}var jE=["solid","dashed","dotted"],Cw=["candles","bars","line","area","baseline","heikinashi"];function zh(r){for(let e of xt())if(e.id===r)return e.basePainting??"candles";return "candles"}function Yo(r){if(Cw.includes(r))return false;for(let e of xt())if(e.id===r)return (e.basePainting??"candles")==="candles";return false}var qE=["candleUpColor","candleDownColor","candleBodyVisible","candleBorderVisible","candleBorderUpColor","candleBorderDownColor","candleWickVisible","candleWickUpColor","candleWickDownColor"];function $c(r,e){if(!Yo(r))return null;let t=e[r]??{},n=i=>ie(i)?i:null,o=i=>Ee(i)?i:null;return {upColor:n(t.candleUpColor),downColor:n(t.candleDownColor),bodyVisible:o(t.candleBodyVisible),borderVisible:o(t.candleBorderVisible),borderUpColor:n(t.candleBorderUpColor),borderDownColor:n(t.candleBorderDownColor),wickVisible:o(t.candleWickVisible),wickUpColor:n(t.candleWickUpColor),wickDownColor:n(t.candleWickDownColor)}}function Ko(r,e,t,n){return e?{up:e.upColor??t,down:e.downColor??n,candle:{bodyVisible:e.bodyVisible??r.bodyVisible,borderVisible:e.borderVisible??r.borderVisible,borderUpColor:e.borderUpColor??r.borderUpColor,borderDownColor:e.borderDownColor??r.borderDownColor,wickVisible:e.wickVisible??r.wickVisible,wickUpColor:e.wickUpColor??r.wickUpColor,wickDownColor:e.wickDownColor??r.wickDownColor}}:{up:t,down:n,candle:r}}function Xo(){let r=[...Cw];for(let e of xt())r.includes(e.id)||r.push(e.id);return r}function Tw(r){if(!r||typeof r!="object")return null;let e=r,t={};Ee(e.vertical)&&(t.vertical=e.vertical),Ee(e.horizontal)&&(t.horizontal=e.horizontal),ie(e.color)&&(t.color=e.color),Ze(e.width)&&(t.width=Math.max(.5,Math.min(8,e.width))),kw(e.style)&&(t.style=e.style),Ze(e.opacity)&&(t.opacity=Bh(e.opacity));let n=e.shadeRight;return n&&typeof n=="object"&&ie(n.color)&&(t.shadeRight=Ze(n.opacity)?{color:n.color,opacity:Bh(n.opacity)}:{color:n.color}),Object.keys(t).length>0?t:null}function ie(r){return typeof r=="string"&&r.trim().length>0}function Ee(r){return typeof r=="boolean"}function Ze(r){return typeof r=="number"&&Number.isFinite(r)}function kw(r){return typeof r=="string"&&jE.includes(r)}function ZE(r){return typeof r=="string"&&Xo().includes(r)}function QE(r){return r==="price"||r==="percent"||r==="indexed"}function Le(r){return r&&typeof r=="object"?r:{}}function Bh(r){return r<0?0:r>1?1:r}function Vh(r){return r<1?1:r>10?10:r}function JE(r){return r<0?0:r>100?100:r}function eP(r){return r<.1?.1:r>10?10:r}function ww(r){return r<0?0:r>40?40:r}function tP(r){return Math.round(r<0?0:r>200?200:r)}function Lw(r,e=r.series.style){let t={};for(let n of xt()){let o=n.settings;if(!o)continue;let i={},s=a=>{for(let l of a??[])for(let c of Ii(l))i[c.key]=c.defval;};for(let a of o.instances??[])a.enableKey&&(i[a.enableKey]=false),s(a.rows);for(let a of o.subsections??[])a.enableKey&&(i[a.enableKey]=false),s(a.rows);o.instances||s(o.rows),t[n.id]=i;}for(let n of xt()){if(!Yo(n.id))continue;let o=t[n.id]??{};for(let i of qE)o[i]=null;t[n.id]=o;}for(let[n,o]of Object.entries(r.chartTypes))t[n]={...t[n]??{},...o};return {...r,chartTypes:t,series:{...r.series,style:e}}}function Mw(r,e){let t=Le(e),n=Le(t.chartTypes),o={...r.chartTypes};for(let[E,I]of Object.entries(n))o[E]={...o[E]??{},...Le(I)};let i=Le(t.layout),s=Le(t.grid),a=Le(s.vertLines),l=Le(s.horzLines),c=Le(t.crosshair),d=Le(t.priceScale),u=Le(t.animations),h=Le(t.panes),p=Le(t.margins),m=Le(t.trades),f=Le(t.timeScale),g=Le(t.marks),b=Le(g.groups),y=Le(t.candles),w=Le(t.bars),S=Le(t.line),M=Le(t.area),C=Le(t.baseline),L=Le(t.series),v=Le(t.sessions),k=Le(t.stacking),x=Le(k.series);return {version:_h,chartTypes:o,layout:{background:ie(i.background)?i.background:r.layout.background,textColor:ie(i.textColor)?i.textColor:r.layout.textColor,fontFamily:ie(i.fontFamily)?i.fontFamily:r.layout.fontFamily,fontSize:Ze(i.fontSize)?Math.max(6,Math.min(32,i.fontSize)):r.layout.fontSize},grid:{vertLines:{visible:Ee(a.visible)?a.visible:r.grid.vertLines.visible,color:ie(a.color)?a.color:r.grid.vertLines.color},horzLines:{visible:Ee(l.visible)?l.visible:r.grid.horzLines.visible,color:ie(l.color)?l.color:r.grid.horzLines.color}},crosshair:{color:ie(c.color)?c.color:r.crosshair.color,width:Ze(c.width)?Math.max(.5,Math.min(8,c.width)):r.crosshair.width,style:kw(c.style)?c.style:r.crosshair.style,opacity:Ze(c.opacity)?Bh(c.opacity):r.crosshair.opacity,labelBackground:ie(c.labelBackground)?c.labelBackground:r.crosshair.labelBackground},priceScale:{mode:QE(d.mode)?d.mode:r.priceScale.mode,log:Ee(d.log)?d.log:r.priceScale.log,invert:Ee(d.invert)?d.invert:r.priceScale.invert,borderColor:ie(d.borderColor)?d.borderColor:r.priceScale.borderColor,labelsVisible:Ee(d.labelsVisible)?d.labelsVisible:r.priceScale.labelsVisible,currentPriceLine:Ee(d.currentPriceLine)?d.currentPriceLine:r.priceScale.currentPriceLine,priceLabel:Ee(d.priceLabel)?d.priceLabel:r.priceScale.priceLabel,countdown:Ee(d.countdown)?d.countdown:r.priceScale.countdown,animateLastPrice:Ee(d.animateLastPrice)?d.animateLastPrice:r.priceScale.animateLastPrice},animations:{zoom:Ee(u.zoom)?u.zoom:r.animations.zoom,pan:Ee(u.pan)?u.pan:r.animations.pan,autoscale:Ee(u.autoscale)?u.autoscale:r.animations.autoscale,intro:Ee(u.intro)?u.intro:r.animations.intro},panes:{separatorColor:ie(h.separatorColor)?h.separatorColor:r.panes.separatorColor},margins:{top:Ze(p.top)?ww(p.top):r.margins.top,bottom:Ze(p.bottom)?ww(p.bottom):r.margins.bottom,right:Ze(p.right)?tP(p.right):r.margins.right},trades:{visible:Ee(m.visible)?m.visible:r.trades.visible,labels:Ee(m.labels)?m.labels:r.trades.labels,qty:Ee(m.qty)?m.qty:r.trades.qty,longColor:ie(m.longColor)?m.longColor:r.trades.longColor,shortColor:ie(m.shortColor)?m.shortColor:r.trades.shortColor,exitColor:ie(m.exitColor)?m.exitColor:r.trades.exitColor},timeScale:{timezone:typeof f.timezone=="string"&&f.timezone?f.timezone:r.timeScale.timezone},marks:{visible:Ee(g.visible)?g.visible:r.marks.visible,groups:{...r.marks.groups,...Object.fromEntries(Object.entries(b).filter(([,E])=>Ee(E)))}},candles:{upColor:ie(y.upColor)?y.upColor:r.candles.upColor,downColor:ie(y.downColor)?y.downColor:r.candles.downColor,bodyVisible:Ee(y.bodyVisible)?y.bodyVisible:r.candles.bodyVisible,borderVisible:Ee(y.borderVisible)?y.borderVisible:r.candles.borderVisible,borderUpColor:ie(y.borderUpColor)?y.borderUpColor:r.candles.borderUpColor,borderDownColor:ie(y.borderDownColor)?y.borderDownColor:r.candles.borderDownColor,wickVisible:Ee(y.wickVisible)?y.wickVisible:r.candles.wickVisible,wickUpColor:ie(y.wickUpColor)?y.wickUpColor:r.candles.wickUpColor,wickDownColor:ie(y.wickDownColor)?y.wickDownColor:r.candles.wickDownColor},bars:{upColor:ie(w.upColor)?w.upColor:r.bars.upColor,downColor:ie(w.downColor)?w.downColor:r.bars.downColor},line:{color:ie(S.color)?S.color:r.line.color,width:Ze(S.width)?Vh(S.width):r.line.width},area:{lineColor:ie(M.lineColor)?M.lineColor:r.area.lineColor,width:Ze(M.width)?Vh(M.width):r.area.width,topColor:ie(M.topColor)?M.topColor:r.area.topColor,bottomColor:ie(M.bottomColor)?M.bottomColor:r.area.bottomColor},baseline:{topLineColor:ie(C.topLineColor)?C.topLineColor:r.baseline.topLineColor,bottomLineColor:ie(C.bottomLineColor)?C.bottomLineColor:r.baseline.bottomLineColor,topFillColor:ie(C.topFillColor)?C.topFillColor:r.baseline.topFillColor,topFillColor2:ie(C.topFillColor2)?C.topFillColor2:r.baseline.topFillColor2,bottomFillColor:ie(C.bottomFillColor)?C.bottomFillColor:r.baseline.bottomFillColor,bottomFillColor2:ie(C.bottomFillColor2)?C.bottomFillColor2:r.baseline.bottomFillColor2,width:Ze(C.width)?Vh(C.width):r.baseline.width,baselineLevel:Ze(C.baselineLevel)?JE(C.baselineLevel):r.baseline.baselineLevel},series:{style:ZE(L.style)?L.style:r.series.style,baseline:L.baseline===null?null:Ze(L.baseline)?L.baseline:r.series.baseline,spacing:Ze(L.spacing)?eP(L.spacing):r.series.spacing},sessions:{premarketColor:ie(v.premarketColor)?v.premarketColor:r.sessions.premarketColor,postmarketColor:ie(v.postmarketColor)?v.postmarketColor:r.sessions.postmarketColor,extendedColor:ie(v.extendedColor)?v.extendedColor:r.sessions.extendedColor},stacking:{candles:Ze(k.candles)?k.candles:r.stacking.candles,series:{...r.stacking.series,...Object.fromEntries(Object.entries(x).filter(([,E])=>Ze(E)))}}}}var Rs=class{constructor(e=4096){this.n=0;this.alpha=1;this.buf=new Float32Array(e*8);}reset(){this.n=0;}get vertexCount(){return this.n/8}get view(){return this.buf.subarray(0,this.n)}ensure(e){let t=this.n+e*8;if(t<=this.buf.length)return;let n=this.buf.length||8;for(;n=nP&&(Ew=jo,jo=new Map),e))}function Iw(r,e="#000000"){let[t,n,o,i]=se(r),s=t,a=n,l=o;if(i<1){let[h,p,m]=se(e);s=t*i+h*(1-i),a=n*i+p*(1-i),l=o*i+m*(1-i);}let c=.2126*Wh(s)+.7152*Wh(a)+.0722*Wh(l),d=(c+.05)/.05,u=1.05/(c+.05);return d>=u?"#000000":"#ffffff"}function Wh(r){return r<=.04045?r/12.92:Math.pow((r+.055)/1.055,2.4)}function rP(r){if(!er){let t=document.createElement("canvas");t.width=1,t.height=1,er=t.getContext("2d",{willReadFrequently:true});}if(!er)return Pw;er.clearRect(0,0,1,1),er.fillStyle="#000",er.fillStyle=r,er.fillRect(0,0,1,1);let e=er.getImageData(0,0,1,1).data;return [e[0]/255,e[1]/255,e[2]/255,e[3]/255]}var oP=`#version 300 es layout(location=0) in vec2 aPos; layout(location=1) in vec4 aColor; layout(location=2) in vec2 aEdge; // (signed perpendicular distance from line center, half-width) @@ -789,7 +818,7 @@ void main() { gl_Position = vec4(clip, 0.0, 1.0); vColor = aColor; vEdge = aEdge; -}`,YE=`#version 300 es +}`,iP=`#version 300 es precision highp float; in vec4 vColor; in vec2 vEdge; @@ -799,13 +828,13 @@ void main() { float aa = fwidth(vEdge.x); float cov = clamp((vEdge.y - abs(vEdge.x)) / max(aa, 1e-4) + 0.5, 0.0, 1.0); frag = vec4(vColor.rgb, vColor.a * cov); -}`,KE=`#version 300 es +}`,sP=`#version 300 es layout(location=0) in vec2 aPos; out vec2 vUv; void main() { vUv = aPos * 0.5 + 0.5; gl_Position = vec4(aPos, 0.0, 1.0); -}`,XE=`#version 300 es +}`,aP=`#version 300 es precision mediump float; in vec2 vUv; uniform sampler2D uTex; @@ -825,15 +854,15 @@ void main() { sum += texture(uTex, vUv + o2) * 0.0702702703; sum += texture(uTex, vUv - o2) * 0.0702702703; frag = sum; -}`,Bh={solid:null,dashed:[6,4],dotted:[2,3]};function Tw(r){return Math.max(6,Math.min(20,Math.round(r*4)))}var Gc=class{constructor(){this.kind="webgl2";this.modelAlpha=1;this.candleBodyAlpha=1;this.candleStructureAlpha=1;this.candleBodyScale=1;this.onNeedsRedraw=null;this.onContextFailed=null;this.glow=0;this.canvas=null;this.gl=null;this.program=null;this.vao=null;this.vbo=null;this.uRes=null;this.batch=new Es;this.contextLost=false;this.screenProgram=null;this.uTex=null;this.uDir=null;this.uIntensity=null;this.quadVao=null;this.quadVbo=null;this.fboA=null;this.texA=null;this.fboB=null;this.texB=null;this.fboW=0;this.fboH=0;this.glowBatch=new Es;this.sliceTex=new Map;this.onLost=e=>{e.preventDefault(),this.contextLost=true;};this.onRestored=()=>{this.contextLost=false,this.initGL()?this.onNeedsRedraw?.():this.onContextFailed?.();};}get ok(){return this.gl!==null}mount(e){if(this.canvas=e,this.gl=e.getContext("webgl2",{alpha:true,antialias:true,depth:false,stencil:false,premultipliedAlpha:true}),!!this.gl){if(!this.initGL()){this.gl=null;return}e.addEventListener("webglcontextlost",this.onLost,false),e.addEventListener("webglcontextrestored",this.onRestored,false);}}initGL(){let e=this.gl;if(!e)return false;this.screenProgram=null,this.quadVao=null,this.quadVbo=null,this.fboA=this.fboB=null,this.texA=this.texB=null,this.fboW=this.fboH=0,this.sliceTex.clear();let t=zc(e,e.VERTEX_SHADER,UE),n=zc(e,e.FRAGMENT_SHADER,YE),o=e.createProgram();if(!t||!n||!o)return t&&e.deleteShader(t),n&&e.deleteShader(n),o&&e.deleteProgram(o),false;if(e.attachShader(o,t),e.attachShader(o,n),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS))return e.deleteProgram(o),e.deleteShader(t),e.deleteShader(n),false;e.deleteShader(t),e.deleteShader(n),this.program=o,this.uRes=e.getUniformLocation(o,"uRes"),this.vbo=e.createBuffer(),this.vao=e.createVertexArray(),e.bindVertexArray(this.vao),e.bindBuffer(e.ARRAY_BUFFER,this.vbo);let i=32;return e.enableVertexAttribArray(0),e.vertexAttribPointer(0,2,e.FLOAT,false,i,0),e.enableVertexAttribArray(1),e.vertexAttribPointer(1,4,e.FLOAT,false,i,8),e.enableVertexAttribArray(2),e.vertexAttribPointer(2,2,e.FLOAT,false,i,24),e.bindVertexArray(null),this.glow>0&&!this.ensureScreenPipeline()&&(this.glow=0),true}ensureScreenPipeline(){if(this.screenProgram&&this.quadVao)return true;let e=this.gl;if(!e)return false;let t=zc(e,e.VERTEX_SHADER,KE),n=zc(e,e.FRAGMENT_SHADER,XE),o=e.createProgram();return !t||!n||!o?(t&&e.deleteShader(t),n&&e.deleteShader(n),o&&e.deleteProgram(o),false):(e.attachShader(o,t),e.attachShader(o,n),e.linkProgram(o),e.getProgramParameter(o,e.LINK_STATUS)?(e.deleteShader(t),e.deleteShader(n),this.screenProgram=o,this.uTex=e.getUniformLocation(o,"uTex"),this.uDir=e.getUniformLocation(o,"uDir"),this.uIntensity=e.getUniformLocation(o,"uIntensity"),this.quadVbo=e.createBuffer(),this.quadVao=e.createVertexArray(),e.bindVertexArray(this.quadVao),e.bindBuffer(e.ARRAY_BUFFER,this.quadVbo),e.bufferData(e.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,-1,1,1,1]),e.STATIC_DRAW),e.enableVertexAttribArray(0),e.vertexAttribPointer(0,2,e.FLOAT,false,0,0),e.bindVertexArray(null),true):(e.deleteProgram(o),false))}ensureFbos(e,t,n){if(this.fboA&&this.fboW===t&&this.fboH===n)return true;this.deleteFbos(e);let o=()=>{let a=e.createTexture();e.bindTexture(e.TEXTURE_2D,a),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,t,n,0,e.RGBA,e.UNSIGNED_BYTE,null),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE);let l=e.createFramebuffer();return e.bindFramebuffer(e.FRAMEBUFFER,l),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,a,0),{tex:a,fbo:l}},i=o(),s=o();return e.bindFramebuffer(e.FRAMEBUFFER,null),this.texA=i.tex,this.fboA=i.fbo,this.texB=s.tex,this.fboB=s.fbo,this.fboW=t,this.fboH=n,!!(this.fboA&&this.fboB)}deleteFbos(e){this.fboA&&e.deleteFramebuffer(this.fboA),this.fboB&&e.deleteFramebuffer(this.fboB),this.texA&&e.deleteTexture(this.texA),this.texB&&e.deleteTexture(this.texB),this.fboA=this.fboB=null,this.texA=this.texB=null,this.fboW=this.fboH=0;}render(e,t,n){let o=this.gl,i=this.canvas;if(!o||!i||!this.program||this.contextLost||o.isContextLost())return;let s=t.dpr,a=t.width;o.viewport(0,0,i.width,i.height),o.disable(o.SCISSOR_TEST),o.clearColor(0,0,0,0),o.clear(o.COLOR_BUFFER_BIT);let l=t.barCount;if(l===0)return;let c=t.visibleLogicalRange(),d=Math.max(0,Math.floor(c.from)),u=Math.min(l-1,Math.ceil(c.to));if(u{g.vertexCount!==0&&(o.blendFuncSeparate(o.SRC_ALPHA,o.ONE_MINUS_SRC_ALPHA,o.ONE,o.ONE_MINUS_SRC_ALPHA),o.useProgram(this.program),o.bindVertexArray(this.vao),o.uniform2f(this.uRes,i.width/s,i.height/s),o.bindBuffer(o.ARRAY_BUFFER,this.vbo),o.bufferData(o.ARRAY_BUFFER,g.view,o.DYNAMIC_DRAW),o.drawArrays(o.TRIANGLES,0,g.vertexCount),g.reset());},C=f.collapsed?[]:e.drawingSlices.get(f.id)??[],M=0,S=L=>{for(;M{let N=e.scaleFor(I,f);return N===f.scale?f:{...f,scale:N}};g.alpha=this.modelAlpha;for(let I of L)for(let N of I.backgrounds)N.overlay!==true&&this.emitBackground(g,N,f,t);if(v)for(let I of e.indicators.values())for(let N of I.backgrounds)N.overlay===true&&this.emitBackground(g,N,f,t);let x=v&&!e.candlesHidden,E=false;for(let I of L){x&&!E&&e.zOf(I.id)>=e.candleZ&&(S(e.candleZ),g.alpha=this.candleStructureAlpha,this.emitPriceSeries(g,e,d,u,t,f,n,h,a),E=true),S(e.zOf(I.id)),g.alpha=this.modelAlpha;let N=e.offsetOf(I.id),V=k(I);for(let Z of I.fills)Z.overlay!==true&&this.emitFill(g,I,Z,V,t,d,u,N);for(let Z of I.series)Z.overlay!==true&&this.emitSeries(g,Z,V,t,d,u,n,N);}if(x&&!E&&(S(e.candleZ),g.alpha=this.candleStructureAlpha,this.emitPriceSeries(g,e,d,u,t,f,n,h,a)),g.alpha=this.modelAlpha,v){for(let I of e.indicators.values()){let N=e.offsetOf(I.id);for(let V of I.fills)V.overlay===true&&this.emitFill(g,I,V,f,t,d,u,N);}for(let I of e.indicators.values()){let N=e.offsetOf(I.id);for(let V of I.series)V.overlay===true&&this.emitSeries(g,V,f,t,d,u,n,N);}}S(1/0);for(let I of L){let N=k(I);for(let V of I.priceLines)this.emitHline(g,V,N,t,a,n);}g.alpha=1;}w();}o.disable(o.SCISSOR_TEST);for(let[f,g]of this.sliceTex)m.has(f)||(o.deleteTexture(g),this.sliceTex.delete(f));this.glow>0&&!this.screenProgram&&!this.ensureScreenPipeline()&&(this.glow=0),this.glow>0&&this.screenProgram&&(this.glowBatch.alpha=this.modelAlpha,this.renderGlow(o,e,t,d,u));}renderGlow(e,t,n,o,i){let s=this.canvas,a=Math.max(1,s.width>>1),l=Math.max(1,s.height>>1);if(!this.ensureFbos(e,a,l))return;let c=n.dpr,d=n.width;e.bindFramebuffer(e.FRAMEBUFFER,this.fboA),e.viewport(0,0,a,l),e.disable(e.SCISSOR_TEST),e.clearColor(0,0,0,0),e.clear(e.COLOR_BUFFER_BIT),e.enable(e.BLEND),e.blendFuncSeparate(e.SRC_ALPHA,e.ONE_MINUS_SRC_ALPHA,e.ONE,e.ONE_MINUS_SRC_ALPHA),e.useProgram(this.program),e.bindVertexArray(this.vao),e.uniform2f(this.uRes,s.width/c,s.height/c),e.enable(e.SCISSOR_TEST);for(let u of t.orderedPanes()){let h=this.glowBatch;if(h.reset(),this.emitGlowSources(h,t,u,n,o,i),h.vertexCount===0)continue;let p=Math.round(u.bounds.top*c*.5),m=Math.round((u.bounds.top+u.bounds.height)*c*.5);e.scissor(0,l-m,Math.round(d*c*.5),m-p),e.bindBuffer(e.ARRAY_BUFFER,this.vbo),e.bufferData(e.ARRAY_BUFFER,h.view,e.DYNAMIC_DRAW),e.drawArrays(e.TRIANGLES,0,h.vertexCount);}e.disable(e.SCISSOR_TEST),e.useProgram(this.screenProgram),e.bindVertexArray(this.quadVao),e.uniform1i(this.uTex,0),e.uniform1f(this.uIntensity,1),e.activeTexture(e.TEXTURE0),e.disable(e.BLEND),e.bindFramebuffer(e.FRAMEBUFFER,this.fboB),e.bindTexture(e.TEXTURE_2D,this.texA),e.uniform2f(this.uDir,1/a,0),e.drawArrays(e.TRIANGLE_STRIP,0,4),e.bindFramebuffer(e.FRAMEBUFFER,this.fboA),e.bindTexture(e.TEXTURE_2D,this.texB),e.uniform2f(this.uDir,0,1/l),e.drawArrays(e.TRIANGLE_STRIP,0,4),e.bindFramebuffer(e.FRAMEBUFFER,null),e.viewport(0,0,s.width,s.height),e.enable(e.BLEND),e.blendFunc(e.ONE,e.ONE),e.bindTexture(e.TEXTURE_2D,this.texA),e.uniform2f(this.uDir,0,0),e.uniform1f(this.uIntensity,this.glow),e.drawArrays(e.TRIANGLE_STRIP,0,4),e.bindTexture(e.TEXTURE_2D,null),e.bindVertexArray(null);}drawSliceTexture(e,t){if(!this.ensureScreenPipeline()||!this.screenProgram)return false;let n=this.sliceTex.get(t)??null;if(!n){if(n=e.createTexture(),!n)return false;this.sliceTex.set(t,n),e.bindTexture(e.TEXTURE_2D,n),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE);}return e.activeTexture(e.TEXTURE0),e.bindTexture(e.TEXTURE_2D,n),e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,true),e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,true),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,t),e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,false),e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,false),e.useProgram(this.screenProgram),e.bindVertexArray(this.quadVao),e.uniform1i(this.uTex,0),e.uniform2f(this.uDir,0,0),e.uniform1f(this.uIntensity,1),e.blendFuncSeparate(e.ONE,e.ONE_MINUS_SRC_ALPHA,e.ONE,e.ONE_MINUS_SRC_ALPHA),e.drawArrays(e.TRIANGLE_STRIP,0,4),e.bindVertexArray(null),true}emitGlowSources(e,t,n,o,i,s){let a=(l,c)=>{!Ge(l)||!Rt(l,"pane")||l.kind==="histogram"||l.kind==="columns"||(l.kind==="circles"||l.kind==="cross"?this.emitPointMarkers(e,l,n,o,i,s,c):this.emitPolyline(e,l,n,o,i,s,l.kind==="step",c));};for(let l of t.indicatorsForPane(n.id)){let c=t.offsetOf(l.id);for(let d of l.series)d.overlay!==true&&a(d,c);}if(n.kind==="price")for(let l of t.indicators.values()){let c=t.offsetOf(l.id);for(let d of l.series)d.overlay===true&&a(d,c);}}destroy(){let e=this.gl;if(this.canvas&&(this.canvas.removeEventListener("webglcontextlost",this.onLost),this.canvas.removeEventListener("webglcontextrestored",this.onRestored)),e){this.program&&e.deleteProgram(this.program),this.vbo&&e.deleteBuffer(this.vbo),this.vao&&e.deleteVertexArray(this.vao),this.screenProgram&&e.deleteProgram(this.screenProgram),this.quadVbo&&e.deleteBuffer(this.quadVbo),this.quadVao&&e.deleteVertexArray(this.quadVao);for(let t of this.sliceTex.values())e.deleteTexture(t);this.sliceTex.clear(),this.deleteFbos(e),e.getExtension("WEBGL_lose_context")?.loseContext();}this.gl=null,this.canvas=null,this.program=null,this.vao=null,this.vbo=null,this.screenProgram=null;}emitBackground(e,t,n,o){let i=o.timeToX(t.from),s=o.timeToX(t.to);s<0||i>o.width||s<=i||e.rect(i,n.bounds.top,s-i,n.bounds.height,se(t.color));}emitFill(e,t,n,o,i,s,a,l=0){let c=Lw(t,n.fromSeriesId),d=Lw(t,n.toSeriesId);if(!(!c||!d))for(let u=Math.max(1,s);u<=a;u+=1){let h=c[u-1-l],p=d[u-1-l],m=c[u-l],f=d[u-l];if(!h||!p||!m||!f||h.value===null||p.value===null||m.value===null||f.value===null)continue;let g=i.logicalToX(u-1),b=i.logicalToX(u),y=i.priceToY(h.value,o.scale,o.bounds),w=i.priceToY(p.value,o.scale,o.bounds),C=i.priceToY(m.value,o.scale,o.bounds),M=i.priceToY(f.value,o.scale,o.bounds),S=n.gradient?.[u-1-l];if(S){let L=i.priceToY(S.topValue,o.scale,o.bounds),v=i.priceToY(S.bottomValue,o.scale,o.bounds),k=v===L?L+1:v,x=se(S.topColor),E=se(S.bottomColor),I=k-L,N=V=>_h(x,E,Wc((V-L)/I));e.quad4(g,y,N(y),b,C,N(C),b,M,N(M),g,w,N(w));}else {let L=n.colors?n.colors[u-1-l]:n.color;if(!L)continue;e.quad(g,y,b,C,b,M,g,w,se(L));}}}emitPriceSeries(e,t,n,o,i,s,a,l,c){if(t.basePainting==="none")return;let d=t.bars,u=t.style;switch(t.priceStyle){case "bars":this.emitBars(e,d,n,o,i,s,u.bars.upColor??a.upColor,u.bars.downColor??a.downColor,l);return;case "line":this.emitPriceLine(e,d,n,o,i,s,se(u.line.color??a.upColor),u.line.width);return;case "area":{let h=u.area.lineColor??a.upColor;this.emitPriceArea(e,d,n,o,i,s,se(u.area.topColor??h),se(u.area.bottomColor??"rgba(0,0,0,0)")),this.emitPriceLine(e,d,n,o,i,s,se(h),u.area.width);return}case "baseline":this.emitBaseline(e,d,n,o,i,s,t,a,c);return;default:this.emitCandles(e,t,d,n,o,i,s,a,l);}}emitBars(e,t,n,o,i,s,a,l,c){let d=i.bodySpacing(),u=_o(d);if(u==="aggregate"){this.emitCandlesAggregated(e,t,n,o,i,s,m=>c.get(m.time)??(m.close>=m.open?a:l));return}let h=Math.max(1,Math.round(d*.35)),p=u==="full";for(let m=n;m<=o;m+=1){let f=t[m];if(!f||f.high<=f.low)continue;let g=se(c.get(f.time)??(f.close>=f.open?a:l)),b=Math.round(i.logicalToX(m)),y=i.priceToY(f.high,s.scale,s.bounds),w=i.priceToY(f.low,s.scale,s.bounds);if(e.rect(b-.5,y,1,w-y,g),p){let C=i.priceToY(f.open,s.scale,s.bounds),M=i.priceToY(f.close,s.scale,s.bounds);e.rect(b-h,C-.5,h,1,g),e.rect(b,M-.5,h,1,g);}}}emitPriceLine(e,t,n,o,i,s,a,l){let c=Math.max(1,l)/2,d=Tw(c),u=false,h=0,p=0;for(let m=Math.max(0,n-1);m<=o;m+=1){let f=t[m];if(!f){u=false;continue}let g=i.logicalToX(m),b=i.priceToY(f.close,s.scale,s.bounds);u&&e.seg(h,p,g,b,l,a),e.circle(g,b,c,a,d),h=g,p=b,u=true;}}emitPriceArea(e,t,n,o,i,s,a,l){let c=s.bounds.top+s.bounds.height,d=[],u=1/0,h=()=>{if(d.length>=2){let p=c-u,m=f=>_h(a,l,p<1e-6?0:Wc((f-u)/p));for(let f=1;fx<=u?y:C,k=x=>{let E=x<=u,I=E?u-S:L-u,N=I>0?Wc(Math.abs(x-u)/I):0;return _h(E?y:C,E?b:w,N)};for(let x=1;x{let w=y.close>=y.open;return (w?f.wickUpColor:f.wickDownColor)??c.get(y.time)??(w?p:m)});return}let g=u==="full",b=this.candleStructureAlpha>this.candleBodyAlpha+.001;for(let y=o;y<=i;y+=1){let w=n[y];if(!w||w.high<=w.low)continue;let C=Bc(s.logicalToX(y),d,s.dpr,this.candleBodyScale),M=w.close>=w.open,S=M?p:m,v=c.get(w.time)??S,k=se(v),x=0,E=0;if(g){let I=s.priceToY(w.open,a.scale,a.bounds),N=s.priceToY(w.close,a.scale,a.bounds);x=un(Math.min(I,N),s.dpr),E=Math.max(1/s.dpr,un(Math.max(I,N),s.dpr)-x);}if(f.wickVisible){let I=un(s.priceToY(w.high,a.scale,a.bounds),s.dpr),N=un(s.priceToY(w.low,a.scale,a.bounds),s.dpr);e.alpha=this.candleStructureAlpha;let V=se((M?f.wickUpColor:f.wickDownColor)??(g?S:v));g?(e.rect(C.wickX,I,C.wickW,Math.max(0,x-I),V),e.rect(C.wickX,x+E,C.wickW,Math.max(0,N-(x+E)),V)):e.rect(C.wickX,I,C.wickW,N-I,V);}if(g&&(f.bodyVisible&&(e.alpha=this.candleBodyAlpha,e.rect(C.bodyX,x,C.bodyW,E,k)),f.borderVisible||b&&f.bodyVisible)){e.alpha=this.candleStructureAlpha;let I=f.borderVisible?se((M?f.borderUpColor:f.borderDownColor)??v):k,N=Math.max(0,C.bodyW-1),V=Math.max(0,E-1);e.rectStroke(C.bodyX+.5,x+.5,N,V,1,I);}}}emitCandlesAggregated(e,t,n,o,i,s,a){let l=c=>i.priceToY(c,s.scale,s.bounds);for(let c of _c(t,n,o,d=>i.logicalToX(d),l,a)){let d=se(c.color),u=l(c.hi);e.rect(c.x-.5,u,1,l(c.lo)-u,d);}}emitSeries(e,t,n,o,i,s,a,l=0){if(Rt(t,"pane")){if(t.kind==="candle"||t.kind==="bar"){this.emitPlotCandles(e,t,n,o,i,s,a,l);return}if(Ge(t))switch(t.kind){case "histogram":case "columns":this.emitHistogram(e,t,n,o,i,s,l);break;case "area":this.emitArea(e,t,n,o,i,s,l),this.emitPolyline(e,t,n,o,i,s,false,l);break;case "circles":case "cross":this.emitPointMarkers(e,t,n,o,i,s,l);break;case "step":this.emitPolyline(e,t,n,o,i,s,true,l);break;default:this.emitPolyline(e,t,n,o,i,s,false,l);}}}emitPolyline(e,t,n,o,i,s,a,l=0){let c=Math.max(1,t.style.width),d=c/2,u=Bh[t.style.lineStyle]??null,h=!u&&!a,p=Tw(d),m=false;for(let f=Math.max(1,i-1);f<=s;f+=1){let g=t.points[f-l],b=t.points[f-1-l];if(!g||g.value===null||!b||b.value===null){m=false;continue}let y=o.logicalToX(f),w=o.priceToY(g.value,n.scale,n.bounds),C=o.logicalToX(f-1),M=o.priceToY(b.value,n.scale,n.bounds),S=se(g.color??t.style.color);a?(e.dashedSeg(C,M,y,M,c,S,u),e.dashedSeg(y,M,y,w,c,S,u)):e.dashedSeg(C,M,y,w,c,S,u),h&&(m||e.circle(C,M,d,se(b.color??t.style.color),p),e.circle(y,w,d,S,p)),m=true;}}emitArea(e,t,n,o,i,s,a=0){let l=n.bounds.top+n.bounds.height,c=se(t.style.color),d=[],u=1/0,h=()=>{if(d.length<1){d=[],u=1/0;return}let p=l-u,m=f=>jE(c,p<1e-6?0:Wc((f-u)/p));for(let f=1;f=g.open?d:u)),w=Math.round(o.logicalToX(f)),C=o.priceToY(g.high,n.scale,n.bounds),M=o.priceToY(g.low,n.scale,n.bounds),S=o.priceToY(g.open,n.scale,n.bounds),L=o.priceToY(g.close,n.scale,n.bounds);if(h){e.rect(w-.5,C,1,M-C,y),e.rect(w-m,S-.5,m,1,y),e.rect(w,L-.5,m,1,y);continue}let v=Math.max(1,Math.round(Ms(c)*o.dpr)),k=(Math.round(w*o.dpr)-(v>>1))/o.dpr;e.rect(k,C,v/o.dpr,M-C,se(b?.wickColor??b?.color??(g.close>=g.open?d:u)));let x=Math.min(S,L),E=Math.max(1,Math.abs(L-S));if(e.rect(w-p,x,p*2,E,y),b?.borderColor){let I=se(b.borderColor);e.rect(w-p,x,p*2,1,I),e.rect(w-p,x+E-1,p*2,1,I),e.rect(w-p,x,1,E,I),e.rect(w+p-1,x,1,E,I);}}}emitHline(e,t,n,o,i,s){let a=Math.round(o.priceToY(t.price,n.scale,n.bounds));an.bounds.top+n.bounds.height||e.dashedSeg(0,a,i,a,t.width??1,se(t.color??s.textColor),Bh[t.lineStyle??"solid"]??null);}};function zc(r,e,t){let n=r.createShader(e);return n?(r.shaderSource(n,t),r.compileShader(n),r.getShaderParameter(n,r.COMPILE_STATUS)?n:(r.deleteShader(n),null)):null}var kw=[0,0,0,0];function Wc(r){return r<0?0:r>1?1:r}function _h(r,e,t){return [r[0]+(e[0]-r[0])*t,r[1]+(e[1]-r[1])*t,r[2]+(e[2]-r[2])*t,r[3]+(e[3]-r[3])*t]}function jE(r,e){let t=1-e;return [r[0]*t,r[1]*t,r[2]*t,r[3]*t]}function Lw(r,e){let t=r.series.find(n=>n.id===e);return t&&Ge(t)?t.points:null}var qE=new Map;function ZE(r){let e=false;for(let n of r.values())if(n.barColors&&n.barColors.length>0){e=true;break}if(!e)return qE;let t=new Map;for(let n of r.values())if(n.barColors)for(let o of n.barColors)t.set(o.time,o.color);return t}function $c(){return {barSpacing:8,rightOffset:6}}function hn(r){return Math.max(.5,Math.min(1e3,r))}function Hh(r){if(r.length<2)return 0;let e=[];for(let t=1;t0&&e.push(n);}return e.length===0?0:(e.sort((t,n)=>t-n),e[Math.floor(e.length/2)])}function Mw(r,e,t){let n=e.length;if(n===0)return 0;let o=e[0],i=e[n-1];if(r<=o)return t>0?(r-o)/t:0;if(r>=i)return n-1+(t>0?(r-i)/t:0);let s=0,a=n-1;for(;a-s>1;){let c=s+a>>1;e[c]<=r?s=c:a=c;}let l=e[a]-e[s];return l>0?s+(r-e[s])/l:s}function Ew(r,e,t){let n=e.length;if(n===0)return 0;if(r<=0)return e[0]+(t>0?r*t:0);if(r>=n-1)return e[n-1]+(t>0?(r-(n-1))*t:0);let o=Math.floor(r),i=r-o;return e[o]+(e[o+1]-e[o])*i}var Uc=class{constructor(){this.widthPx=0;this.dataHeightPx=0;this.devicePixelRatio=1;this.viewport=$c();this.pitchScale=1;this.times=[];this.intervalMs=0;}setSize(e,t,n){this.widthPx=e,this.dataHeightPx=t,this.devicePixelRatio=n>0?n:1;}setBars(e){this.times=e.slice(),this.intervalMs=Hh(this.times);}appendBar(e){this.times.push(e),this.intervalMs<=0&&this.times.length>=2&&(this.intervalMs=Hh(this.times));}setViewport(e){this.viewport=e;}getViewport(){return this.viewport}setPitchScale(e){this.pitchScale=Number.isFinite(e)&&e>0?e:1;}get spacingScale(){return this.pitchScale}pxPerBar(){return this.viewport.barSpacing*this.pitchScale}bodySpacing(){return this.viewport.barSpacing*Math.min(1,this.pitchScale)}get width(){return this.widthPx}get height(){return this.dataHeightPx}get dpr(){return this.devicePixelRatio}get barCount(){return this.times.length}get barInterval(){return this.intervalMs}get rightEdgeLogical(){return this.barCount-1+this.viewport.rightOffset}logicalToX(e){return this.widthPx-(this.rightEdgeLogical-e)*this.pxPerBar()}xToLogical(e){return this.rightEdgeLogical-(this.widthPx-e)/this.pxPerBar()}timeToLogical(e){return Mw(e,this.times,this.intervalMs)}logicalToTime(e){return Ew(e,this.times,this.intervalMs)}timeToX(e){return this.logicalToX(this.timeToLogical(e))}priceToY(e,t,n){if(t.log&&t.min>0&&t.max>t.min&&e>0){let s=Math.log(t.min),a=(Math.log(e)-s)/(Math.log(t.max)-s);return n.top+n.height*(t.invert?a:1-a)}let o=t.max-t.min;if(o<=0)return n.top+n.height/2;let i=(e-t.min)/o;return n.top+n.height*(t.invert?i:1-i)}yToPrice(e,t,n){if(n.height<=0)return t.min;let o=(e-n.top)/n.height,i=t.invert?o:1-o;if(t.log&&t.min>0&&t.max>t.min){let s=Math.log(t.min);return Math.exp(s+i*(Math.log(t.max)-s))}return t.min+(t.max-t.min)*i}visibleLogicalRange(){return {from:this.xToLogical(0),to:this.xToLogical(this.widthPx)}}visibleTimeRange(){let e=this.visibleLogicalRange();return {from:this.logicalToTime(e.from),to:this.logicalToTime(e.to)}}toBitmap(e){return Math.round(e*this.devicePixelRatio)}};function zh(r){return r>=3}function Pw(r){return r>=2}var Yc=class{constructor(e,t,n){this.onFrame=e;this.level=0;this.handle=null;this.raf=t??(o=>requestAnimationFrame(o)),this.cancel=n??(o=>cancelAnimationFrame(o));}invalidate(e){e<=0||(e>this.level&&(this.level=e),this.handle===null&&(this.handle=this.raf(()=>this.flush())));}flushNow(e){this.handle!==null&&(this.cancel(this.handle),this.handle=null),e>this.level&&(this.level=e),this.flush();}flush(){this.handle=null;let e=this.level;this.level=0,e!==0&&this.onFrame(e);}destroy(){this.handle!==null&&(this.cancel(this.handle),this.handle=null),this.level=0;}};var Kc=class{constructor(e,t,n,o){this.tick=e;this.handle=null;this.last=0;this.stopped=false;this.loop=()=>{let e=this.now(),t=e-this.last;this.last=e;let n=this.tick(Math.min(t,64));this.handle=n&&!this.stopped?this.raf(this.loop):null;};this.raf=t??(i=>requestAnimationFrame(i)),this.cancel=n??(i=>cancelAnimationFrame(i)),this.now=o??(()=>performance.now());}get active(){return this.handle!==null}start(){this.stopped=false,this.handle===null&&(this.last=this.now(),this.handle=this.raf(this.loop));}stop(){this.stopped=true,this.handle!==null&&(this.cancel(this.handle),this.handle=null);}},er=class{constructor(e,t=e){this.onMs=e,this.ms=t;}get tau(){return this.ms}get on(){return this.ms>0}set(e){this.ms=e,e>0&&(this.onMs=e);}toggle(e){this.ms=e?this.onMs:0;}};function Lt(r,e,t,n){return n<=0?e:r+(e-r)*(1-Math.exp(-t/n))}var QE=.04,JE=60,eP=2,tP=350,Iw=8,nP=14,rP=350,oP=30,iP=.004,sP=.004,aP=.25;function lP(r,e,t){return t?{logical:r.rightEdgeLogical,x:r.width}:{logical:r.xToLogical(e),x:e}}function cP(r,e){return Math.abs(r)>Math.abs(e)}function dP(r,e,t){return r+e/t}function uP(r,e,t){return cP(r,e)?r:t?e:null}function hP(r,e){return r?"strong":e}function pP(r,e,t){return hn(r*(t/Math.max(1,e)))}function mP(r,e,t,n,o){return r-(e-1)+(t-n)/o}var Xc=class{constructor(e){this.deps=e;this.rightEdgeZoom=true;this.axisDrag=true;this.paneResize=true;this.el=null;this.dragging=false;this.moved=false;this.region="data";this.verticalPan=false;this.startX=0;this.startY=0;this.startRightOffset=0;this.startBarSpacing=0;this.lastX=0;this.lastT=0;this.vx=0;this.middleDeleted=false;this.rightCancelled=false;this.cursorX=NaN;this.cursorY=NaN;this.touches=new Map;this.lpTimer=null;this.pinchStartDist=1;this.pinchStartBarSpacing=0;this.pinchAnchorLogical=0;this.lastTapT=0;this.lastTapX=0;this.lastTapY=0;this.lastPressDrawing=false;this.prevPressDrawing=false;this.onTouchContextMenu=e=>{this.touches.size!==0&&(!(e.target instanceof Node)||!this.el?.contains(e.target)||(e.preventDefault(),e.stopImmediatePropagation()));};this.onMiddleGuard=e=>{e.button===1&&this.middleDeleted&&e.preventDefault();};this.onContextGuard=e=>{this.rightCancelled&&(this.rightCancelled=false,e.preventDefault(),e.stopPropagation());};this.onModifier=e=>{e.repeat||e.key!=="Shift"&&e.key!=="Control"&&e.key!=="Meta"||Number.isNaN(this.cursorX)||this.dragging&&this.region!=="drawing"||this.deps.drawingsPointerMove?.(this.cursorX,this.cursorY,this.snapMode(e),e.shiftKey,e.ctrlKey||e.metaKey);};this.onDown=e=>{if(e.button===1){let{x:i,y:s}=this.local(e);this.middleDeleted=this.deps.drawingsDeleteAt?.(i,s)??false,this.middleDeleted&&e.preventDefault();return}if(e.button===2){this.rightCancelled=this.deps.drawingsCancelPlacement?.()??false,this.rightCancelled&&e.preventDefault();return}if(e.button!==0)return;let{x:t,y:n}=this.local(e);if(e.pointerType==="touch"){if(this.touches.size===1&&this.dragging&&(this.region==="data"||this.region==="crosshair")){this.touches.set(e.pointerId,{x:t,y:n}),this.beginPinch(e);return}if(this.touches.size>=1)return;this.touches.set(e.pointerId,{x:t,y:n});}if(this.deps.drawingsClearTransient?.(),this.dragging=true,this.moved=false,this.startX=t,this.startY=n,this.prevPressDrawing=this.lastPressDrawing,this.lastPressDrawing=false,this.deps.drawingsClaim?.(t,n)){this.region="drawing",this.lastPressDrawing=true,this.deps.drawingsPointerDown?.(t,n,this.snapMode(e),e.shiftKey,e.ctrlKey||e.metaKey),this.capture(e.pointerId);return}if(e.shiftKey&&this.regionAt(t,n)==="data"&&this.deps.drawingsMeasureStart?.(t,n,this.snapMode(e))){this.region="drawing",this.lastPressDrawing=true,this.capture(e.pointerId);return}if((e.ctrlKey||e.metaKey)&&this.regionAt(t,n)==="data"&&this.deps.drawingsMarqueeStart?.(t,n)){this.region="drawing",this.lastPressDrawing=true,this.capture(e.pointerId);return}let o=this.deps.getCoords().getViewport();this.deps.apply(o),this.startRightOffset=o.rightOffset,this.startBarSpacing=o.barSpacing,this.region=this.regionAt(t,n),this.verticalPan=false,this.region==="price"?this.deps.beginPriceScale(t,n):this.region==="separator"?this.deps.beginPaneResize(n):this.region==="data"&&(this.verticalPan=this.deps.beginPricePan(n)),e.pointerType==="touch"&&(this.region==="data"||this.region==="price"||this.region==="time")&&this.startLongPress(t,n,this.region),this.lastX=t,this.lastT=e.timeStamp,this.vx=0,this.capture(e.pointerId);};this.onMove=e=>{let{x:t,y:n}=this.local(e);if(this.cursorX=t,this.cursorY=n,e.pointerType==="touch"&&this.touches.has(e.pointerId)&&this.touches.set(e.pointerId,{x:t,y:n}),this.dragging&&this.region==="pinch"){this.applyPinch();return}if(this.dragging&&this.region==="crosshair"){this.deps.onPointerMove(t,n);return}if(this.dragging&&this.region==="axis-sheet")return;this.lpTimer!==null&&Math.hypot(t-this.startX,n-this.startY)>Iw&&this.cancelLongPress();let o=e.pointerType==="touch"?Iw:eP;if(this.dragging)if(this.region==="price")Math.abs(n-this.startY)>o&&(this.moved=true),this.deps.priceScaleBy(n-this.startY);else if(this.region==="separator")Math.abs(n-this.startY)>o&&(this.moved=true),this.deps.paneResizeBy(n-this.startY);else if(this.region==="time"){Math.abs(t-this.startX)>o&&(this.moved=true);let i=hn(this.startBarSpacing*Math.exp((this.startX-t)*iP));this.deps.apply({barSpacing:i,rightOffset:this.startRightOffset});}else if(this.region==="drawing")(Math.abs(t-this.startX)>o||Math.abs(n-this.startY)>o)&&(this.moved=true),this.deps.drawingsPointerMove?.(t,n,this.snapMode(e),e.shiftKey,e.ctrlKey||e.metaKey);else {let i=this.deps.getCoords(),s=i.getViewport(),a=t-this.startX;Math.abs(a)>o&&(this.moved=true),this.deps.apply({barSpacing:s.barSpacing,rightOffset:this.startRightOffset-a/i.pxPerBar()}),this.verticalPan&&(Math.abs(n-this.startY)>o&&(this.moved=true),this.deps.pricePanBy(n-this.startY));let l=e.timeStamp-this.lastT;if(l>0){let c=(t-this.lastX)/l;this.vx=this.vx*.6+c*.4,this.lastX=t,this.lastT=e.timeStamp;}}else if(this.el){let i=this.deps.drawingsCursor?.(t,n),s=this.regionAt(t,n);this.el.style.cursor=i??(s==="price"?"ns-resize":s==="time"?"ew-resize":s==="separator"?"row-resize":""),this.deps.drawingsPointerMove?.(t,n,this.snapMode(e),e.shiftKey,e.ctrlKey||e.metaKey);}e.pointerType!=="touch"&&this.deps.onPointerMove(t,n);};this.onUp=e=>{if(e.pointerType==="touch"&&this.touches.delete(e.pointerId),this.cancelLongPress(),this.dragging&&this.region==="pinch"){if(this.touches.size===1){let a=[...this.touches.values()][0],l=this.deps.getCoords().getViewport();this.region="data",this.verticalPan=false,this.startX=a.x,this.startY=a.y,this.startRightOffset=l.rightOffset,this.startBarSpacing=l.barSpacing,this.lastX=a.x,this.lastT=e.timeStamp,this.vx=0;return}this.endGesture(e);return}if(this.dragging&&this.region==="crosshair"){this.deps.onPointerMove(null,null),this.endGesture(e);return}if(this.dragging&&this.region==="axis-sheet"){this.endGesture(e);return}let{x:t,y:n}=this.local(e),o=e.pointerType==="touch",i=this.dragging&&!this.moved&&(!o||Math.hypot(t-this.startX,n-this.startY)<=nP);if(this.dragging&&this.region==="drawing")this.deps.drawingsPointerUp?.(t,n,this.snapMode(e));else if(i&&this.region==="data")this.deps.onClick(t,n);else if(this.dragging&&this.region==="data"&&!(e.timeStamp-this.lastT>JE)&&Math.abs(this.vx)>QE){let l=this.deps.getCoords().pxPerBar();this.deps.fling(-this.vx/l);}let s=o&&i;this.endGesture(e),o&&this.deps.onPointerMove(null,null),s&&this.registerTap(e.timeStamp,t,n);};this.onCancel=e=>{e.pointerType==="touch"&&this.touches.delete(e.pointerId),this.cancelLongPress(),this.dragging&&(this.region==="drawing"&&!Number.isNaN(this.cursorX)&&this.deps.drawingsPointerUp?.(this.cursorX,this.cursorY,this.snapMode(e)),(this.region==="crosshair"||e.pointerType==="touch")&&this.deps.onPointerMove(null,null),this.endGesture(e));};this.onLeave=()=>{this.cursorX=NaN,this.cursorY=NaN,this.deps.onPointerMove(null,null);};this.onDblClick=e=>{let{x:t,y:n}=this.local(e);this.doubleActivate(t,n);};this.onWheel=e=>{e.preventDefault(),this.deps.drawingsClearTransient?.();let{x:t,y:n}=this.local(e);if(this.regionAt(t,n)==="price"&&e.deltaY!==0){this.deps.beginPriceScale(t,n),this.deps.priceScaleBy(e.deltaY*aP);return}let o=this.deps.getCoords(),i=o.getViewport(),s=uP(e.deltaX,e.deltaY,e.shiftKey);if(s!=null){this.deps.apply({barSpacing:i.barSpacing,rightOffset:dP(i.rightOffset,s,o.pxPerBar())});return}let a=this.rightEdgeZoom&&!(e.ctrlKey||e.metaKey),l=lP(o,t,a),c=hn(i.barSpacing*Math.exp(-e.deltaY*sP));this.deps.zoomTo(c,l.logical,l.x);};}attach(e){this.el=e,e.style!==void 0&&(e.style.touchAction="none",e.style.userSelect="none",e.style.setProperty("-webkit-user-select","none"),e.style.setProperty("-webkit-touch-callout","none")),e.addEventListener("pointerdown",this.onDown),e.addEventListener("pointermove",this.onMove),e.addEventListener("pointerup",this.onUp),e.addEventListener("pointerleave",this.onLeave),e.addEventListener("pointercancel",this.onCancel),e.addEventListener("dblclick",this.onDblClick),e.addEventListener("wheel",this.onWheel,{passive:false}),e.addEventListener("mousedown",this.onMiddleGuard),e.addEventListener("auxclick",this.onMiddleGuard),e.addEventListener("contextmenu",this.onContextGuard);let t=e.ownerDocument?.defaultView;t?.addEventListener("keydown",this.onModifier),t?.addEventListener("keyup",this.onModifier),t?.addEventListener("contextmenu",this.onTouchContextMenu,true);}detach(){let e=this.el;if(!e)return;let t=e.ownerDocument?.defaultView;t?.removeEventListener("keydown",this.onModifier),t?.removeEventListener("keyup",this.onModifier),t?.removeEventListener("contextmenu",this.onTouchContextMenu,true),e.removeEventListener("pointerdown",this.onDown),e.removeEventListener("pointermove",this.onMove),e.removeEventListener("pointerup",this.onUp),e.removeEventListener("pointerleave",this.onLeave),e.removeEventListener("pointercancel",this.onCancel),e.removeEventListener("dblclick",this.onDblClick),e.removeEventListener("wheel",this.onWheel),e.removeEventListener("mousedown",this.onMiddleGuard),e.removeEventListener("auxclick",this.onMiddleGuard),e.removeEventListener("contextmenu",this.onContextGuard),this.cancelLongPress(),this.touches.clear(),this.el=null;}local(e){let t=this.el.getBoundingClientRect();return {x:e.clientX-t.left,y:e.clientY-t.top}}regionAt(e,t){let n=this.deps.getCoords();if(this.paneResize&&t<=n.height&&this.deps.paneSeparatorAt(t))return "separator";if(this.axisDrag){if(e>n.width&&t<=n.height)return "price";if(t>n.height&&e<=n.width)return "time"}return "data"}snapMode(e){return hP(e.ctrlKey||e.metaKey,this.deps.drawingsSnapMode?.()??"off")}startLongPress(e,t,n){this.cancelLongPress(),this.lpTimer=setTimeout(()=>{if(this.lpTimer=null,!(!this.dragging||this.region!==n)){if(n==="data"){this.region="crosshair",this.deps.onPointerMove(e,t);return}this.region="axis-sheet",this.moved=true,this.deps.onAxisLongPress?.(n,e,t);}},tP);}cancelLongPress(){this.lpTimer!==null&&clearTimeout(this.lpTimer),this.lpTimer=null;}beginPinch(e){this.cancelLongPress(),this.region==="crosshair"&&this.deps.onPointerMove(null,null);let t=this.deps.getCoords(),n=t.getViewport();this.deps.apply(n);let[o,i]=[...this.touches.values()];this.pinchStartDist=Math.max(1,Math.hypot(o.x-i.x,o.y-i.y)),this.pinchStartBarSpacing=n.barSpacing,this.pinchAnchorLogical=t.xToLogical((o.x+i.x)/2),this.region="pinch",this.dragging=true,this.moved=true,this.vx=0,this.capture(e.pointerId);}applyPinch(){let e=this.deps.getCoords(),t=[...this.touches.values()];if(t.length<2)return;let[n,o]=t,i=pP(this.pinchStartBarSpacing,this.pinchStartDist,Math.hypot(n.x-o.x,n.y-o.y)),s=e.getViewport(),a=s.barSpacing>0?e.pxPerBar()/s.barSpacing:1,l=(n.x+o.x)/2;this.deps.apply({barSpacing:i,rightOffset:mP(this.pinchAnchorLogical,e.barCount,e.width,l,i*a)});}capture(e){try{this.el?.setPointerCapture(e);}catch{}}registerTap(e,t,n){if(this.lastTapT>0&&e-this.lastTapT<=rP&&Math.hypot(t-this.lastTapX,n-this.lastTapY)<=oP){this.lastTapT=0,this.doubleActivate(this.lastTapX,this.lastTapY);return}this.lastTapT=e,this.lastTapX=t,this.lastTapY=n;}endGesture(e){this.dragging=false;try{this.el?.releasePointerCapture(e.pointerId);}catch{}}doubleActivate(e,t){if(this.deps.drawingsDblClick?.(e,t))return;let n=this.regionAt(e,t);if(n==="price")this.deps.resetPriceScale(e,t);else if(n==="separator")this.deps.resetPaneSize(t);else if(n==="time")this.deps.resetView();else {if(this.lastPressDrawing||this.prevPressDrawing)return;this.deps.dataDblClick(e,t);}}};function fP(r){if(r.ctrlKey||r.metaKey)return null;switch(r.key){case "ArrowLeft":return r.shiftKey?{kind:"pan",bars:-10}:{kind:"step",delta:-1};case "ArrowRight":return r.altKey&&r.shiftKey?{kind:"realtime"}:r.shiftKey?{kind:"pan",bars:10}:{kind:"step",delta:1};case "+":case "=":return {kind:"zoom",direction:1};case "-":case "_":return {kind:"zoom",direction:-1};case "Home":return {kind:"edge",edge:"first"};case "End":return {kind:"edge",edge:"last"};case "0":return {kind:"reset"};case "Escape":return {kind:"clear"};default:return null}}var jc=class{constructor(e){this.deps=e;this.el=null;this.onKey=e=>{if(this.deps.preempt?.(e)){e.preventDefault();return}let t=fP(e);if(t)switch(e.preventDefault(),t.kind){case "pan":this.deps.panByBars(t.bars);break;case "zoom":this.deps.zoomByStep(t.direction);break;case "step":this.deps.stepCrosshair(t.delta);break;case "edge":this.deps.jumpToEdge(t.edge);break;case "reset":this.deps.resetView();break;case "realtime":this.deps.scrollToRealtime();break;case "clear":this.deps.clearCrosshair();break}};}attach(e){this.el=e,e.addEventListener("keydown",this.onKey);}detach(){this.el?.removeEventListener("keydown",this.onKey),this.el=null;}};var gP=Gm,bP=$m,vP=Um;function Vw(){return {visible:true,labels:true,qty:true,colors:{long:gP,short:bP,exit:vP}}}function Bw(r,e){let t=e&&typeof e=="object"?e:{},n=t.colors&&typeof t.colors=="object"?t.colors:{},o=(s,a)=>typeof s=="boolean"?s:a,i=(s,a)=>typeof s=="string"&&s.trim().length>0?s:a;return {visible:o(t.visible,r.visible),labels:o(t.labels,r.labels),qty:o(t.qty,r.qty),colors:{long:i(n.long,r.colors.long),short:i(n.short,r.colors.short),exit:i(n.exit,r.colors.exit)}}}var Wh=10,tr=9,Wr=6,Yo=14,qc=3,Gh=2,_w=2,$h=3,Uh=6,Aw=6,Rw=8;function Hw(r){return r+4}function yP(r){if(r.qty==null||!Number.isFinite(r.qty))return null;let e=Number(Math.abs(r.qty).toFixed(8));return `${r.side==="buy"?"+":"-"}${e}`}function wP(r,e,t){let n=[];if(e.labels&&r.label&&n.push(r.label),e.qty){let o=yP(r);o&&n.push(o);}return {exec:r,lines:n,height:Yo+(n.length?$h+n.length*t:0)}}function zw(r,e,t,n,o,i){let s=new Map;for(let a of r){let l=Math.round(t.timeToLogical(a.time));if(lo)continue;let c=s.get(l);c||(c={logical:l,buys:[],sells:[]},s.set(l,c)),(a.side==="buy"?c.buys:c.sells).push(wP(a,e,i));}return [...s.values()]}function Dw(r){if(r.length===0)return 0;let e=Wh;for(let t of r)e+=t.height;return e+(r.length-1)*Uh}function Ww(r,e,t,n,o,i){if(r.length===0)return null;let s=Hw(i),a=1/0,l=-1/0,c=0,d=0;for(let u of zw(r,e,t,Math.floor(n),Math.ceil(o),s)){let h=t.barAt(u.logical);h&&(h.lowl&&(l=h.high),d=Math.max(d,Dw(u.buys)),c=Math.max(c,Dw(u.sells)));}return !Number.isFinite(a)||!Number.isFinite(l)?null:{min:a,max:l,abovePx:c,belowPx:d}}function Gw(r,e,t,n,o,i,s,a,l){if(e.length===0)return;let c=Hw(s.fontSize),d=zw(e,t,n,-1/0,1/0,c);if(d.length!==0){r.save(),r.font=`${s.fontSize}px ${s.fontFamily}`,r.textAlign="center",r.textBaseline="middle";for(let u of d){let h=o(u.logical);if(h<-150||h>a+150)continue;let p=n.barAt(u.logical);if(!p)continue;let m=Math.max(i(p.low),i(p.high)),f=Math.min(i(p.low),i(p.high)),g=m+Wh;for(let b of u.buys)r.fillStyle=Ow(b.exec,t.colors),xP(r,h,g,b.exec.kind==="exit"),Nw(r,b.exec.side,h,i(b.exec.price),l),Fw(r,b.lines,h,g+Yo+$h+c/2,c,s.color),g+=b.height+Uh;g=f-Wh;for(let b of u.sells)r.fillStyle=Ow(b.exec,t.colors),CP(r,h,g,b.exec.kind==="exit"),Nw(r,b.exec.side,h,i(b.exec.price),l),Fw(r,b.lines,h,g-Yo-$h-c/2,-c,s.color),g-=b.height+Uh;}r.restore();}}function Ow(r,e){return r.kind==="exit"?e.exit:r.side==="buy"?e.long:e.short}function xP(r,e,t,n){r.beginPath(),r.moveTo(e,t),r.lineTo(e-tr/2,t+Wr),r.lineTo(e+tr/2,t+Wr),r.closePath(),r.fill(),r.fillRect(e-qc/2,t+Wr,qc,Yo-Wr),n&&r.fillRect(e-tr/2,t-_w-Gh,tr,Gh);}function CP(r,e,t,n){r.beginPath(),r.moveTo(e,t),r.lineTo(e-tr/2,t-Wr),r.lineTo(e+tr/2,t-Wr),r.closePath(),r.fill(),r.fillRect(e-qc/2,t-Yo,qc,Yo-Wr),n&&r.fillRect(e-tr/2,t+_w,tr,Gh);}function Nw(r,e,t,n,o){let i=e==="buy"?t-o:t+o,s=e==="buy"?i-Aw:i+Aw;r.beginPath(),r.moveTo(i,n),r.lineTo(s,n-Rw/2),r.lineTo(s,n+Rw/2),r.closePath(),r.fill();}function Fw(r,e,t,n,o,i){if(e.length!==0){r.fillStyle=i;for(let s=0;se.order-t.order)),this.orderedCache}sessionHighlightBands(){if(!this.sessionZones)return [];let e=[];for(let[t,n]of this.sessionZones.pre)e.push({from:t,to:n,color:this.style.sessions.premarketColor});for(let[t,n]of this.sessionZones.post)e.push({from:t,to:n,color:this.style.sessions.postmarketColor});for(let[t,n]of this.sessionZones.extended)e.push({from:t,to:n,color:this.style.sessions.extendedColor});return e}indicatorsForPane(e){let t=[];for(let n of this.indicators.values())n.paneId===e&&t.push(n);return t}ownScaleIndicatorsForPane(e){return this.orderedIndicatorsForPane(e).filter(t=>t.ownScale===true)}ensureIndicatorScale(e,t){let n=this.indicatorScales.get(e);if(!n){let o=t??{min:0,max:1};n={scale:{...o},scaleTarget:{...o},initialized:false,manualScale:null},this.indicatorScales.set(e,n);}return n}dropIndicatorScale(e){this.indicatorScales.delete(e);}scaleFor(e,t){if(e.ownScale===true){let n=this.indicatorScales.get(e.id);if(n)return n.scale}return t.scale}orderPanes(e){e.forEach((t,n)=>{let o=this.panes.get(t);o&&(o.order=n);}),this.orderedCache=null;}orderedIndicatorsForPane(e){return this.indicatorsForPane(e).sort((t,n)=>this.zOf(t.id)-this.zOf(n.id))}zOf(e){return this.seriesZ.get(e)??0}offsetOf(e){return this.anchorOffsets.get(e)??0}setAnchorOffset(e,t){t!==0&&Number.isFinite(t)?this.anchorOffsets.set(e,t):this.anchorOffsets.delete(e);}forgetAnchorOffset(e){this.anchorOffsets.delete(e);}baselinePriceFor(e){if(this.baselineValue!=null)return this.baselineValue;let t=this.style.baseline.baselineLevel/100;if(e.log&&e.min>0&&e.max>e.min){let n=Math.log(e.min);return Math.exp(n+t*(Math.log(e.max)-n))}return e.min+(e.max-e.min)*t}assignIndicatorZ(e){this.seriesZ.has(e)||this.seriesZ.set(e,this.bottomZ()-1);}assignIndicatorZTop(e){this.seriesZ.has(e)||this.seriesZ.set(e,this.topZ()+1);}forgetIndicatorZ(e){this.seriesZ.delete(e);}setIndicatorZ(e,t){this.seriesZ.set(e,t);}indicatorZOrder(){return [...this.seriesZ.entries()].map(([e,t])=>({id:e,z:t})).sort((e,t)=>e.z-t.z)}seriesBoundaries(e){let t=new Set;e==="price"&&t.add(this.candleZ);for(let n of this.indicatorsForPane(e))t.add(this.zOf(n.id));return [...t].sort((n,o)=>n-o)}bringIndicatorToFront(e){this.seriesZ.set(e,this.topZ()+1);}sendIndicatorToBack(e){this.seriesZ.set(e,this.bottomZ()-1);}topZ(){let e=this.candleZ;for(let t of this.seriesZ.values())t>e&&(e=t);return e}bottomZ(){let e=this.candleZ;for(let t of this.seriesZ.values())t{let x=e.scaleFor(k,g);return x===g.scale?g:{...g,scale:x}};o.globalAlpha=this.modelAlpha;for(let k of b)for(let x of k.backgrounds)x.overlay!==true&&this.drawBackground(o,x,g,t);if(y)for(let k of e.indicators.values())for(let x of k.backgrounds)x.overlay===true&&this.drawBackground(o,x,g,t);let C=e.drawingSlices.get(g.id)??[],M=0,S=k=>{for(;M=e.candleZ&&(S(e.candleZ),o.globalAlpha=this.candleStructureAlpha,this.drawPriceSeries(o,e,h,p,t,g,n,m,c),v=true),S(e.zOf(k.id)),o.globalAlpha=this.modelAlpha;let x=e.offsetOf(k.id),E=w(k);for(let I of k.fills)I.overlay!==true&&this.drawFill(o,k,I,E,t,h,p,x);for(let I of k.series)I.overlay!==true&&this.drawSeries(o,I,E,t,h,p,n,x);}if(L&&!v&&(S(e.candleZ),o.globalAlpha=this.candleStructureAlpha,this.drawPriceSeries(o,e,h,p,t,g,n,m,c)),y){o.globalAlpha=this.modelAlpha;for(let k of e.indicators.values()){let x=e.offsetOf(k.id);for(let E of k.fills)E.overlay===true&&this.drawFill(o,k,E,g,t,h,p,x);}for(let k of e.indicators.values()){let x=e.offsetOf(k.id);for(let E of k.series)E.overlay===true&&this.drawSeries(o,E,g,t,h,p,n,x);}}S(1/0),o.globalAlpha=this.modelAlpha;for(let k of b){let x=w(k);for(let E of k.priceLines)this.drawHline(o,E,x,t,c,n);}o.restore();}}destroy(){this.canvas=null,this.ctx=null;}drawPriceSeries(e,t,n,o,i,s,a,l,c){if(t.basePainting==="none")return;let d=t.bars,u=t.style;switch(t.priceStyle){case "bars":this.drawBars(e,d,n,o,i,s,u.bars.upColor??a.upColor,u.bars.downColor??a.downColor,l);return;case "line":this.drawPriceLine(e,d,n,o,i,s,u.line.color??a.upColor,u.line.width);return;case "area":{let h=u.area.lineColor??a.upColor;this.drawPriceArea(e,d,n,o,i,s,u.area.topColor??h,u.area.bottomColor??"rgba(0,0,0,0)"),this.drawPriceLine(e,d,n,o,i,s,h,u.area.width);return}case "baseline":this.drawBaseline(e,d,n,o,i,s,t,a,c);return;default:this.drawCandles(e,t,d,n,o,i,s,a,l);}}drawBars(e,t,n,o,i,s,a,l,c){let d=i.bodySpacing(),u=_o(d);if(u==="aggregate"){this.drawCandlesAggregated(e,t,n,o,i,s,m=>c.get(m.time)??(m.close>=m.open?a:l));return}let h=Math.max(1,Math.round(d*.35)),p=u==="full";e.lineWidth=1;for(let m=n;m<=o;m+=1){let f=t[m];if(!f||f.high<=f.low)continue;let g=Math.round(i.logicalToX(m))+.5,b=c.get(f.time)??(f.close>=f.open?a:l),y=i.priceToY(f.high,s.scale,s.bounds),w=i.priceToY(f.low,s.scale,s.bounds);if(e.strokeStyle=b,e.beginPath(),e.moveTo(g,y),e.lineTo(g,w),p){let C=i.priceToY(f.open,s.scale,s.bounds),M=i.priceToY(f.close,s.scale,s.bounds);e.moveTo(g-h,C),e.lineTo(g,C),e.moveTo(g,M),e.lineTo(g+h,M);}e.stroke();}}drawPriceLine(e,t,n,o,i,s,a,l){e.lineWidth=l,e.lineJoin="round",e.lineCap="round",e.strokeStyle=a,e.beginPath();let c=false;for(let d=Math.max(0,n-1);d<=o;d+=1){let u=t[d];if(!u){c=false;continue}let h=i.logicalToX(d),p=i.priceToY(u.close,s.scale,s.bounds);c?e.lineTo(h,p):(e.moveTo(h,p),c=true);}e.stroke(),e.lineCap="butt";}drawPriceArea(e,t,n,o,i,s,a,l){let c=s.bounds.top+s.bounds.height,d=[],u=1/0;for(let p=Math.max(0,n-1);p<=o;p+=1){let m=t[p];if(!m)continue;let f=i.logicalToX(p),g=i.priceToY(m.close,s.scale,s.bounds);d.push({x:f,y:g}),g{e.beginPath(),e.moveTo(M[0].x,u);for(let v of M)e.lineTo(v.x,v.y);e.lineTo(M[M.length-1].x,u),e.closePath();};if(u>h){e.save(),e.beginPath(),e.rect(0,h,c,u-h),e.clip();let v=e.createLinearGradient(0,h,0,u);v.addColorStop(0,b),v.addColorStop(1,y),e.fillStyle=v,S(),e.fill(),e.restore();}if(u{e.strokeStyle=I,e.beginPath(),e.moveTo(v,k),e.lineTo(x,E),e.stroke();};for(let v=1;v{let b=g.close>=g.open;return (b?p.wickUpColor:p.wickDownColor)??c.get(g.time)??(b?h.up:h.down)});return}let m=u==="full",f=this.candleStructureAlpha>this.candleBodyAlpha+.001;for(let g=o;g<=i;g+=1){let b=n[g];if(!b||b.high<=b.low)continue;let y=Bc(s.logicalToX(g),d,s.dpr,this.candleBodyScale),w=y.center,C=b.close>=b.open,M=C?h.up:h.down,L=c.get(b.time)??M,v=0,k=0;if(m){let x=s.priceToY(b.open,a.scale,a.bounds),E=s.priceToY(b.close,a.scale,a.bounds);v=un(Math.min(x,E),s.dpr),k=Math.max(1/s.dpr,un(Math.max(x,E),s.dpr)-v);}if(p.wickVisible){let x=(C?p.wickUpColor:p.wickDownColor)??(m?M:L),E=un(s.priceToY(b.high,a.scale,a.bounds),s.dpr),I=un(s.priceToY(b.low,a.scale,a.bounds),s.dpr);e.globalAlpha=this.candleStructureAlpha,e.strokeStyle=x,e.lineWidth=y.wickW,e.beginPath(),m?(e.moveTo(w,E),e.lineTo(w,v),e.moveTo(w,v+k),e.lineTo(w,I)):(e.moveTo(w,E),e.lineTo(w,I)),e.stroke();}if(m&&(p.bodyVisible&&(e.globalAlpha=this.candleBodyAlpha,e.fillStyle=L,e.fillRect(y.bodyX,v,y.bodyW,k)),p.borderVisible||f&&p.bodyVisible)){e.globalAlpha=this.candleStructureAlpha,e.strokeStyle=p.borderVisible?(C?p.borderUpColor:p.borderDownColor)??L:L,e.lineWidth=1;let x=Math.max(0,y.bodyW-1),E=Math.max(0,k-1);e.strokeRect(y.bodyX+.5,v+.5,x,E);}}}drawCandlesAggregated(e,t,n,o,i,s,a){let l=c=>i.priceToY(c,s.scale,s.bounds);e.lineWidth=1;for(let c of _c(t,n,o,d=>i.logicalToX(d),l,a)){let d=c.x+.5;e.strokeStyle=c.color,e.beginPath(),e.moveTo(d,l(c.hi)),e.lineTo(d,l(c.lo)),e.stroke();}}drawSeries(e,t,n,o,i,s,a,l=0){if(Rt(t,"pane")){if(t.kind==="candle"||t.kind==="bar"){this.drawPlotCandles(e,t,n,o,i,s,a,l);return}if(Ge(t))switch(t.kind){case "histogram":case "columns":this.drawHistogram(e,t,n,o,i,s,l);break;case "area":this.drawArea(e,t,n,o,i,s,l),this.drawPolyline(e,t,n,o,i,s,false,l);break;case "circles":case "cross":this.drawPointMarkers(e,t,n,o,i,s,l);break;case "step":this.drawPolyline(e,t,n,o,i,s,true,l);break;default:this.drawPolyline(e,t,n,o,i,s,false,l);}}}drawPolyline(e,t,n,o,i,s,a,l=0){e.lineWidth=Math.max(1,t.style.width),e.lineJoin="round",Xo(e,t.style.lineStyle);let c=0,d=0,u=false;for(let h=Math.max(1,i-1);h<=s;h+=1){let p=t.points[h-l],m=t.points[h-1-l];if(!p||p.value===null||!m||m.value===null){u=false;continue}let f=o.logicalToX(h),g=o.priceToY(p.value,n.scale,n.bounds);u||(c=o.logicalToX(h-1),d=o.priceToY(m.value,n.scale,n.bounds)),e.strokeStyle=p.color??t.style.color,e.beginPath(),e.moveTo(c,d),a&&e.lineTo(f,d),e.lineTo(f,g),e.stroke(),c=f,d=g,u=true;}Xo(e,"solid");}drawArea(e,t,n,o,i,s,a=0){let l=n.bounds.top+n.bounds.height,c=[],d=1/0,u=()=>{if(c.length===0)return;let h=e.createLinearGradient(0,d,0,l);h.addColorStop(0,t.style.color),h.addColorStop(1,"rgba(0,0,0,0)"),e.fillStyle=h,e.beginPath(),e.moveTo(c[0].x,l);for(let p of c)e.lineTo(p.x,p.y);e.lineTo(c[c.length-1].x,l),e.closePath(),e.fill(),c=[],d=1/0;};for(let h=i;h<=s;h+=1){let p=t.points[h-a];if(!p||p.value===null){u();continue}let m=o.logicalToX(h),f=o.priceToY(p.value,n.scale,n.bounds);c.push({x:m,y:f}),f=g.open?d:u),w=Math.round(o.logicalToX(f))+.5,C=o.priceToY(g.high,n.scale,n.bounds),M=o.priceToY(g.low,n.scale,n.bounds),S=o.priceToY(g.open,n.scale,n.bounds),L=o.priceToY(g.close,n.scale,n.bounds);if(h){e.strokeStyle=y,e.lineWidth=1,e.beginPath(),e.moveTo(w,C),e.lineTo(w,M),e.moveTo(w-m,S),e.lineTo(w,S),e.moveTo(w,L),e.lineTo(w+m,L),e.stroke();continue}e.strokeStyle=b?.wickColor??y,e.lineWidth=Ms(c),e.beginPath(),e.moveTo(w,C),e.lineTo(w,M),e.stroke(),e.fillStyle=y,e.fillRect(w-p,Math.min(S,L),p*2,Math.max(1,Math.abs(L-S))),b?.borderColor&&(e.strokeStyle=b.borderColor,e.strokeRect(w-p,Math.min(S,L),p*2,Math.max(1,Math.abs(L-S))));}}drawFill(e,t,n,o,i,s,a,l=0){let c=Yw(t,n.fromSeriesId),d=Yw(t,n.toSeriesId);if(!c||!d)return;let u=NaN,h=NaN,p="",m="",f=null;for(let g=Math.max(1,s);g<=a;g+=1){let b=c[g-1-l],y=d[g-1-l],w=c[g-l],C=d[g-l];if(!b||!y||!w||!C||b.value===null||y.value===null||w.value===null||C.value===null)continue;let M=i.logicalToX(g-1),S=i.logicalToX(g),L=i.priceToY(b.value,o.scale,o.bounds),v=i.priceToY(y.value,o.scale,o.bounds),k=i.priceToY(w.value,o.scale,o.bounds),x=i.priceToY(C.value,o.scale,o.bounds),E=n.gradient?.[g-1-l];if(E){let I=i.priceToY(E.topValue,o.scale,o.bounds),N=i.priceToY(E.bottomValue,o.scale,o.bounds),V=N===I?I+1:N;(!f||I!==u||V!==h||E.topColor!==p||E.bottomColor!==m)&&(f=e.createLinearGradient(0,I,0,V),f.addColorStop(0,E.topColor),f.addColorStop(1,E.bottomColor),u=I,h=V,p=E.topColor,m=E.bottomColor),e.fillStyle=f;}else {let I=n.colors?n.colors[g-1-l]:n.color;if(!I)continue;e.fillStyle=I;}e.beginPath(),e.moveTo(M,L),e.lineTo(S,k),e.lineTo(S,x),e.lineTo(M,v),e.closePath(),e.fill();}}drawBackground(e,t,n,o){let i=o.timeToX(t.from),s=o.timeToX(t.to);s<0||i>o.width||s<=i||(e.fillStyle=t.color,e.fillRect(i,n.bounds.top,s-i,n.bounds.height));}drawHline(e,t,n,o,i,s){let a=Math.round(o.priceToY(t.price,n.scale,n.bounds))+.5;an.bounds.top+n.bounds.height||(e.strokeStyle=t.color??s.textColor,e.lineWidth=t.width??1,Xo(e,t.lineStyle??"solid"),e.beginPath(),e.moveTo(0,a),e.lineTo(i,a),e.stroke(),Xo(e,"solid"));}};function Xo(r,e){e==="dashed"?r.setLineDash([6,4]):e==="dotted"?r.setLineDash([2,3]):r.setLineDash([]);}function Yw(r,e){let t=r.series.find(n=>n.id===e);return t&&Ge(t)?t.points:null}var SP=new Map;function TP(r){let e=false;for(let n of r.values())if(n.barColors&&n.barColors.length>0){e=true;break}if(!e)return SP;let t=new Map;for(let n of r.values())if(n.barColors)for(let o of n.barColors)t.set(o.time,o.color);return t}function nr(r,e){let t=Math.max(1,e);return r==="dotted"?[t,t*2]:r==="dashed"?[t*4,t*3]:[]}function jo(r,e,t,n,o,i,s){if(o==="none")return [r,e,t,n];let a=t-r,l=o==="left"||o==="both",c=o==="right"||o==="both";if(Math.abs(a)<1e-6){if(l&&c)return [r,0,t,s];let m=n>=e;return c?m?[r,e,t,s]:[r,e,t,0]:m?[r,0,t,n]:[r,s,t,n]}let d=(n-e)/a,u=m=>e+d*(m-r),h=l?-2:Math.min(r,t),p=c?i+2:Math.max(r,t);return [h,u(h),p,u(p)]}function Kw(r,e,t,n){let o=Math.atan2(n-e,t-r);return o>Math.PI/2&&(o-=Math.PI),o<-Math.PI/2&&(o+=Math.PI),o}function kP(r){let e=r.trim(),t=/^#([0-9a-f]{3})$/i.exec(e);if(t){let n=t[1];return {r:parseInt(n[0]+n[0],16),g:parseInt(n[1]+n[1],16),b:parseInt(n[2]+n[2],16),a:1}}if(t=/^#([0-9a-f]{6})([0-9a-f]{2})?$/i.exec(e),t){let n=t[1];return {r:parseInt(n.slice(0,2),16),g:parseInt(n.slice(2,4),16),b:parseInt(n.slice(4,6),16),a:t[2]?parseInt(t[2],16)/255:1}}if(t=/^rgba?\(([^)]+)\)$/i.exec(e),t){let n=t[1].split(",").map(o=>parseFloat(o.trim()));return {r:n[0]??0,g:n[1]??0,b:n[2]??0,a:n[3]??1}}return null}function LP(r,e,t){return (.299*r+.587*e+.114*t)/255}function Ye(r){if(!r)return "#000000";let e=kP(r);return e?LP(e.r,e.g,e.b)>.55?"#000000":"#ffffff":"#000000"}function pn(r){return Math.round(r*1.4)}var Gr=5,$r=3;function Ke(r){switch(r){case "tiny":return 10;case "small":return 12;case "large":return 18;case "huge":return 28;case "normal":return 14;default:return 0}}function Xw(r,e,t,n){let o=1;for(let l of r)l.length>o&&(o=l.length);let i=n?.62:.55,s=e*.9/(o*i),a=t*.85/(r.length*1.3);return Math.max(6,Math.min(s,a,48))}var MP={lines:[],boxes:[],labels:[],polylines:[],linefills:[]};function Zo(r,e){let t=n=>!!n.overlay===e;return {lines:(r.lines??[]).filter(t),boxes:(r.boxes??[]).filter(t),labels:(r.labels??[]).filter(t),polylines:(r.polylines??[]).filter(t),linefills:(r.linefills??[]).filter(t)}}function Xh(r){return !r.lines.length&&!r.boxes.length&&!r.labels.length&&!r.polylines.length&&!r.linefills.length}function jw(r){return r==="auto"?12:Ke(r)}function EP(r,e,t,n,o){let i=Math.min(r,e),s=Math.max(r,e);return r===e?r>=n&&r<=o:t==="both"?true:t==="left"?s>=n:(t==="right"||s>=n)&&i<=o}var qo=class{constructor(e,t=MP){this.deps=e;this.set=t;this.widthCache=new Map;this.tipRegions=[];this.indexOffset=0;}setSet(e,t=0){this.set=e,this.indexOffset=t;}setDeps(e){this.deps=e;}isEmpty(){let e=this.set;return !e.lines.length&&!e.boxes.length&&!e.labels.length&&!e.polylines.length&&!e.linefills.length}labelTipRegions(){return this.tipRegions}render(e,t,n,o,i){this.tipRegions=[],!this.isEmpty()&&(e.save(),this.drawLinefills(e,t,n,o,i),this.drawBoxes(e,t,n,o,i),this.drawPolylines(e,t,o,i),this.drawLines(e,t,n,o,i),this.drawLabels(e,t,n,o,i),e.restore());}priceRange(e,t){let n=Math.min(e,t),o=Math.max(e,t),i=(u,h,p)=>p==="both"?true:p==="left"?Math.max(u,h)>=n:(p==="right"||Math.max(u,h)>=n)&&Math.min(u,h)<=o,s=1/0,a=-1/0,l=u=>{ua&&(a=u);};for(let u of this.set.lines)u.invisible||EP(this.logicalOf(u.xloc,u.x1),this.logicalOf(u.xloc,u.x2),u.extend,n,o)&&(l(u.y1),l(u.y2));for(let u of this.set.boxes)!u.bgColor&&!(u.borderColor&&u.borderWidth>0)&&!u.text||i(this.logicalOf(u.xloc,u.left),this.logicalOf(u.xloc,u.right),u.extend)&&(l(u.top),l(u.bottom));for(let u of this.set.linefills){if(!u.color)continue;let h=[u.line1.x1,u.line1.x2,u.line2.x1,u.line2.x2].map((m,f)=>this.logicalOf(f<2?u.line1.xloc:u.line2.xloc,m)),p=u.line1.extend!=="none"||u.line2.extend!=="none"?"both":"none";i(Math.min(...h),Math.max(...h),p)&&(l(u.line1.y1),l(u.line1.y2),l(u.line2.y1),l(u.line2.y2));}for(let u of this.set.polylines){if(u.points.length<2)continue;let h=u.points.map(p=>this.logicalOf(p.xloc,p.x));if(i(Math.min(...h),Math.max(...h),"none"))for(let p of u.points)l(p.price);}let c=0,d=0;for(let u of this.set.labels){let h=this.logicalOf(u.xloc,u.x);if(!i(h,h,"none"))continue;if(u.yloc==="price"){l(u.y);continue}if(u.yloc==="top"||u.yloc==="bottom")continue;let p=this.deps.barAt(h);if(!p)continue;l(u.yloc==="abovebar"?p.high:p.low);let m=jw(u.size),f=Math.max(1,(u.text??"").split(` -`).length),g=this.isPointShape(u.style)?14+Math.max(4,m*.6)+2:14+m*1.25*f+8+7;u.yloc==="abovebar"?c=Math.max(c,g):d=Math.max(d,g);}return !Number.isFinite(s)||!Number.isFinite(a)?null:{min:s,max:a,aboveMargin:c,belowMargin:d}}logicalOf(e,t){return e==="bar_time"?this.deps.timeToLogical(t):t+this.indexOffset}drawLines(e,t,n,o,i){for(let s of this.set.lines){if(s.invisible)continue;let a=o(this.logicalOf(s.xloc,s.x1)),l=o(this.logicalOf(s.xloc,s.x2)),c=i(s.y1),d=i(s.y2);if(c===null||d===null)continue;let u=s.extend==="left"||s.extend==="both",h=s.extend==="right"||s.extend==="both";if(!u&&!h&&(Math.max(a,l)<0||Math.min(a,l)>t))continue;let[p,m,f,g]=jo(a,c,l,d,s.extend,t,n),b=s.color??this.deps.theme.textColor;e.beginPath(),e.moveTo(p,m),e.lineTo(f,g),e.strokeStyle=b,e.lineWidth=s.width,e.setLineDash(nr(s.style,s.width)),e.stroke(),e.setLineDash([]);let y=l>=a;if(s.arrowRight){let w=(y?h:u)?y?[f,g]:[p,m]:[l,d];this.drawArrow(e,w[0],w[1],a,c,s.width,b);}if(s.arrowLeft){let w=(y?u:h)?y?[p,m]:[f,g]:[a,c];this.drawArrow(e,w[0],w[1],l,d,s.width,b);}}}drawArrow(e,t,n,o,i,s,a){let l=Math.atan2(n-i,t-o),c=6+s*2,d=.45;e.beginPath(),e.moveTo(t,n),e.lineTo(t-c*Math.cos(l-d),n-c*Math.sin(l-d)),e.lineTo(t-c*Math.cos(l+d),n-c*Math.sin(l+d)),e.closePath(),e.fillStyle=a,e.fill();}drawLinefills(e,t,n,o,i){for(let s of this.set.linefills){if(!s.color)continue;let a=this.resolveLine(s.line1,t,n,o,i),l=this.resolveLine(s.line2,t,n,o,i);if(!a||!l)continue;let c=h=>h[0]>h[2]||h[0]===h[2]&&h[1]>h[3]?[h[2],h[3],h[0],h[1]]:h,d=c(a),u=c(l);e.beginPath(),e.moveTo(d[0],d[1]),e.lineTo(d[2],d[3]),e.lineTo(u[2],u[3]),e.lineTo(u[0],u[1]),e.closePath(),e.fillStyle=s.color,e.fill();}}resolveLine(e,t,n,o,i){let s=o(this.logicalOf(e.xloc,e.x1)),a=o(this.logicalOf(e.xloc,e.x2)),l=i(e.y1),c=i(e.y2);return l===null||c===null?null:jo(s,l,a,c,e.extend,t,n)}drawPolylines(e,t,n,o){for(let i of this.set.polylines){let s=[];for(let c of i.points){let d=o(c.price);d!==null&&s.push([n(this.logicalOf(c.xloc,c.x)),d]);}if(s.length<2)continue;let a=1/0,l=-1/0;for(let c of s)c[0]l&&(l=c[0]);if(!(l<0||a>t)){if(e.beginPath(),i.curved)this.curvedPath(e,s,i.closed);else {e.moveTo(s[0][0],s[0][1]);for(let c=1;cn?t[(a%o+o)%o]:t[Math.max(0,Math.min(o-1,a))];e.moveTo(t[0][0],t[0][1]);let s=n?o:o-1;for(let a=0;at||m<0||p>n||(s.bgColor&&(e.fillStyle=s.bgColor,e.fillRect(u,p,f,g)),s.borderColor&&s.borderWidth>0&&(e.strokeStyle=s.borderColor,e.lineWidth=s.borderWidth,e.setLineDash(nr(s.borderStyle,s.borderWidth)),e.strokeRect(u,p,f,g),e.setLineDash([])),s.text&&this.drawBoxText(e,s,u,p,f,g));}}measure(e,t,n){let o=`${t} ${n}`,i=this.widthCache.get(o);return i===void 0&&(e.font=t,i=e.measureText(n).width,this.widthCache.set(o,i)),i}wrapText(e,t,n,o){let i=[];for(let s of n.split(` +}`,Gh={solid:null,dashed:[6,4],dotted:[2,3]};function Aw(r){return Math.max(6,Math.min(20,Math.round(r*4)))}var Kc=class{constructor(){this.kind="webgl2";this.modelAlpha=1;this.candleBodyAlpha=1;this.candleStructureAlpha=1;this.candleBodyScale=1;this.onNeedsRedraw=null;this.onContextFailed=null;this.glow=0;this.canvas=null;this.gl=null;this.program=null;this.vao=null;this.vbo=null;this.uRes=null;this.batch=new Rs;this.contextLost=false;this.screenProgram=null;this.uTex=null;this.uDir=null;this.uIntensity=null;this.quadVao=null;this.quadVbo=null;this.fboA=null;this.texA=null;this.fboB=null;this.texB=null;this.fboW=0;this.fboH=0;this.glowBatch=new Rs;this.sliceTex=new Map;this.onLost=e=>{e.preventDefault(),this.contextLost=true;};this.onRestored=()=>{this.contextLost=false,this.initGL()?this.onNeedsRedraw?.():this.onContextFailed?.();};}get ok(){return this.gl!==null}mount(e){if(this.canvas=e,this.gl=e.getContext("webgl2",{alpha:true,antialias:false,depth:false,stencil:false,premultipliedAlpha:true}),!!this.gl){if(!this.initGL()){this.gl=null;return}e.addEventListener("webglcontextlost",this.onLost,false),e.addEventListener("webglcontextrestored",this.onRestored,false);}}initGL(){let e=this.gl;if(!e)return false;this.screenProgram=null,this.quadVao=null,this.quadVbo=null,this.fboA=this.fboB=null,this.texA=this.texB=null,this.fboW=this.fboH=0,this.sliceTex.clear();let t=Uc(e,e.VERTEX_SHADER,oP),n=Uc(e,e.FRAGMENT_SHADER,iP),o=e.createProgram();if(!t||!n||!o)return t&&e.deleteShader(t),n&&e.deleteShader(n),o&&e.deleteProgram(o),false;if(e.attachShader(o,t),e.attachShader(o,n),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS))return e.deleteProgram(o),e.deleteShader(t),e.deleteShader(n),false;e.deleteShader(t),e.deleteShader(n),this.program=o,this.uRes=e.getUniformLocation(o,"uRes"),this.vbo=e.createBuffer(),this.vao=e.createVertexArray(),e.bindVertexArray(this.vao),e.bindBuffer(e.ARRAY_BUFFER,this.vbo);let i=32;return e.enableVertexAttribArray(0),e.vertexAttribPointer(0,2,e.FLOAT,false,i,0),e.enableVertexAttribArray(1),e.vertexAttribPointer(1,4,e.FLOAT,false,i,8),e.enableVertexAttribArray(2),e.vertexAttribPointer(2,2,e.FLOAT,false,i,24),e.bindVertexArray(null),this.glow>0&&!this.ensureScreenPipeline()&&(this.glow=0),true}ensureScreenPipeline(){if(this.screenProgram&&this.quadVao)return true;let e=this.gl;if(!e)return false;let t=Uc(e,e.VERTEX_SHADER,sP),n=Uc(e,e.FRAGMENT_SHADER,aP),o=e.createProgram();return !t||!n||!o?(t&&e.deleteShader(t),n&&e.deleteShader(n),o&&e.deleteProgram(o),false):(e.attachShader(o,t),e.attachShader(o,n),e.linkProgram(o),e.getProgramParameter(o,e.LINK_STATUS)?(e.deleteShader(t),e.deleteShader(n),this.screenProgram=o,this.uTex=e.getUniformLocation(o,"uTex"),this.uDir=e.getUniformLocation(o,"uDir"),this.uIntensity=e.getUniformLocation(o,"uIntensity"),this.quadVbo=e.createBuffer(),this.quadVao=e.createVertexArray(),e.bindVertexArray(this.quadVao),e.bindBuffer(e.ARRAY_BUFFER,this.quadVbo),e.bufferData(e.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,-1,1,1,1]),e.STATIC_DRAW),e.enableVertexAttribArray(0),e.vertexAttribPointer(0,2,e.FLOAT,false,0,0),e.bindVertexArray(null),true):(e.deleteProgram(o),false))}ensureFbos(e,t,n){if(this.fboA&&this.fboW===t&&this.fboH===n)return true;this.deleteFbos(e);let o=()=>{let a=e.createTexture();e.bindTexture(e.TEXTURE_2D,a),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,t,n,0,e.RGBA,e.UNSIGNED_BYTE,null),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE);let l=e.createFramebuffer();return e.bindFramebuffer(e.FRAMEBUFFER,l),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,a,0),{tex:a,fbo:l}},i=o(),s=o();return e.bindFramebuffer(e.FRAMEBUFFER,null),this.texA=i.tex,this.fboA=i.fbo,this.texB=s.tex,this.fboB=s.fbo,this.fboW=t,this.fboH=n,!!(this.fboA&&this.fboB)}deleteFbos(e){this.fboA&&e.deleteFramebuffer(this.fboA),this.fboB&&e.deleteFramebuffer(this.fboB),this.texA&&e.deleteTexture(this.texA),this.texB&&e.deleteTexture(this.texB),this.fboA=this.fboB=null,this.texA=this.texB=null,this.fboW=this.fboH=0;}render(e,t,n){let o=this.gl,i=this.canvas;if(!o||!i||!this.program||this.contextLost||o.isContextLost())return;let s=t.dpr,a=t.width;o.viewport(0,0,i.width,i.height),o.disable(o.SCISSOR_TEST),o.clearColor(0,0,0,0),o.clear(o.COLOR_BUFFER_BIT);let l=t.barCount;if(l===0)return;let c=t.visibleLogicalRange(),d=Math.max(0,Math.floor(c.from)),u=Math.min(l-1,Math.ceil(c.to));if(u{g.vertexCount!==0&&(o.blendFuncSeparate(o.SRC_ALPHA,o.ONE_MINUS_SRC_ALPHA,o.ONE,o.ONE_MINUS_SRC_ALPHA),o.useProgram(this.program),o.bindVertexArray(this.vao),o.uniform2f(this.uRes,i.width/s,i.height/s),o.bindBuffer(o.ARRAY_BUFFER,this.vbo),o.bufferData(o.ARRAY_BUFFER,g.view,o.DYNAMIC_DRAW),o.drawArrays(o.TRIANGLES,0,g.vertexCount),g.reset());},S=f.collapsed?[]:e.drawingSlices.get(f.id)??[],M=0,C=L=>{for(;M{let N=e.scaleFor(I,f);return N===f.scale?f:{...f,scale:N}};g.alpha=this.modelAlpha;for(let I of L)for(let N of I.backgrounds)N.overlay!==true&&this.emitBackground(g,N,f,t);if(v)for(let I of e.indicators.values())for(let N of I.backgrounds)N.overlay===true&&this.emitBackground(g,N,f,t);let x=v&&!e.candlesHidden,E=false;for(let I of L){x&&!E&&e.zOf(I.id)>=e.candleZ&&(C(e.candleZ),g.alpha=this.candleStructureAlpha,this.emitPriceSeries(g,e,d,u,t,f,n,h,a),E=true),C(e.zOf(I.id)),g.alpha=this.modelAlpha;let N=e.offsetOf(I.id),V=k(I);for(let Z of I.fills)Z.overlay!==true&&this.emitFill(g,I,Z,V,t,d,u,N);for(let Z of I.series)Z.overlay!==true&&this.emitSeries(g,Z,V,t,d,u,n,N);}if(x&&!E&&(C(e.candleZ),g.alpha=this.candleStructureAlpha,this.emitPriceSeries(g,e,d,u,t,f,n,h,a)),g.alpha=this.modelAlpha,v){for(let I of e.indicators.values()){let N=e.offsetOf(I.id);for(let V of I.fills)V.overlay===true&&this.emitFill(g,I,V,f,t,d,u,N);}for(let I of e.indicators.values()){let N=e.offsetOf(I.id);for(let V of I.series)V.overlay===true&&this.emitSeries(g,V,f,t,d,u,n,N);}}C(1/0);for(let I of L){let N=k(I);for(let V of I.priceLines)this.emitHline(g,V,N,t,a,n);}g.alpha=1;}w();}o.disable(o.SCISSOR_TEST);for(let[f,g]of this.sliceTex)m.has(f)||(o.deleteTexture(g),this.sliceTex.delete(f));this.glow>0&&!this.screenProgram&&!this.ensureScreenPipeline()&&(this.glow=0),this.glow>0&&this.screenProgram&&(this.glowBatch.alpha=this.modelAlpha,this.renderGlow(o,e,t,d,u));}renderGlow(e,t,n,o,i){let s=this.canvas,a=Math.max(1,s.width>>1),l=Math.max(1,s.height>>1);if(!this.ensureFbos(e,a,l))return;let c=n.dpr,d=n.width;e.bindFramebuffer(e.FRAMEBUFFER,this.fboA),e.viewport(0,0,a,l),e.disable(e.SCISSOR_TEST),e.clearColor(0,0,0,0),e.clear(e.COLOR_BUFFER_BIT),e.enable(e.BLEND),e.blendFuncSeparate(e.SRC_ALPHA,e.ONE_MINUS_SRC_ALPHA,e.ONE,e.ONE_MINUS_SRC_ALPHA),e.useProgram(this.program),e.bindVertexArray(this.vao),e.uniform2f(this.uRes,s.width/c,s.height/c),e.enable(e.SCISSOR_TEST);for(let u of t.orderedPanes()){let h=this.glowBatch;if(h.reset(),this.emitGlowSources(h,t,u,n,o,i),h.vertexCount===0)continue;let p=Math.round(u.bounds.top*c*.5),m=Math.round((u.bounds.top+u.bounds.height)*c*.5);e.scissor(0,l-m,Math.round(d*c*.5),m-p),e.bindBuffer(e.ARRAY_BUFFER,this.vbo),e.bufferData(e.ARRAY_BUFFER,h.view,e.DYNAMIC_DRAW),e.drawArrays(e.TRIANGLES,0,h.vertexCount);}e.disable(e.SCISSOR_TEST),e.useProgram(this.screenProgram),e.bindVertexArray(this.quadVao),e.uniform1i(this.uTex,0),e.uniform1f(this.uIntensity,1),e.activeTexture(e.TEXTURE0),e.disable(e.BLEND),e.bindFramebuffer(e.FRAMEBUFFER,this.fboB),e.bindTexture(e.TEXTURE_2D,this.texA),e.uniform2f(this.uDir,1/a,0),e.drawArrays(e.TRIANGLE_STRIP,0,4),e.bindFramebuffer(e.FRAMEBUFFER,this.fboA),e.bindTexture(e.TEXTURE_2D,this.texB),e.uniform2f(this.uDir,0,1/l),e.drawArrays(e.TRIANGLE_STRIP,0,4),e.bindFramebuffer(e.FRAMEBUFFER,null),e.viewport(0,0,s.width,s.height),e.enable(e.BLEND),e.blendFunc(e.ONE,e.ONE),e.bindTexture(e.TEXTURE_2D,this.texA),e.uniform2f(this.uDir,0,0),e.uniform1f(this.uIntensity,this.glow),e.drawArrays(e.TRIANGLE_STRIP,0,4),e.bindTexture(e.TEXTURE_2D,null),e.bindVertexArray(null);}drawSliceTexture(e,t){if(!this.ensureScreenPipeline()||!this.screenProgram)return false;let n=this.sliceTex.get(t)??null;if(!n){if(n=e.createTexture(),!n)return false;this.sliceTex.set(t,n),e.bindTexture(e.TEXTURE_2D,n),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE);}return e.activeTexture(e.TEXTURE0),e.bindTexture(e.TEXTURE_2D,n),e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,true),e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,true),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,t),e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,false),e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,false),e.useProgram(this.screenProgram),e.bindVertexArray(this.quadVao),e.uniform1i(this.uTex,0),e.uniform2f(this.uDir,0,0),e.uniform1f(this.uIntensity,1),e.blendFuncSeparate(e.ONE,e.ONE_MINUS_SRC_ALPHA,e.ONE,e.ONE_MINUS_SRC_ALPHA),e.drawArrays(e.TRIANGLE_STRIP,0,4),e.bindVertexArray(null),true}emitGlowSources(e,t,n,o,i,s){let a=(l,c)=>{!$e(l)||!Rt(l,"pane")||l.kind==="histogram"||l.kind==="columns"||(l.kind==="circles"||l.kind==="cross"?this.emitPointMarkers(e,l,n,o,i,s,c):this.emitPolyline(e,l,n,o,i,s,l.kind==="step",c));};for(let l of t.indicatorsForPane(n.id)){let c=t.offsetOf(l.id);for(let d of l.series)d.overlay!==true&&a(d,c);}if(n.kind==="price")for(let l of t.indicators.values()){let c=t.offsetOf(l.id);for(let d of l.series)d.overlay===true&&a(d,c);}}destroy(){let e=this.gl;if(this.canvas&&(this.canvas.removeEventListener("webglcontextlost",this.onLost),this.canvas.removeEventListener("webglcontextrestored",this.onRestored)),e){this.program&&e.deleteProgram(this.program),this.vbo&&e.deleteBuffer(this.vbo),this.vao&&e.deleteVertexArray(this.vao),this.screenProgram&&e.deleteProgram(this.screenProgram),this.quadVbo&&e.deleteBuffer(this.quadVbo),this.quadVao&&e.deleteVertexArray(this.quadVao);for(let t of this.sliceTex.values())e.deleteTexture(t);this.sliceTex.clear(),this.deleteFbos(e),e.getExtension("WEBGL_lose_context")?.loseContext();}this.gl=null,this.canvas=null,this.program=null,this.vao=null,this.vbo=null,this.screenProgram=null;}emitBackground(e,t,n,o){let i=o.timeToX(t.from),s=o.timeToX(t.to);s<0||i>o.width||s<=i||e.rect(i,n.bounds.top,s-i,n.bounds.height,se(t.color));}emitFill(e,t,n,o,i,s,a,l=0){let c=Dw(t,n.fromSeriesId),d=Dw(t,n.toSeriesId);if(!(!c||!d))for(let u=Math.max(1,s);u<=a;u+=1){let h=c[u-1-l],p=d[u-1-l],m=c[u-l],f=d[u-l];if(!h||!p||!m||!f||h.value===null||p.value===null||m.value===null||f.value===null)continue;let g=i.logicalToX(u-1),b=i.logicalToX(u),y=i.priceToY(h.value,o.scale,o.bounds),w=i.priceToY(p.value,o.scale,o.bounds),S=i.priceToY(m.value,o.scale,o.bounds),M=i.priceToY(f.value,o.scale,o.bounds),C=n.gradient?.[u-1-l];if(C){let L=i.priceToY(C.topValue,o.scale,o.bounds),v=i.priceToY(C.bottomValue,o.scale,o.bounds),k=v===L?L+1:v,x=se(C.topColor),E=se(C.bottomColor),I=k-L,N=V=>$h(x,E,Yc((V-L)/I));e.quad4(g,y,N(y),b,S,N(S),b,M,N(M),g,w,N(w));}else {let L=n.colors?n.colors[u-1-l]:n.color;if(!L)continue;e.quad(g,y,b,S,b,M,g,w,se(L));}}}emitPriceSeries(e,t,n,o,i,s,a,l,c){if(t.basePainting==="none")return;let d=t.bars,u=t.style;switch(t.priceStyle){case "bars":this.emitBars(e,d,n,o,i,s,u.bars.upColor??a.upColor,u.bars.downColor??a.downColor,l);return;case "line":this.emitPriceLine(e,d,n,o,i,s,se(u.line.color??a.upColor),u.line.width);return;case "area":{let h=u.area.lineColor??a.upColor;this.emitPriceArea(e,d,n,o,i,s,se(u.area.topColor??h),se(u.area.bottomColor??"rgba(0,0,0,0)")),this.emitPriceLine(e,d,n,o,i,s,se(h),u.area.width);return}case "baseline":this.emitBaseline(e,d,n,o,i,s,t,a,c);return;default:this.emitCandles(e,t,d,n,o,i,s,a,l);}}emitBars(e,t,n,o,i,s,a,l,c){let d=i.bodySpacing(),u=Go(d);if(u==="aggregate"){this.emitCandlesAggregated(e,t,n,o,i,s,m=>c.get(m.time)??(m.close>=m.open?a:l));return}let h=Math.max(1,Math.round(d*.35)),p=u==="full";for(let m=n;m<=o;m+=1){let f=t[m];if(!f||f.high<=f.low)continue;let g=se(c.get(f.time)??(f.close>=f.open?a:l)),b=Math.round(i.logicalToX(m)),y=i.priceToY(f.high,s.scale,s.bounds),w=i.priceToY(f.low,s.scale,s.bounds);if(e.rect(b-.5,y,1,w-y,g),p){let S=i.priceToY(f.open,s.scale,s.bounds),M=i.priceToY(f.close,s.scale,s.bounds);e.rect(b-h,S-.5,h,1,g),e.rect(b,M-.5,h,1,g);}}}emitPriceLine(e,t,n,o,i,s,a,l){let c=Math.max(1,l)/2,d=Aw(c),u=false,h=0,p=0;for(let m=Math.max(0,n-1);m<=o;m+=1){let f=t[m];if(!f){u=false;continue}let g=i.logicalToX(m),b=i.priceToY(f.close,s.scale,s.bounds);u&&e.seg(h,p,g,b,l,a),e.circle(g,b,c,a,d),h=g,p=b,u=true;}}emitPriceArea(e,t,n,o,i,s,a,l){let c=s.bounds.top+s.bounds.height,d=[],u=1/0,h=()=>{if(d.length>=2){let p=c-u,m=f=>$h(a,l,p<1e-6?0:Yc((f-u)/p));for(let f=1;fx<=u?y:S,k=x=>{let E=x<=u,I=E?u-C:L-u,N=I>0?Yc(Math.abs(x-u)/I):0;return $h(E?y:S,E?b:w,N)};for(let x=1;x{let w=y.close>=y.open;return (w?f.wickUpColor:f.wickDownColor)??c.get(y.time)??(w?p:m)});return}let g=u==="full",b=this.candleStructureAlpha>this.candleBodyAlpha+.001;for(let y=o;y<=i;y+=1){let w=n[y];if(!w||w.high<=w.low)continue;let S=Wc(s.logicalToX(y),d,s.dpr,this.candleBodyScale),M=w.close>=w.open,C=M?p:m,v=c.get(w.time)??C,k=se(v),x=0,E=0;if(g){let I=s.priceToY(w.open,a.scale,a.bounds),N=s.priceToY(w.close,a.scale,a.bounds);x=hn(Math.min(I,N),s.dpr),E=Math.max(1/s.dpr,hn(Math.max(I,N),s.dpr)-x);}if(f.wickVisible){let I=hn(s.priceToY(w.high,a.scale,a.bounds),s.dpr),N=hn(s.priceToY(w.low,a.scale,a.bounds),s.dpr);e.alpha=this.candleStructureAlpha;let V=se((M?f.wickUpColor:f.wickDownColor)??(g?C:v));g?(e.rect(S.wickX,I,S.wickW,Math.max(0,x-I),V),e.rect(S.wickX,x+E,S.wickW,Math.max(0,N-(x+E)),V)):e.rect(S.wickX,I,S.wickW,N-I,V);}if(g&&(f.bodyVisible&&(e.alpha=this.candleBodyAlpha,e.rect(S.bodyX,x,S.bodyW,E,k)),f.borderVisible||b&&f.bodyVisible)){e.alpha=this.candleStructureAlpha;let I=f.borderVisible?se((M?f.borderUpColor:f.borderDownColor)??v):k,N=Math.max(0,S.bodyW-1),V=Math.max(0,E-1);e.rectStroke(S.bodyX+.5,x+.5,N,V,1,I);}}}emitCandlesAggregated(e,t,n,o,i,s,a){let l=c=>i.priceToY(c,s.scale,s.bounds);for(let c of Gc(t,n,o,d=>i.logicalToX(d),l,a)){let d=se(c.color),u=l(c.hi);e.rect(c.x-.5,u,1,l(c.lo)-u,d);}}emitSeries(e,t,n,o,i,s,a,l=0){if(Rt(t,"pane")){if(t.kind==="candle"||t.kind==="bar"){this.emitPlotCandles(e,t,n,o,i,s,a,l);return}if($e(t))switch(t.kind){case "histogram":case "columns":this.emitHistogram(e,t,n,o,i,s,l);break;case "area":this.emitArea(e,t,n,o,i,s,l),this.emitPolyline(e,t,n,o,i,s,false,l);break;case "circles":case "cross":this.emitPointMarkers(e,t,n,o,i,s,l);break;case "step":this.emitPolyline(e,t,n,o,i,s,true,l);break;default:this.emitPolyline(e,t,n,o,i,s,false,l);}}}emitPolyline(e,t,n,o,i,s,a,l=0){let c=Math.max(1,t.style.width),d=c/2,u=Gh[t.style.lineStyle]??null,h=!u&&!a,p=Aw(d),m=false;for(let f=Math.max(1,i-1);f<=s;f+=1){let g=t.points[f-l],b=t.points[f-1-l];if(!g||g.value===null||!b||b.value===null){m=false;continue}let y=o.logicalToX(f),w=o.priceToY(g.value,n.scale,n.bounds),S=o.logicalToX(f-1),M=o.priceToY(b.value,n.scale,n.bounds),C=se(g.color??t.style.color);a?(e.dashedSeg(S,M,y,M,c,C,u),e.dashedSeg(y,M,y,w,c,C,u)):e.dashedSeg(S,M,y,w,c,C,u),h&&(m||e.circle(S,M,d,se(b.color??t.style.color),p),e.circle(y,w,d,C,p)),m=true;}}emitArea(e,t,n,o,i,s,a=0){let l=n.bounds.top+n.bounds.height,c=se(t.style.color),d=[],u=1/0,h=()=>{if(d.length<1){d=[],u=1/0;return}let p=l-u,m=f=>lP(c,p<1e-6?0:Yc((f-u)/p));for(let f=1;f=g.open?d:u)),w=Math.round(o.logicalToX(f)),S=o.priceToY(g.high,n.scale,n.bounds),M=o.priceToY(g.low,n.scale,n.bounds),C=o.priceToY(g.open,n.scale,n.bounds),L=o.priceToY(g.close,n.scale,n.bounds);if(h){e.rect(w-.5,S,1,M-S,y),e.rect(w-m,C-.5,m,1,y),e.rect(w,L-.5,m,1,y);continue}let v=Math.max(1,Math.round(As(c)*o.dpr)),k=(Math.round(w*o.dpr)-(v>>1))/o.dpr;e.rect(k,S,v/o.dpr,M-S,se(b?.wickColor??b?.color??(g.close>=g.open?d:u)));let x=Math.min(C,L),E=Math.max(1,Math.abs(L-C));if(e.rect(w-p,x,p*2,E,y),b?.borderColor){let I=se(b.borderColor);e.rect(w-p,x,p*2,1,I),e.rect(w-p,x+E-1,p*2,1,I),e.rect(w-p,x,1,E,I),e.rect(w+p-1,x,1,E,I);}}}emitHline(e,t,n,o,i,s){let a=Math.round(o.priceToY(t.price,n.scale,n.bounds));an.bounds.top+n.bounds.height||e.dashedSeg(0,a,i,a,t.width??1,se(t.color??s.textColor),Gh[t.lineStyle??"solid"]??null);}};function Uc(r,e,t){let n=r.createShader(e);return n?(r.shaderSource(n,t),r.compileShader(n),r.getShaderParameter(n,r.COMPILE_STATUS)?n:(r.deleteShader(n),null)):null}var Rw=[0,0,0,0];function Yc(r){return r<0?0:r>1?1:r}function $h(r,e,t){return [r[0]+(e[0]-r[0])*t,r[1]+(e[1]-r[1])*t,r[2]+(e[2]-r[2])*t,r[3]+(e[3]-r[3])*t]}function lP(r,e){let t=1-e;return [r[0]*t,r[1]*t,r[2]*t,r[3]*t]}function Dw(r,e){let t=r.series.find(n=>n.id===e);return t&&$e(t)?t.points:null}var cP=new Map;function dP(r){let e=false;for(let n of r.values())if(n.barColors&&n.barColors.length>0){e=true;break}if(!e)return cP;let t=new Map;for(let n of r.values())if(n.barColors)for(let o of n.barColors)t.set(o.time,o.color);return t}function Xc(){return {barSpacing:8,rightOffset:6}}function pn(r){return Math.max(.5,Math.min(1e3,r))}function Uh(r){if(r.length<2)return 0;let e=[];for(let t=1;t0&&e.push(n);}return e.length===0?0:(e.sort((t,n)=>t-n),e[Math.floor(e.length/2)])}function Ow(r,e,t){let n=e.length;if(n===0)return 0;let o=e[0],i=e[n-1];if(r<=o)return t>0?(r-o)/t:0;if(r>=i)return n-1+(t>0?(r-i)/t:0);let s=0,a=n-1;for(;a-s>1;){let c=s+a>>1;e[c]<=r?s=c:a=c;}let l=e[a]-e[s];return l>0?s+(r-e[s])/l:s}function Nw(r,e,t){let n=e.length;if(n===0)return 0;if(r<=0)return e[0]+(t>0?r*t:0);if(r>=n-1)return e[n-1]+(t>0?(r-(n-1))*t:0);let o=Math.floor(r),i=r-o;return e[o]+(e[o+1]-e[o])*i}var jc=class{constructor(){this.widthPx=0;this.dataHeightPx=0;this.devicePixelRatio=1;this.viewport=Xc();this.pitchScale=1;this.times=[];this.intervalMs=0;}setSize(e,t,n){this.widthPx=e,this.dataHeightPx=t,this.devicePixelRatio=n>0?n:1;}setBars(e){this.times=e.slice(),this.intervalMs=Uh(this.times);}appendBar(e){this.times.push(e),this.intervalMs<=0&&this.times.length>=2&&(this.intervalMs=Uh(this.times));}setViewport(e){this.viewport=e;}getViewport(){return this.viewport}setPitchScale(e){this.pitchScale=Number.isFinite(e)&&e>0?e:1;}get spacingScale(){return this.pitchScale}pxPerBar(){return this.viewport.barSpacing*this.pitchScale}bodySpacing(){return this.viewport.barSpacing*Math.min(1,this.pitchScale)}get width(){return this.widthPx}get height(){return this.dataHeightPx}get dpr(){return this.devicePixelRatio}get barCount(){return this.times.length}get barInterval(){return this.intervalMs}get rightEdgeLogical(){return this.barCount-1+this.viewport.rightOffset}logicalToX(e){return this.widthPx-(this.rightEdgeLogical-e)*this.pxPerBar()}xToLogical(e){return this.rightEdgeLogical-(this.widthPx-e)/this.pxPerBar()}timeToLogical(e){return Ow(e,this.times,this.intervalMs)}logicalToTime(e){return Nw(e,this.times,this.intervalMs)}timeToX(e){return this.logicalToX(this.timeToLogical(e))}priceToY(e,t,n){if(t.log&&t.min>0&&t.max>t.min&&e>0){let s=Math.log(t.min),a=(Math.log(e)-s)/(Math.log(t.max)-s);return n.top+n.height*(t.invert?a:1-a)}let o=t.max-t.min;if(o<=0)return n.top+n.height/2;let i=(e-t.min)/o;return n.top+n.height*(t.invert?i:1-i)}yToPrice(e,t,n){if(n.height<=0)return t.min;let o=(e-n.top)/n.height,i=t.invert?o:1-o;if(t.log&&t.min>0&&t.max>t.min){let s=Math.log(t.min);return Math.exp(s+i*(Math.log(t.max)-s))}return t.min+(t.max-t.min)*i}visibleLogicalRange(){return {from:this.xToLogical(0),to:this.xToLogical(this.widthPx)}}visibleTimeRange(){let e=this.visibleLogicalRange();return {from:this.logicalToTime(e.from),to:this.logicalToTime(e.to)}}toBitmap(e){return Math.round(e*this.devicePixelRatio)}};function Yh(r){return r>=3}function Fw(r){return r>=2}var qc=class{constructor(e,t,n){this.onFrame=e;this.level=0;this.handle=null;this.raf=t??(o=>requestAnimationFrame(o)),this.cancel=n??(o=>cancelAnimationFrame(o));}invalidate(e){e<=0||(e>this.level&&(this.level=e),this.handle===null&&(this.handle=this.raf(()=>this.flush())));}flushNow(e){this.handle!==null&&(this.cancel(this.handle),this.handle=null),e>this.level&&(this.level=e),this.flush();}flush(){this.handle=null;let e=this.level;this.level=0,e!==0&&this.onFrame(e);}destroy(){this.handle!==null&&(this.cancel(this.handle),this.handle=null),this.level=0;}};var Zc=class{constructor(e,t,n,o){this.tick=e;this.handle=null;this.last=0;this.stopped=false;this.loop=()=>{let e=this.now(),t=e-this.last;this.last=e;let n=this.tick(Math.min(t,64));this.handle=n&&!this.stopped?this.raf(this.loop):null;};this.raf=t??(i=>requestAnimationFrame(i)),this.cancel=n??(i=>cancelAnimationFrame(i)),this.now=o??(()=>performance.now());}get active(){return this.handle!==null}start(){this.stopped=false,this.handle===null&&(this.last=this.now(),this.handle=this.raf(this.loop));}stop(){this.stopped=true,this.handle!==null&&(this.cancel(this.handle),this.handle=null);}},tr=class{constructor(e,t=e){this.onMs=e,this.ms=t;}get tau(){return this.ms}get on(){return this.ms>0}set(e){this.ms=e,e>0&&(this.onMs=e);}toggle(e){this.ms=e?this.onMs:0;}};function Lt(r,e,t,n){return n<=0?e:r+(e-r)*(1-Math.exp(-t/n))}var uP=.04,hP=60,pP=2,mP=350,Vw=8,fP=14,gP=350,bP=30,vP=.004,yP=.004,wP=.25;function xP(r,e,t){return t?{logical:r.rightEdgeLogical,x:r.width}:{logical:r.xToLogical(e),x:e}}function SP(r,e){return Math.abs(r)>Math.abs(e)}function CP(r,e,t){return r+e/t}function TP(r,e,t){return SP(r,e)?r:t?e:null}function kP(r,e){return r?"strong":e}function LP(r,e,t){return pn(r*(t/Math.max(1,e)))}function MP(r,e,t,n,o){return r-(e-1)+(t-n)/o}var Qc=class{constructor(e){this.deps=e;this.rightEdgeZoom=true;this.axisDrag=true;this.paneResize=true;this.drawings=true;this.el=null;this.dragging=false;this.moved=false;this.region="data";this.verticalPan=false;this.startX=0;this.startY=0;this.startRightOffset=0;this.startBarSpacing=0;this.lastX=0;this.lastT=0;this.vx=0;this.middleDeleted=false;this.rightCancelled=false;this.cursorX=NaN;this.cursorY=NaN;this.touches=new Map;this.lpTimer=null;this.pinchStartDist=1;this.pinchStartBarSpacing=0;this.pinchAnchorLogical=0;this.lastTapT=0;this.lastTapX=0;this.lastTapY=0;this.lastPressDrawing=false;this.prevPressDrawing=false;this.onTouchContextMenu=e=>{this.touches.size!==0&&(!(e.target instanceof Node)||!this.el?.contains(e.target)||(e.preventDefault(),e.stopImmediatePropagation()));};this.onMiddleGuard=e=>{e.button===1&&this.middleDeleted&&e.preventDefault();};this.onContextGuard=e=>{this.rightCancelled&&(this.rightCancelled=false,e.preventDefault(),e.stopPropagation());};this.onModifier=e=>{e.repeat||e.key!=="Shift"&&e.key!=="Control"&&e.key!=="Meta"||Number.isNaN(this.cursorX)||(this.dragging?this.region!=="drawing":!this.drawings)||this.deps.drawingsPointerMove?.(this.cursorX,this.cursorY,this.snapMode(e),e.shiftKey,e.ctrlKey||e.metaKey);};this.onDown=e=>{if(e.button===1){let{x:i,y:s}=this.local(e);this.middleDeleted=this.drawings&&(this.deps.drawingsDeleteAt?.(i,s)??false),this.middleDeleted&&e.preventDefault();return}if(e.button===2){this.rightCancelled=this.drawings&&(this.deps.drawingsCancelPlacement?.()??false),this.rightCancelled&&e.preventDefault();return}if(e.button!==0)return;let{x:t,y:n}=this.local(e);if(e.pointerType==="touch"){if(this.touches.size===1&&this.dragging&&(this.region==="data"||this.region==="crosshair")){this.touches.set(e.pointerId,{x:t,y:n}),this.beginPinch(e);return}if(this.touches.size>=1)return;this.touches.set(e.pointerId,{x:t,y:n});}if(this.deps.drawingsClearTransient?.(),this.dragging=true,this.moved=false,this.startX=t,this.startY=n,this.prevPressDrawing=this.lastPressDrawing,this.lastPressDrawing=false,this.drawings&&this.deps.drawingsClaim?.(t,n)){this.region="drawing",this.lastPressDrawing=true,this.deps.drawingsPointerDown?.(t,n,this.snapMode(e),e.shiftKey,e.ctrlKey||e.metaKey),this.capture(e.pointerId);return}if(this.drawings&&e.shiftKey&&this.regionAt(t,n)==="data"&&this.deps.drawingsMeasureStart?.(t,n,this.snapMode(e))){this.region="drawing",this.lastPressDrawing=true,this.capture(e.pointerId);return}if(this.drawings&&(e.ctrlKey||e.metaKey)&&this.regionAt(t,n)==="data"&&this.deps.drawingsMarqueeStart?.(t,n)){this.region="drawing",this.lastPressDrawing=true,this.capture(e.pointerId);return}let o=this.deps.getCoords().getViewport();this.deps.apply(o),this.startRightOffset=o.rightOffset,this.startBarSpacing=o.barSpacing,this.region=this.regionAt(t,n),this.verticalPan=false,this.region==="price"?this.deps.beginPriceScale(t,n):this.region==="separator"?this.deps.beginPaneResize(n):this.region==="data"&&(this.verticalPan=this.deps.beginPricePan(n)),e.pointerType==="touch"&&(this.region==="data"||this.region==="price"||this.region==="time")&&this.startLongPress(t,n,this.region),this.lastX=t,this.lastT=e.timeStamp,this.vx=0,this.capture(e.pointerId);};this.onMove=e=>{let{x:t,y:n}=this.local(e);if(this.cursorX=t,this.cursorY=n,e.pointerType==="touch"&&this.touches.has(e.pointerId)&&this.touches.set(e.pointerId,{x:t,y:n}),this.dragging&&this.region==="pinch"){this.applyPinch();return}if(this.dragging&&this.region==="crosshair"){this.deps.onPointerMove(t,n);return}if(this.dragging&&this.region==="axis-sheet")return;this.lpTimer!==null&&Math.hypot(t-this.startX,n-this.startY)>Vw&&this.cancelLongPress();let o=e.pointerType==="touch"?Vw:pP;if(this.dragging)if(this.region==="price")Math.abs(n-this.startY)>o&&(this.moved=true),this.deps.priceScaleBy(n-this.startY);else if(this.region==="separator")Math.abs(n-this.startY)>o&&(this.moved=true),this.deps.paneResizeBy(n-this.startY);else if(this.region==="time"){Math.abs(t-this.startX)>o&&(this.moved=true);let i=pn(this.startBarSpacing*Math.exp((this.startX-t)*vP));this.deps.apply({barSpacing:i,rightOffset:this.startRightOffset});}else if(this.region==="drawing")(Math.abs(t-this.startX)>o||Math.abs(n-this.startY)>o)&&(this.moved=true),this.deps.drawingsPointerMove?.(t,n,this.snapMode(e),e.shiftKey,e.ctrlKey||e.metaKey);else {let i=this.deps.getCoords(),s=i.getViewport(),a=t-this.startX;Math.abs(a)>o&&(this.moved=true),this.deps.apply({barSpacing:s.barSpacing,rightOffset:this.startRightOffset-a/i.pxPerBar()}),this.verticalPan&&(Math.abs(n-this.startY)>o&&(this.moved=true),this.deps.pricePanBy(n-this.startY));let l=e.timeStamp-this.lastT;if(l>0){let c=(t-this.lastX)/l;this.vx=this.vx*.6+c*.4,this.lastX=t,this.lastT=e.timeStamp;}}else if(this.el){let i=this.deps.drawingsCursor?.(t,n),s=this.regionAt(t,n);this.el.style.cursor=i??(s==="price"?"ns-resize":s==="time"?"ew-resize":s==="separator"?"row-resize":""),this.drawings&&this.deps.drawingsPointerMove?.(t,n,this.snapMode(e),e.shiftKey,e.ctrlKey||e.metaKey);}e.pointerType!=="touch"&&this.deps.onPointerMove(t,n);};this.onUp=e=>{if(e.pointerType==="touch"&&this.touches.delete(e.pointerId),this.cancelLongPress(),this.dragging&&this.region==="pinch"){if(this.touches.size===1){let a=[...this.touches.values()][0],l=this.deps.getCoords().getViewport();this.region="data",this.verticalPan=false,this.startX=a.x,this.startY=a.y,this.startRightOffset=l.rightOffset,this.startBarSpacing=l.barSpacing,this.lastX=a.x,this.lastT=e.timeStamp,this.vx=0;return}this.endGesture(e);return}if(this.dragging&&this.region==="crosshair"){this.deps.onPointerMove(null,null),this.endGesture(e);return}if(this.dragging&&this.region==="axis-sheet"){this.endGesture(e);return}let{x:t,y:n}=this.local(e),o=e.pointerType==="touch",i=this.dragging&&!this.moved&&(!o||Math.hypot(t-this.startX,n-this.startY)<=fP);if(this.dragging&&this.region==="drawing")this.deps.drawingsPointerUp?.(t,n,this.snapMode(e));else if(i&&this.region==="data")this.deps.onClick(t,n);else if(this.dragging&&this.region==="data"&&o&&!(e.timeStamp-this.lastT>hP)&&Math.abs(this.vx)>uP){let l=this.deps.getCoords().pxPerBar();this.deps.fling(-this.vx/l);}let s=o&&i;this.endGesture(e),o&&this.deps.onPointerMove(null,null),s&&this.registerTap(e.timeStamp,t,n);};this.onCancel=e=>{e.pointerType==="touch"&&this.touches.delete(e.pointerId),this.cancelLongPress(),this.dragging&&(this.region==="drawing"&&!Number.isNaN(this.cursorX)&&this.deps.drawingsPointerUp?.(this.cursorX,this.cursorY,this.snapMode(e)),(this.region==="crosshair"||e.pointerType==="touch")&&this.deps.onPointerMove(null,null),this.endGesture(e));};this.onLeave=()=>{this.cursorX=NaN,this.cursorY=NaN,this.deps.onPointerMove(null,null);};this.onDblClick=e=>{let{x:t,y:n}=this.local(e);this.doubleActivate(t,n);};this.onWheel=e=>{e.preventDefault(),this.deps.drawingsClearTransient?.();let{x:t,y:n}=this.local(e);if(this.regionAt(t,n)==="price"&&e.deltaY!==0){this.deps.beginPriceScale(t,n),this.deps.priceScaleBy(e.deltaY*wP);return}let o=this.deps.getCoords(),i=o.getViewport(),s=TP(e.deltaX,e.deltaY,e.shiftKey);if(s!=null){this.deps.apply({barSpacing:i.barSpacing,rightOffset:CP(i.rightOffset,s,o.pxPerBar())});return}let a=this.rightEdgeZoom&&!(e.ctrlKey||e.metaKey),l=xP(o,t,a),c=pn(i.barSpacing*Math.exp(-e.deltaY*yP));this.deps.zoomTo(c,l.logical,l.x);};}attach(e){this.el=e,e.style!==void 0&&(e.style.touchAction="none",e.style.userSelect="none",e.style.setProperty("-webkit-user-select","none"),e.style.setProperty("-webkit-touch-callout","none")),e.addEventListener("pointerdown",this.onDown),e.addEventListener("pointermove",this.onMove),e.addEventListener("pointerup",this.onUp),e.addEventListener("pointerleave",this.onLeave),e.addEventListener("pointercancel",this.onCancel),e.addEventListener("dblclick",this.onDblClick),e.addEventListener("wheel",this.onWheel,{passive:false}),e.addEventListener("mousedown",this.onMiddleGuard),e.addEventListener("auxclick",this.onMiddleGuard),e.addEventListener("contextmenu",this.onContextGuard);let t=e.ownerDocument?.defaultView;t?.addEventListener("keydown",this.onModifier),t?.addEventListener("keyup",this.onModifier),t?.addEventListener("contextmenu",this.onTouchContextMenu,true);}detach(){let e=this.el;if(!e)return;let t=e.ownerDocument?.defaultView;t?.removeEventListener("keydown",this.onModifier),t?.removeEventListener("keyup",this.onModifier),t?.removeEventListener("contextmenu",this.onTouchContextMenu,true),e.removeEventListener("pointerdown",this.onDown),e.removeEventListener("pointermove",this.onMove),e.removeEventListener("pointerup",this.onUp),e.removeEventListener("pointerleave",this.onLeave),e.removeEventListener("pointercancel",this.onCancel),e.removeEventListener("dblclick",this.onDblClick),e.removeEventListener("wheel",this.onWheel),e.removeEventListener("mousedown",this.onMiddleGuard),e.removeEventListener("auxclick",this.onMiddleGuard),e.removeEventListener("contextmenu",this.onContextGuard),this.cancelLongPress(),this.touches.clear(),this.el=null;}local(e){let t=this.el.getBoundingClientRect();return {x:e.clientX-t.left,y:e.clientY-t.top}}regionAt(e,t){let n=this.deps.getCoords();if(this.paneResize&&t<=n.height&&this.deps.paneSeparatorAt(t))return "separator";if(this.axisDrag){if(e>n.width&&t<=n.height)return "price";if(t>n.height&&e<=n.width)return "time"}return "data"}snapMode(e){return kP(e.ctrlKey||e.metaKey,this.deps.drawingsSnapMode?.()??"off")}startLongPress(e,t,n){this.cancelLongPress(),this.lpTimer=setTimeout(()=>{if(this.lpTimer=null,!(!this.dragging||this.region!==n)){if(n==="data"){this.region="crosshair",this.deps.onPointerMove(e,t);return}this.region="axis-sheet",this.moved=true,this.deps.onAxisLongPress?.(n,e,t);}},mP);}cancelLongPress(){this.lpTimer!==null&&clearTimeout(this.lpTimer),this.lpTimer=null;}beginPinch(e){this.cancelLongPress(),this.region==="crosshair"&&this.deps.onPointerMove(null,null);let t=this.deps.getCoords(),n=t.getViewport();this.deps.apply(n);let[o,i]=[...this.touches.values()];this.pinchStartDist=Math.max(1,Math.hypot(o.x-i.x,o.y-i.y)),this.pinchStartBarSpacing=n.barSpacing,this.pinchAnchorLogical=t.xToLogical((o.x+i.x)/2),this.region="pinch",this.dragging=true,this.moved=true,this.vx=0,this.capture(e.pointerId);}applyPinch(){let e=this.deps.getCoords(),t=[...this.touches.values()];if(t.length<2)return;let[n,o]=t,i=LP(this.pinchStartBarSpacing,this.pinchStartDist,Math.hypot(n.x-o.x,n.y-o.y)),s=e.getViewport(),a=s.barSpacing>0?e.pxPerBar()/s.barSpacing:1,l=(n.x+o.x)/2;this.deps.apply({barSpacing:i,rightOffset:MP(this.pinchAnchorLogical,e.barCount,e.width,l,i*a)});}capture(e){try{this.el?.setPointerCapture(e);}catch{}}registerTap(e,t,n){if(this.lastTapT>0&&e-this.lastTapT<=gP&&Math.hypot(t-this.lastTapX,n-this.lastTapY)<=bP){this.lastTapT=0,this.doubleActivate(this.lastTapX,this.lastTapY);return}this.lastTapT=e,this.lastTapX=t,this.lastTapY=n;}endGesture(e){this.dragging=false;try{this.el?.releasePointerCapture(e.pointerId);}catch{}}doubleActivate(e,t){if(this.drawings&&this.deps.drawingsDblClick?.(e,t))return;let n=this.regionAt(e,t);if(n==="price")this.deps.resetPriceScale(e,t);else if(n==="separator")this.deps.resetPaneSize(t);else if(n==="time")this.deps.resetView();else {if(this.lastPressDrawing||this.prevPressDrawing)return;this.deps.dataDblClick(e,t);}}};function EP(r){if(r.ctrlKey||r.metaKey)return null;switch(r.key){case "ArrowLeft":return r.shiftKey?{kind:"pan",bars:-10}:{kind:"step",delta:-1};case "ArrowRight":return r.altKey&&r.shiftKey?{kind:"realtime"}:r.shiftKey?{kind:"pan",bars:10}:{kind:"step",delta:1};case "+":case "=":return {kind:"zoom",direction:1};case "-":case "_":return {kind:"zoom",direction:-1};case "Home":return {kind:"edge",edge:"first"};case "End":return {kind:"edge",edge:"last"};case "0":return {kind:"reset"};case "Escape":return {kind:"clear"};default:return null}}var Jc=class{constructor(e){this.deps=e;this.el=null;this.onKey=e=>{if(this.deps.preempt?.(e)){e.preventDefault();return}let t=EP(e);if(t)switch(e.preventDefault(),t.kind){case "pan":this.deps.panByBars(t.bars);break;case "zoom":this.deps.zoomByStep(t.direction);break;case "step":this.deps.stepCrosshair(t.delta);break;case "edge":this.deps.jumpToEdge(t.edge);break;case "reset":this.deps.resetView();break;case "realtime":this.deps.scrollToRealtime();break;case "clear":this.deps.clearCrosshair();break}};}attach(e){this.el=e,e.addEventListener("keydown",this.onKey);}detach(){this.el?.removeEventListener("keydown",this.onKey),this.el=null;}};var PP=jm,IP=qm,AP=Zm;function $w(){return {visible:true,labels:true,qty:true,colors:{long:PP,short:IP,exit:AP}}}function Uw(r,e){let t=e&&typeof e=="object"?e:{},n=t.colors&&typeof t.colors=="object"?t.colors:{},o=(s,a)=>typeof s=="boolean"?s:a,i=(s,a)=>typeof s=="string"&&s.trim().length>0?s:a;return {visible:o(t.visible,r.visible),labels:o(t.labels,r.labels),qty:o(t.qty,r.qty),colors:{long:i(n.long,r.colors.long),short:i(n.short,r.colors.short),exit:i(n.exit,r.colors.exit)}}}var Kh=10,nr=9,Yr=6,qo=14,ed=3,Xh=2,Yw=2,jh=3,qh=6,Bw=6,_w=8;function Kw(r){return r+4}function RP(r){if(r.qty==null||!Number.isFinite(r.qty))return null;let e=Number(Math.abs(r.qty).toFixed(8));return `${r.side==="buy"?"+":"-"}${e}`}function DP(r,e,t){let n=[];if(e.labels&&r.label&&n.push(r.label),e.qty){let o=RP(r);o&&n.push(o);}return {exec:r,lines:n,height:qo+(n.length?jh+n.length*t:0)}}function Xw(r,e,t,n,o,i){let s=new Map;for(let a of r){let l=Math.round(t.timeToLogical(a.time));if(lo)continue;let c=s.get(l);c||(c={logical:l,buys:[],sells:[]},s.set(l,c)),(a.side==="buy"?c.buys:c.sells).push(DP(a,e,i));}return [...s.values()]}function Hw(r){if(r.length===0)return 0;let e=Kh;for(let t of r)e+=t.height;return e+(r.length-1)*qh}function jw(r,e,t,n,o,i){if(r.length===0)return null;let s=Kw(i),a=1/0,l=-1/0,c=0,d=0;for(let u of Xw(r,e,t,Math.floor(n),Math.ceil(o),s)){let h=t.barAt(u.logical);h&&(h.lowl&&(l=h.high),d=Math.max(d,Hw(u.buys)),c=Math.max(c,Hw(u.sells)));}return !Number.isFinite(a)||!Number.isFinite(l)?null:{min:a,max:l,abovePx:c,belowPx:d}}function qw(r,e,t,n,o,i,s,a,l){if(e.length===0)return;let c=Kw(s.fontSize),d=Xw(e,t,n,-1/0,1/0,c);if(d.length!==0){r.save(),r.font=`${s.fontSize}px ${s.fontFamily}`,r.textAlign="center",r.textBaseline="middle";for(let u of d){let h=o(u.logical);if(h<-150||h>a+150)continue;let p=n.barAt(u.logical);if(!p)continue;let m=Math.max(i(p.low),i(p.high)),f=Math.min(i(p.low),i(p.high)),g=m+Kh;for(let b of u.buys)r.fillStyle=zw(b.exec,t.colors),OP(r,h,g,b.exec.kind==="exit"),Ww(r,b.exec.side,h,i(b.exec.price),l),Gw(r,b.lines,h,g+qo+jh+c/2,c,s.color),g+=b.height+qh;g=f-Kh;for(let b of u.sells)r.fillStyle=zw(b.exec,t.colors),NP(r,h,g,b.exec.kind==="exit"),Ww(r,b.exec.side,h,i(b.exec.price),l),Gw(r,b.lines,h,g-qo-jh-c/2,-c,s.color),g-=b.height+qh;}r.restore();}}function zw(r,e){return r.kind==="exit"?e.exit:r.side==="buy"?e.long:e.short}function OP(r,e,t,n){r.beginPath(),r.moveTo(e,t),r.lineTo(e-nr/2,t+Yr),r.lineTo(e+nr/2,t+Yr),r.closePath(),r.fill(),r.fillRect(e-ed/2,t+Yr,ed,qo-Yr),n&&r.fillRect(e-nr/2,t-Yw-Xh,nr,Xh);}function NP(r,e,t,n){r.beginPath(),r.moveTo(e,t),r.lineTo(e-nr/2,t-Yr),r.lineTo(e+nr/2,t-Yr),r.closePath(),r.fill(),r.fillRect(e-ed/2,t-qo,ed,qo-Yr),n&&r.fillRect(e-nr/2,t+Yw,nr,Xh);}function Ww(r,e,t,n,o){let i=e==="buy"?t-o:t+o,s=e==="buy"?i-Bw:i+Bw;r.beginPath(),r.moveTo(i,n),r.lineTo(s,n-_w/2),r.lineTo(s,n+_w/2),r.closePath(),r.fill();}function Gw(r,e,t,n,o,i){if(e.length!==0){r.fillStyle=i;for(let s=0;se.order-t.order)),this.orderedCache}sessionHighlightBands(){if(!this.sessionZones)return [];let e=[];for(let[t,n]of this.sessionZones.pre)e.push({from:t,to:n,color:this.style.sessions.premarketColor});for(let[t,n]of this.sessionZones.post)e.push({from:t,to:n,color:this.style.sessions.postmarketColor});for(let[t,n]of this.sessionZones.extended)e.push({from:t,to:n,color:this.style.sessions.extendedColor});return e}indicatorsForPane(e){let t=[];for(let n of this.indicators.values())n.paneId===e&&t.push(n);return t}ownScaleIndicatorsForPane(e){return this.orderedIndicatorsForPane(e).filter(t=>t.ownScale===true)}ensureIndicatorScale(e,t){let n=this.indicatorScales.get(e);if(!n){let o=t??{min:0,max:1};n={scale:{...o},scaleTarget:{...o},initialized:false,manualScale:null},this.indicatorScales.set(e,n);}return n}dropIndicatorScale(e){this.indicatorScales.delete(e);}scaleFor(e,t){if(e.ownScale===true){let n=this.indicatorScales.get(e.id);if(n)return n.scale}return t.scale}orderPanes(e){e.forEach((t,n)=>{let o=this.panes.get(t);o&&(o.order=n);}),this.orderedCache=null;}orderedIndicatorsForPane(e){return this.indicatorsForPane(e).sort((t,n)=>this.zOf(t.id)-this.zOf(n.id))}zOf(e){return this.seriesZ.get(e)??0}offsetOf(e){return this.anchorOffsets.get(e)??0}setAnchorOffset(e,t){t!==0&&Number.isFinite(t)?this.anchorOffsets.set(e,t):this.anchorOffsets.delete(e);}forgetAnchorOffset(e){this.anchorOffsets.delete(e);}baselinePriceFor(e){if(this.baselineValue!=null)return this.baselineValue;let t=this.style.baseline.baselineLevel/100;if(e.log&&e.min>0&&e.max>e.min){let n=Math.log(e.min);return Math.exp(n+t*(Math.log(e.max)-n))}return e.min+(e.max-e.min)*t}assignIndicatorZ(e){this.seriesZ.has(e)||this.seriesZ.set(e,this.bottomZ()-1);}assignIndicatorZTop(e){this.seriesZ.has(e)||this.seriesZ.set(e,this.topZ()+1);}forgetIndicatorZ(e){this.seriesZ.delete(e);}setIndicatorZ(e,t){this.seriesZ.set(e,t);}indicatorZOrder(){return [...this.seriesZ.entries()].map(([e,t])=>({id:e,z:t})).sort((e,t)=>e.z-t.z)}seriesBoundaries(e){let t=new Set;e==="price"&&t.add(this.candleZ);for(let n of this.indicatorsForPane(e))t.add(this.zOf(n.id));return [...t].sort((n,o)=>n-o)}bringIndicatorToFront(e){this.seriesZ.set(e,this.topZ()+1);}sendIndicatorToBack(e){this.seriesZ.set(e,this.bottomZ()-1);}topZ(){let e=this.candleZ;for(let t of this.seriesZ.values())t>e&&(e=t);return e}bottomZ(){let e=this.candleZ;for(let t of this.seriesZ.values())t{let x=e.scaleFor(k,g);return x===g.scale?g:{...g,scale:x}};o.globalAlpha=this.modelAlpha;for(let k of b)for(let x of k.backgrounds)x.overlay!==true&&this.drawBackground(o,x,g,t);if(y)for(let k of e.indicators.values())for(let x of k.backgrounds)x.overlay===true&&this.drawBackground(o,x,g,t);let S=e.drawingSlices.get(g.id)??[],M=0,C=k=>{for(;M=e.candleZ&&(C(e.candleZ),o.globalAlpha=this.candleStructureAlpha,this.drawPriceSeries(o,e,h,p,t,g,n,m,c),v=true),C(e.zOf(k.id)),o.globalAlpha=this.modelAlpha;let x=e.offsetOf(k.id),E=w(k);for(let I of k.fills)I.overlay!==true&&this.drawFill(o,k,I,E,t,h,p,x);for(let I of k.series)I.overlay!==true&&this.drawSeries(o,I,E,t,h,p,n,x);}if(L&&!v&&(C(e.candleZ),o.globalAlpha=this.candleStructureAlpha,this.drawPriceSeries(o,e,h,p,t,g,n,m,c)),y){o.globalAlpha=this.modelAlpha;for(let k of e.indicators.values()){let x=e.offsetOf(k.id);for(let E of k.fills)E.overlay===true&&this.drawFill(o,k,E,g,t,h,p,x);}for(let k of e.indicators.values()){let x=e.offsetOf(k.id);for(let E of k.series)E.overlay===true&&this.drawSeries(o,E,g,t,h,p,n,x);}}C(1/0),o.globalAlpha=this.modelAlpha;for(let k of b){let x=w(k);for(let E of k.priceLines)this.drawHline(o,E,x,t,c,n);}o.restore();}}destroy(){this.canvas=null,this.ctx=null;}drawPriceSeries(e,t,n,o,i,s,a,l,c){if(t.basePainting==="none")return;let d=t.bars,u=t.style;switch(t.priceStyle){case "bars":this.drawBars(e,d,n,o,i,s,u.bars.upColor??a.upColor,u.bars.downColor??a.downColor,l);return;case "line":this.drawPriceLine(e,d,n,o,i,s,u.line.color??a.upColor,u.line.width);return;case "area":{let h=u.area.lineColor??a.upColor;this.drawPriceArea(e,d,n,o,i,s,u.area.topColor??h,u.area.bottomColor??"rgba(0,0,0,0)"),this.drawPriceLine(e,d,n,o,i,s,h,u.area.width);return}case "baseline":this.drawBaseline(e,d,n,o,i,s,t,a,c);return;default:this.drawCandles(e,t,d,n,o,i,s,a,l);}}drawBars(e,t,n,o,i,s,a,l,c){let d=i.bodySpacing(),u=Go(d);if(u==="aggregate"){this.drawCandlesAggregated(e,t,n,o,i,s,m=>c.get(m.time)??(m.close>=m.open?a:l));return}let h=Math.max(1,Math.round(d*.35)),p=u==="full";e.lineWidth=1;for(let m=n;m<=o;m+=1){let f=t[m];if(!f||f.high<=f.low)continue;let g=Math.round(i.logicalToX(m))+.5,b=c.get(f.time)??(f.close>=f.open?a:l),y=i.priceToY(f.high,s.scale,s.bounds),w=i.priceToY(f.low,s.scale,s.bounds);if(e.strokeStyle=b,e.beginPath(),e.moveTo(g,y),e.lineTo(g,w),p){let S=i.priceToY(f.open,s.scale,s.bounds),M=i.priceToY(f.close,s.scale,s.bounds);e.moveTo(g-h,S),e.lineTo(g,S),e.moveTo(g,M),e.lineTo(g+h,M);}e.stroke();}}drawPriceLine(e,t,n,o,i,s,a,l){e.lineWidth=l,e.lineJoin="round",e.lineCap="round",e.strokeStyle=a,e.beginPath();let c=false;for(let d=Math.max(0,n-1);d<=o;d+=1){let u=t[d];if(!u){c=false;continue}let h=i.logicalToX(d),p=i.priceToY(u.close,s.scale,s.bounds);c?e.lineTo(h,p):(e.moveTo(h,p),c=true);}e.stroke(),e.lineCap="butt";}drawPriceArea(e,t,n,o,i,s,a,l){let c=s.bounds.top+s.bounds.height,d=[],u=1/0;for(let p=Math.max(0,n-1);p<=o;p+=1){let m=t[p];if(!m)continue;let f=i.logicalToX(p),g=i.priceToY(m.close,s.scale,s.bounds);d.push({x:f,y:g}),g{e.beginPath(),e.moveTo(M[0].x,u);for(let v of M)e.lineTo(v.x,v.y);e.lineTo(M[M.length-1].x,u),e.closePath();};if(u>h){e.save(),e.beginPath(),e.rect(0,h,c,u-h),e.clip();let v=e.createLinearGradient(0,h,0,u);v.addColorStop(0,b),v.addColorStop(1,y),e.fillStyle=v,C(),e.fill(),e.restore();}if(u{e.strokeStyle=I,e.beginPath(),e.moveTo(v,k),e.lineTo(x,E),e.stroke();};for(let v=1;v{let b=g.close>=g.open;return (b?p.wickUpColor:p.wickDownColor)??c.get(g.time)??(b?h.up:h.down)});return}let m=u==="full",f=this.candleStructureAlpha>this.candleBodyAlpha+.001;for(let g=o;g<=i;g+=1){let b=n[g];if(!b||b.high<=b.low)continue;let y=Wc(s.logicalToX(g),d,s.dpr,this.candleBodyScale),w=y.center,S=b.close>=b.open,M=S?h.up:h.down,L=c.get(b.time)??M,v=0,k=0;if(m){let x=s.priceToY(b.open,a.scale,a.bounds),E=s.priceToY(b.close,a.scale,a.bounds);v=hn(Math.min(x,E),s.dpr),k=Math.max(1/s.dpr,hn(Math.max(x,E),s.dpr)-v);}if(p.wickVisible){let x=(S?p.wickUpColor:p.wickDownColor)??(m?M:L),E=hn(s.priceToY(b.high,a.scale,a.bounds),s.dpr),I=hn(s.priceToY(b.low,a.scale,a.bounds),s.dpr);e.globalAlpha=this.candleStructureAlpha,e.strokeStyle=x,e.lineWidth=y.wickW,e.beginPath(),m?(e.moveTo(w,E),e.lineTo(w,v),e.moveTo(w,v+k),e.lineTo(w,I)):(e.moveTo(w,E),e.lineTo(w,I)),e.stroke();}if(m&&(p.bodyVisible&&(e.globalAlpha=this.candleBodyAlpha,e.fillStyle=L,e.fillRect(y.bodyX,v,y.bodyW,k)),p.borderVisible||f&&p.bodyVisible)){e.globalAlpha=this.candleStructureAlpha,e.strokeStyle=p.borderVisible?(S?p.borderUpColor:p.borderDownColor)??L:L,e.lineWidth=1;let x=Math.max(0,y.bodyW-1),E=Math.max(0,k-1);e.strokeRect(y.bodyX+.5,v+.5,x,E);}}}drawCandlesAggregated(e,t,n,o,i,s,a){let l=c=>i.priceToY(c,s.scale,s.bounds);e.lineWidth=1;for(let c of Gc(t,n,o,d=>i.logicalToX(d),l,a)){let d=c.x+.5;e.strokeStyle=c.color,e.beginPath(),e.moveTo(d,l(c.hi)),e.lineTo(d,l(c.lo)),e.stroke();}}drawSeries(e,t,n,o,i,s,a,l=0){if(Rt(t,"pane")){if(t.kind==="candle"||t.kind==="bar"){this.drawPlotCandles(e,t,n,o,i,s,a,l);return}if($e(t))switch(t.kind){case "histogram":case "columns":this.drawHistogram(e,t,n,o,i,s,l);break;case "area":this.drawArea(e,t,n,o,i,s,l),this.drawPolyline(e,t,n,o,i,s,false,l);break;case "circles":case "cross":this.drawPointMarkers(e,t,n,o,i,s,l);break;case "step":this.drawPolyline(e,t,n,o,i,s,true,l);break;default:this.drawPolyline(e,t,n,o,i,s,false,l);}}}drawPolyline(e,t,n,o,i,s,a,l=0){e.lineWidth=Math.max(1,t.style.width),e.lineJoin="round",Qo(e,t.style.lineStyle);let c=0,d=0,u=false;for(let h=Math.max(1,i-1);h<=s;h+=1){let p=t.points[h-l],m=t.points[h-1-l];if(!p||p.value===null||!m||m.value===null){u=false;continue}let f=o.logicalToX(h),g=o.priceToY(p.value,n.scale,n.bounds);u||(c=o.logicalToX(h-1),d=o.priceToY(m.value,n.scale,n.bounds)),e.strokeStyle=p.color??t.style.color,e.beginPath(),e.moveTo(c,d),a&&e.lineTo(f,d),e.lineTo(f,g),e.stroke(),c=f,d=g,u=true;}Qo(e,"solid");}drawArea(e,t,n,o,i,s,a=0){let l=n.bounds.top+n.bounds.height,c=[],d=1/0,u=()=>{if(c.length===0)return;let h=e.createLinearGradient(0,d,0,l);h.addColorStop(0,t.style.color),h.addColorStop(1,"rgba(0,0,0,0)"),e.fillStyle=h,e.beginPath(),e.moveTo(c[0].x,l);for(let p of c)e.lineTo(p.x,p.y);e.lineTo(c[c.length-1].x,l),e.closePath(),e.fill(),c=[],d=1/0;};for(let h=i;h<=s;h+=1){let p=t.points[h-a];if(!p||p.value===null){u();continue}let m=o.logicalToX(h),f=o.priceToY(p.value,n.scale,n.bounds);c.push({x:m,y:f}),f=g.open?d:u),w=Math.round(o.logicalToX(f))+.5,S=o.priceToY(g.high,n.scale,n.bounds),M=o.priceToY(g.low,n.scale,n.bounds),C=o.priceToY(g.open,n.scale,n.bounds),L=o.priceToY(g.close,n.scale,n.bounds);if(h){e.strokeStyle=y,e.lineWidth=1,e.beginPath(),e.moveTo(w,S),e.lineTo(w,M),e.moveTo(w-m,C),e.lineTo(w,C),e.moveTo(w,L),e.lineTo(w+m,L),e.stroke();continue}e.strokeStyle=b?.wickColor??y,e.lineWidth=As(c),e.beginPath(),e.moveTo(w,S),e.lineTo(w,M),e.stroke(),e.fillStyle=y,e.fillRect(w-p,Math.min(C,L),p*2,Math.max(1,Math.abs(L-C))),b?.borderColor&&(e.strokeStyle=b.borderColor,e.strokeRect(w-p,Math.min(C,L),p*2,Math.max(1,Math.abs(L-C))));}}drawFill(e,t,n,o,i,s,a,l=0){let c=Jw(t,n.fromSeriesId),d=Jw(t,n.toSeriesId);if(!c||!d)return;let u=NaN,h=NaN,p="",m="",f=null;for(let g=Math.max(1,s);g<=a;g+=1){let b=c[g-1-l],y=d[g-1-l],w=c[g-l],S=d[g-l];if(!b||!y||!w||!S||b.value===null||y.value===null||w.value===null||S.value===null)continue;let M=i.logicalToX(g-1),C=i.logicalToX(g),L=i.priceToY(b.value,o.scale,o.bounds),v=i.priceToY(y.value,o.scale,o.bounds),k=i.priceToY(w.value,o.scale,o.bounds),x=i.priceToY(S.value,o.scale,o.bounds),E=n.gradient?.[g-1-l];if(E){let I=i.priceToY(E.topValue,o.scale,o.bounds),N=i.priceToY(E.bottomValue,o.scale,o.bounds),V=N===I?I+1:N;(!f||I!==u||V!==h||E.topColor!==p||E.bottomColor!==m)&&(f=e.createLinearGradient(0,I,0,V),f.addColorStop(0,E.topColor),f.addColorStop(1,E.bottomColor),u=I,h=V,p=E.topColor,m=E.bottomColor),e.fillStyle=f;}else {let I=n.colors?n.colors[g-1-l]:n.color;if(!I)continue;e.fillStyle=I;}e.beginPath(),e.moveTo(M,L),e.lineTo(C,k),e.lineTo(C,x),e.lineTo(M,v),e.closePath(),e.fill();}}drawBackground(e,t,n,o){let i=o.timeToX(t.from),s=o.timeToX(t.to);s<0||i>o.width||s<=i||(e.fillStyle=t.color,e.fillRect(i,n.bounds.top,s-i,n.bounds.height));}drawHline(e,t,n,o,i,s){let a=Math.round(o.priceToY(t.price,n.scale,n.bounds))+.5;an.bounds.top+n.bounds.height||(e.strokeStyle=t.color??s.textColor,e.lineWidth=t.width??1,Qo(e,t.lineStyle??"solid"),e.beginPath(),e.moveTo(0,a),e.lineTo(i,a),e.stroke(),Qo(e,"solid"));}};function Qo(r,e){e==="dashed"?r.setLineDash([6,4]):e==="dotted"?r.setLineDash([2,3]):r.setLineDash([]);}function Jw(r,e){let t=r.series.find(n=>n.id===e);return t&&$e(t)?t.points:null}var FP=new Map;function VP(r){let e=false;for(let n of r.values())if(n.barColors&&n.barColors.length>0){e=true;break}if(!e)return FP;let t=new Map;for(let n of r.values())if(n.barColors)for(let o of n.barColors)t.set(o.time,o.color);return t}function or(r,e){let t=Math.max(1,e);return r==="dotted"?[t,t*2]:r==="dashed"?[t*4,t*3]:[]}function Jo(r,e,t,n,o,i,s){if(o==="none")return [r,e,t,n];let a=t-r,l=o==="left"||o==="both",c=o==="right"||o==="both";if(Math.abs(a)<1e-6){if(l&&c)return [r,0,t,s];let m=n>=e;return c?m?[r,e,t,s]:[r,e,t,0]:m?[r,0,t,n]:[r,s,t,n]}let d=(n-e)/a,u=m=>e+d*(m-r),h=l?-2:Math.min(r,t),p=c?i+2:Math.max(r,t);return [h,u(h),p,u(p)]}function ex(r,e,t,n){let o=Math.atan2(n-e,t-r);return o>Math.PI/2&&(o-=Math.PI),o<-Math.PI/2&&(o+=Math.PI),o}function BP(r){let e=r.trim(),t=/^#([0-9a-f]{3})$/i.exec(e);if(t){let n=t[1];return {r:parseInt(n[0]+n[0],16),g:parseInt(n[1]+n[1],16),b:parseInt(n[2]+n[2],16),a:1}}if(t=/^#([0-9a-f]{6})([0-9a-f]{2})?$/i.exec(e),t){let n=t[1];return {r:parseInt(n.slice(0,2),16),g:parseInt(n.slice(2,4),16),b:parseInt(n.slice(4,6),16),a:t[2]?parseInt(t[2],16)/255:1}}if(t=/^rgba?\(([^)]+)\)$/i.exec(e),t){let n=t[1].split(",").map(o=>parseFloat(o.trim()));return {r:n[0]??0,g:n[1]??0,b:n[2]??0,a:n[3]??1}}return null}function _P(r,e,t){return (.299*r+.587*e+.114*t)/255}function Ye(r){if(!r)return "#000000";let e=BP(r);return e?_P(e.r,e.g,e.b)>.55?"#000000":"#ffffff":"#000000"}function mn(r){return Math.round(r*1.4)}var Kr=5,Xr=3;function Ke(r){switch(r){case "tiny":return 10;case "small":return 12;case "large":return 18;case "huge":return 28;case "normal":return 14;default:return 0}}function tx(r,e,t,n){let o=1;for(let l of r)l.length>o&&(o=l.length);let i=n?.62:.55,s=e*.9/(o*i),a=t*.85/(r.length*1.3);return Math.max(6,Math.min(s,a,48))}var HP={lines:[],boxes:[],labels:[],polylines:[],linefills:[]};function ti(r,e){let t=n=>!!n.overlay===e;return {lines:(r.lines??[]).filter(t),boxes:(r.boxes??[]).filter(t),labels:(r.labels??[]).filter(t),polylines:(r.polylines??[]).filter(t),linefills:(r.linefills??[]).filter(t)}}function Jh(r){return !r.lines.length&&!r.boxes.length&&!r.labels.length&&!r.polylines.length&&!r.linefills.length}function nx(r){return r==="auto"?12:Ke(r)}function zP(r,e,t,n,o){let i=Math.min(r,e),s=Math.max(r,e);return r===e?r>=n&&r<=o:t==="both"?true:t==="left"?s>=n:(t==="right"||s>=n)&&i<=o}var ei=class{constructor(e,t=HP){this.deps=e;this.set=t;this.widthCache=new Map;this.tipRegions=[];this.indexOffset=0;}setSet(e,t=0){this.set=e,this.indexOffset=t;}setDeps(e){this.deps=e;}isEmpty(){let e=this.set;return !e.lines.length&&!e.boxes.length&&!e.labels.length&&!e.polylines.length&&!e.linefills.length}labelTipRegions(){return this.tipRegions}render(e,t,n,o,i){this.tipRegions=[],!this.isEmpty()&&(e.save(),this.drawLinefills(e,t,n,o,i),this.drawBoxes(e,t,n,o,i),this.drawPolylines(e,t,o,i),this.drawLines(e,t,n,o,i),this.drawLabels(e,t,n,o,i),e.restore());}priceRange(e,t){let n=Math.min(e,t),o=Math.max(e,t),i=(u,h,p)=>p==="both"?true:p==="left"?Math.max(u,h)>=n:(p==="right"||Math.max(u,h)>=n)&&Math.min(u,h)<=o,s=1/0,a=-1/0,l=u=>{ua&&(a=u);};for(let u of this.set.lines)u.invisible||zP(this.logicalOf(u.xloc,u.x1),this.logicalOf(u.xloc,u.x2),u.extend,n,o)&&(l(u.y1),l(u.y2));for(let u of this.set.boxes)!u.bgColor&&!(u.borderColor&&u.borderWidth>0)&&!u.text||i(this.logicalOf(u.xloc,u.left),this.logicalOf(u.xloc,u.right),u.extend)&&(l(u.top),l(u.bottom));for(let u of this.set.linefills){if(!u.color)continue;let h=[u.line1.x1,u.line1.x2,u.line2.x1,u.line2.x2].map((m,f)=>this.logicalOf(f<2?u.line1.xloc:u.line2.xloc,m)),p=u.line1.extend!=="none"||u.line2.extend!=="none"?"both":"none";i(Math.min(...h),Math.max(...h),p)&&(l(u.line1.y1),l(u.line1.y2),l(u.line2.y1),l(u.line2.y2));}for(let u of this.set.polylines){if(u.points.length<2)continue;let h=u.points.map(p=>this.logicalOf(p.xloc,p.x));if(i(Math.min(...h),Math.max(...h),"none"))for(let p of u.points)l(p.price);}let c=0,d=0;for(let u of this.set.labels){let h=this.logicalOf(u.xloc,u.x);if(!i(h,h,"none"))continue;if(u.yloc==="price"){l(u.y);continue}if(u.yloc==="top"||u.yloc==="bottom")continue;let p=this.deps.barAt(h);if(!p)continue;l(u.yloc==="abovebar"?p.high:p.low);let m=nx(u.size),f=Math.max(1,(u.text??"").split(` +`).length),g=this.isPointShape(u.style)?14+Math.max(4,m*.6)+2:14+m*1.25*f+8+7;u.yloc==="abovebar"?c=Math.max(c,g):d=Math.max(d,g);}return !Number.isFinite(s)||!Number.isFinite(a)?null:{min:s,max:a,aboveMargin:c,belowMargin:d}}logicalOf(e,t){return e==="bar_time"?this.deps.timeToLogical(t):t+this.indexOffset}drawLines(e,t,n,o,i){for(let s of this.set.lines){if(s.invisible)continue;let a=o(this.logicalOf(s.xloc,s.x1)),l=o(this.logicalOf(s.xloc,s.x2)),c=i(s.y1),d=i(s.y2);if(c===null||d===null)continue;let u=s.extend==="left"||s.extend==="both",h=s.extend==="right"||s.extend==="both";if(!u&&!h&&(Math.max(a,l)<0||Math.min(a,l)>t))continue;let[p,m,f,g]=Jo(a,c,l,d,s.extend,t,n),b=s.color??this.deps.theme.textColor;e.beginPath(),e.moveTo(p,m),e.lineTo(f,g),e.strokeStyle=b,e.lineWidth=s.width,e.setLineDash(or(s.style,s.width)),e.stroke(),e.setLineDash([]);let y=l>=a;if(s.arrowRight){let w=(y?h:u)?y?[f,g]:[p,m]:[l,d];this.drawArrow(e,w[0],w[1],a,c,s.width,b);}if(s.arrowLeft){let w=(y?u:h)?y?[p,m]:[f,g]:[a,c];this.drawArrow(e,w[0],w[1],l,d,s.width,b);}}}drawArrow(e,t,n,o,i,s,a){let l=Math.atan2(n-i,t-o),c=6+s*2,d=.45;e.beginPath(),e.moveTo(t,n),e.lineTo(t-c*Math.cos(l-d),n-c*Math.sin(l-d)),e.lineTo(t-c*Math.cos(l+d),n-c*Math.sin(l+d)),e.closePath(),e.fillStyle=a,e.fill();}drawLinefills(e,t,n,o,i){for(let s of this.set.linefills){if(!s.color)continue;let a=this.resolveLine(s.line1,t,n,o,i),l=this.resolveLine(s.line2,t,n,o,i);if(!a||!l)continue;let c=h=>h[0]>h[2]||h[0]===h[2]&&h[1]>h[3]?[h[2],h[3],h[0],h[1]]:h,d=c(a),u=c(l);e.beginPath(),e.moveTo(d[0],d[1]),e.lineTo(d[2],d[3]),e.lineTo(u[2],u[3]),e.lineTo(u[0],u[1]),e.closePath(),e.fillStyle=s.color,e.fill();}}resolveLine(e,t,n,o,i){let s=o(this.logicalOf(e.xloc,e.x1)),a=o(this.logicalOf(e.xloc,e.x2)),l=i(e.y1),c=i(e.y2);return l===null||c===null?null:Jo(s,l,a,c,e.extend,t,n)}drawPolylines(e,t,n,o){for(let i of this.set.polylines){let s=[];for(let c of i.points){let d=o(c.price);d!==null&&s.push([n(this.logicalOf(c.xloc,c.x)),d]);}if(s.length<2)continue;let a=1/0,l=-1/0;for(let c of s)c[0]l&&(l=c[0]);if(!(l<0||a>t)){if(e.beginPath(),i.curved)this.curvedPath(e,s,i.closed);else {e.moveTo(s[0][0],s[0][1]);for(let c=1;cn?t[(a%o+o)%o]:t[Math.max(0,Math.min(o-1,a))];e.moveTo(t[0][0],t[0][1]);let s=n?o:o-1;for(let a=0;at||m<0||p>n||(s.bgColor&&(e.fillStyle=s.bgColor,e.fillRect(u,p,f,g)),s.borderColor&&s.borderWidth>0&&(e.strokeStyle=s.borderColor,e.lineWidth=s.borderWidth,e.setLineDash(or(s.borderStyle,s.borderWidth)),e.strokeRect(u,p,f,g),e.setLineDash([])),s.text&&this.drawBoxText(e,s,u,p,f,g));}}measure(e,t,n){let o=`${t} ${n}`,i=this.widthCache.get(o);return i===void 0&&(e.font=t,i=e.measureText(n).width,this.widthCache.set(o,i)),i}wrapText(e,t,n,o){let i=[];for(let s of n.split(` `)){if(this.measure(e,t,s)<=o){i.push(s);continue}let a="";for(let l of s.split(/(\s+)/)){let c=a+l;a&&this.measure(e,t,c)>o?(i.push(a.trimEnd()),a=l.trimStart()):a=c;}a.trim()&&i.push(a.trimEnd());}return i}drawBoxText(e,t,n,o,i,s){let a=t.text,l=t.fontFamily==="monospace"?"monospace":this.deps.theme.fontFamily||"sans-serif",c=`${t.italic?"italic ":""}${t.bold?"bold ":""}`,d=4,u=Ke(t.textSize),h;if(u===0){let b=`${c}14px ${l}`;h=t.wrap?this.wrapText(e,b,a,Math.max(1,i-d*2)):a.split(` -`),u=Xw(h,i,s,t.bold);}else {let b=`${c}${u}px ${l}`;h=t.wrap?this.wrapText(e,b,a,Math.max(1,i-d*2)):a.split(` -`);}e.font=`${c}${u}px ${l}`,e.fillStyle=t.textColor??Ye(t.bgColor);let p=u*1.3,m=p*h.length,f;t.hAlign==="left"?(e.textAlign="left",f=n+d):t.hAlign==="right"?(e.textAlign="right",f=n+i-d):(e.textAlign="center",f=n+i/2),e.textBaseline="top";let g;t.vAlign==="top"?g=o+d:t.vAlign==="bottom"?g=o+s-d-m:g=o+(s-m)/2,e.save(),e.beginPath(),e.rect(n,o,i,s),e.clip();for(let b=0;bt+50)continue;let l;if(s.yloc==="price")l=i(s.y);else if(s.yloc==="top")l=14;else if(s.yloc==="bottom")l=n-14;else {let u=this.deps.barAt(this.logicalOf(s.xloc,s.x));if(!u)continue;let h=i(s.yloc==="abovebar"?u.high:u.low);l=h===null?null:h+(s.yloc==="abovebar"?-14:14);}if(l===null)continue;let c=s.color??this.deps.theme.textColor,d=jw(s.size);if(this.isPointShape(s.style)){if(s.noFill||this.drawLabelShape(e,s.style,a,l,d,c),s.text&&this.drawLabelText(e,s,a,l+d,d),s.tooltip){let u=Math.max(4,d*.6)+3;this.tipRegions.push({left:a-u,top:l-u,right:a+u,bottom:l+u,text:s.tooltip});}}else if(s.style==="none"||s.style==="text_outline")s.text&&(this.drawLabelText(e,s,a,l,d,s.style==="text_outline"),s.tooltip&&this.tipRegions.push(this.textRegion(e,s,a,l,d,s.tooltip)));else {let u=this.drawBubble(e,s,a,l,d,c);s.tooltip&&this.tipRegions.push({left:u.x,top:u.y,right:u.x+u.w,bottom:u.y+u.h,text:s.tooltip});}}}labelFont(e,t){let n=e.fontFamily==="monospace"?"monospace":this.deps.theme.fontFamily||"sans-serif";return `${e.italic?"italic ":""}${e.bold?"bold ":""}${t}px ${n}`}textRegion(e,t,n,o,i,s){let a=this.labelFont(t,i),l=(t.text??"").split(` +`),u=tx(h,i,s,t.bold);}else {let b=`${c}${u}px ${l}`;h=t.wrap?this.wrapText(e,b,a,Math.max(1,i-d*2)):a.split(` +`);}e.font=`${c}${u}px ${l}`,e.fillStyle=t.textColor??Ye(t.bgColor);let p=u*1.3,m=p*h.length,f;t.hAlign==="left"?(e.textAlign="left",f=n+d):t.hAlign==="right"?(e.textAlign="right",f=n+i-d):(e.textAlign="center",f=n+i/2),e.textBaseline="top";let g;t.vAlign==="top"?g=o+d:t.vAlign==="bottom"?g=o+s-d-m:g=o+(s-m)/2,e.save(),e.beginPath(),e.rect(n,o,i,s),e.clip();for(let b=0;bt+50)continue;let l;if(s.yloc==="price")l=i(s.y);else if(s.yloc==="top")l=14;else if(s.yloc==="bottom")l=n-14;else {let u=this.deps.barAt(this.logicalOf(s.xloc,s.x));if(!u)continue;let h=i(s.yloc==="abovebar"?u.high:u.low);l=h===null?null:h+(s.yloc==="abovebar"?-14:14);}if(l===null)continue;let c=s.color??this.deps.theme.textColor,d=nx(s.size);if(this.isPointShape(s.style)){if(s.noFill||this.drawLabelShape(e,s.style,a,l,d,c),s.text&&this.drawLabelText(e,s,a,l+d,d),s.tooltip){let u=Math.max(4,d*.6)+3;this.tipRegions.push({left:a-u,top:l-u,right:a+u,bottom:l+u,text:s.tooltip});}}else if(s.style==="none"||s.style==="text_outline")s.text&&(this.drawLabelText(e,s,a,l,d,s.style==="text_outline"),s.tooltip&&this.tipRegions.push(this.textRegion(e,s,a,l,d,s.tooltip)));else {let u=this.drawBubble(e,s,a,l,d,c);s.tooltip&&this.tipRegions.push({left:u.x,top:u.y,right:u.x+u.w,bottom:u.y+u.h,text:s.tooltip});}}}labelFont(e,t){let n=e.fontFamily==="monospace"?"monospace":this.deps.theme.fontFamily||"sans-serif";return `${e.italic?"italic ":""}${e.bold?"bold ":""}${t}px ${n}`}textRegion(e,t,n,o,i,s){let a=this.labelFont(t,i),l=(t.text??"").split(` `),c=Math.max(1,...l.map(h=>this.measure(e,a,h))),d=i*1.25*l.length,u=t.textAlign==="left"?n:t.textAlign==="right"?n-c:n-c/2;return {left:u,top:o-d/2,right:u+c,bottom:o+d/2,text:s}}isPointShape(e){switch(e){case "circle":case "square":case "diamond":case "flag":case "arrowup":case "arrowdown":case "triangleup":case "triangledown":case "cross":case "xcross":return true;default:return false}}drawLabelText(e,t,n,o,i,s=false){e.font=this.labelFont(t,i),e.textAlign=t.textAlign==="left"?"left":t.textAlign==="right"?"right":"center",e.textBaseline="middle";let a=t.text.split(` `),l=i*1.25,c=o-l*(a.length-1)/2;if(s){e.lineWidth=3,e.strokeStyle=Ye(t.textColor??this.deps.theme.textColor);for(let d=0;dthis.measure(e,e.font,y)))+l*2,p=d*a.length+c*2,m=7,f=n-h/2,g=o-p-m,b="down";switch(t.style){case "label_up":f=n-h/2,g=o+m,b="up";break;case "label_left":f=n+m,g=o-p/2,b="left";break;case "label_right":f=n-h-m,g=o-p/2,b="right";break;case "label_center":f=n-h/2,g=o-p/2,b="none";break;case "label_lower_left":f=n+m,g=o-p-m,b="none";break;case "label_lower_right":f=n-h-m,g=o-p-m,b="none";break;case "label_upper_left":f=n+m,g=o+m,b="none";break;case "label_upper_right":f=n-h-m,g=o+m,b="none";break;default:f=n-h/2,g=o-p-m,b="down";}if(t.noFill||(e.fillStyle=s,this.roundRect(e,f,g,h,p,4),e.fill(),b!=="none"&&(e.beginPath(),b==="down"?(e.moveTo(n-m,g+p),e.lineTo(n+m,g+p),e.lineTo(n,o)):b==="up"?(e.moveTo(n-m,g),e.lineTo(n+m,g),e.lineTo(n,o)):b==="left"?(e.moveTo(f,o-m),e.lineTo(f,o+m),e.lineTo(n,o)):(e.moveTo(f+h,o-m),e.lineTo(f+h,o+m),e.lineTo(n,o)),e.closePath(),e.fill())),t.text){e.fillStyle=t.textColor??(t.noFill?this.deps.theme.textColor:Ye(s)),e.textBaseline="middle";let y;t.textAlign==="left"?(e.textAlign="left",y=f+l):t.textAlign==="right"?(e.textAlign="right",y=f+h-l):(e.textAlign="center",y=f+h/2);let w=g+c+d/2;for(let C=0;CNumber(n.find(a=>a.type===s)?.value);return Date.UTC(o("year"),o("month")-1,o("day"),o("hour")%24,o("minute"),o("second"))-r}catch{return 0}}function Jc(r,e){return new Date(r+Is(r,e))}function td(r,e,t=6){if(!(e>r)||!Number.isFinite(r)||!Number.isFinite(e))return [];let n=(e-r)/Math.max(1,t),o=Math.pow(10,Math.floor(Math.log10(n))),i=n/o,s=(i<1.5?1:i<3?2:i<7?5:10)*o,a=Math.max(0,-Math.floor(Math.log10(s))+1),l=[],c=Math.ceil(r/s)*s;for(let d=c;d<=e+s*1e-6;d+=s)l.push(Number(d.toFixed(a)));return l}function PP(r,e,t=6){if(!(e>r))return 2;let n=(e-r)/Math.max(1,t),o=Math.pow(10,Math.floor(Math.log10(n))),i=n/o,s=(i<1.5?1:i<3?2:i<7?5:10)*o;return Math.max(0,Math.min(8,-Math.floor(Math.log10(s))+1))}function IP(r,e,t=6){if(r<=0||!(e>r)||!Number.isFinite(r)||!Number.isFinite(e))return [];if(Math.log10(e)-Math.log10(r)<1.1)return td(r,e,t);let n=[],o=Math.floor(Math.log10(r)),i=Math.ceil(Math.log10(e));for(let s=o;s<=i;s+=1)for(let a of [1,2,5]){let l=a*Math.pow(10,s);l>=r&&l<=e&&n.push(l);}return n}function Jh(r){let e=Math.abs(r);return e>=100?0:e>=1?2:e>=.01?4:6}function AP(r){if(!(r>0)||!Number.isFinite(r))return 2;for(let e=0;e<=8;e+=1)if(Math.abs(Number(r.toFixed(e))-r)<=r*1e-6)return e;return 8}function RP(r,e,t){let n=t!=null&&t>0?AP(t):PP(r.min,r.max,Ns(e));return n===0?2:n}function Ns(r){return Math.max(2,Math.min(16,Math.round(r/50)))}function qw(r,e){return r.log?IP(r.min,r.max,Ns(e)):td(r.min,r.max,Ns(e))}function qh(r,e){return (r/e-1)*100}function Zh(r,e){return r/e*100}function Zw(r){return `${r>=0?"+":"-"}${Math.abs(r).toFixed(2)}%`}function Qw(r){return r.toFixed(2)}function Jw(r){let e=Math.abs(r);return e>=1e9?`${ed(r/1e9)}B`:e>=1e6?`${ed(r/1e6)}M`:e>=1e3?`${ed(r/1e3)}K`:ed(r)}function ed(r){return Number(r.toFixed(2)).toString()}function Fs(r,e,t,n,o){if(o==="none")return [];if(t){let{baseline:i,indexed:s}=t,a=Math.min(r.min,r.max),l=Math.max(r.min,r.max);if(s){let u=Zh(a,i),h=Zh(l,i);return td(u,h,Ns(e)).map(p=>({price:i*p/100,label:Qw(p)}))}let c=qh(a,i),d=qh(l,i);return td(c,d,Ns(e)).map(u=>({price:i*(1+u/100),label:Zw(u)}))}return o==="volume"?qw(r,e).map(i=>({price:i,label:Jw(i)})):qw(r,e).map(i=>({price:i,label:rd(r,e,i,n)}))}function Vs(r,e,t,n,o,i){return i==="none"?"":n?n.indexed?Qw(Zh(t,n.baseline)):Zw(qh(t,n.baseline)):i==="volume"?Jw(t):rd(r,e,t,o)}function rd(r,e,t,n){if(r.log&&Math.log10(r.max)-Math.log10(r.min)>=1.1){let i=Jh(t);return t.toFixed(i===0?2:i)}return t.toFixed(RP(r,e,n))}var As=1e3,Rs=60*As,Qo=60*Rs,Ur=24*Qo,DP=7*Ur,nd=30*Ur,Qh=365*Ur,jh=[As,5*As,15*As,30*As,Rs,5*Rs,15*Rs,30*Rs,Qo,2*Qo,4*Qo,6*Qo,12*Qo,Ur,2*Ur,DP,nd,3*nd,Qh],Ds=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],OP=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],Os=r=>r<10?`0${r}`:String(r);function ep(r,e,t){let n=Jc(r,e),o=`${OP[n.getUTCDay()]} ${n.getUTCDate()} ${Ds[n.getUTCMonth()]} '${Os(n.getUTCFullYear()%100)}`;return t>=Ur?o:`${o} ${Os(n.getUTCHours())}:${Os(n.getUTCMinutes())}`}function NP(r){for(let e of jh)if(e>=r)return e;return jh[jh.length-1]}function od(r,e,t=8,n=0){let o=e-r;if(!(o>0))return [];let i=NP(o/Math.max(1,t)),s=r+n,a=e+n;if(i>=nd)return FP(s,a,i>=Qh?12:i>=3*nd?3:1,n);let l=Math.ceil(s/i)*i,c=[];for(let d=l;d<=a;d+=i){let u=d-n,h=new Date(d),p,m=false;if(i0))return null;let n=r+e-t;return n<=0?null:VP(n)}function VP(r){let e=Math.max(0,Math.ceil(r/1e3)),t=e%60,n=Math.floor(e/60)%60,o=Math.floor(e/3600),i=s=>String(s).padStart(2,"0");return o>0?`${o}:${i(n)}:${i(t)}`:`${i(n)}:${i(t)}`}function t0(r,e){let[t,n,o,i]=se(r),s=t,a=n,l=o;if(i<1){let[u,h,p]=se(e);s=t*i+u*(1-i),a=n*i+h*(1-i),l=o*i+p*(1-i);}let c=u=>u<=.04045?u/12.92:Math.pow((u+.055)/1.055,2.4);return .2126*c(s)+.7152*c(a)+.0722*c(l)>=.4?"#000000":"#ffffff"}function BP(r,e,t){let n=e.length;if(n===0||!(t>0)||!Number.isFinite(r)||r=o+t)return n-1+Math.floor((r-o)/t);let i=0,s=n-1;for(;i>1;e[a]<=r?i=a:s=a-1;}return r{if(s.group!==void 0&&n(s.group))return;let l=BP(s.time,e,t);if(l===null)return;let c=`${l}|${s.group??""}`,d=o.get(c);d||(d={key:c,bar:l,group:s.group,marks:[],seq:[]},o.set(c,d)),d.marks.push(s),d.seq.push(a);});let i=[];for(let s of o.values()){let a=s.marks.map((l,c)=>({m:l,seq:s.seq[c]})).sort((l,c)=>l.m.time-c.m.time||l.seq-c.seq);i.push({key:s.key,bar:s.bar,group:s.group,marks:a.map(l=>l.m)});}return i}function HP(r,e,t=20){let n=new Map;for(let i of r){let s=n.get(i.group);s?s.push(i):n.set(i.group,[i]);}let o=[];for(let i of n.values()){i.sort((l,c)=>l.bar-c.bar);let s=[],a=Number.NaN;for(let l of i){let c=e(l.bar),d=s[s.length-1];d&&Number.isFinite(c)&&Number.isFinite(a)&&c-at.set(n.id,o));for(let n of e)n.group!==void 0&&!t.has(n.group)&&t.set(n.group,t.size);return n=>n===void 0?Number.MAX_SAFE_INTEGER:t.get(n)??Number.MAX_SAFE_INTEGER-1}function n0(r){let e=HP(_P(r.marks,r.barTimes,r.intervalMs,r.hidden),r.xOf),t=zP(r.groups,e),n=new Map;for(let s of e){let a=n.get(s.bar);a?a.push(s):n.set(s.bar,[s]);}let o=[],i=new Map;for(let[s,a]of n){let l=r.xOf(s);if(!Number.isFinite(l)||l<-20||l>r.dataW+20)continue;a.sort((f,g)=>t(f.group)-t(g.group));let c=a.length>1,d=c&&r.expanded===s,u=c&&!d,h=[],p=a[0].marks.length>1?20:16,m=r.axisY-4;a.forEach((f,g)=>{let b=u?p:f.marks.length>1?20:16,y;d?(y=m-b/2,m-=b+4):y=r.axisY-4-b/2-g*3,h.push({cluster:f,x:l,y,size:b,stack:s,depth:g,decked:u});});for(let f=h.length-1;f>=0;f--)o.push(h[f]);i.set(s,h);}return {glyphs:o,stacks:i}}function r0(r,e,t){for(let n=r.glyphs.length-1;n>=0;n--){let o=r.glyphs[n];if(o.decked&&o.depth!==0)continue;let i=o.size/2+3;if(Math.abs(e-o.x)<=i&&Math.abs(t-o.y)<=i)return o}return null}function o0(r,e,t){for(let[n,o]of r.stacks){for(let i of o){let s=i.size/2+3;if(Math.abs(e-i.x)<=s&&Math.abs(t-i.y)<=s)return n}if(o.length>1&&!o[0].decked){let i=o[o.length-1],s=o[0],a=Math.max(i.size,s.size)/2+3;if(Math.abs(e-s.x)<=a&&t>=i.y-i.size/2-8&&t<=s.y+s.size/2+3)return n}}return null}function i0(r,e){let t=r.marks[0];return t?r.marks.length===1?t.tooltip??t.title??null:`${r.group!==void 0?s0(r.group,e):t.title??t.tooltip??"Marks"} \xB7 ${r.marks.length}`:null}function s0(r,e){let t=e.find(n=>n.id===r);return t?t.label:r.charAt(0).toUpperCase()+r.slice(1)}function a0(r,e){let t=e.map(o=>({...o})),n=new Set(t.map(o=>o.id));for(let o of r)o.group===void 0||n.has(o.group)||(n.add(o.group),t.push({id:o.group,label:s0(o.group,e)}));return t}var id=360,WP=.1,GP="#ffffff";function $P(r){return !(r>0)||r>=id?1:1+WP*Math.sin(Math.PI*r/id)}function l0(r,e,t){if(e.glyphs.length!==0){r.save(),r.setLineDash([]),r.textAlign="center",r.textBaseline="middle";for(let n of e.glyphs){let o=n.cluster.marks[0];if(!o)continue;let i=n.cluster.key,s=o.glyph.color,a=i===t.activeKey||i===t.flashKey,l=n.size*(i===t.hoverKey?$P(t.nowMs-t.hoverSince):1);if(n.depth===0){let p=Math.round(n.x)+.5;r.lineWidth=1,r.strokeStyle=t.stemColor,r.beginPath(),r.moveTo(p,n.y+n.size/2),r.lineTo(p,t.axisY),r.stroke();}let c=o.glyph.shape??"circle",d=XP(r,c,n.x,n.y,l);r.lineWidth=4,r.strokeStyle=t.background,r.stroke(),r.fillStyle=a?s:t.background,r.fill(),r.lineWidth=1.5,r.strokeStyle=s,r.stroke();let u=a?GP:s,h=Math.round(l*.62);if(o.glyph.icon){let p=t.icons.get(o.glyph.icon,u,h,t.dpr);p&&r.drawImage(p,d.x-h/2,d.y-h/2,h,h);}else if(o.glyph.letter){let p=o.glyph.letter.slice(0,2);r.fillStyle=u;let m=UP(l,p);r.font=`600 ${m}px ${t.fontFamily}`,p.length>1&&(m=KP(m,r.measureText(p).width,YP(c,l)),r.font=`600 ${m}px ${t.fontFamily}`),r.fillText(p,d.x,d.y+.5);}}r.restore();}}function UP(r,e){return Math.round(r*(e.length>1?.38:.58))}function YP(r,e){return (r==="pin"?e*.82:e)-3}function KP(r,e,t){return !(e>t)||!(e>0)?r:Math.max(4,Math.floor(r*t/e))}function XP(r,e,t,n,o){let i=o/2;switch(r.beginPath(),e){case "square":{let s=Math.min(3,i/2);return jP(r,t-i,n-i,o,o,s),{x:t,y:n}}case "diamond":return r.moveTo(t,n-i),r.lineTo(t+i,n),r.lineTo(t,n+i),r.lineTo(t-i,n),r.closePath(),{x:t,y:n};case "pin":{let s=i*.82,a=n-i+s;return r.arc(t,a,s,Math.PI*.75,Math.PI*.25,false),r.lineTo(t,n+i),r.closePath(),{x:t,y:a}}default:return r.arc(t,n,i,0,Math.PI*2),{x:t,y:n}}}function jP(r,e,t,n,o,i){r.moveTo(e+i,t),r.lineTo(e+n-i,t),r.quadraticCurveTo(e+n,t,e+n,t+i),r.lineTo(e+n,t+o-i),r.quadraticCurveTo(e+n,t+o,e+n-i,t+o),r.lineTo(e+i,t+o),r.quadraticCurveTo(e,t+o,e,t+o-i),r.lineTo(e,t+i),r.quadraticCurveTo(e,t,e+i,t),r.closePath();}var sd=class{constructor(e){this.onReady=e;this.cache=new Map;}get(e,t,n,o){let i=`${e}|${t}|${n}|${o}`;if(this.cache.has(i)){let c=this.cache.get(i);return c&&c.complete&&c.naturalWidth>0?c:null}let s=to(e);if(!s||typeof document>"u"||typeof Image>"u"||typeof XMLSerializer>"u")return this.cache.set(i,null),null;let a=qP(s,t,Math.max(1,Math.ceil(n*o)));if(!a)return this.cache.set(i,null),null;let l=new Image;return l.onload=()=>this.onReady(),l.src=`data:image/svg+xml;charset=utf-8,${encodeURIComponent(a)}`,this.cache.set(i,l),null}clear(){this.cache.clear();}};function qP(r,e,t){let n=document.createElement("template");n.innerHTML=r;let o=n.content.firstElementChild;return !o||o.tagName.toLowerCase()!=="svg"?null:(o.setAttribute("xmlns","http://www.w3.org/2000/svg"),o.setAttribute("width",String(t)),o.setAttribute("height",String(t)),o.setAttribute("color",e),new XMLSerializer().serializeToString(o))}var ad=class{constructor(){this.canvas=null;this.ctx=null;this.axisTextColor=en.textColor;this.drawScene=new qo({timeToLogical:()=>0,barAt:()=>null,theme:{}});this.markLayout={glyphs:[],stacks:new Map};this.markIcons=new sd(()=>this.onMarkIconReady?.());this.onMarkIconReady=null;this.barTimesSrc=null;this.barTimesCache=[];}mount(e){this.canvas=e,this.ctx=e.getContext("2d");}setMarkIconReady(e){this.onMarkIconReady=e;}markGlyphAt(e,t){return r0(this.markLayout,e,t)}markStackAt(e,t){return o0(this.markLayout,e,t)}markGlyphByKey(e){return this.markLayout.glyphs.find(t=>t.cluster.key===e)??null}markTooltipAt(e,t,n){let o=this.markGlyphAt(e,t);return o?i0(o.cluster,n):null}prepare(e,t,n){this.drawScene.setDeps({timeToLogical:o=>t.timeToLogical(o),barAt:o=>{let i=e.bars[Math.round(o)];return i?{high:i.high,low:i.low}:null},theme:n});}paneDrawingsRange(e,t,n,o){let i=null;for(let s of e)i=c0(i,this.drawingsRange(Zo(s,false),o,t.offsetOf(s.id)));if(n)for(let s of t.indicators.values())i=c0(i,this.drawingsRange(Zo(s,true),o,t.offsetOf(s.id)));return i}render(e,t,n,o){let i=this.ctx,s=this.canvas;if(!i||!s)return;let a=t.dpr,l=s.width/a,c=s.height/a,d=t.width,u=t.height;this.axisTextColor=o?.textColor??n.textColor,i.setTransform(a,0,0,a,0,0),i.clearRect(0,0,l,c),o&&(l>d||c>u)&&(i.fillStyle=o.background,l>d&&i.fillRect(d,0,l-d,c),c>u&&i.fillRect(0,u,d,c-u)),i.font=`${e.style.fontSize}px ${n.fontFamily}`,i.textBaseline="middle";let h=e.orderedPanes();if(t.barCount===0){this.drawPaneSeparators(i,e,n,l,h),this.markLayout={glyphs:[],stacks:new Map};return}let p=h.find(m=>m.kind==="price")??null;if(p&&!p.collapsed&&e.tradeMarkers.visible)for(let m of e.indicators.values())m.trades?.length&&this.renderTrades(i,t,e,n,m.trades,p,d);this.drawPriceAxes(i,e,t,n,d,h),this.drawMergedScaleColumns(i,e,t,d),this.drawPaneSeparators(i,e,n,l,h),this.drawPriceLineAndCountdown(i,e,t,n,d,p),this.drawTimeAxis(i,e,t,n,d,u,c),this.drawMarkLane(i,e,t,n,d,u);}drawMarkLane(e,t,n,o,i,s){if(!t.marks.visible||t.timelineMarks.length===0){this.markLayout={glyphs:[],stacks:new Map};return}this.markLayout=n0({marks:t.timelineMarks,groups:t.markGroups,hidden:l=>!Zc(t.marks,l,t.markGroups),barTimes:this.barTimes(t),intervalMs:n.barInterval,xOf:l=>n.logicalToX(l),axisY:s,dataW:i,expanded:t.marksExpandedStack});let a=typeof performance<"u"?performance.now():Date.now();l0(e,this.markLayout,{axisY:s,background:o.background,stemColor:t.style.borderColor??o.borderColor,fontFamily:o.fontFamily,dpr:n.dpr,icons:this.markIcons,hoverKey:t.marksHoverKey,hoverSince:t.marksHoverSince,activeKey:t.marksActiveKey,flashKey:t.marksFlash&&t.marksFlash.until>a?t.marksFlash.key:null,nowMs:a});}barTimes(e){return (this.barTimesSrc!==e.bars||this.barTimesCache.length!==e.bars.length)&&(this.barTimesSrc=e.bars,this.barTimesCache=e.bars.map(t=>t.time)),this.barTimesCache}destroy(){this.canvas=null,this.ctx=null;}drawingsRange(e,t,n=0){if(this.drawScene.setSet(e,n),this.drawScene.isEmpty())return null;let o=this.drawScene.priceRange(t.from,t.to);return o?{min:o.min,max:o.max}:null}renderTrades(e,t,n,o,i,s,a){e.save(),e.translate(0,s.bounds.top),e.beginPath(),e.rect(0,0,a,s.bounds.height),e.clip(),Gw(e,i,n.tradeMarkers,{timeToLogical:l=>t.timeToLogical(l),barAt:l=>{let c=n.bars[Math.round(l)];return c?{high:c.high,low:c.low}:null}},l=>t.logicalToX(l),l=>t.priceToY(l,s.scale,s.bounds)-s.bounds.top,{fontSize:n.style.fontSize,fontFamily:o.fontFamily,color:o.textColor},a,Math.max(1.5,t.bodySpacing()*.4)),e.restore();}drawPriceAxes(e,t,n,o,i,s){if(e.strokeStyle=t.style.borderColor??o.borderColor,e.lineWidth=1,e.beginPath(),e.moveTo(i+.5,0),e.lineTo(i+.5,n.height),e.stroke(),!!t.showAxisLabels){e.fillStyle=this.axisTextColor,e.textAlign="left";for(let a of s){if(a.collapsed)continue;let l=Dn(t,a);for(let c of Fs(a.scale,a.bounds.height,l,t.priceMintick,a.axisFormat)){let d=n.priceToY(c.price,a.scale,a.bounds);da.bounds.top+a.bounds.height-4||e.fillText(c.label,i+6,d);}if(a.axisBands)for(let c of a.axisBands){let d=a.bounds.top+c.frac*a.bounds.height;da.bounds.top+a.bounds.height-4||e.fillText(c.label,i+6,d);}}e.textAlign="start";}}drawPaneSeparators(e,t,n,o,i){e.fillStyle=t.style.separatorColor??n.borderColor;for(let s of i)s.order<=0||e.fillRect(0,Math.round(s.bounds.top)-1,o,3);}drawMergedScaleColumns(e,t,n,o){if(t.showAxisLabels){e.textAlign="left",e.fillStyle=this.axisTextColor;for(let i of t.orderedPanes()){if(i.collapsed)continue;t.ownScaleIndicatorsForPane(i.id).forEach((a,l)=>{let c=t.indicatorScales.get(a.id)?.scale;if(!c)return;let d=sw(o,l+1);for(let u of Fs(c,i.bounds.height,void 0,t.priceMintick)){let h=n.priceToY(u.price,c,i.bounds);hi.bounds.top+i.bounds.height-4||e.fillText(u.label,d+5,h);}});}e.textAlign="start";}}drawPriceLineAndCountdown(e,t,n,o,i,s){let a=t.bars.length;if(!s||a===0||t.candlesHidden||s.collapsed||s.bounds.height<=0)return;let l=t.bars[a-1],c=n.priceToY(l.close,s.scale,s.bounds);if(cs.bounds.top+s.bounds.height)return;let d=this.priceElementColor(t,n,o,l);if(t.showPriceLine){let C=Math.round(c)+.5;e.strokeStyle=d,e.lineWidth=1,d0(e,"dotted"),e.beginPath(),e.moveTo(0,C),e.lineTo(i,C),e.stroke(),d0(e,"solid");}let u=t.showCountdown?e0(l.time,n.barInterval,Date.now()):null,h=u!==null,p=t.showPriceLabel;if(!p&&!h)return;let m=Vs(s.scale,s.bounds.height,l.close,Dn(t,s),t.priceMintick),f=8,g=i+1,b=t0(d,o.background);if(e.textBaseline="middle",p&&u!==null){let C=Math.max(e.measureText(m).width,e.measureText(u).width)+f,M=c-8,S=g+f/2;e.fillStyle=d,e.fillRect(g,M,C,32),e.fillStyle=b,e.textAlign="left",e.fillText(m,S,M+8),e.fillText(u,S,M+24),e.textAlign="start";return}let y=p?m:u??"",w=e.measureText(y).width+f;e.fillStyle=d,e.fillRect(g,c-8,w,16),e.fillStyle=b,e.textAlign="center",e.fillText(y,g+w/2,c),e.textAlign="start";}priceElementColor(e,t,n,o){let i=e.style;switch(e.priceStyle){case "bars":return o.close>=o.open?i.bars.upColor??n.upColor:i.bars.downColor??n.downColor;case "line":return i.line.color??n.upColor;case "area":return i.area.lineColor??n.upColor;case "baseline":{let s=Math.max(0,Math.floor(t.visibleLogicalRange().from)),a=e.baselineValue??e.bars[s]?.close??0;return o.close>=a?i.baseline.topLineColor??n.upColor:i.baseline.bottomLineColor??n.downColor}default:return o.close>=o.open?n.upColor:n.downColor}}drawTimeAxis(e,t,n,o,i,s,a){if(e.strokeStyle=t.style.borderColor??o.borderColor,e.lineWidth=1,e.beginPath(),e.moveTo(0,s+.5),e.lineTo(i,s+.5),e.stroke(),!t.showAxisLabels)return;e.fillStyle=this.axisTextColor,e.textAlign="center";let l=s+(a-s)/2,c=n.visibleTimeRange(),d=Is((c.from+c.to)/2,t.timezone),u=Math.max(3,Math.min(8,Math.floor(i/64))),h=od(c.from,c.to,u,d).map(g=>({...g,x:n.timeToX(g.time),half:e.measureText(g.label).width/2})).filter(g=>g.x>=20&&g.x<=i-20),p=12,m=[],f=g=>{let b=g.x-g.half,y=g.x+g.half;m.every(w=>y+p<=w.l||b-p>=w.r)&&(m.push({l:b,r:y}),e.fillText(g.label,g.x,l));};for(let g of h)g.major&&f(g);for(let g of h)g.major||f(g);e.textAlign="start";}};function c0(r,e){return r?e?{min:Math.min(r.min,e.min),max:Math.max(r.max,e.max)}:r:e}function d0(r,e){e==="dashed"?r.setLineDash([6,4]):e==="dotted"?r.setLineDash([2,3]):r.setLineDash([]);}var QP=350,ld=class{constructor(e,t){this.plot=e;this.deps=t;this.tip=null;this.timer=null;this.current=null;this.onMove=e=>{if(e.pointerType!=="mouse")return;let t=this.plot.getBoundingClientRect(),n=e.clientX-t.left,o=e.clientY-t.top,i=this.deps.lookup(n,o);if(!i){this.clear();return}i!==this.current&&(this.clear(),this.current=i,this.timer=window.setTimeout(()=>this.show(i,n,o),QP));};this.onLeave=()=>{this.clear();};e.addEventListener("pointermove",this.onMove),e.addEventListener("pointerleave",this.onLeave),e.addEventListener("pointerdown",this.onLeave);}destroy(){this.plot.removeEventListener("pointermove",this.onMove),this.plot.removeEventListener("pointerleave",this.onLeave),this.plot.removeEventListener("pointerdown",this.onLeave),this.clear();}show(e,t,n){let i=this.plot.ownerDocument.createElement("div");i.textContent=e,i.style.cssText="position:absolute;z-index:var(--vela-z-tooltip);pointer-events:none;background:var(--vela-bg);border:1px solid var(--vela-border);color:var(--vela-fg);border-radius:var(--vela-radius-md);padding:4px 9px;box-shadow:var(--vela-shadow);font:var(--vela-font-size-md) var(--vela-font);max-width:260px;",Be(i,this.deps.theme()),this.plot.appendChild(i);let s=this.plot.clientWidth,a=this.plot.clientHeight;i.style.left=`${Math.max(0,Math.min(t+12,s-i.offsetWidth-4))}px`,i.style.top=`${Math.max(0,Math.min(n+16,a-i.offsetHeight-4))}px`,this.tip=i;}clear(){this.timer!==null&&(clearTimeout(this.timer),this.timer=null),this.tip?.remove(),this.tip=null,this.current=null;}};var cd=class{constructor(){this.canvas=null;this.ctx=null;}mount(e){this.canvas=e,this.ctx=e.getContext("2d");}render(e,t,n,o=null,i=null){let s=this.ctx,a=this.canvas;if(!s||!a)return;let l=t.dpr;s.setTransform(l,0,0,l,0,0),s.clearRect(0,0,a.width/l,a.height/l),o!==null&&this.drawSeparatorHover(s,a.width/l,n,o),i&&this.drawExternal(s,i,e,t,n);let c=e.crosshair,d=t.width,u=t.height;if(!c||c.x<0||c.x>d||c.y<0||c.y>u)return;let h=e.style.crosshair,p=e.crosshairOverride,m=p?.vertical!==false,f=p?.horizontal!==false;s.font=`${e.style.fontSize}px ${n.fontFamily}`,s.textBaseline="middle";let g=Math.round(t.xToLogical(c.x)),b=u0(t.logicalToX(g),p?.width??h.width);if(m&&p?.shadeRight){let C=Math.max(0,Math.round(t.logicalToX(g+.5)));C=C.bounds.top&&c.y<=C.bounds.top+C.bounds.height){y=C;break}let w=h.labelBackground??n.borderColor;if(f&&y&&y.axisFormat!=="none"){let C=t.yToPrice(c.y,y.scale,y.bounds);this.chip(s,d+1,c.y,Vs(y.scale,y.bounds.height,C,Dn(e,y),e.priceMintick,y.axisFormat),w,"left",false,n.background);}m&&this.chip(s,b,u+1,ep(t.logicalToTime(g),e.timezone,t.barInterval),w,"center",true,n.background);}destroy(){this.canvas=null,this.ctx=null;}drawExternal(e,t,n,o,i){let s=n.style.crosshair,a=n.crosshairOverride,l=o.width,c=o.height,d=u0(t.x,a?.width??s.width);if(a?.vertical===false)return;if(a?.shadeRight){let h=Math.max(0,Math.round(o.logicalToX(Math.round(o.xToLogical(t.x))+.5)));hl)return;e.font=`${n.style.fontSize}px ${i.fontFamily}`,e.textBaseline="middle",e.strokeStyle=a?.color??s.color??i.textColor,e.lineWidth=a?.width??s.width,e.globalAlpha=(a?.opacity??s.opacity)*.55,h0(e,a?.style??s.style),e.beginPath(),e.moveTo(d,0),e.lineTo(d,c),t.y!=null&&a?.horizontal!==false&&(e.moveTo(0,Math.round(t.y)+.5),e.lineTo(l,Math.round(t.y)+.5)),e.stroke(),e.setLineDash([]),e.lineWidth=1,e.globalAlpha=.8;let u=s.labelBackground??i.borderColor;if(t.y!=null&&t.price!=null&&a?.horizontal!==false){let h;for(let p of n.panes.values())if(t.y>=p.bounds.top&&t.y<=p.bounds.top+p.bounds.height){h=p;break}h&&h.axisFormat!=="none"&&this.chip(e,l+1,t.y,Vs(h.scale,h.bounds.height,t.price,Dn(n,h),n.priceMintick,h.axisFormat),u,"left",false,i.background);}this.chip(e,d,c+1,ep(t.time,n.timezone,o.barInterval),u,"center",true,i.background),e.globalAlpha=1;}drawSeparatorHover(e,t,n,o){let i=Math.round(o);e.fillStyle=n.textColor,e.globalAlpha=.1,e.fillRect(0,i-4,t,8),e.globalAlpha=.55,e.fillRect(0,i-1,t,2),e.globalAlpha=1;}chip(e,t,n,o,i,s,a=false,l="#000000"){let c=e.measureText(o).width+8,d=16,u=s==="left"?t:t-c/2,h=a?n:n-d/2;e.fillStyle=i,e.fillRect(u,h,c,d),e.fillStyle=Sw(i,l),e.textAlign="center",e.fillText(o,u+c/2,h+d/2+(a?2:0)),e.textAlign="start";}};function u0(r,e){return Math.round(r)+(Math.round(e)%2===1?.5:0)}function h0(r,e){e==="dashed"?r.setLineDash([6,4]):e==="dotted"?r.setLineDash([2,3]):r.setLineDash([]);}var tp=[{value:"Etc/UTC",label:"UTC"},{value:"Etc/GMT+12",label:"International Date Line West"},{value:"Pacific/Pago_Pago",label:"Pago Pago"},{value:"Pacific/Honolulu",label:"Honolulu"},{value:"Pacific/Marquesas",label:"Marquesas Islands"},{value:"America/Anchorage",label:"Anchorage"},{value:"America/Los_Angeles",label:"Los Angeles"},{value:"America/Phoenix",label:"Phoenix"},{value:"America/Denver",label:"Denver"},{value:"America/Chicago",label:"Chicago"},{value:"America/Mexico_City",label:"Mexico City"},{value:"America/New_York",label:"New York"},{value:"America/Bogota",label:"Bogot\xE1"},{value:"America/Caracas",label:"Caracas"},{value:"America/Santiago",label:"Santiago"},{value:"America/St_Johns",label:"St. John's"},{value:"America/Sao_Paulo",label:"S\xE3o Paulo"},{value:"America/Argentina/Buenos_Aires",label:"Buenos Aires"},{value:"America/Noronha",label:"Fernando de Noronha"},{value:"Atlantic/Azores",label:"Azores"},{value:"Atlantic/Reykjavik",label:"Reykjavik"},{value:"Europe/London",label:"London"},{value:"Europe/Paris",label:"Paris"},{value:"Europe/Berlin",label:"Berlin"},{value:"Europe/Athens",label:"Athens"},{value:"Africa/Cairo",label:"Cairo"},{value:"Africa/Johannesburg",label:"Johannesburg"},{value:"Europe/Moscow",label:"Moscow"},{value:"Europe/Istanbul",label:"Istanbul"},{value:"Asia/Tehran",label:"Tehran"},{value:"Asia/Dubai",label:"Dubai"},{value:"Asia/Kabul",label:"Kabul"},{value:"Asia/Karachi",label:"Karachi"},{value:"Asia/Kolkata",label:"Mumbai"},{value:"Asia/Kathmandu",label:"Kathmandu"},{value:"Asia/Dhaka",label:"Dhaka"},{value:"Asia/Yangon",label:"Yangon"},{value:"Asia/Bangkok",label:"Bangkok"},{value:"Asia/Shanghai",label:"Shanghai"},{value:"Asia/Hong_Kong",label:"Hong Kong"},{value:"Asia/Singapore",label:"Singapore"},{value:"Australia/Eucla",label:"Eucla"},{value:"Asia/Tokyo",label:"Tokyo"},{value:"Asia/Seoul",label:"Seoul"},{value:"Australia/Adelaide",label:"Adelaide"},{value:"Australia/Sydney",label:"Sydney"},{value:"Australia/Lord_Howe",label:"Lord Howe Island"},{value:"Pacific/Noumea",label:"Noum\xE9a"},{value:"Pacific/Auckland",label:"Auckland"},{value:"Pacific/Chatham",label:"Chatham Islands"},{value:"Pacific/Apia",label:"Apia"},{value:"Pacific/Kiritimati",label:"Kiritimati"}];function dd(r){return r==="UTC"||r==="Etc/UTC"||r==="Etc/GMT"?"Etc/UTC":r}function JP(r,e=new Date){try{let o=(new Intl.DateTimeFormat("en-US",{timeZone:r,timeZoneName:"shortOffset"}).formatToParts(e).find(l=>l.type==="timeZoneName")?.value??"").match(/GMT(?:(\+|-)(\d{1,2})(?::(\d{2}))?)?/);if(!o||!o[1])return "UTC";let i=o[1]==="-"?"-":"+",s=o[2]??"0",a=o[3]??"";return a?`UTC${i}${s}:${a}`:`UTC${i}${s}`}catch{return "UTC"}}function np(r,e){return dd(r)==="Etc/UTC"?e:`(${JP(r)}) ${e}`}function rr(r){return r.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}var rp="events",ud="events.groups";function op(r){return `${ud}.${rr(r)}`}function Mt(r,e){if(e.size===0)return false;let t=r;for(;;){if(e.has(t))return true;let n=t.lastIndexOf(".");if(n<0)return false;t=t.slice(0,n);}}function p0(r){if(r.kind==="heading"||r.kind==="header")return rr(r.label);let e=co(r);if(e.toggle)return e.toggle.key;for(let t of e.controls)if(t.kind!=="hint")return t.key;return rr(e.label)}function hd(r,e,t){if(t.size===0)return [...r];let n=[],o=false,i=false;for(let s of r){let a=`${e}.${p0(s)}`;if(s.kind==="heading"){o=Mt(a,t),i=false,o||n.push(s);continue}if(s.kind==="header"){if(o)continue;i=Mt(a,t),i||n.push(s);continue}o||i||Mt(a,t)||n.push(s);}return n}function ip(r){return r.id??rr(r.title)}function m0(r){return r.id??rr(r.label)}function f0(r,e,t){if(t.size===0)return [...r];let n=[],o=false;for(let i of r){let s=`${e}.${m0(i)}`;if(i.kind==="heading"){o=Mt(s,t),o||n.push(i);continue}o||Mt(s,t)||n.push(i);}return n}var eI=["symbol","symbol.type","symbol.style.candles","symbol.style.candles.body","symbol.style.candles.borders","symbol.style.candles.wick","symbol.style.candles.spacing","symbol.style.bars","symbol.style.bars.up-color","symbol.style.bars.down-color","symbol.style.bars.spacing","symbol.style.line","symbol.style.line.color","symbol.style.line.width","symbol.style.area","symbol.style.area.line-color","symbol.style.area.width","symbol.style.area.top-fill","symbol.style.area.bottom-fill","symbol.style.baseline","symbol.style.baseline.top-line","symbol.style.baseline.bottom-line","symbol.style.baseline.fill-top","symbol.style.baseline.fill-bottom","symbol.style.baseline.base-level","symbol.style.baseline.width","symbol.animation","symbol.animation.zoom","symbol.animation.pan","symbol.animation.autoscale","symbol.animation.price-changes","symbol.animation.intro","symbol.timezone","scales","scales.price-scale","scales.price-scale.mode","scales.price-scale.invert","scales.price-scale.last-price-line","scales.price-scale.last-price-label","scales.price-scale.countdown","scales.price-scale.axis-labels","scales.price-scale.border-color","scales.crosshair","scales.crosshair.color","scales.crosshair.width","scales.crosshair.style","canvas","canvas.background","canvas.background.color","canvas.background.text-color","canvas.background.text-size","canvas.background.pane-separator","canvas.grid","canvas.grid.vertical","canvas.grid.horizontal","canvas.margins","canvas.margins.top","canvas.margins.bottom","canvas.margins.right","canvas.theme"];function g0(r,e=[]){let t=new Set(eI);if(e.length>0){t.add(rp),t.add(ud);for(let n of e)t.add(op(n.id));}for(let n of xt()){if(Wo(n.id)){let a=`symbol.style.${n.id}`;for(let l of ["",".body",".borders",".wick",".spacing"])t.add(a+l);}let o=n.settings;if(!o)continue;let i=`type:${n.id}`;t.add(i);let s=a=>{for(let l of a)t.add(`${i}.${p0(l)}`);};o.rows&&s(o.rows);for(let a of o.instances??[])s(a.rows);for(let a of o.subsections??[])t.add(`${i}.${rr(a.title)}`),s(a.rows);}for(let n of r){let o=ip(n);t.add(o);for(let i of n.rows)t.add(`${o}.${m0(i)}`);}return [...t]}var tI={candles:"Candles",bars:"Bars",line:"Line",area:"Area",baseline:"Baseline"};function nI(r){return xn(r)?.label??tI[r]??r}var b0="vela-settings-controls",v0="6";var rI="var(--vela-border)";function oI(){if(typeof document>"u")return;let r=document.getElementById(b0);if(r?.dataset.rev===v0)return;let e=r??document.createElement("style");e.id=b0,e.dataset.rev=v0,e.textContent=` -${Ir(".vela-sd-pane")} +`),l=6,c=4,d=i*1.25,h=Math.max(1,...a.map(y=>this.measure(e,e.font,y)))+l*2,p=d*a.length+c*2,m=7,f=n-h/2,g=o-p-m,b="down";switch(t.style){case "label_up":f=n-h/2,g=o+m,b="up";break;case "label_left":f=n+m,g=o-p/2,b="left";break;case "label_right":f=n-h-m,g=o-p/2,b="right";break;case "label_center":f=n-h/2,g=o-p/2,b="none";break;case "label_lower_left":f=n+m,g=o-p-m,b="none";break;case "label_lower_right":f=n-h-m,g=o-p-m,b="none";break;case "label_upper_left":f=n+m,g=o+m,b="none";break;case "label_upper_right":f=n-h-m,g=o+m,b="none";break;default:f=n-h/2,g=o-p-m,b="down";}if(t.noFill||(e.fillStyle=s,this.roundRect(e,f,g,h,p,4),e.fill(),b!=="none"&&(e.beginPath(),b==="down"?(e.moveTo(n-m,g+p),e.lineTo(n+m,g+p),e.lineTo(n,o)):b==="up"?(e.moveTo(n-m,g),e.lineTo(n+m,g),e.lineTo(n,o)):b==="left"?(e.moveTo(f,o-m),e.lineTo(f,o+m),e.lineTo(n,o)):(e.moveTo(f+h,o-m),e.lineTo(f+h,o+m),e.lineTo(n,o)),e.closePath(),e.fill())),t.text){e.fillStyle=t.textColor??(t.noFill?this.deps.theme.textColor:Ye(s)),e.textBaseline="middle";let y;t.textAlign==="left"?(e.textAlign="left",y=f+l):t.textAlign==="right"?(e.textAlign="right",y=f+h-l):(e.textAlign="center",y=f+h/2);let w=g+c+d/2;for(let S=0;SNumber(n.find(a=>a.type===s)?.value);return Date.UTC(o("year"),o("month")-1,o("day"),o("hour")%24,o("minute"),o("second"))-r}catch{return 0}}function rd(r,e){return new Date(r+Os(r,e))}function id(r,e,t=6){if(!(e>r)||!Number.isFinite(r)||!Number.isFinite(e))return [];let n=(e-r)/Math.max(1,t),o=Math.pow(10,Math.floor(Math.log10(n))),i=n/o,s=(i<1.5?1:i<3?2:i<7?5:10)*o,a=Math.max(0,-Math.floor(Math.log10(s))+1),l=Math.ceil(r/s)*s;if(!(s>0)||l+s===l)return [];let c=Math.floor((e-l)/s+1e-6)+1;if(!(c>0)||c>1e3)return [];let d=[];for(let u=0;ur))return 2;let n=(e-r)/Math.max(1,t),o=Math.pow(10,Math.floor(Math.log10(n))),i=n/o,s=(i<1.5?1:i<3?2:i<7?5:10)*o;return Math.max(0,Math.min(8,-Math.floor(Math.log10(s))+1))}function GP(r,e,t=6){if(r<=0||!(e>r)||!Number.isFinite(r)||!Number.isFinite(e))return [];if(Math.log10(e)-Math.log10(r)<1.1)return id(r,e,t);let n=[],o=Math.floor(Math.log10(r)),i=Math.ceil(Math.log10(e));for(let s=o;s<=i;s+=1)for(let a of [1,2,5]){let l=a*Math.pow(10,s);l>=r&&l<=e&&n.push(l);}return n}function op(r){let e=Math.abs(r);return e>=100?0:e>=1?2:e>=.01?4:6}function $P(r){if(!(r>0)||!Number.isFinite(r))return 2;for(let e=0;e<=8;e+=1)if(Math.abs(Number(r.toFixed(e))-r)<=r*1e-6)return e;return 8}function UP(r,e,t){let n=t!=null&&t>0?$P(t):WP(r.min,r.max,_s(e));return n===0?2:n}function _s(r){return Math.max(2,Math.min(16,Math.round(r/50)))}function rx(r,e){return r.log?GP(r.min,r.max,_s(e)):id(r.min,r.max,_s(e))}function tp(r,e){return (r/e-1)*100}function np(r,e){return r/e*100}function ox(r){return `${r>=0?"+":"-"}${Math.abs(r).toFixed(2)}%`}function ix(r){return r.toFixed(2)}function sx(r){let e=Math.abs(r);return e>=1e9?`${od(r/1e9)}B`:e>=1e6?`${od(r/1e6)}M`:e>=1e3?`${od(r/1e3)}K`:od(r)}function od(r){return Number(r.toFixed(2)).toString()}function Hs(r,e,t,n,o){if(o==="none")return [];if(t){let{baseline:i,indexed:s}=t,a=Math.min(r.min,r.max),l=Math.max(r.min,r.max);if(s){let u=np(a,i),h=np(l,i);return id(u,h,_s(e)).map(p=>({price:i*p/100,label:ix(p)}))}let c=tp(a,i),d=tp(l,i);return id(c,d,_s(e)).map(u=>({price:i*(1+u/100),label:ox(u)}))}return o==="volume"?rx(r,e).map(i=>({price:i,label:sx(i)})):rx(r,e).map(i=>({price:i,label:ad(r,e,i,n)}))}function zs(r,e,t,n,o,i){return i==="none"?"":n?n.indexed?ix(np(t,n.baseline)):ox(tp(t,n.baseline)):i==="volume"?sx(t):ad(r,e,t,o)}function ad(r,e,t,n){if(r.log&&Math.log10(r.max)-Math.log10(r.min)>=1.1){let i=op(t);return t.toFixed(i===0?2:i)}return t.toFixed(UP(r,e,n))}var Ns=1e3,Fs=60*Ns,ni=60*Fs,jr=24*ni,YP=7*jr,sd=30*jr,rp=365*jr,ep=[Ns,5*Ns,15*Ns,30*Ns,Fs,5*Fs,15*Fs,30*Fs,ni,2*ni,4*ni,6*ni,12*ni,jr,2*jr,YP,sd,3*sd,rp],Vs=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],KP=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],Bs=r=>r<10?`0${r}`:String(r);function ip(r,e,t){let n=rd(r,e),o=`${KP[n.getUTCDay()]} ${n.getUTCDate()} ${Vs[n.getUTCMonth()]} '${Bs(n.getUTCFullYear()%100)}`;return t>=jr?o:`${o} ${Bs(n.getUTCHours())}:${Bs(n.getUTCMinutes())}`}function XP(r){for(let e of ep)if(e>=r)return e;return ep[ep.length-1]}function ld(r,e,t=8,n=0){let o=e-r;if(!(o>0))return [];let i=XP(o/Math.max(1,t)),s=r+n,a=e+n;if(i>=sd)return jP(s,a,i>=rp?12:i>=3*sd?3:1,n);let l=Math.ceil(s/i)*i,c=[];for(let d=l;d<=a;d+=i){let u=d-n,h=new Date(d),p,m=false;if(i0))return Hs(t.scale,s,i,e.priceMintick,o);let l=t.scale,c=this.memo.get(t),d=e.style.fontSize;if(c&&c.kind===t.kind&&c.min===l.min&&c.max===l.max&&c.log===!!l.log&&c.invert===!!l.invert&&c.height===s&&c.baseline===i?.baseline&&c.indexed===!!i?.indexed&&c.mintick===e.priceMintick&&c.format===o&&c.fontSize===d)return c.ticks;let u=Hs(l,s,i,e.priceMintick,o),h=this.callHook(a,e,t,n,u,i?.baseline,i?i.indexed?"indexed":"percent":"price");return this.memo.set(t,{kind:t.kind,min:l.min,max:l.max,log:!!l.log,invert:!!l.invert,height:s,baseline:i?.baseline,indexed:!!i?.indexed,mintick:e.priceMintick,format:o,fontSize:d,ticks:h}),h}callHook(e,t,n,o,i,s,a){let l={min:n.scale.min,max:n.scale.max,log:!!n.scale.log,invert:!!n.scale.invert},c={top:0,height:n.bounds.height},d={pane:{id:n.id,kind:n.kind},min:Math.min(l.min,l.max),max:Math.max(l.min,l.max),log:!!l.log,height:c.height,mode:a,baseline:s,mintick:t.priceMintick,fontSize:t.style.fontSize,priceToY:p=>o.priceToY(p,l,c),defaults:i},u;try{u=e(d);}catch(p){return this.warnOnce("threw",p),i}if(u==null)return i;if(!Array.isArray(u))return this.warnOnce("returned a non-array",u),i;let h=[];for(let p of u){if(!p||typeof p!="object")continue;let{price:m,label:f,major:g}=p;typeof m!="number"||!Number.isFinite(m)||typeof f!="string"||h.push(typeof g=="boolean"?{price:m,label:f,major:g}:{price:m,label:f});}return h}warnOnce(e,t){this.warned||(this.warned=true,console.warn(`[vela] the priceAxisTicks function ${e} \u2014 the default ticks are used instead.`,t));}};function ax(r,e,t){if(!(e>0))return null;let n=r+e-t;return n<=0?null:qP(n)}function qP(r){let e=Math.max(0,Math.ceil(r/1e3)),t=e%60,n=Math.floor(e/60)%60,o=Math.floor(e/3600),i=s=>String(s).padStart(2,"0");return o>0?`${o}:${i(n)}:${i(t)}`:`${i(n)}:${i(t)}`}function lx(r,e){let[t,n,o,i]=se(r),s=t,a=n,l=o;if(i<1){let[u,h,p]=se(e);s=t*i+u*(1-i),a=n*i+h*(1-i),l=o*i+p*(1-i);}let c=u=>u<=.04045?u/12.92:Math.pow((u+.055)/1.055,2.4);return .2126*c(s)+.7152*c(a)+.0722*c(l)>=.4?"#000000":"#ffffff"}function ZP(r,e,t){let n=e.length;if(n===0||!(t>0)||!Number.isFinite(r)||r=o+t)return n-1+Math.floor((r-o)/t);let i=0,s=n-1;for(;i>1;e[a]<=r?i=a:s=a-1;}return r{if(s.group!==void 0&&n(s.group))return;let l=ZP(s.time,e,t);if(l===null)return;let c=`${l}|${s.group??""}`,d=o.get(c);d||(d={key:c,bar:l,group:s.group,marks:[],seq:[]},o.set(c,d)),d.marks.push(s),d.seq.push(a);});let i=[];for(let s of o.values()){let a=s.marks.map((l,c)=>({m:l,seq:s.seq[c]})).sort((l,c)=>l.m.time-c.m.time||l.seq-c.seq);i.push({key:s.key,bar:s.bar,group:s.group,marks:a.map(l=>l.m)});}return i}function JP(r,e,t=20){let n=new Map;for(let i of r){let s=n.get(i.group);s?s.push(i):n.set(i.group,[i]);}let o=[];for(let i of n.values()){i.sort((l,c)=>l.bar-c.bar);let s=[],a=Number.NaN;for(let l of i){let c=e(l.bar),d=s[s.length-1];d&&Number.isFinite(c)&&Number.isFinite(a)&&c-at.set(n.id,o));for(let n of e)n.group!==void 0&&!t.has(n.group)&&t.set(n.group,t.size);return n=>n===void 0?Number.MAX_SAFE_INTEGER:t.get(n)??Number.MAX_SAFE_INTEGER-1}function cx(r){let e=JP(QP(r.marks,r.barTimes,r.intervalMs,r.hidden),r.xOf),t=eI(r.groups,e),n=new Map;for(let s of e){let a=n.get(s.bar);a?a.push(s):n.set(s.bar,[s]);}let o=[],i=new Map;for(let[s,a]of n){let l=r.xOf(s);if(!Number.isFinite(l)||l<-20||l>r.dataW+20)continue;a.sort((f,g)=>t(f.group)-t(g.group));let c=a.length>1,d=c&&r.expanded===s,u=c&&!d,h=[],p=a[0].marks.length>1?20:16,m=r.axisY-4;a.forEach((f,g)=>{let b=u?p:f.marks.length>1?20:16,y;d?(y=m-b/2,m-=b+4):y=r.axisY-4-b/2-g*3,h.push({cluster:f,x:l,y,size:b,stack:s,depth:g,decked:u});});for(let f=h.length-1;f>=0;f--)o.push(h[f]);i.set(s,h);}return {glyphs:o,stacks:i}}function dx(r,e,t){for(let n=r.glyphs.length-1;n>=0;n--){let o=r.glyphs[n];if(o.decked&&o.depth!==0)continue;let i=o.size/2+3;if(Math.abs(e-o.x)<=i&&Math.abs(t-o.y)<=i)return o}return null}function ux(r,e,t){for(let[n,o]of r.stacks){for(let i of o){let s=i.size/2+3;if(Math.abs(e-i.x)<=s&&Math.abs(t-i.y)<=s)return n}if(o.length>1&&!o[0].decked){let i=o[o.length-1],s=o[0],a=Math.max(i.size,s.size)/2+3;if(Math.abs(e-s.x)<=a&&t>=i.y-i.size/2-8&&t<=s.y+s.size/2+3)return n}}return null}function hx(r,e){let t=r.marks[0];return t?r.marks.length===1?t.tooltip??t.title??null:`${r.group!==void 0?px(r.group,e):t.title??t.tooltip??"Marks"} \xB7 ${r.marks.length}`:null}function px(r,e){let t=e.find(n=>n.id===r);return t?t.label:r.charAt(0).toUpperCase()+r.slice(1)}function mx(r,e){let t=e.map(o=>({...o})),n=new Set(t.map(o=>o.id));for(let o of r)o.group===void 0||n.has(o.group)||(n.add(o.group),t.push({id:o.group,label:px(o.group,e)}));return t}var cd=360,tI=.1,nI="#ffffff";function rI(r){return !(r>0)||r>=cd?1:1+tI*Math.sin(Math.PI*r/cd)}function fx(r,e,t){if(e.glyphs.length!==0){r.save(),r.setLineDash([]),r.textAlign="center",r.textBaseline="middle";for(let n of e.glyphs){let o=n.cluster.marks[0];if(!o)continue;let i=n.cluster.key,s=o.glyph.color,a=i===t.activeKey||i===t.flashKey,l=n.size*(i===t.hoverKey?rI(t.nowMs-t.hoverSince):1);if(n.depth===0){let p=Math.round(n.x)+.5;r.lineWidth=1,r.strokeStyle=t.stemColor,r.beginPath(),r.moveTo(p,n.y+n.size/2),r.lineTo(p,t.axisY),r.stroke();}let c=o.glyph.shape??"circle",d=aI(r,c,n.x,n.y,l);r.lineWidth=4,r.strokeStyle=t.background,r.stroke(),r.fillStyle=a?s:t.background,r.fill(),r.lineWidth=1.5,r.strokeStyle=s,r.stroke();let u=a?nI:s,h=Math.round(l*.62);if(o.glyph.icon){let p=t.icons.get(o.glyph.icon,u,h,t.dpr);p&&r.drawImage(p,d.x-h/2,d.y-h/2,h,h);}else if(o.glyph.letter){let p=o.glyph.letter.slice(0,2);r.fillStyle=u;let m=oI(l,p);r.font=`600 ${m}px ${t.fontFamily}`,p.length>1&&(m=sI(m,r.measureText(p).width,iI(c,l)),r.font=`600 ${m}px ${t.fontFamily}`),r.fillText(p,d.x,d.y+.5);}}r.restore();}}function oI(r,e){return Math.round(r*(e.length>1?.38:.58))}function iI(r,e){return (r==="pin"?e*.82:e)-3}function sI(r,e,t){return !(e>t)||!(e>0)?r:Math.max(4,Math.floor(r*t/e))}function aI(r,e,t,n,o){let i=o/2;switch(r.beginPath(),e){case "square":{let s=Math.min(3,i/2);return lI(r,t-i,n-i,o,o,s),{x:t,y:n}}case "diamond":return r.moveTo(t,n-i),r.lineTo(t+i,n),r.lineTo(t,n+i),r.lineTo(t-i,n),r.closePath(),{x:t,y:n};case "pin":{let s=i*.82,a=n-i+s;return r.arc(t,a,s,Math.PI*.75,Math.PI*.25,false),r.lineTo(t,n+i),r.closePath(),{x:t,y:a}}default:return r.arc(t,n,i,0,Math.PI*2),{x:t,y:n}}}function lI(r,e,t,n,o,i){r.moveTo(e+i,t),r.lineTo(e+n-i,t),r.quadraticCurveTo(e+n,t,e+n,t+i),r.lineTo(e+n,t+o-i),r.quadraticCurveTo(e+n,t+o,e+n-i,t+o),r.lineTo(e+i,t+o),r.quadraticCurveTo(e,t+o,e,t+o-i),r.lineTo(e,t+i),r.quadraticCurveTo(e,t,e+i,t),r.closePath();}var dd=class{constructor(e){this.onReady=e;this.cache=new Map;}get(e,t,n,o){let i=`${e}|${t}|${n}|${o}`;if(this.cache.has(i)){let c=this.cache.get(i);return c&&c.complete&&c.naturalWidth>0?c:null}let s=io(e);if(!s||typeof document>"u"||typeof Image>"u"||typeof XMLSerializer>"u")return this.cache.set(i,null),null;let a=cI(s,t,Math.max(1,Math.ceil(n*o)));if(!a)return this.cache.set(i,null),null;let l=new Image;return l.onload=()=>this.onReady(),l.src=`data:image/svg+xml;charset=utf-8,${encodeURIComponent(a)}`,this.cache.set(i,l),null}clear(){this.cache.clear();}};function cI(r,e,t){let n=document.createElement("template");n.innerHTML=r;let o=n.content.firstElementChild;return !o||o.tagName.toLowerCase()!=="svg"?null:(o.setAttribute("xmlns","http://www.w3.org/2000/svg"),o.setAttribute("width",String(t)),o.setAttribute("height",String(t)),o.setAttribute("color",e),new XMLSerializer().serializeToString(o))}var uI=.5,ud=class{constructor(e=new ir){this.axisTicks=e;this.canvas=null;this.ctx=null;this.axisTextColor=tn.textColor;this.drawScene=new ei({timeToLogical:()=>0,barAt:()=>null,theme:{}});this.markLayout={glyphs:[],stacks:new Map};this.markIcons=new dd(()=>this.onMarkIconReady?.());this.onMarkIconReady=null;this.barTimesSrc=null;this.barTimesCache=[];}mount(e){this.canvas=e,this.ctx=e.getContext("2d");}setMarkIconReady(e){this.onMarkIconReady=e;}markGlyphAt(e,t){return dx(this.markLayout,e,t)}markStackAt(e,t){return ux(this.markLayout,e,t)}markGlyphByKey(e){return this.markLayout.glyphs.find(t=>t.cluster.key===e)??null}markTooltipAt(e,t,n){let o=this.markGlyphAt(e,t);return o?hx(o.cluster,n):null}prepare(e,t,n){this.drawScene.setDeps({timeToLogical:o=>t.timeToLogical(o),barAt:o=>{let i=e.bars[Math.round(o)];return i?{high:i.high,low:i.low}:null},theme:n});}paneDrawingsRange(e,t,n,o){let i=null;for(let s of e)i=gx(i,this.drawingsRange(ti(s,false),o,t.offsetOf(s.id)));if(n)for(let s of t.indicators.values())i=gx(i,this.drawingsRange(ti(s,true),o,t.offsetOf(s.id)));return i}render(e,t,n,o){let i=this.ctx,s=this.canvas;if(!i||!s)return;let a=t.dpr,l=s.width/a,c=s.height/a,d=t.width,u=t.height;this.axisTextColor=o?.textColor??n.textColor,i.setTransform(a,0,0,a,0,0),i.clearRect(0,0,l,c),o&&(l>d||c>u)&&(i.fillStyle=o.background,l>d&&i.fillRect(d,0,l-d,c),c>u&&i.fillRect(0,u,d,c-u)),i.font=`${e.style.fontSize}px ${n.fontFamily}`,i.textBaseline="middle";let h=e.orderedPanes();if(t.barCount===0){this.drawPaneSeparators(i,e,n,l,h),this.markLayout={glyphs:[],stacks:new Map};return}let p=h.find(m=>m.kind==="price")??null;if(p&&!p.collapsed&&e.tradeMarkers.visible)for(let m of e.indicators.values())m.trades?.length&&this.renderTrades(i,t,e,n,m.trades,p,d);this.drawPriceAxes(i,e,t,n,d,h),this.drawMergedScaleColumns(i,e,t,d),this.drawPaneSeparators(i,e,n,l,h),this.drawPriceLineAndCountdown(i,e,t,n,d,p),this.drawTimeAxis(i,e,t,n,d,u,c),this.drawMarkLane(i,e,t,n,d,u);}drawMarkLane(e,t,n,o,i,s){if(!t.marks.visible||t.timelineMarks.length===0){this.markLayout={glyphs:[],stacks:new Map};return}this.markLayout=cx({marks:t.timelineMarks,groups:t.markGroups,hidden:l=>!td(t.marks,l,t.markGroups),barTimes:this.barTimes(t),intervalMs:n.barInterval,xOf:l=>n.logicalToX(l),axisY:s,dataW:i,expanded:t.marksExpandedStack});let a=typeof performance<"u"?performance.now():Date.now();e.save(),e.beginPath(),e.rect(0,0,i,s),e.clip(),fx(e,this.markLayout,{axisY:s,background:o.background,stemColor:t.style.borderColor??o.borderColor,fontFamily:o.fontFamily,dpr:n.dpr,icons:this.markIcons,hoverKey:t.marksHoverKey,hoverSince:t.marksHoverSince,activeKey:t.marksActiveKey,flashKey:t.marksFlash&&t.marksFlash.until>a?t.marksFlash.key:null,nowMs:a}),e.restore();}barTimes(e){return (this.barTimesSrc!==e.bars||this.barTimesCache.length!==e.bars.length)&&(this.barTimesSrc=e.bars,this.barTimesCache=e.bars.map(t=>t.time)),this.barTimesCache}destroy(){this.canvas=null,this.ctx=null;}drawingsRange(e,t,n=0){if(this.drawScene.setSet(e,n),this.drawScene.isEmpty())return null;let o=this.drawScene.priceRange(t.from,t.to);return o?{min:o.min,max:o.max}:null}renderTrades(e,t,n,o,i,s,a){e.save(),e.translate(0,s.bounds.top),e.beginPath(),e.rect(0,0,a,s.bounds.height),e.clip(),qw(e,i,n.tradeMarkers,{timeToLogical:l=>t.timeToLogical(l),barAt:l=>{let c=n.bars[Math.round(l)];return c?{high:c.high,low:c.low}:null}},l=>t.logicalToX(l),l=>t.priceToY(l,s.scale,s.bounds)-s.bounds.top,{fontSize:n.style.fontSize,fontFamily:o.fontFamily,color:o.textColor},a,Math.max(1.5,t.bodySpacing()*.4)),e.restore();}drawPriceAxes(e,t,n,o,i,s){if(e.strokeStyle=t.style.borderColor??o.borderColor,e.lineWidth=1,e.beginPath(),e.moveTo(i+.5,0),e.lineTo(i+.5,n.height),e.stroke(),!t.showAxisLabels)return;e.fillStyle=this.axisTextColor,e.textAlign="left";let a=`${t.style.fontSize}px ${o.fontFamily}`,l=`600 ${a}`,c=e.globalAlpha;for(let d of s)if(!d.collapsed){for(let u of this.axisTicks.ticksFor(t,d,n)){let h=n.priceToY(u.price,d.scale,d.bounds);hd.bounds.top+d.bounds.height-4||(u.major===true?e.font=l:u.major===false&&(e.globalAlpha=c*uI),e.fillText(u.label,i+6,h),u.major===true?e.font=a:u.major===false&&(e.globalAlpha=c));}if(d.axisBands)for(let u of d.axisBands){let h=d.bounds.top+u.frac*d.bounds.height;hd.bounds.top+d.bounds.height-4||e.fillText(u.label,i+6,h);}}e.textAlign="start";}drawPaneSeparators(e,t,n,o,i){e.fillStyle=t.style.separatorColor??n.borderColor;for(let s of i)s.order<=0||e.fillRect(0,Math.round(s.bounds.top)-1,o,3);}drawMergedScaleColumns(e,t,n,o){if(t.showAxisLabels){e.textAlign="left",e.fillStyle=this.axisTextColor;for(let i of t.orderedPanes()){if(i.collapsed)continue;t.ownScaleIndicatorsForPane(i.id).forEach((a,l)=>{let c=t.indicatorScales.get(a.id)?.scale;if(!c)return;let d=pw(o,l+1);for(let u of Hs(c,i.bounds.height,void 0,t.priceMintick)){let h=n.priceToY(u.price,c,i.bounds);hi.bounds.top+i.bounds.height-4||e.fillText(u.label,d+5,h);}});}e.textAlign="start";}}drawPriceLineAndCountdown(e,t,n,o,i,s){let a=t.bars.length;if(!s||a===0||t.candlesHidden||s.collapsed||s.bounds.height<=0)return;let l=t.bars[a-1],c=n.priceToY(l.close,s.scale,s.bounds);if(cs.bounds.top+s.bounds.height)return;let d=this.priceElementColor(t,n,o,l);if(t.showPriceLine){let S=Math.round(c)+.5;e.strokeStyle=d,e.lineWidth=1,bx(e,"dotted"),e.beginPath(),e.moveTo(0,S),e.lineTo(i,S),e.stroke(),bx(e,"solid");}let u=t.showCountdown?ax(l.time,n.barInterval,Date.now()):null,h=u!==null,p=t.showPriceLabel;if(!p&&!h)return;let m=zs(s.scale,s.bounds.height,l.close,rr(t,s),t.priceMintick),f=8,g=i+1,b=lx(d,o.background);if(e.textBaseline="middle",p&&u!==null){let S=Math.max(e.measureText(m).width,e.measureText(u).width)+f,M=c-8,C=g+f/2;e.fillStyle=d,e.fillRect(g,M,S,32),e.fillStyle=b,e.textAlign="left",e.fillText(m,C,M+8),e.fillText(u,C,M+24),e.textAlign="start";return}let y=p?m:u??"",w=e.measureText(y).width+f;e.fillStyle=d,e.fillRect(g,c-8,w,16),e.fillStyle=b,e.textAlign="center",e.fillText(y,g+w/2,c),e.textAlign="start";}priceElementColor(e,t,n,o){let i=e.style;switch(e.priceStyle){case "bars":return o.close>=o.open?i.bars.upColor??n.upColor:i.bars.downColor??n.downColor;case "line":return i.line.color??n.upColor;case "area":return i.area.lineColor??n.upColor;case "baseline":{let s=Math.max(0,Math.floor(t.visibleLogicalRange().from)),a=e.baselineValue??e.bars[s]?.close??0;return o.close>=a?i.baseline.topLineColor??n.upColor:i.baseline.bottomLineColor??n.downColor}default:return o.close>=o.open?n.upColor:n.downColor}}drawTimeAxis(e,t,n,o,i,s,a){if(e.strokeStyle=t.style.borderColor??o.borderColor,e.lineWidth=1,e.beginPath(),e.moveTo(0,s+.5),e.lineTo(i,s+.5),e.stroke(),!t.showAxisLabels)return;e.fillStyle=this.axisTextColor,e.textAlign="center";let l=s+(a-s)/2,c=n.visibleTimeRange(),d=Os((c.from+c.to)/2,t.timezone),u=Math.max(3,Math.min(8,Math.floor(i/64))),h=ld(c.from,c.to,u,d).map(g=>({...g,x:n.timeToX(g.time),half:e.measureText(g.label).width/2})).filter(g=>g.x>=20&&g.x<=i-20),p=12,m=[],f=g=>{let b=g.x-g.half,y=g.x+g.half;m.every(w=>y+p<=w.l||b-p>=w.r)&&(m.push({l:b,r:y}),e.fillText(g.label,g.x,l));};for(let g of h)g.major&&f(g);for(let g of h)g.major||f(g);e.textAlign="start";}};function gx(r,e){return r?e?{min:Math.min(r.min,e.min),max:Math.max(r.max,e.max)}:r:e}function bx(r,e){e==="dashed"?r.setLineDash([6,4]):e==="dotted"?r.setLineDash([2,3]):r.setLineDash([]);}var hI=350,hd=class{constructor(e,t){this.plot=e;this.deps=t;this.tip=null;this.timer=null;this.current=null;this.onMove=e=>{if(e.pointerType!=="mouse")return;let t=this.plot.getBoundingClientRect(),n=e.clientX-t.left,o=e.clientY-t.top,i=this.deps.lookup(n,o);if(!i){this.clear();return}i!==this.current&&(this.clear(),this.current=i,this.timer=window.setTimeout(()=>this.show(i,n,o),hI));};this.onLeave=()=>{this.clear();};e.addEventListener("pointermove",this.onMove),e.addEventListener("pointerleave",this.onLeave),e.addEventListener("pointerdown",this.onLeave);}destroy(){this.plot.removeEventListener("pointermove",this.onMove),this.plot.removeEventListener("pointerleave",this.onLeave),this.plot.removeEventListener("pointerdown",this.onLeave),this.clear();}show(e,t,n){let i=this.plot.ownerDocument.createElement("div");i.textContent=e,i.style.cssText="position:absolute;z-index:var(--vela-z-tooltip);pointer-events:none;background:var(--vela-bg);border:1px solid var(--vela-border);color:var(--vela-fg);border-radius:var(--vela-radius-md);padding:4px 9px;box-shadow:var(--vela-shadow);font:var(--vela-font-size-md) var(--vela-font);max-width:260px;",_e(i,this.deps.theme()),this.plot.appendChild(i);let s=this.plot.clientWidth,a=this.plot.clientHeight;i.style.left=`${Math.max(0,Math.min(t+12,s-i.offsetWidth-4))}px`,i.style.top=`${Math.max(0,Math.min(n+16,a-i.offsetHeight-4))}px`,this.tip=i;}clear(){this.timer!==null&&(clearTimeout(this.timer),this.timer=null),this.tip?.remove(),this.tip=null,this.current=null;}};var pd=class{constructor(){this.canvas=null;this.ctx=null;this.shade=null;}mount(e){this.canvas=e,this.ctx=e.getContext("2d");}get shadeRightArea(){return this.shade}render(e,t,n,o=null,i=null){this.shade=null;let s=this.ctx,a=this.canvas;if(!s||!a)return;let l=t.dpr;s.setTransform(l,0,0,l,0,0),s.clearRect(0,0,a.width/l,a.height/l),o!==null&&this.drawSeparatorHover(s,a.width/l,n,o),i&&this.drawExternal(s,i,e,t,n);let c=e.crosshair,d=t.width,u=t.height;if(!c||c.x<0||c.x>d||c.y<0||c.y>u)return;let h=e.style.crosshair,p=e.crosshairOverride,m=p?.vertical!==false,f=p?.horizontal!==false;s.font=`${e.style.fontSize}px ${n.fontFamily}`,s.textBaseline="middle";let g=Math.round(t.xToLogical(c.x)),b=vx(t.logicalToX(g),p?.width??h.width);if(m&&p?.shadeRight){let S=Math.max(0,Math.round(t.logicalToX(g+.5)));S=S.bounds.top&&c.y<=S.bounds.top+S.bounds.height){y=S;break}let w=h.labelBackground??n.borderColor;if(f&&y&&y.axisFormat!=="none"){let S=t.yToPrice(c.y,y.scale,y.bounds);this.chip(s,d+1,c.y,zs(y.scale,y.bounds.height,S,rr(e,y),e.priceMintick,y.axisFormat),w,"left",false,n.background);}m&&this.chip(s,b,u+1,ip(t.logicalToTime(g),e.timezone,t.barInterval),w,"center",true,n.background);}destroy(){this.canvas=null,this.ctx=null,this.shade=null;}drawExternal(e,t,n,o,i){let s=n.style.crosshair,a=n.crosshairOverride,l=o.width,c=o.height,d=vx(t.x,a?.width??s.width);if(a?.vertical===false)return;if(a?.shadeRight){let h=Math.max(0,Math.round(o.logicalToX(Math.round(o.xToLogical(t.x))+.5)));hl)return;e.font=`${n.style.fontSize}px ${i.fontFamily}`,e.textBaseline="middle",e.strokeStyle=a?.color??s.color??i.textColor,e.lineWidth=a?.width??s.width,e.globalAlpha=(a?.opacity??s.opacity)*.55,yx(e,a?.style??s.style),e.beginPath(),e.moveTo(d,0),e.lineTo(d,c),t.y!=null&&a?.horizontal!==false&&(e.moveTo(0,Math.round(t.y)+.5),e.lineTo(l,Math.round(t.y)+.5)),e.stroke(),e.setLineDash([]),e.lineWidth=1,e.globalAlpha=.8;let u=s.labelBackground??i.borderColor;if(t.y!=null&&t.price!=null&&a?.horizontal!==false){let h;for(let p of n.panes.values())if(t.y>=p.bounds.top&&t.y<=p.bounds.top+p.bounds.height){h=p;break}h&&h.axisFormat!=="none"&&this.chip(e,l+1,t.y,zs(h.scale,h.bounds.height,t.price,rr(n,h),n.priceMintick,h.axisFormat),u,"left",false,i.background);}this.chip(e,d,c+1,ip(t.time,n.timezone,o.barInterval),u,"center",true,i.background),e.globalAlpha=1;}paintShade(e,t,n,o,i){e.fillStyle=t.color,e.globalAlpha=t.opacity??1,e.fillRect(n,0,o-n,i),e.globalAlpha=1;let s=this.shade?Math.min(this.shade.x,n):n;this.shade={x:s,width:o-s,height:i};}drawSeparatorHover(e,t,n,o){let i=Math.round(o);e.fillStyle=n.textColor,e.globalAlpha=.1,e.fillRect(0,i-4,t,8),e.globalAlpha=.55,e.fillRect(0,i-1,t,2),e.globalAlpha=1;}chip(e,t,n,o,i,s,a=false,l="#000000"){let c=e.measureText(o).width+8,d=16,u=s==="left"?t:t-c/2,h=a?n:n-d/2;e.fillStyle=i,e.fillRect(u,h,c,d),e.fillStyle=Iw(i,l),e.textAlign="center",e.fillText(o,u+c/2,h+d/2+(a?2:0)),e.textAlign="start";}};function vx(r,e){return Math.round(r)+(Math.round(e)%2===1?.5:0)}function yx(r,e){e==="dashed"?r.setLineDash([6,4]):e==="dotted"?r.setLineDash([2,3]):r.setLineDash([]);}var sp=[{value:"Etc/UTC",label:"UTC"},{value:"Etc/GMT+12",label:"International Date Line West"},{value:"Pacific/Pago_Pago",label:"Pago Pago"},{value:"Pacific/Honolulu",label:"Honolulu"},{value:"Pacific/Marquesas",label:"Marquesas Islands"},{value:"America/Anchorage",label:"Anchorage"},{value:"America/Los_Angeles",label:"Los Angeles"},{value:"America/Phoenix",label:"Phoenix"},{value:"America/Denver",label:"Denver"},{value:"America/Chicago",label:"Chicago"},{value:"America/Mexico_City",label:"Mexico City"},{value:"America/New_York",label:"New York"},{value:"America/Bogota",label:"Bogot\xE1"},{value:"America/Caracas",label:"Caracas"},{value:"America/Santiago",label:"Santiago"},{value:"America/St_Johns",label:"St. John's"},{value:"America/Sao_Paulo",label:"S\xE3o Paulo"},{value:"America/Argentina/Buenos_Aires",label:"Buenos Aires"},{value:"America/Noronha",label:"Fernando de Noronha"},{value:"Atlantic/Azores",label:"Azores"},{value:"Atlantic/Reykjavik",label:"Reykjavik"},{value:"Europe/London",label:"London"},{value:"Europe/Paris",label:"Paris"},{value:"Europe/Berlin",label:"Berlin"},{value:"Europe/Athens",label:"Athens"},{value:"Africa/Cairo",label:"Cairo"},{value:"Africa/Johannesburg",label:"Johannesburg"},{value:"Europe/Moscow",label:"Moscow"},{value:"Europe/Istanbul",label:"Istanbul"},{value:"Asia/Tehran",label:"Tehran"},{value:"Asia/Dubai",label:"Dubai"},{value:"Asia/Kabul",label:"Kabul"},{value:"Asia/Karachi",label:"Karachi"},{value:"Asia/Kolkata",label:"Mumbai"},{value:"Asia/Kathmandu",label:"Kathmandu"},{value:"Asia/Dhaka",label:"Dhaka"},{value:"Asia/Yangon",label:"Yangon"},{value:"Asia/Bangkok",label:"Bangkok"},{value:"Asia/Shanghai",label:"Shanghai"},{value:"Asia/Hong_Kong",label:"Hong Kong"},{value:"Asia/Singapore",label:"Singapore"},{value:"Australia/Eucla",label:"Eucla"},{value:"Asia/Tokyo",label:"Tokyo"},{value:"Asia/Seoul",label:"Seoul"},{value:"Australia/Adelaide",label:"Adelaide"},{value:"Australia/Sydney",label:"Sydney"},{value:"Australia/Lord_Howe",label:"Lord Howe Island"},{value:"Pacific/Noumea",label:"Noum\xE9a"},{value:"Pacific/Auckland",label:"Auckland"},{value:"Pacific/Chatham",label:"Chatham Islands"},{value:"Pacific/Apia",label:"Apia"},{value:"Pacific/Kiritimati",label:"Kiritimati"}];function md(r){return r==="UTC"||r==="Etc/UTC"||r==="Etc/GMT"?"Etc/UTC":r}function pI(r,e=new Date){try{let o=(new Intl.DateTimeFormat("en-US",{timeZone:r,timeZoneName:"shortOffset"}).formatToParts(e).find(l=>l.type==="timeZoneName")?.value??"").match(/GMT(?:(\+|-)(\d{1,2})(?::(\d{2}))?)?/);if(!o||!o[1])return "UTC";let i=o[1]==="-"?"-":"+",s=o[2]??"0",a=o[3]??"";return a?`UTC${i}${s}:${a}`:`UTC${i}${s}`}catch{return "UTC"}}function ap(r,e){return md(r)==="Etc/UTC"?e:`(${pI(r)}) ${e}`}function sr(r){return r.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}var lp="events",fd="events.groups";function cp(r){return `${fd}.${sr(r)}`}function Mt(r,e){if(e.size===0)return false;let t=r;for(;;){if(e.has(t))return true;let n=t.lastIndexOf(".");if(n<0)return false;t=t.slice(0,n);}}function wx(r){if(r.kind==="heading"||r.kind==="header")return sr(r.label);let e=mo(r);if(e.toggle)return e.toggle.key;for(let t of e.controls)if(t.kind!=="hint")return t.key;return sr(e.label)}function gd(r,e,t){if(t.size===0)return [...r];let n=[],o=false,i=false;for(let s of r){let a=`${e}.${wx(s)}`;if(s.kind==="heading"){o=Mt(a,t),i=false,o||n.push(s);continue}if(s.kind==="header"){if(o)continue;i=Mt(a,t),i||n.push(s);continue}o||i||Mt(a,t)||n.push(s);}return n}function dp(r){return r.id??sr(r.title)}function xx(r){return r.id??sr(r.label)}function Sx(r,e,t){if(t.size===0)return [...r];let n=[],o=false;for(let i of r){let s=`${e}.${xx(i)}`;if(i.kind==="heading"){o=Mt(s,t),o||n.push(i);continue}o||Mt(s,t)||n.push(i);}return n}var mI=["symbol","symbol.type","symbol.style.candles","symbol.style.candles.body","symbol.style.candles.borders","symbol.style.candles.wick","symbol.style.candles.spacing","symbol.style.bars","symbol.style.bars.up-color","symbol.style.bars.down-color","symbol.style.bars.spacing","symbol.style.line","symbol.style.line.color","symbol.style.line.width","symbol.style.area","symbol.style.area.line-color","symbol.style.area.width","symbol.style.area.top-fill","symbol.style.area.bottom-fill","symbol.style.baseline","symbol.style.baseline.top-line","symbol.style.baseline.bottom-line","symbol.style.baseline.fill-top","symbol.style.baseline.fill-bottom","symbol.style.baseline.base-level","symbol.style.baseline.width","symbol.animation","symbol.animation.zoom","symbol.animation.pan","symbol.animation.autoscale","symbol.animation.price-changes","symbol.animation.intro","symbol.timezone","scales","scales.price-scale","scales.price-scale.mode","scales.price-scale.invert","scales.price-scale.last-price-line","scales.price-scale.last-price-label","scales.price-scale.countdown","scales.price-scale.axis-labels","scales.price-scale.border-color","scales.crosshair","scales.crosshair.color","scales.crosshair.width","scales.crosshair.style","canvas","canvas.background","canvas.background.color","canvas.background.text-color","canvas.background.text-size","canvas.background.pane-separator","canvas.grid","canvas.grid.vertical","canvas.grid.horizontal","canvas.margins","canvas.margins.top","canvas.margins.bottom","canvas.margins.right","canvas.theme"];function Cx(r,e=[]){let t=new Set(mI);if(e.length>0){t.add(lp),t.add(fd);for(let n of e)t.add(cp(n.id));}for(let n of xt()){if(Yo(n.id)){let a=`symbol.style.${n.id}`;for(let l of ["",".body",".borders",".wick",".spacing"])t.add(a+l);}let o=n.settings;if(!o)continue;let i=`type:${n.id}`;t.add(i);let s=a=>{for(let l of a)t.add(`${i}.${wx(l)}`);};o.rows&&s(o.rows);for(let a of o.instances??[])s(a.rows);for(let a of o.subsections??[])t.add(`${i}.${sr(a.title)}`),s(a.rows);}for(let n of r){let o=dp(n);t.add(o);for(let i of n.rows)t.add(`${o}.${xx(i)}`);}return [...t]}var fI={candles:"Candles",bars:"Bars",line:"Line",area:"Area",baseline:"Baseline"};function gI(r){return Sn(r)?.label??fI[r]??r}var Tx="vela-settings-controls",kx="6";var bI="var(--vela-border)";function vI(){if(typeof document>"u")return;let r=document.getElementById(Tx);if(r?.dataset.rev===kx)return;let e=r??document.createElement("style");e.id=Tx,e.dataset.rev=kx,e.textContent=` +${Or(".vela-sd-pane")} /* Tab rail / footer button / header close: base styles live HERE, not inline on the elements \u2014 inline declarations always beat stylesheet :hover rules, which is exactly what killed these hovers before. Active tab state is the .on class, @@ -911,11 +940,11 @@ ${Ir(".vela-sd-pane")} alignment device; on mobile the trigger hugs its value instead (the grid's control column is max-content), capped so a long option still ellipsizes before the label. */ .vela-sd-mobile .vela-select-trigger .vela-select-label{white-space:nowrap !important;} -.vela-sd-mobile .vela-select:not([data-fill]){width:auto;min-width:100px;max-width:min(220px,55vw);}`,r||document.head.appendChild(e);}var Bs=class{constructor(e,t){this.container=e;this.theme=t;this.root=null;this.ui=null;this.onChange=null;this.onImport=null;this.onReset=null;this.config=null;this.syncTypeTabs=null;this.hostSections=[];this.markGroups=[];this.markGroupOwnVisible=()=>true;this.markGroupVisible=()=>true;this.themeControl=null;this.tabs=[];this.hintTips=[];this.typeActiveInstance=new Map;this.typeActiveGroup=new Map;this.activeSection=null;this.mobileLayout=false;this.toggleRail=null;this.hiddenSettings=new Set;getComputedStyle(e).position==="static"&&(e.style.position="relative");}setHostSections(e){this.hostSections=e;}setMarkGroups(e,t,n=t){this.markGroupOwnVisible=n,this.markGroups=e,this.markGroupVisible=t;}setHiddenSettings(e){let t=new Set(e),n=t.size===this.hiddenSettings.size&&[...t].every(o=>this.hiddenSettings.has(o));this.hiddenSettings=t,n||this.reopenIfLive();}setThemeControl(e,t){this.themeControl={current:e,onSelect:t};}refreshConfig(e){this.config&&(this.config=e);}setTheme(e){this.theme=e,this.reopenIfLive();}setLayoutMode(e){let t=e==="mobile";t!==this.mobileLayout&&(this.mobileLayout=t,this.reopenIfLive());}reopenIfLive(){if(!this.root)return;let e=this.config,t=this.onChange,n=this.onImport,o=this.onReset,i=this.activeSection;this.close(),e&&t&&this.open(e,t,n??void 0,o??void 0,i??void 0);}isOpen(){return this.root!==null}toggle(e,t,n,o,i){this.root?this.close():this.open(e,t,n,o,i);}showSection(e){this.tabs.find(t=>t.title.toLowerCase()===e.toLowerCase())?.show();}open(e,t,n,o,i){this.close(),this.config=e,this.onChange=t,this.onImport=n??null,this.onReset=o??null,oI();let s=this.mobileLayout,a;s&&(a=document.createElement("button"),a.type="button",a.className="vela-sd-burger",a.innerHTML=Re("burger",16),a.title="Sections",a.addEventListener("click",()=>this.toggleRail?.()));let l=new En({host:this.container,title:"Chart settings",modal:false,contained:true,align:"top",draggable:!s,flush:true,className:"vela-dialog--settings",headerStart:a,closeOnBackdrop:true,footer:d=>{d.style.cssText="padding:10px 14px;display:flex;align-items:center;justify-content:flex-start;gap:8px;";let u=document.createElement("button");u.type="button",u.textContent="Reset defaults",u.className="vela-sd-btn",u.addEventListener("click",()=>this.onReset?.()),d.appendChild(u);},onOpenChange:d=>{!d&&this.ui===l&&this.close();}});s&&l.positioner.classList.add("vela-sd-mobile"),l.positioner.style.paddingTop=s?"0":"8vh",this.root=l.positioner,this.ui=l;let c=this.buildContent(l,e,i,s);l.show(),this.layoutPanes(c);}refresh(e){let t=this.ui;if(t){Me(),Lc();for(let n of this.hintTips)n();this.hintTips=[],this.config=e,t.body.replaceChildren(),this.layoutPanes(this.buildContent(t,e,this.activeSection??void 0,this.mobileLayout));}}layoutPanes(e){for(let t of e){let n=[...t.querySelectorAll("[data-sd-rows-host]")];if(n.length===0){this.layoutSettingsGrids(t);continue}for(let o of n)this.layoutSettingsGrids(o);}}buildContent(e,t,n,o){let i=document.createElement("div");i.style.cssText="display:flex;flex-direction:column;gap:0;";let s=(v,k)=>(v.dataset.sdId=k,v);i.append(s(this.section("Symbol"),"symbol")),i.append(s(this.sectionTitle("Chart type"),"symbol.type"));let a={},l=v=>{let k=v==="heikinashi"?"candles":v;for(let x of $o())a[x]?.classList.toggle("vela-sd-hide",x!==k);};i.append(s(this.selectRowLabeled("Type",t.series.style,$o().map(v=>[v,nI(v)]),v=>{this.emit({series:{style:v}}),l(v),this.syncTypeTabs?.(v);}),"symbol.type"));let c=s(this.group(),"symbol.style.candles");c.append(this.sectionTitle("Candles")),c.append(s(this.toggleRow("Body",t.candles.bodyVisible,v=>this.emit({candles:{bodyVisible:v}}),[this.swatch(t.candles.upColor,v=>this.emit({candles:{upColor:v}})),this.swatch(t.candles.downColor,v=>this.emit({candles:{downColor:v}}))]),"symbol.style.candles.body")),c.append(s(this.toggleRow("Borders",t.candles.borderVisible,v=>this.emit({candles:{borderVisible:v}}),[this.swatch(t.candles.borderUpColor,v=>this.emit({candles:{borderUpColor:v}})),this.swatch(t.candles.borderDownColor,v=>this.emit({candles:{borderDownColor:v}}))]),"symbol.style.candles.borders")),c.append(s(this.toggleRow("Wick",t.candles.wickVisible,v=>this.emit({candles:{wickVisible:v}}),[this.swatch(t.candles.wickUpColor,v=>this.emit({candles:{wickUpColor:v}})),this.swatch(t.candles.wickDownColor,v=>this.emit({candles:{wickDownColor:v}}))]),"symbol.style.candles.wick")),c.append(s(this.numberRow("Spacing",t.series.spacing,.1,10,.1,v=>this.emit({series:{spacing:v}})),"symbol.style.candles.spacing")),a.candles=c,i.append(c);let d=s(this.group(),"symbol.style.bars");d.append(this.sectionTitle("Bars")),d.append(s(this.colorRow("Color Up",t.bars.upColor,v=>this.emit({bars:{upColor:v}})),"symbol.style.bars.up-color")),d.append(s(this.colorRow("Color Down",t.bars.downColor,v=>this.emit({bars:{downColor:v}})),"symbol.style.bars.down-color")),d.append(s(this.numberRow("Spacing",t.series.spacing,.1,10,.1,v=>this.emit({series:{spacing:v}})),"symbol.style.bars.spacing")),a.bars=d,i.append(d);let u=s(this.group(),"symbol.style.line");u.append(this.sectionTitle("Line")),u.append(s(this.colorRow("Color",t.line.color,v=>this.emit({line:{color:v}})),"symbol.style.line.color")),u.append(s(this.numberRow("Width",t.line.width,1,10,1,v=>this.emit({line:{width:v}})),"symbol.style.line.width")),a.line=u,i.append(u);let h=s(this.group(),"symbol.style.area");h.append(this.sectionTitle("Area")),h.append(s(this.colorRow("Line color",t.area.lineColor,v=>this.emit({area:{lineColor:v}})),"symbol.style.area.line-color")),h.append(s(this.numberRow("Width",t.area.width,1,10,1,v=>this.emit({area:{width:v}})),"symbol.style.area.width")),h.append(s(this.colorRow("Top fill",t.area.topColor,v=>this.emit({area:{topColor:v}})),"symbol.style.area.top-fill")),h.append(s(this.colorRow("Bottom fill",t.area.bottomColor,v=>this.emit({area:{bottomColor:v}})),"symbol.style.area.bottom-fill")),a.area=h,i.append(h);let p=s(this.group(),"symbol.style.baseline");p.append(this.sectionTitle("Baseline")),p.append(s(this.rowWith("Top line",[this.swatch(t.baseline.topLineColor,v=>this.emit({baseline:{topLineColor:v}}))]),"symbol.style.baseline.top-line")),p.append(s(this.rowWith("Bottom line",[this.swatch(t.baseline.bottomLineColor,v=>this.emit({baseline:{bottomLineColor:v}}))]),"symbol.style.baseline.bottom-line")),p.append(s(this.rowWith("Fill top area",[this.swatch(t.baseline.topFillColor,v=>this.emit({baseline:{topFillColor:v}})),this.swatch(t.baseline.topFillColor2,v=>this.emit({baseline:{topFillColor2:v}}))]),"symbol.style.baseline.fill-top")),p.append(s(this.rowWith("Fill bottom area",[this.swatch(t.baseline.bottomFillColor2,v=>this.emit({baseline:{bottomFillColor2:v}})),this.swatch(t.baseline.bottomFillColor,v=>this.emit({baseline:{bottomFillColor:v}}))]),"symbol.style.baseline.fill-bottom")),p.append(s(this.numberRow("Base level %",t.baseline.baselineLevel,0,100,1,v=>this.emit({baseline:{baselineLevel:v}})),"symbol.style.baseline.base-level")),p.append(s(this.numberRow("Width",t.baseline.width,1,10,1,v=>this.emit({baseline:{width:v}})),"symbol.style.baseline.width")),a.baseline=p,i.append(p);for(let v of xt()){if(!Wo(v.id))continue;let k=t.chartTypes[v.id]??{},x=(N,V)=>typeof k[N]=="string"&&k[N]!==""?k[N]:V,E=(N,V)=>typeof k[N]=="boolean"?k[N]:V,I=s(this.group(),`symbol.style.${v.id}`);I.append(this.sectionTitle("Candles")),I.append(s(this.toggleRow("Body",E("candleBodyVisible",t.candles.bodyVisible),N=>this.emitType(v.id,"candleBodyVisible",N),[this.swatch(x("candleUpColor",t.candles.upColor),N=>this.emitType(v.id,"candleUpColor",N)),this.swatch(x("candleDownColor",t.candles.downColor),N=>this.emitType(v.id,"candleDownColor",N))]),`symbol.style.${v.id}.body`)),I.append(s(this.toggleRow("Borders",E("candleBorderVisible",t.candles.borderVisible),N=>this.emitType(v.id,"candleBorderVisible",N),[this.swatch(x("candleBorderUpColor",t.candles.borderUpColor),N=>this.emitType(v.id,"candleBorderUpColor",N)),this.swatch(x("candleBorderDownColor",t.candles.borderDownColor),N=>this.emitType(v.id,"candleBorderDownColor",N))]),`symbol.style.${v.id}.borders`)),I.append(s(this.toggleRow("Wick",E("candleWickVisible",t.candles.wickVisible),N=>this.emitType(v.id,"candleWickVisible",N),[this.swatch(x("candleWickUpColor",t.candles.wickUpColor),N=>this.emitType(v.id,"candleWickUpColor",N)),this.swatch(x("candleWickDownColor",t.candles.wickDownColor),N=>this.emitType(v.id,"candleWickDownColor",N))]),`symbol.style.${v.id}.wick`)),I.append(s(this.numberRow("Spacing",t.series.spacing,.1,10,.1,N=>this.emit({series:{spacing:N}})),`symbol.style.${v.id}.spacing`)),a[v.id]=I,i.append(I);}l(t.series.style),i.append(s(this.sectionTitle("Animation"),"symbol.animation")),i.append(s(this.boolRow("Animate zoom",t.animations.zoom,v=>this.emit({animations:{zoom:v}}),this.hint("Glide the chart to each zoom step instead of jumping.")),"symbol.animation.zoom")),i.append(s(this.boolRow("Pan momentum",t.animations.pan,v=>this.emit({animations:{pan:v}}),this.hint("Keep gliding briefly after a drag release, and ease scroll-to-latest and keyboard pans.")),"symbol.animation.pan")),i.append(s(this.boolRow("Animate price scale",t.animations.autoscale,v=>this.emit({animations:{autoscale:v}}),this.hint("Glide the price scale to its new range while zooming or panning.")),"symbol.animation.autoscale")),i.append(s(this.boolRow("Animate price changes",t.priceScale.animateLastPrice,v=>this.emit({priceScale:{animateLastPrice:v}}),this.hint("Glide the live bar to each new price instead of snapping.")),"symbol.animation.price-changes")),i.append(s(this.boolRow("Reveal on load",t.animations.intro,v=>this.emit({animations:{intro:v}}),this.hint("Draw the candles in when a chart first loads. Takes effect on the next load.")),"symbol.animation.intro")),i.append(s(this.sectionTitle("Time zone"),"symbol.timezone")),i.append(s(this.selectRowLabeled("Time zone",dd(t.timeScale.timezone),iI(t.timeScale.timezone),v=>this.emit({timeScale:{timezone:v}})),"symbol.timezone"));let m=v=>{for(let k of this.hostSections){if((k.placement??"after-symbol")!==v)continue;let x=ip(k);if(Mt(x,this.hiddenSettings))continue;let E=f0(k.rows,x,this.hiddenSettings);if(E.length!==0){i.append(v==="symbol"?this.sectionTitle(k.title):this.section(k.title));for(let I of E)I.kind==="heading"?i.append(this.sectionTitle(I.label)):I.kind==="toggle"?i.append(this.boolRow(I.label,I.get(),N=>I.set(N))):I.kind==="color"?i.append(this.colorRow(I.label,I.get(),N=>I.set(N))):i.append(this.selectRowLabeled(I.label,I.get(),y0(I.options),N=>I.set(N)));}}},f=v=>{for(let k of xt()){let x=k.settings;x&&(x.placement??"end")===v&&(Mt(`type:${k.id}`,this.hiddenSettings)||this.chartTypeSection(k.id,x,t,i));}};if(m("symbol"),f("after-symbol"),m("after-symbol"),i.append(s(this.section("Scales and lines"),"scales")),i.append(s(this.sectionTitle("Price scale"),"scales.price-scale")),i.append(s(this.selectRowLabeled("Mode",t.priceScale.log?"log":t.priceScale.mode,[["price","Regular"],["percent","Percent"],["indexed","Indexed to 100"],["log","Logarithmic"]],v=>this.emit({priceScale:v==="log"?{mode:"price",log:true}:{mode:v,log:false}})),"scales.price-scale.mode")),i.append(s(this.boolRow("Invert scale",t.priceScale.invert,v=>this.emit({priceScale:{invert:v}})),"scales.price-scale.invert")),i.append(s(this.separator(),"scales.price-scale")),i.append(s(this.boolRow("Last Price Line",t.priceScale.currentPriceLine,v=>this.emit({priceScale:{currentPriceLine:v}})),"scales.price-scale.last-price-line")),i.append(s(this.boolRow("Last price label",t.priceScale.priceLabel,v=>this.emit({priceScale:{priceLabel:v}})),"scales.price-scale.last-price-label")),i.append(s(this.boolRow("Countdown to bar close",t.priceScale.countdown,v=>this.emit({priceScale:{countdown:v}})),"scales.price-scale.countdown")),i.append(s(this.boolRow("Axis labels",t.priceScale.labelsVisible,v=>this.emit({priceScale:{labelsVisible:v}})),"scales.price-scale.axis-labels")),i.append(s(this.colorRow("Scale border color",t.priceScale.borderColor,v=>this.emit({priceScale:{borderColor:v}})),"scales.price-scale.border-color")),i.append(s(this.sectionTitle("Crosshair"),"scales.crosshair")),i.append(s(this.colorRow("Color",t.crosshair.color,v=>this.emit({crosshair:{color:v}})),"scales.crosshair.color")),i.append(s(this.numberRow("Width",t.crosshair.width,.5,8,.5,v=>this.emit({crosshair:{width:v}})),"scales.crosshair.width")),i.append(s(this.selectRowLabeled("Style",t.crosshair.style,[["solid","Solid"],["dashed","Dashed"],["dotted","Dotted"]],v=>this.emit({crosshair:{style:v}})),"scales.crosshair.style")),i.append(s(this.section("Canvas"),"canvas")),i.append(s(this.sectionTitle("Background & text"),"canvas.background")),i.append(s(this.colorRow("Background",t.layout.background,v=>this.emit({layout:{background:v}})),"canvas.background.color")),i.append(s(this.colorRow("Text color",t.layout.textColor,v=>this.emit({layout:{textColor:v}})),"canvas.background.text-color")),i.append(s(this.numberRow("Text size",t.layout.fontSize,6,32,1,v=>this.emit({layout:{fontSize:v}})),"canvas.background.text-size")),i.append(s(this.colorRow("Pane separator color",t.panes.separatorColor,v=>this.emit({panes:{separatorColor:v}})),"canvas.background.pane-separator")),i.append(s(this.sectionTitle("Grid"),"canvas.grid")),i.append(s(this.toggleRow("Vertical",t.grid.vertLines.visible,v=>this.emit({grid:{vertLines:{visible:v}}}),[this.swatch(t.grid.vertLines.color,v=>this.emit({grid:{vertLines:{color:v}}}))]),"canvas.grid.vertical")),i.append(s(this.toggleRow("Horizontal",t.grid.horzLines.visible,v=>this.emit({grid:{horzLines:{visible:v}}}),[this.swatch(t.grid.horzLines.color,v=>this.emit({grid:{horzLines:{color:v}}}))]),"canvas.grid.horizontal")),i.append(s(this.sectionTitle("Margins"),"canvas.margins")),i.append(s(this.numberRow("Top",t.margins.top,0,40,1,v=>this.emit({margins:{top:v}}),"%"),"canvas.margins.top")),i.append(s(this.numberRow("Bottom",t.margins.bottom,0,40,1,v=>this.emit({margins:{bottom:v}}),"%"),"canvas.margins.bottom")),i.append(s(this.numberRow("Right",t.margins.right,0,200,1,v=>this.emit({margins:{right:v}}),"bars"),"canvas.margins.right")),this.themeControl){let v=this.themeControl;i.append(s(this.sectionTitle("Theme"),"canvas.theme")),i.append(s(this.selectRow("Color theme",v.current==="dark"?"Dark":"Light",["Dark","Light"],k=>v.onSelect(k==="Dark"?"dark":"light")),"canvas.theme"));}if(this.markGroups.length>0){i.append(s(this.section("Events"),rp)),i.append(s(this.sectionTitle("Visible events"),ud));let v=new Map,k=iu(this.markGroups),x=()=>{for(let{group:E}of k){let I=v.get(E.id);!I||E.parent===void 0||I.classList.toggle("vela-sd-soft",!this.markGroupVisible(E.parent));}};for(let{group:E,depth:I}of k){let N=this.boolRow(E.label,this.markGroupOwnVisible(E.id),V=>{this.emit({marks:{groups:{[E.id]:V}}}),x();});I>0&&(N.classList.add("vela-sd-nested"),N.style.setProperty("--vela-sd-depth",String(I))),v.set(E.id,N),i.append(s(N,op(E.id)));}x();}if(f("end"),m("end"),this.hiddenSettings.size>0){let v=false;for(let k of [...i.children]){if(k.dataset.sdTab!==void 0&&(v=k.dataset.sdId!==void 0&&Mt(k.dataset.sdId,this.hiddenSettings)),v||k.dataset.sdId!==void 0&&Mt(k.dataset.sdId,this.hiddenSettings)){k.remove();continue}for(let x of [...k.querySelectorAll("[data-sd-id]")])Mt(x.dataset.sdId,this.hiddenSettings)&&x.remove();}}let g=document.createElement("div");g.style.cssText=o?"display:flex;min-height:0;flex:1 1 auto;position:relative;overflow:hidden;":"display:flex;min-height:360px;max-height:calc(70vh - 100px);flex:1 1 auto;";let b=document.createElement("div");b.className="vela-sd-rail",b.style.cssText=o?"display:flex;flex-direction:column;gap:2px;padding:10px 8px;overflow-y:auto;":`flex:0 0 170px;display:flex;flex-direction:column;gap:2px;padding:10px 8px;border-right:1px solid ${rI};overflow-y:auto;`;let y=null;o&&(y=document.createElement("div"),y.className="vela-sd-railscrim",y.addEventListener("click",()=>this.toggleRail?.()),this.toggleRail=v=>{let k=v??!b.classList.contains("open");b.classList.toggle("open",k),y?.classList.toggle("open",k);});let w=document.createElement("div");w.className="vela-sd-pane",w.style.cssText=o?"flex:1;min-width:0;overflow-y:auto;overflow-anchor:none;padding:6px 14px calc(14px + env(safe-area-inset-bottom, 0px));":"flex:1;overflow-y:auto;overflow-anchor:none;padding:6px 18px 14px;";let C=[],M=null;for(let v of [...i.children]){let k=v.dataset.sdTab;if(k!==void 0){let x=document.createElement("div");x.style.display="none";let E=document.createElement("button");E.type="button",E.textContent=k,E.className="vela-sd-tab"+(v.dataset.sdSub!==void 0?" vela-sd-tab-sub":""),C.push({title:k,el:x,tab:E,style:v.dataset.sdStyle,visibility:v.dataset.sdVisibility}),M=x,v.remove();continue}M&&M.appendChild(v);}for(let v=C.length-1;v>=0;v--)C[v].el.childElementCount===0&&C.splice(v,1);this.syncTypeTabs=v=>{let k=false;C.forEach((x,E)=>{if(!x.style)return;let I=x.visibility==="always"||x.style===v||v==="heikinashi"&&x.style==="heikinashi";x.tab.style.display=I?"":"none",!I&&x.el.style.display==="block"&&(k=true);}),k&&S(0);};let S=v=>{C.forEach((k,x)=>{k.el.style.display=x===v?"block":"none",k.tab.classList.toggle("on",x===v);}),this.activeSection=C[v]?.title??null,o&&(e.titleEl.textContent=C[v]?.title??"Chart settings",this.toggleRail?.(false));};C.forEach((v,k)=>{v.tab.addEventListener("click",()=>S(k)),b.appendChild(v.tab),w.appendChild(v.el);}),this.tabs=C.map((v,k)=>({title:v.title,show:()=>S(k)}));let L=n!==void 0?C.findIndex(v=>v.title.toLowerCase()===n.toLowerCase()):C.findIndex(v=>v.style===t.series.style&&!v.tab.classList.contains("vela-sd-tab-sub"));return S(L>=0?L:0),this.syncTypeTabs?.(t.series.style),g.append(b,w),y&&g.append(y),e.body.appendChild(g),C.map(v=>v.el)}close(){Me(),Lc();let e=this.ui;this.ui=null,this.root=null,this.toggleRail=null,this.tabs=[];for(let t of this.hintTips)t();this.hintTips=[],e?.destroy();}destroy(){this.close(),this.onChange=null,this.onImport=null,this.config=null;}emitType(e,t,n){this.emit({chartTypes:{[e]:{[t]:n}}});}emit(e){this.onChange?.(e);}sectionTitle(e){return Pn(e)}chartTypeSection(e,t,n,o){let i=this.section(t.title);i.dataset.sdStyle=e,i.dataset.sdVisibility=t.visibility??"active",o.append(i);let s=n.chartTypes[e]??{},a={},l=h=>{for(let p of h)for(let m of Li(p)){let f=s[m.key];a[m.key]=typeof f===m.type?f:m.defval;}};t.rows&&l(t.rows);for(let h of t.instances??[])l(h.rows);for(let h of t.subsections??[])l(h.rows);for(let h of t.instances??[])!h.enableKey||h.enableKey in a||(a[h.enableKey]=s[h.enableKey]===true);for(let h of t.subsections??[])!h.enableKey||h.enableKey in a||(a[h.enableKey]=s[h.enableKey]===true);let c=[],d=(h,p)=>{a[h]=p,this.emitType(e,h,p);for(let m of c)m();},u=`type:${e}`;if(t.instances&&t.instances.length>0){let h=t.instances.map(p=>({...p,rows:hd(p.rows,u,this.hiddenSettings)}));o.append(this.instancesBlock(e,h,a,d,c));}else if(t.rows){let h=hd(t.rows,u,this.hiddenSettings);t.layout==="grouped"?o.append(this.groupedRows(`${e}/rows`,h,a,d,c)):this.flatTypeRows(h,a,d,c,o);}for(let h of t.subsections??[]){if(Mt(`${u}.${rr(h.title)}`,this.hiddenSettings))continue;let p=hd(h.rows,u,this.hiddenSettings);if(p.length===0)continue;let m=this.section(h.title);m.dataset.sdStyle=e,m.dataset.sdVisibility=t.visibility??"active",m.dataset.sdSub="1",o.append(m),o.append(this.groupedRows(`${e}/${h.title}`,p,a,d,c,h.enableKey));}for(let h of c)h();}flatTypeRows(e,t,n,o,i){let s=[];for(let a of e){let l=a.kind==="heading"||a.kind==="header"?this.sectionTitle(a.label):this.typeRow(a,t,n,o);s.push({el:l,when:a.when}),i.append(l);}o.push(()=>{for(let a of s)a.el.classList.toggle("vela-sd-hide",!kr(a.when,t));});}typeRow(e,t,n,o){let i=co(e),s=[];for(let a of i.controls){let l=this.inlineControl(a,t,n,i.toggle!==void 0);if(a.kind!=="hint"&&o.push(()=>l.dispatchEvent(new Event("vela-sync"))),a.kind!=="hint"&&a.when){l.dataset.sdSelfGated="1";let c=a.when;o.push(()=>{l.style.display=kr(c,t)?"":"none";});}s.push(l);}if(i.toggle){let a=i.toggle,l=this.toggleRow(i.label,t[a.key],c=>n(a.key,c),s,()=>t[a.key]===true);return o.push(()=>l.dispatchEvent(new Event("vela-sync"))),l}return this.rowWith(i.label,s)}inlineControl(e,t,n,o){if(e.kind==="hint"){let s=document.createElement("span");return s.textContent=e.text,s.style.cssText="color:var(--vela-fg-muted);",s}if(e.kind==="color")return de({kind:"color",theme:this.theme,get:()=>t[e.key],onChange:s=>n(e.key,s),title:e.label}).el;if(e.kind==="width"){let s=typeof t[e.key]=="number"?t[e.key]:e.defval;return de({kind:"width",theme:this.theme,get:()=>typeof t[e.key]=="number"?t[e.key]:s,onChange:a=>n(e.key,a),title:e.label}).el}if(e.kind==="select"){let s=typeof t[e.key]=="string"?t[e.key]:e.defval;return de({kind:"select",options:y0(e.options).map(([a,l])=>({value:a,label:l})),value:s,fill:false,theme:this.theme,title:e.label,onChange:a=>n(e.key,a),sync:()=>typeof t[e.key]=="string"?t[e.key]:e.defval}).el}let i=typeof t[e.key]=="number"?t[e.key]:e.defval;return de({kind:"number",value:i,min:e.min,max:e.max,step:e.step??1,fill:false,commit:"live",clamp:e.placeholder!==void 0,steppers:true,compact:o,title:e.label,placeholder:e.placeholder,emptyValue:e.placeholder!==void 0?e.defval:void 0,onChange:s=>n(e.key,s),sync:()=>typeof t[e.key]=="number"?t[e.key]:e.defval}).el}instancesBlock(e,t,n,o,i){let s=document.createElement("div"),a=document.createElement("div");a.className="vela-sd-itabs",(t.length>1||t[0]?.enableKey!==void 0)&&s.append(a);let l=t.map((u,h)=>{let p=this.groupedRows(`${e}/#${h}`,u.rows,n,o,i);return s.append(p),p}),c=u=>!u.enableKey||n[u.enableKey]===true,d=()=>{let u=this.typeActiveInstance.get(e)??0;c(t[u]??t[0])||(u=0),this.typeActiveInstance.set(e,u),a.replaceChildren(),t.forEach((p,m)=>{if(!c(p))return;let f=document.createElement("button");f.type="button",f.className="vela-sd-itab"+(m===u?" on":"");let g=document.createElement("span");if(g.textContent=p.label,f.append(g),m===u&&p.enableKey){let b=document.createElement("span");b.className="vela-sd-ix",b.textContent="\u2715",b.title=`Remove ${p.label}`,b.addEventListener("click",y=>{y.stopPropagation(),this.typeActiveInstance.set(e,0),o(p.enableKey,false);}),f.append(b);}f.addEventListener("click",()=>{this.typeActiveInstance.set(e,m),d();}),a.append(f);});let h=t.findIndex(p=>!c(p));if(h>=0){let p=document.createElement("button");p.type="button",p.className="vela-sd-itab vela-sd-itab-add",p.textContent="+",p.title=`Add ${t[h].label}`,p.addEventListener("click",()=>{this.typeActiveInstance.set(e,h),o(t[h].enableKey,true);}),a.append(p);}l.forEach((p,m)=>p.classList.toggle("vela-sd-hide",m!==u));};return i.push(d),s}groupedRows(e,t,n,o,i,s){let a=document.createElement("div");a.className="vela-sd-struct";let l=document.createElement("div");l.className="vela-sd-toc";let c=document.createElement("div");c.dataset.sdRowsHost="1",c.style.cssText="flex:1 1 auto;min-width:0;",a.append(l,c);let d=[],u=[],h=[],p=-1;for(let f of t){if(f.kind==="heading"){p=u.length,u.push(f.label),h.push(f.when);continue}if(f.kind==="header"){d.push({el:this.sectionTitle(f.label),when:f.when,group:p,header:true}),c.append(d[d.length-1].el);continue}let g=this.typeRow(f,n,o,i),b=f.kind==="row"?f.toggle?.key:f.kind==="range"?void 0:f.key;d.push({el:g,when:f.when,group:p,key:b}),c.append(g);}let m=()=>{let f=u.map((w,C)=>kr(h[C],n)&&d.some(M=>M.group===C&&!M.header&&kr(M.when,n))),g=u.indexOf(this.typeActiveGroup.get(e)??"");(g<0||!f[g])&&(g=f.findIndex(Boolean)),g>=0&&this.typeActiveGroup.set(e,u[g]),l.replaceChildren(),u.forEach((w,C)=>{if(!f[C])return;let M=document.createElement("button");M.type="button",M.className="vela-sd-toc-btn"+(C===g?" on":""),M.textContent=w,M.addEventListener("click",()=>{this.typeActiveGroup.set(e,w),m();}),l.append(M);});let b=f.some(Boolean);l.classList.toggle("vela-sd-hide",!b),a.classList.toggle("no-toc",!b);let y=!s||n[s]===true;for(let w=0;wn?n():o,onChange:i=>{o=i,t(i);}}).el}rowWith(e,t){return He({label:e,labelSize:"sm",control:t,className:"vela-sd-row"})}section(e){let t=document.createElement("div");return t.dataset.sdTab=e,t.style.display="none",t}group(){let e=document.createElement("div");return e.dataset.sdGroup="",e.style.cssText="display:contents;",e}colorRow(e,t,n){let o=t;return He({label:e,labelSize:"sm",fit:true,className:"vela-sd-row",control:de({kind:"color",theme:this.theme,get:()=>o,onChange:i=>{o=i,n(i);}}).el})}boolRow(e,t,n,o){return this.toggleRow(e,t,n,[],void 0,o)}toggleRow(e,t,n,o,i,s){return He({label:e,labelSize:"sm",bool:o.length===0,toggle:{checked:t,onChange:n,get:i},control:o,info:s,className:o.length===0?"vela-sd-bool":"vela-sd-row"})}hint(e){let{el:t,dispose:n}=Pl(e,{host:this.container,theme:()=>this.theme});return this.hintTips.push(n),t}numberRow(e,t,n,o,i,s,a){let l=[de({kind:"number",value:t,min:n,max:o,step:i,fill:false,commit:"live",steppers:true,onChange:s}).el];if(a){let c=document.createElement("span");c.textContent=a,c.style.cssText="color:var(--vela-fg-muted);",l.push(c);}return this.rowWith(e,l)}selectRowLabeled(e,t,n,o){return He({label:e,labelSize:"sm",className:"vela-sd-row",control:de({kind:"select",options:n.map(([i,s])=>({value:i,label:s})),value:t,fill:false,theme:this.theme,onChange:o}).el})}selectRow(e,t,n,o){return this.selectRowLabeled(e,t,n.map(i=>[i,i]),o)}};function y0(r){return r.map(e=>typeof e=="string"?[e,e]:e)}function iI(r){let e=tp.map(n=>[n.value,np(n.value,n.label)]),t=dd(r);return tp.some(n=>n.value===t)?e:[[t,np(t,t)],...e]}var _s=ia,Hs=sa;function Et(r,e){if(r instanceof We){if(!r.fillTriangles().length)return null;let t=r.valid();return r.style.fillColor??(t==null?r.style.lineColor:t?_s:Hs)}return r instanceof vt?r.style.fillColor??e.background:r.style.fillColor??null}var sI=4.5,sp=_,aI=J(A,.55),lI=.7,w0=Hm,cI=zm,x0={selected:.3,hovered:.12};function ap(r){let e=new Set(r.selected);return r.dragged&&e.add(r.dragged),r.hovered&&e.add(r.hovered),r.mutedLabel&&e.delete(r.mutedLabel),e}var pd=class{constructor(){this.targets={};this.seriesLook={style:"candles",upColor:O,downColor:D,lineColor:O};}paintAll(e,t,n,o,i={}){this.targets=i;for(let s of t)s.visible&&this.paintClipped(e,s,n,()=>this.paintOne(e,s,n,o));this.targets={},this.paintHighlights(e,t,n,ap(i));}paintHighlights(e,t,n,o){if(o.size!==0)for(let i of t)i.visible&&o.has(i.id)&&this.paintClipped(e,i,n,()=>this.paintHandles(e,i.handlePoints(n)));}paintClipped(e,t,n,o){if(!n.paneRect){o();return}let i=n.paneRect(t.paneId);!i||i.height<=0||(e.save(),e.beginPath(),e.rect(0,i.top,n.width,i.height),e.clip(),o(),e.restore());}paintGhost(e,t,n,o){e.globalAlpha=lI,t instanceof vn||t instanceof gt?this.paintTimeSpanGhost(e,t,n):t instanceof ht?this.paintMagnifierGhost(e,t,n,o):this.paintOne(e,t,n,o),e.globalAlpha=1;}paintTimeSpanGhost(e,t,n){let o=t.anchors[0],i=t.anchors[1];if(!o)return;let s=t instanceof vn?t.reg?.midColor||A:A,a=u=>{let h=n.xOf(u);e.save(),e.strokeStyle=s,e.globalAlpha=.6*e.globalAlpha,e.lineWidth=1,e.setLineDash([4,4]),e.beginPath(),e.moveTo(h,0),e.lineTo(h,n.height),e.stroke(),e.restore();};a(o.time),i&&a(i.time);let l=n.yOf(o.price,t.paneId),c=i?n.yOf(i.price,t.paneId):null,d=[];l!=null&&d.push([n.xOf(o.time),l]),i&&c!=null&&(e.save(),e.strokeStyle=s,e.lineWidth=1,e.setLineDash([]),e.beginPath(),e.moveTo(n.xOf(o.time),l??c),e.lineTo(n.xOf(i.time),c),e.stroke(),e.restore(),d.push([n.xOf(i.time),c])),this.paintHandles(e,d);}paintMarquee(e,t){e.save(),e.fillStyle=J(sp,.08),e.fillRect(t.x,t.y,t.w,t.h),e.strokeStyle=sp,e.lineWidth=1,e.setLineDash([4,3]),e.strokeRect(t.x+.5,t.y+.5,t.w,t.h),e.restore();}paintSnapRing(e,t,n,o){e.setLineDash([]),e.globalAlpha=.9,e.beginPath(),e.arc(t,n,5.5,0,Math.PI*2),e.strokeStyle=o.textColor,e.lineWidth=1.5,e.stroke(),e.globalAlpha=1;}paintOne(e,t,n,o){if(t.type==="highlighter"&&t instanceof ve){this.paintHighlighter(e,t,n),this.paintLabel(e,t,n,o);return}if(t instanceof ve){if(this.paintSegments(e,t,n),t.type==="path"){let i=t.handlePoints(n);i.length>=2&&this.paintArrowhead(e,i[i.length-2],i[i.length-1],t.style);}this.paintLabel(e,t,n,o);return}if(t instanceof fr){this.paintArrowMark(e,t,n),this.paintLabel(e,t,n,o);return}if(t instanceof gr){this.paintGlyphStamp(e,t,n,o),this.paintLabel(e,t,n,o);return}if(t instanceof Ot){this.paintRadialFib(e,t,n,o),this.paintLabel(e,t,n,o);return}if(t instanceof wr){this.paintFibSpiral(e,t,n),this.paintLabel(e,t,n,o);return}if(t instanceof Cr){this.paintDedekind(e,t,n),this.paintLabel(e,t,n,o);return}if(t instanceof dt){this.paintMachFigure(e,t,n,o),this.paintLabel(e,t,n,o);return}if(t instanceof xr){this.paintFibRatios(e,t,n,o),this.paintGannArcs(e,t,n),this.paintLabel(e,t,n,o);return}if(t instanceof Ce){this.paintFibRatios(e,t,n,o),this.paintLabel(e,t,n,o);return}if(t instanceof Sr){this.paintMeasureBox(e,t,n,o);return}if(t instanceof yt){this.paintPosition(e,t,n,o);return}if(t instanceof vn){this.paintRegressionChannel(e,t,n,o),this.paintLabel(e,t,n,o);return}if(t instanceof mr){this.paintAnchoredVwap(e,t,n),this.paintLabel(e,t,n,o);return}if(t instanceof gt){this.paintFixedRangeVp(e,t,n,o),this.paintLabel(e,t,n,o);return}if(t instanceof ht){this.paintMagnifier(e,t,n,o);return}if(t instanceof We){this.paintPattern(e,t,n,o);return}if(t instanceof hr){this.paintComment(e,t,n,o);return}if(t instanceof ur){this.paintPriceNote(e,t,n,o);return}if(t instanceof pr){this.paintSignpost(e,t,n,o);return}if(t instanceof Xt){this.paintCallout(e,t,n,o);return}if(t instanceof cr){this.paintNote(e,t,n,o);return}if(t instanceof dr){this.paintPriceLabel(e,t,n,o);return}switch(t.type){case "hline":{let i=t.handlePoints(n);if(i.length===0)return;this.stroke(e,t.style,()=>{e.moveTo(0,i[0][1]),e.lineTo(n.width,i[0][1]);});break}case "trendline":case "arrow":{let i=t.handlePoints(n);if(i.length<2)return;this.stroke(e,t.style,()=>{e.moveTo(i[0][0],i[0][1]),e.lineTo(i[1][0],i[1][1]);}),t.style.arrowRight&&this.paintArrowhead(e,i[0],i[1],t.style),t.style.arrowLeft&&this.paintArrowhead(e,i[1],i[0],t.style);break}case "ellipse":{let i=t.handlePoints(n);if(i.length<2)return;let s=(i[0][0]+i[1][0])/2,a=(i[0][1]+i[1][1])/2,l=Math.abs(i[1][0]-i[0][0])/2,c=Math.abs(i[1][1]-i[0][1])/2;t.style.fillColor&&(e.save(),e.fillStyle=t.style.fillColor,e.beginPath(),e.ellipse(s,a,l,c,0,0,Math.PI*2),e.fill(),e.restore()),this.applyStroke(e,t.style),e.beginPath(),e.ellipse(s,a,l,c,0,0,Math.PI*2),e.stroke(),e.setLineDash([]);break}case "ray":{let i=t.handlePoints(n);if(i.length<2)return;let[s,a,l,c]=jo(i[0][0],i[0][1],i[1][0],i[1][1],"right",n.width,n.height);this.stroke(e,t.style,()=>{e.moveTo(s,a),e.lineTo(l,c);});break}case "extendedline":{let i=t.handlePoints(n);if(i.length<2)return;let[s,a,l,c]=jo(i[0][0],i[0][1],i[1][0],i[1][1],"both",n.width,n.height);this.stroke(e,t.style,()=>{e.moveTo(s,a),e.lineTo(l,c);});break}case "vline":{let i=t.handlePoints(n);if(i.length===0)return;this.stroke(e,t.style,()=>{e.moveTo(i[0][0],0),e.lineTo(i[0][0],n.height);});break}case "hray":{let i=t.handlePoints(n);if(i.length===0)return;this.stroke(e,t.style,()=>{e.moveTo(i[0][0],i[0][1]),e.lineTo(n.width,i[0][1]);});break}case "crossline":{let i=t.handlePoints(n);if(i.length===0)return;this.stroke(e,t.style,()=>{e.moveTo(0,i[0][1]),e.lineTo(n.width,i[0][1]),e.moveTo(i[0][0],0),e.lineTo(i[0][0],n.height);});break}case "infoline":this.paintInfoLine(e,t,n);break;case "trendangle":this.paintTrendAngle(e,t,n,o);break;case "circle":{let i=t.handlePoints(n);if(i.length<2)return;let s=i[0][0],a=i[0][1],l=Math.hypot(i[1][0]-s,i[1][1]-a);if(l<1)return;t.style.fillColor&&(e.save(),e.fillStyle=t.style.fillColor,e.beginPath(),e.arc(s,a,l,0,Math.PI*2),e.fill(),e.restore()),this.applyStroke(e,t.style),e.beginPath(),e.arc(s,a,l,0,Math.PI*2),e.stroke(),e.setLineDash([]);break}case "box":{let i=t.handlePoints(n);if(i.length<2)return;let s=Math.min(i[0][0],i[1][0]),a=Math.min(i[0][1],i[1][1]),l=Math.abs(i[1][0]-i[0][0]),c=Math.abs(i[1][1]-i[0][1]);t.style.fillColor&&(e.save(),e.fillStyle=t.style.fillColor,e.fillRect(s,a,l,c),e.restore()),this.applyStroke(e,t.style),e.strokeRect(s,a,l,c),e.setLineDash([]);break}}this.paintLabel(e,t,n,o);}paintLabel(e,t,n,o){let i=t.text;if(!i||!i.value||t.id===this.targets.mutedLabel)return;let s=uI(t,n);if(!s)return;let a=Ke(i.size);e.save(),s.rotate&&(e.translate(s.rotate.cx,s.rotate.cy),e.rotate(s.rotate.angle)),e.font=`${i.bold?"bold ":""}${i.italic?"italic ":""}${a}px ${o.fontFamily}`,e.textBaseline="top",e.textAlign=s.align,e.fillStyle=i.color??o.textColor;let l=pn(a),c=i.value.split(` -`);c.forEach((d,u)=>e.fillText(d,s.x,s.top+u*l)),t.type==="text"&&this.paintTextFrame(e,t.id,s.x,s.top,c,a,o),e.restore();}paintTextFrame(e,t,n,o,i,s,a){let l=this.targets,c=l.selected?.has(t)?x0.selected:l.hovered===t?x0.hovered:0;if(c===0)return;let d=pn(s),u=Math.max(8,...i.map(h=>e.measureText(h).width));e.save(),e.setLineDash([]),e.lineWidth=1,e.strokeStyle=J(a.textColor,c),Wt(e,n-Gr,o-(d-s)/2-$r,u+Gr*2,i.length*d+$r*2,4),e.stroke(),e.restore();}paintFibRatios(e,t,n,o){let i=t.entryLines(n);if(!i||i.length===0)return;for(let l of t.fillBands(n))e.save(),e.globalAlpha=.06*e.globalAlpha,e.fillStyle=l.color,e.fillRect(l.x,l.y,l.w,l.h),e.restore();e.textBaseline="middle";let s=`${Ke(t.numbersSize)}px ${o.fontFamily}`,a=`${Ke(t.labelsSize)}px ${o.fontFamily}`;for(let l of i)this.stroke(e,{...t.style,lineColor:l.color},()=>{e.moveTo(l.x1,l.y1),e.lineTo(l.x2,l.y2);}),e.fillStyle=l.color,e.font=s,e.textAlign=l.numberAlign,e.fillText(l.numberText,l.numberX,l.numberY),l.label&&(e.font=a,e.textAlign="center",e.fillText(l.label,l.labelX,l.labelY));e.textAlign="left",e.textBaseline="alphabetic";}paintRadialFib(e,t,n,o){let i=t.radial(n);if(i&&i.R0>=1){let s=`${Ke(t.numbersSize)}px ${o.fontFamily}`,a=(i.a0+i.a1)/2;e.textBaseline="middle";for(let l of t.levels){if(!l.enabled)continue;let c=i.R0*l.ratio;c<.5||(this.applyStroke(e,{...t.style,lineColor:l.color}),e.beginPath(),e.arc(i.cx,i.cy,c,i.a0,i.a1),e.stroke(),e.setLineDash([]),e.fillStyle=l.color,e.font=s,e.textAlign="left",e.fillText(String(l.ratio),i.cx+Math.cos(a)*c+3,i.cy+Math.sin(a)*c));}e.textBaseline="alphabetic",e.textAlign="left";}for(let s of t.boundingLines(n))this.stroke(e,t.style,()=>{e.moveTo(s[0],s[1]),e.lineTo(s[2],s[3]);});}paintGannArcs(e,t,n){let o=t.arcGeom(n);if(!o||Math.abs(o.bx)<1||Math.abs(o.py)<1)return;let i=24;for(let s of Jd){this.applyStroke(e,{...t.style,lineColor:s.color}),e.beginPath();for(let a=0;a<=i;a+=1){let l=a/i*(Math.PI/2),c=o.ox+s.k*o.bx*Math.cos(l),d=o.oy+s.k*o.py*Math.sin(l);a===0?e.moveTo(c,d):e.lineTo(c,d);}e.stroke();}e.setLineDash([]);}paintFibSpiral(e,t,n){let o=t.spiralPoints(n);!o||o.length<2||this.stroke(e,t.style,()=>{e.moveTo(o[0][0],o[0][1]);for(let i=1;ie.fillText(f,s+l/2,m+g*p)),e.textAlign="left",e.textBaseline="alphabetic";}paintPosition(e,t,n,o){let i=t.layout(n);if(!i)return;let{x1:s,x2:a,ey:l,sy:c,ty:d}=i,u=a-s,h=(b,y,w)=>{e.save(),e.globalAlpha=.13*e.globalAlpha,e.fillStyle=w,e.fillRect(s,Math.min(b,y),u,Math.abs(y-b)),e.restore();};h(l,d,t.profitColor),h(l,c,t.lossColor);let p=(b,y)=>this.stroke(e,{...t.style,lineColor:y},()=>{e.moveTo(s,b),e.lineTo(a,b);});if(p(d,t.profitColor),p(c,t.lossColor),p(l,t.style.lineColor),!t.showText)return;let m=Ke(t.text?.size??"normal");e.fillStyle=t.text?.color??o.textColor,e.textAlign="center",e.textBaseline="middle",e.font=`${m}px ${o.fontFamily}`;let f=s+u/2,g=Math.min(l,c,d)-9;t.showHeader&&e.fillText(t.headerLabel(),f,t.showLossSize?g-Math.round(m*1.15):g),e.font=`${Math.max(10,m-1)}px ${o.fontFamily}`,t.showLossSize&&e.fillText(t.lossSizeLabel(),f,g),t.showTargetLabel&&e.fillText(t.targetLabel(),f,(l+d)/2),t.showStopLabel&&e.fillText(t.stopLabel(),f,(l+c)/2),e.textAlign="left",e.textBaseline="alphabetic";}paintRegressionChannel(e,t,n,o){let i=t.layout(n);if(!i)return;let s=t.reg,a=(c,d,u,h,p)=>{e.save(),e.fillStyle=c,e.beginPath(),e.moveTo(i.x0,d),e.lineTo(i.x1,u),e.lineTo(i.x1,p),e.lineTo(i.x0,h),e.closePath(),e.fill(),e.restore();};a(s.upperFill,i.midY0,i.midY1,i.upperY0,i.upperY1),a(s.lowerFill,i.midY0,i.midY1,i.lowerY0,i.lowerY1);let l=(c,d,u,h)=>this.stroke(e,{lineColor:c,lineWidth:t.style.lineWidth,lineStyle:d},()=>{e.moveTo(i.x0,u),e.lineTo(i.x1,h);});if(l(s.upperColor,s.upperStyle,i.upperY0,i.upperY1),l(s.lowerColor,s.lowerStyle,i.lowerY0,i.lowerY1),l(s.midColor,s.midStyle,i.midY0,i.midY1),i.showR2){let c=`R\xB2 ${Math.round(i.r2*100)}%`;e.font=`11px ${o.fontFamily}`;let d=e.measureText(c).width,u=5,h=4,p=d+u*2,m=i.x0-h-p,f=i.midY0-9;e.save(),e.globalAlpha=.9*e.globalAlpha,Wt(e,m,f-8,p,16,3),e.fillStyle=w0,e.fill(),e.restore(),e.fillStyle=o.textColor,e.textAlign="left",e.textBaseline="middle",e.fillText(c,m+u,f),e.textBaseline="alphabetic";}}paintMagnifierGhost(e,t,n,o){let i=t.rect(n);i&&(e.save(),e.strokeStyle=t.style.lineColor||Ye(o.background),e.lineWidth=1,e.setLineDash([4,4]),e.strokeRect(Math.min(i.x1,i.x2),Math.min(i.y1,i.y2),Math.abs(i.x2-i.x1),Math.abs(i.y2-i.y1)),e.restore());}paintMagnifier(e,t,n,o){let i=t.rect(n),s=t.anchors[0],a=t.anchors[1];if(!i||!s||!a)return;let l=Math.min(i.x1,i.x2),c=Math.max(i.x1,i.x2),d=Math.min(i.y1,i.y2),u=Math.max(i.y1,i.y2),h=c-l,p=u-d;e.save(),e.globalAlpha=1,e.fillStyle=o.background,e.fillRect(l,d,h,p),e.restore();let m=Math.min(s.time,a.time),f=Math.max(s.time,a.time),g=n.barsBetween?n.barsBetween(m,f):0,b=g>0?(f-m)/g:0,y=n.seriesInRange&&b>0&&h>1&&p>1?n.seriesInRange(t.magnifier.timeframe,m,f+b):void 0,w=y?.state==="ready"||y?.state==="loading"?y.bars??[]:[];if(y&&(y.state==="ready"||y.state==="loading")&&w.length>0){let C=this.seriesLook,M=C.style!=="candles"?uo(C.style):null;M&&(w=M.full(w));let S=C.style==="bars"?"bars":C.style==="line"||C.style==="baseline"?"line":C.style==="area"?"area":"candles",L=(n.xOf(m+b)-n.xOf(m))/2;e.save(),e.beginPath(),e.rect(l,d,h,p),e.clip(),S==="line"||S==="area"?this.paintMagnifierLine(e,t,n,w,y.barMs,L,u,S==="area",t.magnifier.upColor||C.lineColor):this.paintMagnifierBars(e,t,n,w,y.barMs,L,l,c,S,t.magnifier.upColor||C.upColor,t.magnifier.downColor||C.downColor),e.restore();}else if(y){let C=y.state==="loading"?"Loading\u2026":y.state==="ready"?"No lower-timeframe data":y.reason==="too-wide"?"Area too wide for this timeframe":y.reason==="none-lower"?"No lower timeframe available":y.reason==="not-lower"?"Pick a timeframe below the chart":"No data source";this.paintMagnifierNotice(e,C,l,d,h,p,o);}if(e.save(),e.strokeStyle=t.style.lineColor||Ye(o.background),e.lineWidth=t.style.lineWidth||1,e.setLineDash(nr(t.style.lineStyle,t.style.lineWidth||1)),e.strokeRect(l,d,h,p),e.restore(),h>44){let C=xi(y?.state==="ready"||y?.state==="loading"?y.timeframe:t.magnifier.timeframe),M=17,S=4,L=n.paneRect?.(t.paneId),v=L?L.top+L.height:n.height,x=u+S+M<=v?u+S:u-S-M;e.save(),e.font=`10px ${o.fontFamily}`;let E=e.measureText(C).width,N=E+12+11;Wt(e,l,x,N,M,3),e.fillStyle=o.background,e.fill(),e.strokeStyle=J(o.textColor,.28),e.lineWidth=1,e.setLineDash([]),e.stroke(),e.fillStyle=o.textColor,e.textAlign="left",e.textBaseline="middle",e.fillText(C,l+6,x+M/2+.5);let V=l+6+E+5,Z=x+M/2;e.strokeStyle=J(o.textColor,.7),e.lineWidth=1.2,e.beginPath(),e.moveTo(V,Z-1.5),e.lineTo(V+2.5,Z+1.5),e.lineTo(V+5,Z-1.5),e.stroke(),e.restore(),t.chipRect={x:l,y:x,w:N,h:M};}else t.chipRect=null;}paintMagnifierBars(e,t,n,o,i,s,a,l,c,d,u){e.setLineDash([]),e.lineWidth=1;for(let h of o){let p=n.xOf(h.time)-s,m=n.xOf(h.time+i)-s;if(ml)continue;let f=n.yOf(h.high,t.paneId),g=n.yOf(h.low,t.paneId),b=n.yOf(h.open,t.paneId),y=n.yOf(h.close,t.paneId);if(f==null||g==null||b==null||y==null)continue;let w=h.close>=h.open?d:u,C=m-p,M=(p+m)/2;if(e.strokeStyle=w,e.beginPath(),e.moveTo(M,f),e.lineTo(M,g),e.stroke(),!(C<3))if(c==="bars"){let S=Math.max(1,C*.35);e.beginPath(),e.moveTo(M-S,b),e.lineTo(M,b),e.moveTo(M,y),e.lineTo(M+S,y),e.stroke();}else {let S=Math.max(1,C*.7);e.fillStyle=w,e.fillRect(M-S/2,Math.min(b,y),S,Math.max(1,Math.abs(y-b)));}}}paintMagnifierLine(e,t,n,o,i,s,a,l,c){let d=[];for(let u of o){let h=n.yOf(u.close,t.paneId);h!=null&&d.push([n.xOf(u.time+i/2)-s,h]);}if(!(d.length<2)){if(l){e.beginPath(),e.moveTo(d[0][0],a);for(let[u,h]of d)e.lineTo(u,h);e.lineTo(d[d.length-1][0],a),e.closePath(),e.fillStyle=J(c,.15),e.fill();}e.setLineDash([]),e.lineWidth=1.5,e.strokeStyle=c,e.beginPath(),e.moveTo(d[0][0],d[0][1]);for(let u=1;u=a.vaFrom&&f<=a.vaTo,k=v?s.vaUpColor:s.upColor,x=v?s.vaDownColor:s.downColor,E=d===1?c:c-S;L>0&&(e.fillStyle=k,e.fillRect(E,C,L,M)),S-L>0&&(e.fillStyle=x,e.fillRect(E+L,C,S-L,M));}let h=t.style.lineWidth,p=(f,g,b,y)=>{!f||y==null||C0(g)||this.stroke(e,{lineColor:g,lineWidth:h,lineStyle:b},()=>{e.moveTo(i.x0,y),e.lineTo(i.x1,y);});};p(s.showVah,s.vahColor,s.vahStyle,i.vahY),p(s.showVal,s.valColor,s.valStyle,i.valY),p(s.showPoc,s.pocColor??Ye(o.background),s.pocStyle,i.pocY);let m=Math.max(1,h);if(s.showDevelopingPoc&&this.strokePolyline(e,i.developingPoc,{lineColor:s.developingPocColor,lineWidth:m,lineStyle:s.developingPocStyle}),s.showDevelopingVa){let f={lineColor:s.developingVaColor,lineWidth:m,lineStyle:s.developingVaStyle};this.strokePolyline(e,i.developingVaHigh,f),this.strokePolyline(e,i.developingVaLow,f);}}paintAnchoredVwap(e,t,n){let o=t.layout(n);if(!o)return;let i=t.vwap,s=t.style.lineWidth;if(o.upper.length>=2&&i.bandFill){e.save(),e.fillStyle=i.bandFill,e.beginPath(),e.moveTo(o.upper[0][0],o.upper[0][1]);for(let a=1;a=0;a-=1)e.lineTo(o.lower[a][0],o.lower[a][1]);e.closePath(),e.fill(),e.restore();}this.strokePolyline(e,o.upper,{lineColor:i.upperColor,lineWidth:s,lineStyle:i.upperStyle}),this.strokePolyline(e,o.lower,{lineColor:i.lowerColor,lineWidth:s,lineStyle:i.lowerStyle}),this.strokePolyline(e,o.mid,{lineColor:i.midColor,lineWidth:s,lineStyle:i.midStyle});}strokePolyline(e,t,n){t.length<2||C0(n.lineColor)||this.stroke(e,n,()=>{e.moveTo(t[0][0],t[0][1]);for(let o=1;oe.measureText(I).width)),f=9,g=6,b=pn(h),y=m+f*2,w=p.length*b+g*2,C=c-y/2,M=d-w/2,S=y/2,L=w/2,v=a-c,k=l-d,x=Math.min(i,y/2,w/2),E=null;if(Math.abs(v)>S||Math.abs(k)>L){let I=Math.max(6,Math.min(y,w)*.18);if(Math.abs(v)/S>=Math.abs(k)/L){let N=v>0?C+y:C,V=Math.max(M+x+I,Math.min(M+w-x-I,d+k*(N-c)/(v||1)));E={edge:v>0?"right":"left",at:V,apex:[a,l],half:I};}else {let N=k>0?M+w:M,V=Math.max(C+x+I,Math.min(C+y-x-I,c+v*(N-d)/(k||1)));E={edge:k>0?"bottom":"top",at:V,apex:[a,l],half:I};}}e.save(),e.fillStyle=Et(t,o)??o.background,T0(e,C,M,y,w,x,E),e.fill(),e.restore(),this.applyStroke(e,t.style),T0(e,C,M,y,w,x,E),e.stroke(),e.setLineDash([]),e.fillStyle=u?.color??Ye(Et(t,o)??o.background),e.textBaseline="top",e.textAlign="left",p.forEach((I,N)=>e.fillText(I,C+f,M+g+N*b));}paintTextPlate(e,t,n,o,i,s,a,l,c,d,u){e.save(),e.fillStyle=Et(t,n)??n.background,Wt(e,o,i,s,a,5),e.fill(),e.restore(),this.applyStroke(e,t.style),Wt(e,o,i,s,a,5),e.stroke(),e.setLineDash([]),e.fillStyle=t.text?.color??Ye(Et(t,n)??n.background),e.textBaseline="top",e.textAlign="left",l.forEach((h,p)=>e.fillText(h,o+d,i+u+p*c));}measureText(e,t,n,o){let i=t.text,s=Ke(i?.size??"normal");e.font=`${i?.bold?"bold ":""}${i?.italic?"italic ":""}${s}px ${n.fontFamily}`;let a=(i?.value||o).split(` -`),l=Math.max(8,...a.map(c=>e.measureText(c).width));return {lines:a,tw:l,fs:s,lh:pn(s)}}paintNote(e,t,n,o){let i=t.handlePoints(n);if(!i.length)return;let[s,a]=i[0],{lines:l,tw:c,lh:d}=this.measureText(e,t,o,"Note"),u=8,h=5;this.paintTextPlate(e,t,o,s,a,c+u*2,l.length*d+h*2,l,d,u,h);}paintPriceNote(e,t,n,o){let i=t.points(n),s=t.anchors[0];if(!i||!s)return;let[a,l]=i[0],[c,d]=i[1],u=S0(s.price),h=t.text,p=Ke(h?.size??"normal");e.font=`${h?.bold?"bold ":""}${h?.italic?"italic ":""}${p}px ${o.fontFamily}`;let m=9,f=6,g=e.measureText(u).width+m*2,b=pn(p)+f*2,y=c-g/2,w=d-b/2;this.stroke(e,t.style,()=>{e.moveTo(a,l),e.lineTo(c,d);}),e.fillStyle=t.style.lineColor,e.beginPath(),e.arc(a,l,3,0,Math.PI*2),e.fill(),e.save(),e.fillStyle=Et(t,o)??o.background,Wt(e,y,w,g,b,5),e.fill(),e.restore(),this.applyStroke(e,t.style),Wt(e,y,w,g,b,5),e.stroke(),e.setLineDash([]),e.fillStyle=h?.color??Ye(Et(t,o)??o.background),e.textBaseline="middle",e.textAlign="center",e.fillText(u,c,d+.5);}paintSignpost(e,t,n,o){let i=t.points(n);if(!i)return;let[s,a]=i[0],[l,c]=i[1],{lines:d,tw:u,lh:h}=this.measureText(e,t,o,"Signpost"),p=9,m=6,f=u+p*2,g=d.length*h+m*2;this.stroke(e,t.style,()=>{e.moveTo(s,a),e.lineTo(l,c);}),e.fillStyle=t.style.lineColor,e.beginPath(),e.arc(s,a,3.5,0,Math.PI*2),e.fill(),this.paintTextPlate(e,t,o,l-f/2,c-g/2,f,g,d,h,p,m);}paintPriceLabel(e,t,n,o){let i=t.handlePoints(n),s=t.anchors[0];if(!i.length||!s)return;let[a,l]=i[0],c=S0(s.price),d=t.text,u=Ke(d?.size??"normal");e.font=`${d?.bold?"bold ":""}${d?.italic?"italic ":""}${u}px ${o.fontFamily}`;let h=e.measureText(c).width,p=8,m=4,f=6,g=h+p*2,b=pn(u)+m*2,y=l-b/2,w=Et(t,o)??o.background;e.save(),e.fillStyle=w,e.beginPath(),e.moveTo(a,l),e.lineTo(a+f,l-5),e.lineTo(a+f,l+5),e.closePath(),e.fill(),Wt(e,a+f,y,g,b,4),e.fill(),e.restore(),this.applyStroke(e,t.style),Wt(e,a+f,y,g,b,4),e.stroke(),e.setLineDash([]),e.fillStyle=d?.color??Ye(w),e.textBaseline="middle",e.textAlign="left",e.fillText(c,a+f+p,l+.5);}paintPattern(e,t,n,o){let i=t.handlePoints(n);if(i.length<2)return;let s=t.valid(),a=Et(t,o)??t.style.lineColor,l=t.style.fillColor?1:.1;for(let[h,p,m]of t.fillTriangles()){let f=i[h],g=i[p],b=i[m];!f||!g||!b||(e.save(),e.globalAlpha=l*e.globalAlpha,e.fillStyle=a,e.beginPath(),e.moveTo(f[0],f[1]),e.lineTo(g[0],g[1]),e.lineTo(b[0],b[1]),e.closePath(),e.fill(),e.restore());}this.stroke(e,t.style,()=>{e.moveTo(i[0][0],i[0][1]);for(let h=1;h=2){let f=qd(h[0],h[1],p[0],p[1],i[0][0],i[0][1],i[1][0],i[1][1])??h,g=qd(h[0],h[1],p[0],p[1],i[m-2][0],i[m-2][1],i[m-1][0],i[m-1][1])??p;this.stroke(e,{...t.style,lineStyle:"dashed"},()=>{e.moveTo(f[0],f[1]),e.lineTo(g[0],g[1]);});}}let d=t.vertexLabels();if(e.fillStyle=o.textColor,e.font=`bold 12px ${o.fontFamily}`,e.textAlign="center",i.forEach((h,p)=>{let m=d[p];if(!m)return;let f=((i[p-1]?.[1]??h[1])+(i[p+1]?.[1]??h[1]))/2,g=h[1]<=f;e.textBaseline=g?"bottom":"top",e.fillText(m,h[0],g?h[1]-7:h[1]+7);}),t.legRatios()){e.font=`11px ${o.fontFamily}`,e.textAlign="left",e.textBaseline="middle";for(let h=2;h=2){let h=i[i.length-1],p=i[i.length-2],m=p?h[1]<=p[1]:false;e.font=`bold 12px ${o.fontFamily}`,e.fillStyle=s===false?Hs:_s,e.textAlign="center",e.textBaseline=m?"bottom":"top",e.fillText(`${u} ${s?"\u2713":"\u2717"}`,h[0],m?h[1]-22:h[1]+22);}e.textAlign="left",e.textBaseline="alphabetic";}paintHighlighter(e,t,n){let o=t.geometry(n);if(!o||o.segments.length===0)return;e.save(),e.strokeStyle=t.style.lineColor,e.lineWidth=t.style.lineWidth,e.lineCap="round",e.lineJoin="round",e.setLineDash([]),e.beginPath();let i=o.segments[0];e.moveTo(i[0],i[1]);for(let s of o.segments)e.lineTo(s[2],s[3]);e.stroke(),e.restore();}paintSegments(e,t,n){let o=t.geometry(n);if(o){if(o.fill&&o.fill.length>=3&&t.style.fillColor){e.save(),e.fillStyle=t.style.fillColor,e.beginPath(),e.moveTo(o.fill[0][0],o.fill[0][1]);for(let i=1;i{e.moveTo(i[0],i[1]),e.lineTo(i[2],i[3]);});}}paintInfoLine(e,t,n){let o=t.handlePoints(n);if(o.length<2)return;let[i,s]=o[0],[a,l]=o[1];this.stroke(e,t.style,()=>{e.moveTo(i,s),e.lineTo(a,l);});let c=t.anchors[0],d=t.anchors[1];if(!c||!d)return;let u=d.price-c.price,h=c.price!==0?u/c.price*100:0,p=n.barsBetween?Math.abs(Math.round(n.barsBetween(c.time,d.time))):0,m=u>=0?"+":"",f=`${m}${u.toFixed(2)} (${m}${h.toFixed(2)}%) ${p} bars`,g=(i+a)/2,b=(s+l)/2;e.font="11px monospace";let y=e.measureText(f).width+12,w=18,C=g-2,M=b-w-4;e.save(),e.globalAlpha=.9*e.globalAlpha,Wt(e,C,M,y,w,3),e.fillStyle=w0,e.fill(),e.strokeStyle=cI,e.lineWidth=1,e.stroke(),e.restore(),e.fillStyle=u>=0?O:D,e.textAlign="left",e.textBaseline="middle",e.fillText(f,C+6,M+w/2),e.textBaseline="alphabetic";}paintTrendAngle(e,t,n,o){let i=t.handlePoints(n);if(i.length<2)return;let[s,a]=i[0],[l,c]=i[1];this.stroke(e,t.style,()=>{e.moveTo(s,a),e.lineTo(l,c);});let d=l-s,u=c-a,h=Math.atan2(-u,d),p=h*(180/Math.PI),m=Math.min(30,Math.hypot(d,u)*.3),f=t.style.lineColor;if(e.save(),e.globalAlpha=.4*e.globalAlpha,e.strokeStyle=f,e.lineWidth=1,e.setLineDash([4,4]),e.beginPath(),e.moveTo(s,a),e.lineTo(s+Math.max(Math.abs(d),m+20),a),e.stroke(),e.restore(),e.setLineDash([]),m>1){let g=-h;e.strokeStyle=f,e.lineWidth=1.5,e.beginPath(),e.arc(s,a,m,Math.min(0,g),Math.max(0,g)),e.stroke();}e.fillStyle=f,e.font=`11px ${o.fontFamily}`,e.textAlign="left",e.textBaseline="alphabetic",e.fillText(`${p.toFixed(1)}\xB0`,s+m+6,a+(u<0?-14:2));}paintArrowMark(e,t,n){let o=t.glyphPoints(n);if(!(!o||o.length<3)){e.save(),e.setLineDash([]),e.fillStyle=t.style.lineColor,e.beginPath(),e.moveTo(o[0][0],o[0][1]);for(let i=1;i{if(s&&s.edge===l){let[u,h]=s.apex;l==="top"?(r.lineTo(s.at-s.half,t),r.lineTo(u,h),r.lineTo(s.at+s.half,t)):l==="bottom"?(r.lineTo(s.at+s.half,t+o),r.lineTo(u,h),r.lineTo(s.at-s.half,t+o)):l==="right"?(r.lineTo(e+n,s.at-s.half),r.lineTo(u,h),r.lineTo(e+n,s.at+s.half)):(r.lineTo(e,s.at+s.half),r.lineTo(u,h),r.lineTo(e,s.at-s.half));}r.lineTo(c,d);};r.beginPath(),r.moveTo(e+i,t),a("top",e+n-i,t),r.arcTo(e+n,t,e+n,t+i,i),a("right",e+n,t+o-i),r.arcTo(e+n,t+o,e+n-i,t+o,i),a("bottom",e+i,t+o),r.arcTo(e,t+o,e,t+o-i,i),a("left",e,t+i),r.arcTo(e,t,e+i,t,i),r.closePath();}function dI(r){if(!Number.isFinite(r))return "";let e=Math.round(r*1e3)/1e3;return String(e)}function uI(r,e){let t=r.text;if(!t)return null;let n=r.handlePoints(e),o=t.value.split(` -`).length,i=pn(Ke(t.size));switch(r.type){case "text":return n[0]?{x:n[0][0]+2,top:n[0][1]+2,align:"left"}:null;case "hline":return n[0]?{x:n[0][0]+8,top:n[0][1]-4-i*o,align:"left"}:null;case "trendline":case "ray":case "extendedline":case "infoline":case "trendangle":{if(n.length<2)return null;let[s,a]=n[0],[l,c]=n[1];return {x:0,top:-6-i*o,align:"center",rotate:{angle:Kw(s,a,l,c),cx:(s+l)/2,cy:(a+c)/2}}}case "box":return n.length<2?null:{x:(n[0][0]+n[1][0])/2,top:(n[0][1]+n[1][1])/2-i*o/2,align:"center"};default:return n[0]?{x:n[0][0],top:n[0][1],align:"left"}:null}}function Jo(r,e,t,n,o=6){for(let i=r.length-1;i>=0;i-=1){let s=r[i];if(!s.visible)continue;let a=n.paneRect?.(s.paneId);if(!(a&&a.height<=0)&&s.hitTest(e,t,n,o))return s}return null}function lp(r,e){let t=[...r];return t.length<2?t:t.filter(n=>!e.find(o=>o.id===n)?.locked)}function k0(r,e,t,n){return n&&e.size>=2&&e.has(r.id)?lp(e,t):r.locked?[]:[r.id]}var md=3,hI=4,L0=Math.PI/4,M0=new Set(["trendline","ray","extendedline","infoline","trendangle","arrow"]),fd=class{constructor(e){this.deps=e;this.state={kind:"idle"};this.snapAt=null;}snapMarker(){return this.snapAt}placingMarkers(e){if(this.state.kind!=="placing")return null;let{draft:t}=this.state;if(t.placementMode()==="freehand")return null;let n=[];for(let o of t.anchors){let i=e.yOf(o.price,t.paneId);i!=null&&n.push([e.xOf(o.time),i]);}return n.length?n:null}resolve(e,t,n,o){let i=this.deps.projector().pxToPoint(e,t,n);if(o==="off")return this.snapAt=null,i;let s=this.deps.snap(i,n,o,{x:e,y:t}),a=s.time!==i.time||s.price!==i.price;return this.snapAt=a?{point:s,paneId:n}:null,s}snapCursor(e,t,n){let o=this.deps.projector(),i=o.paneIdAtY(t)??"price",s=this.resolve(e,t,i,n),a=o.yOf(s.price,i);return {x:o.xOf(s.time),y:a??t}}clearSnapMarker(){this.snapAt=null;}resolveAngleSnapped(e,t,n,o){let i=this.deps.projector(),s=i.xOf(e.time),a=i.yOf(e.price,t);if(this.snapAt=null,a==null)return i.pxToPoint(n,o,t);let l=Math.hypot(n-s,o-a);if(l<1)return i.pxToPoint(n,o,t);let c=Math.round(Math.atan2(o-a,n-s)/L0)*L0;return i.pxToPoint(s+l*Math.cos(c),a+l*Math.sin(c),t)}placingPivot(e){return M0.has(e.type)?e.anchors[e.anchors.length-1]??null:null}claim(e,t){return this.deps.activeTool()!=null||this.state.kind!=="idle"?true:this.hitAt(e,t)!=null}cursorAt(e,t){return this.deps.activeTool()!=null?null:this.hitAt(e,t)?"pointer":null}isPlacing(){return this.state.kind==="placing"}isDragging(){return this.state.kind==="pressed"&&this.state.moved}activeDragId(){return this.state.kind==="pressed"&&this.state.moved?this.state.id:null}pressedId(){return this.state.kind==="pressed"?this.state.id:null}dragClones(){return this.state.kind==="pressed"&&this.state.moved&&this.state.clones?this.state.clones.map(e=>e.d):null}marqueeRect(){if(this.state.kind!=="marquee")return null;let{x0:e,y0:t,x1:n,y1:o}=this.state;return {x:Math.min(e,n),y:Math.min(t,o),w:Math.abs(n-e),h:Math.abs(o-t)}}beginMarquee(e,t){return this.state.kind!=="idle"||this.deps.activeTool()!=null?false:(this.state={kind:"marquee",x0:e,y0:t,x1:e,y1:t},true)}down(e,t,n="off",o=false,i=false){let s=this.deps.projector();if(this.state.kind==="placing"){if(this.state.draft.placementMode()!=="click")return;let c=o?this.placingPivot(this.state.draft):null,d=c?this.resolveAngleSnapped(c,this.state.draft.paneId,e,t):this.resolve(e,t,this.state.draft.paneId,n);this.state.draft.anchors.push(this.placementAnchor(this.state.draft,d)),this.state.draft.anchors.length>=this.state.need?this.finalize():this.deps.changed();return}let a=this.deps.activeTool();if(a){let c=s.paneIdAtY(t)??"price",d=Wn(a,{paneId:c,anchors:[this.resolve(e,t,c,n)],style:this.deps.lastStyle()});if(!d)return;this.state={kind:"placing",draft:d,need:d.anchorSchema().max,cursor:null},d.placementMode()==="click"&&d.anchors.length>=this.state.need?this.finalize():this.deps.changed();return}let l=this.hitAt(e,t);if(l){if(o){this.deps.emit({kind:"select",ids:[l.id],additive:true});return}let c=l.hitHandle(e,t,s,6),d=[];if(c<0&&this.deps.selectedIds().has(l.id))for(let u of this.deps.selectedIds()){let h=u===l.id?null:this.byId(u);h&&!h.locked&&h.visible&&d.push({id:u,orig:cp(h)});}this.state={kind:"pressed",id:l.id,handle:c,orig:cp(l),px:e,py:t,moved:false,riders:d,mod:i,clones:null};}}bodyDelta(e,t,n){if(this.state.kind!=="pressed")return {dt:0,dp:0};let o=this.deps.projector(),i=o.pxToPoint(this.state.px,this.state.py,e),s=o.pxToPoint(t,n,e);return {dt:s.time-i.time,dp:s.price-i.price}}dragSources(e){if(this.state.kind!=="pressed")return [];let t=[{d:e,orig:this.state.orig}];for(let n of this.state.riders){let o=this.byId(n.id);o&&t.push({d:o,orig:n.orig});}return t}dragBody(e,t,n){if(this.state.kind==="pressed"){this.snapAt=null,this.state.mod&&!this.state.clones&&(this.state.clones=this.dragSources(e).flatMap(o=>{let i=wt(o.d.serialize());return i?[{d:i,orig:cp(i)}]:[]}));for(let o of this.state.clones??this.dragSources(e)){let{dt:i,dp:s}=this.bodyDelta(o.d.paneId,t,n);o.d.anchors=o.d.translateBody(i,s,o.orig);}}}move(e,t,n="off",o=false){if(this.state.kind==="idle"){let s=this.deps.activeTool(),a=this.snapAt!=null;s&&n!=="off"?this.resolve(e,t,this.deps.projector().paneIdAtY(t)??"price",n):this.snapAt=null,(this.snapAt!=null||a)&&this.deps.changed();return}if(this.state.kind==="placing"){if(this.state.draft.placementMode()==="freehand"){this.captureFreehand(e,t);return}let s=o?this.placingPivot(this.state.draft):null;this.state.cursor=s?this.resolveAngleSnapped(s,this.state.draft.paneId,e,t):this.resolve(e,t,this.state.draft.paneId,n),this.deps.changed();return}if(this.state.kind==="marquee"){this.state.x1=e,this.state.y1=t,this.deps.changed();return}if(this.state.kind!=="pressed")return;let i=this.byId(this.state.id);if(!(!i||i.locked)&&!(!this.state.moved&&Math.abs(e-this.state.px)<=md&&Math.abs(t-this.state.py)<=md)){if(this.state.moved=true,this.state.handle<0)this.dragBody(i,e,t);else {let s=i.anchors[this.state.handle];if(s){let a=o&&M0.has(i.type)&&i.anchors.length===2?i.anchors[1-this.state.handle]:void 0,l=a?this.resolveAngleSnapped(a,i.paneId,e,t):this.resolve(e,t,i.paneId,n);mI(s,l,i.anchorSchema().slots[this.state.handle]?.free??"both");}i.constrainHandleDrag(this.state.handle);}this.deps.changed();}}up(e,t){if(this.snapAt=null,this.state.kind==="placing"){let c=this.state.draft.placementMode();c==="drag"?(this.state.cursor&&this.state.draft.anchors.push(this.state.cursor),this.state.draft.anchors.length>=this.state.draft.anchorSchema().min?this.finalize():this.discardPlacing()):c==="freehand"&&(this.state.draft.anchors.length>=this.state.draft.anchorSchema().min?this.finalize():this.discardPlacing());return}if(this.state.kind==="marquee"){let c=this.marqueeRect();this.state={kind:"idle"},(c.w>md||c.h>md)&&this.selectWithin(c),this.deps.changed();return}if(this.state.kind!=="pressed")return;let{id:n,moved:o,riders:i,mod:s,clones:a}=this.state;this.state={kind:"idle"};let l=this.byId(n);if(!o){s?this.deps.emit({kind:"select",ids:[n],additive:true}):this.deps.openSettings(n,e,t);return}if(a)this.deps.emit({kind:"clone",docs:a.map(c=>c.d.serialize())});else if(l){let c=[l.serialize()];for(let d of i){let u=this.byId(d.id);u&&c.push(u.serialize());}c.length>1?this.deps.emit({kind:"edit-many",docs:c}):this.deps.emit({kind:"edit",doc:c[0]});}this.deps.changed();}selectWithin(e){let t=this.deps.projector(),n=[...this.deps.selectedIds()];for(let o of this.deps.drawings()){if(!o.visible||n.includes(o.id))continue;let i=o.bounds(t);i&&pI(e,i)&&n.push(o.id);}n.length>this.deps.selectedIds().size&&this.deps.emit({kind:"select",ids:n});}cancel(){if(this.snapAt=null,this.state.kind==="placing"){let e=this.state.draft.type;return this.state={kind:"idle"},this.deps.emit({kind:"tool-finished",type:e}),this.deps.changed(),true}if(this.state.kind==="pressed"){if(this.state.moved&&!this.state.clones){let e=this.byId(this.state.id);if(e)for(let t of this.dragSources(e))t.d.anchors=t.orig.map(n=>({time:n.time,price:n.price}));}return this.state={kind:"idle"},this.deps.changed(),true}return this.state.kind==="marquee"?(this.state={kind:"idle"},this.deps.changed(),true):false}onToolCleared(){this.state.kind==="placing"&&(this.state={kind:"idle"},this.deps.changed());}ghost(){if(this.state.kind!=="placing")return null;let{draft:e,cursor:t}=this.state;return t?Wn(e.type,{paneId:e.paneId,anchors:[...e.anchors,this.placementAnchor(e,t)],style:e.style}):e.anchors.length>=1&&e.type==="hline"?e:null}placementAnchor(e,t){if(e.type!=="parallelchannel"||e.anchors.length!==2)return t;let n=e.anchors[0],o=e.anchors[1],i=o.time-n.time,s=i===0?n.price:n.price+(o.price-n.price)*(t.time-n.time)/i,a=t.price-s;return {time:(n.time+o.time)/2,price:(n.price+o.price)/2+a}}captureFreehand(e,t){if(this.state.kind!=="placing")return;this.snapAt=null;let n=this.state.draft,o=this.deps.projector(),i=n.anchors[n.anchors.length-1],s=i?o.xOf(i.time):NaN,a=i?o.yOf(i.price,n.paneId)??NaN:NaN;if(Math.hypot(e-s,t-a)>hI){if(n.anchors.length>=this.state.need){let l=n.anchors.length-1;n.anchors=n.anchors.filter((c,d)=>d%2===0||d===l);}n.anchors.push(o.pxToPoint(e,t,n.paneId));}this.state.cursor=o.pxToPoint(e,t,n.paneId),this.deps.changed();}finishPlacing(e){if(this.state.kind!=="placing")return false;let t=this.state.draft,n=t.anchorSchema();return t.placementMode()!=="click"||n.max<=n.min||(e&&t.anchors.length>n.min&&t.anchors.pop(),t.anchors.length=0)return o;return Jo(this.deps.drawings(),e,t,n,6)}handleDrawings(){let e=new Set(this.deps.selectedIds()),t=this.deps.hoveredId();t&&e.add(t);let n=[];for(let o of e){let i=this.byId(o);i&&n.push(i);}return n}byId(e){return this.deps.drawings().find(t=>t.id===e)??null}};function cp(r){return r.anchors.map(e=>({time:e.time,price:e.price}))}function pI(r,e){return r.x<=e.x+e.w&&e.x<=r.x+r.w&&r.y<=e.y+e.h&&e.y<=r.y+r.h}function mI(r,e,t){(t==="both"||t==="x")&&(r.time=e.time),(t==="both"||t==="y")&&(r.price=e.price);}var fI=[{value:"price",label:"Price"},{value:"points",label:"Points"}],gI=[{value:"right",label:"Right"},{value:"left",label:"Left"}],bI={position:"Position size",frvp:"Volume profile",levels:"Levels"},gd=class{constructor(e,t){this.host=e;this.ui=null;this.theme=t;}setTheme(e){this.theme=e;}isOpen(){return this.ui!=null}contains(e){return this.ui?.contains(e)===true}open(e,t,n){this.close();let o=Zt(e.serialize()),i=Ss({variant:"inputs"});if(i.style.padding="16px 20px",i.style.overflowY="auto",i.style.overflowX="hidden",i.style.flex="1 1 auto",n==="position"&&e instanceof yt)this.buildPosition(i,e,t);else if(n==="frvp"&&e instanceof gt)this.buildFrvp(i,e,t);else if(n==="levels")this.buildLevels(i,e,t);else return;let s=new En({host:this.host,title:bI[n],modal:false,contained:true,align:"center",draggable:true,flush:true,className:"vela-dialog--form",closeOnEscape:false,footer:l=>{l.append(E0("Cancel",false,()=>{t.restore?.(o),this.close();}),E0("Ok",true,()=>this.close()));},onOpenChange:l=>{l||this.close();}});Be(s.panel,this.theme),s.body.appendChild(i);let a=l=>{if(!(l.target!==s.backdrop&&l.target!==s.positioner)){if(dn()||Br(l)){Me();return}this.close();}};s.backdrop.addEventListener("pointerdown",a),s.positioner.addEventListener("pointerdown",a),s.panel.addEventListener("keydown",l=>{l.key==="Escape"&&(l.preventDefault(),t.restore?.(o),this.close());}),this.ui=s,s.show();}close(){let e=this.ui;this.ui=null,e?.destroy();}destroy(){this.close();}buildPosition(e,t,n){let o=()=>{let p=n.resolve();return p instanceof yt?p:t},i=[],s=()=>i.forEach(p=>p()),a=p=>Math.round(p*1e8)/1e8,l=(p,m,f)=>{let g=de({kind:"number",value:a(o()[m]),min:f?.min,max:f?.max,step:f?.step,integer:f?.integer,fill:false,commit:"blur",onChange:b=>{n.patch({[m]:b}),s();}});i.push(()=>{document.activeElement!==g.el.querySelector("input")&&g.setValue?.(a(o()[m]));}),e.appendChild(He({label:p,control:g.el}));},c=(p,m,f)=>{let g="price",b=()=>a(o().levelDisplayValue(f,g)),y=de({kind:"number",value:b(),fill:false,commit:"blur",onChange:C=>{n.patch({[m]:o().levelPriceFromDisplay(f,g,C)}),s();}}),w=de({kind:"select",options:fI,value:g,fill:false,theme:this.theme,onChange:C=>{g=C,y.setValue?.(b());}});i.push(()=>{document.activeElement!==y.el.querySelector("input")&&y.setValue?.(b());}),e.appendChild(He({label:p,control:[y.el,w.el]}));};e.appendChild(Pn("Account",{variant:"inputs",first:true})),l("Risk %","riskPercent",{min:0,max:100,step:.1}),l("Account balance","accountBalance",{min:0,max:1e12,step:1,integer:true}),l("Position size","quantity"),e.appendChild(Pn("Levels",{variant:"inputs"}));let d=de({kind:"select",options:hl,value:o().direction,fill:false,theme:this.theme,onChange:p=>{n.patch({direction:p}),s();}});i.push(()=>d.setValue?.(o().direction)),e.appendChild(He({label:"Direction",control:d.el})),l("Entry price","entryPrice"),c("Stop","stopPrice","stop"),c("Target","targetPrice","target"),e.appendChild(Pn("Display",{variant:"inputs"}));let u=[["Show text","showText"],["Show direction & ratio","showHeader"],["Show loss & size","showLossSize"],["Show target label","showTargetLabel"],["Show stop label","showStopLabel"],["Show level prices","showPrices"]];for(let[p,m]of u)e.appendChild(He({label:p,bool:true,toggle:{checked:o()[m],onChange:f=>{n.patch({[m]:f}),s();},get:()=>o()[m]}}));let h=document.createElement("div");h.className="vela-field-span",h.style.cssText="opacity:0.7;font-size:11px;line-height:1.4;border-top:1px solid var(--vela-border);padding-top:6px;font-variant-numeric:tabular-nums;",i.push(()=>{let p=o();h.textContent=`${p.headerLabel()} \u2014 ${p.lossSizeLabel()}`;}),e.appendChild(h),s();}buildFrvp(e,t,n){let o=()=>{let d=n.resolve();return d instanceof gt?d.frvp:t.frvp},i=o(),s=(d,u,h,p,m,f=true)=>{e.appendChild(He({label:d,control:de({kind:"number",value:i[u],min:h,max:p,step:m,integer:f,fill:false,commit:"blur",onChange:g=>n.patch({[`frvp.${u}`]:g})}).el}));};s("Rows","rows",1,500,1),s("Value Area","valueAreaPct",0,100,1),s("Width %","widthPct",0,100,1),e.appendChild(He({label:"Anchor",control:de({kind:"select",options:gI,value:i.anchor,fill:false,theme:this.theme,onChange:d=>n.patch({"frvp.anchor":d})}).el}));let a=(d,u)=>{e.appendChild(He({label:d,fit:true,control:de({kind:"color",theme:this.theme,get:()=>o()[u],onChange:h=>n.patch({[`frvp.${u}`]:h})}).el}));};a("Up Volume","upColor"),a("Down Volume","downColor"),a("Value Area Up","vaUpColor"),a("Value Area Down","vaDownColor");let l=rt.map(d=>({value:d.value,label:d.label})),c=(d,u,h,p)=>{let m=document.createElement("div");m.className="vela-field-span",m.style.cssText="display:flex;align-items:center;gap:8px;";let f=de({kind:"switch",checked:!!i[u],onChange:C=>n.patch({[`frvp.${u}`]:C})}),g=document.createElement("span");g.className="vela-field-label",g.style.flex="1",g.textContent=d;let b=i[h]??Ye(this.theme.background),y=de({kind:"color",theme:this.theme,get:()=>b,onChange:C=>{b=C,n.patch({[`frvp.${h}`]:C});}}),w=de({kind:"select",options:l,value:i[p],fill:false,theme:this.theme,onChange:C=>n.patch({[`frvp.${p}`]:C})});m.append(f.el,g,y.el,w.el),e.appendChild(m);};c("VAH","showVah","vahColor","vahStyle"),c("VAL","showVal","valColor","valStyle"),c("POC","showPoc","pocColor","pocStyle"),c("Developing POC","showDevelopingPoc","developingPocColor","developingPocStyle"),c("Developing VA","showDevelopingVa","developingVaColor","developingVaStyle");}buildLevels(e,t,n){let o=t.editableLevels();if(!o)return;let i=t instanceof dt;if(i){let s=t;e.appendChild(He({label:"Show ratio labels",bool:true,toggle:{checked:s.showRatios!==false,onChange:a=>n.patch({showRatios:a})}}));}o.forEach((s,a)=>{let l=document.createElement("div");l.className="vela-field-span",l.style.cssText="display:flex;align-items:center;gap:8px;";let c=de({kind:"switch",checked:s.enabled,onChange:m=>n.patch({[`levels.${a}.enabled`]:m})}),d=s.color,u=de({kind:"color",theme:this.theme,get:()=>d,onChange:m=>{d=m,n.patch({[`levels.${a}.color`]:m});}}),h=s.ratio,p=de({kind:"number",value:h,min:0,step:.01,fill:i,compact:!i,commit:"blur",onChange:m=>{if(m<=0){p.setValue?.(h);return}h=m,n.patch({[`levels.${a}.ratio`]:m});}});if(i&&(p.el.style.flex="1"),l.append(c.el,u.el,p.el),!i){let m=de({kind:"text",value:s.label??"",fill:true,placeholder:"label\u2026",onChange:f=>n.patch({[`levels.${a}.label`]:f})});m.el.style.flex="1",m.el.style.minWidth="60px",l.appendChild(m.el);}e.appendChild(l);});}};function E0(r,e,t){let n=document.createElement("button");return n.type="button",n.textContent=r,n.className=e?"vela-dialog-btn vela-dialog-btn-primary":"vela-dialog-btn",n.addEventListener("click",t),n}var Gt=Symbol("mixed");function vI(r){let[e,...t]=r,n=new Set(e?.schema().fields.map(o=>o.path)??[]);for(let o of t){let i=new Set(o.schema().fields.map(s=>s.path));for(let s of n)i.has(s)||n.delete(s);}return n}function yI(r,e){let t=e(r[0]);return r.every(n=>e(n)===t)?t:Gt}function wI(r,e){return [...new Set(r.map(e))]}var ir=30,xI=21,P0="vela-drawing-popup-styles",I0="4";function A0(){if(typeof document>"u")return;let r=document.getElementById(P0);if(r?.dataset.rev===I0)return;let e=r??document.createElement("style");e.id=P0,e.dataset.rev=I0,e.textContent=` +.vela-sd-mobile .vela-select:not([data-fill]){width:auto;min-width:100px;max-width:min(220px,55vw);}`,r||document.head.appendChild(e);}var Ws=class{constructor(e,t){this.container=e;this.theme=t;this.root=null;this.ui=null;this.onChange=null;this.onImport=null;this.onReset=null;this.config=null;this.syncTypeTabs=null;this.hostSections=[];this.markGroups=[];this.markGroupOwnVisible=()=>true;this.markGroupVisible=()=>true;this.themeControl=null;this.tabs=[];this.hintTips=[];this.typeActiveInstance=new Map;this.typeActiveGroup=new Map;this.activeSection=null;this.mobileLayout=false;this.toggleRail=null;this.hiddenSettings=new Set;getComputedStyle(e).position==="static"&&(e.style.position="relative");}setHostSections(e){this.hostSections=e;}setMarkGroups(e,t,n=t){this.markGroupOwnVisible=n,this.markGroups=e,this.markGroupVisible=t;}setHiddenSettings(e){let t=new Set(e),n=t.size===this.hiddenSettings.size&&[...t].every(o=>this.hiddenSettings.has(o));this.hiddenSettings=t,n||this.reopenIfLive();}setThemeControl(e,t){this.themeControl={current:e,onSelect:t};}refreshConfig(e){this.config&&(this.config=e);}setTheme(e){this.theme=e,this.reopenIfLive();}setLayoutMode(e){let t=e==="mobile";t!==this.mobileLayout&&(this.mobileLayout=t,this.reopenIfLive());}reopenIfLive(){if(!this.root)return;let e=this.config,t=this.onChange,n=this.onImport,o=this.onReset,i=this.activeSection;this.close(),e&&t&&this.open(e,t,n??void 0,o??void 0,i??void 0);}isOpen(){return this.root!==null}toggle(e,t,n,o,i){this.root?this.close():this.open(e,t,n,o,i);}showSection(e){this.tabs.find(t=>t.title.toLowerCase()===e.toLowerCase())?.show();}open(e,t,n,o,i){this.close(),this.config=e,this.onChange=t,this.onImport=n??null,this.onReset=o??null,vI();let s=this.mobileLayout,a;s&&(a=document.createElement("button"),a.type="button",a.className="vela-sd-burger",a.innerHTML=Re("burger",16),a.title="Sections",a.addEventListener("click",()=>this.toggleRail?.()));let l=new Pn({host:this.container,title:"Chart settings",modal:false,contained:true,align:"top",draggable:!s,flush:true,className:"vela-dialog--settings",headerStart:a,closeOnBackdrop:true,footer:d=>{d.style.cssText="padding:10px 14px;display:flex;align-items:center;justify-content:flex-start;gap:8px;";let u=document.createElement("button");u.type="button",u.textContent="Reset defaults",u.className="vela-sd-btn",u.addEventListener("click",()=>this.onReset?.()),d.appendChild(u);},onOpenChange:d=>{!d&&this.ui===l&&this.close();}});s&&l.positioner.classList.add("vela-sd-mobile"),l.positioner.style.paddingTop=s?"0":"8vh",this.root=l.positioner,this.ui=l;let c=this.buildContent(l,e,i,s);l.show(),this.layoutPanes(c);}refresh(e){let t=this.ui;if(t){Me(),Ic();for(let n of this.hintTips)n();this.hintTips=[],this.config=e,t.body.replaceChildren(),this.layoutPanes(this.buildContent(t,e,this.activeSection??void 0,this.mobileLayout));}}layoutPanes(e){for(let t of e){let n=[...t.querySelectorAll("[data-sd-rows-host]")];if(n.length===0){this.layoutSettingsGrids(t);continue}for(let o of n)this.layoutSettingsGrids(o);}}buildContent(e,t,n,o){let i=document.createElement("div");i.style.cssText="display:flex;flex-direction:column;gap:0;";let s=(v,k)=>(v.dataset.sdId=k,v);i.append(s(this.section("Symbol"),"symbol")),i.append(s(this.sectionTitle("Chart type"),"symbol.type"));let a={},l=v=>{let k=v==="heikinashi"?"candles":v;for(let x of Xo())a[x]?.classList.toggle("vela-sd-hide",x!==k);};i.append(s(this.selectRowLabeled("Type",t.series.style,Xo().map(v=>[v,gI(v)]),v=>{this.emit({series:{style:v}}),l(v),this.syncTypeTabs?.(v);}),"symbol.type"));let c=s(this.group(),"symbol.style.candles");c.append(this.sectionTitle("Candles")),c.append(s(this.toggleRow("Body",t.candles.bodyVisible,v=>this.emit({candles:{bodyVisible:v}}),[this.swatch(t.candles.upColor,v=>this.emit({candles:{upColor:v}})),this.swatch(t.candles.downColor,v=>this.emit({candles:{downColor:v}}))]),"symbol.style.candles.body")),c.append(s(this.toggleRow("Borders",t.candles.borderVisible,v=>this.emit({candles:{borderVisible:v}}),[this.swatch(t.candles.borderUpColor,v=>this.emit({candles:{borderUpColor:v}})),this.swatch(t.candles.borderDownColor,v=>this.emit({candles:{borderDownColor:v}}))]),"symbol.style.candles.borders")),c.append(s(this.toggleRow("Wick",t.candles.wickVisible,v=>this.emit({candles:{wickVisible:v}}),[this.swatch(t.candles.wickUpColor,v=>this.emit({candles:{wickUpColor:v}})),this.swatch(t.candles.wickDownColor,v=>this.emit({candles:{wickDownColor:v}}))]),"symbol.style.candles.wick")),c.append(s(this.numberRow("Spacing",t.series.spacing,.1,10,.1,v=>this.emit({series:{spacing:v}})),"symbol.style.candles.spacing")),a.candles=c,i.append(c);let d=s(this.group(),"symbol.style.bars");d.append(this.sectionTitle("Bars")),d.append(s(this.colorRow("Color Up",t.bars.upColor,v=>this.emit({bars:{upColor:v}})),"symbol.style.bars.up-color")),d.append(s(this.colorRow("Color Down",t.bars.downColor,v=>this.emit({bars:{downColor:v}})),"symbol.style.bars.down-color")),d.append(s(this.numberRow("Spacing",t.series.spacing,.1,10,.1,v=>this.emit({series:{spacing:v}})),"symbol.style.bars.spacing")),a.bars=d,i.append(d);let u=s(this.group(),"symbol.style.line");u.append(this.sectionTitle("Line")),u.append(s(this.colorRow("Color",t.line.color,v=>this.emit({line:{color:v}})),"symbol.style.line.color")),u.append(s(this.numberRow("Width",t.line.width,1,10,1,v=>this.emit({line:{width:v}})),"symbol.style.line.width")),a.line=u,i.append(u);let h=s(this.group(),"symbol.style.area");h.append(this.sectionTitle("Area")),h.append(s(this.colorRow("Line color",t.area.lineColor,v=>this.emit({area:{lineColor:v}})),"symbol.style.area.line-color")),h.append(s(this.numberRow("Width",t.area.width,1,10,1,v=>this.emit({area:{width:v}})),"symbol.style.area.width")),h.append(s(this.colorRow("Top fill",t.area.topColor,v=>this.emit({area:{topColor:v}})),"symbol.style.area.top-fill")),h.append(s(this.colorRow("Bottom fill",t.area.bottomColor,v=>this.emit({area:{bottomColor:v}})),"symbol.style.area.bottom-fill")),a.area=h,i.append(h);let p=s(this.group(),"symbol.style.baseline");p.append(this.sectionTitle("Baseline")),p.append(s(this.rowWith("Top line",[this.swatch(t.baseline.topLineColor,v=>this.emit({baseline:{topLineColor:v}}))]),"symbol.style.baseline.top-line")),p.append(s(this.rowWith("Bottom line",[this.swatch(t.baseline.bottomLineColor,v=>this.emit({baseline:{bottomLineColor:v}}))]),"symbol.style.baseline.bottom-line")),p.append(s(this.rowWith("Fill top area",[this.swatch(t.baseline.topFillColor,v=>this.emit({baseline:{topFillColor:v}})),this.swatch(t.baseline.topFillColor2,v=>this.emit({baseline:{topFillColor2:v}}))]),"symbol.style.baseline.fill-top")),p.append(s(this.rowWith("Fill bottom area",[this.swatch(t.baseline.bottomFillColor2,v=>this.emit({baseline:{bottomFillColor2:v}})),this.swatch(t.baseline.bottomFillColor,v=>this.emit({baseline:{bottomFillColor:v}}))]),"symbol.style.baseline.fill-bottom")),p.append(s(this.numberRow("Base level %",t.baseline.baselineLevel,0,100,1,v=>this.emit({baseline:{baselineLevel:v}})),"symbol.style.baseline.base-level")),p.append(s(this.numberRow("Width",t.baseline.width,1,10,1,v=>this.emit({baseline:{width:v}})),"symbol.style.baseline.width")),a.baseline=p,i.append(p);for(let v of xt()){if(!Yo(v.id))continue;let k=t.chartTypes[v.id]??{},x=(N,V)=>typeof k[N]=="string"&&k[N]!==""?k[N]:V,E=(N,V)=>typeof k[N]=="boolean"?k[N]:V,I=s(this.group(),`symbol.style.${v.id}`);I.append(this.sectionTitle("Candles")),I.append(s(this.toggleRow("Body",E("candleBodyVisible",t.candles.bodyVisible),N=>this.emitType(v.id,"candleBodyVisible",N),[this.swatch(x("candleUpColor",t.candles.upColor),N=>this.emitType(v.id,"candleUpColor",N)),this.swatch(x("candleDownColor",t.candles.downColor),N=>this.emitType(v.id,"candleDownColor",N))]),`symbol.style.${v.id}.body`)),I.append(s(this.toggleRow("Borders",E("candleBorderVisible",t.candles.borderVisible),N=>this.emitType(v.id,"candleBorderVisible",N),[this.swatch(x("candleBorderUpColor",t.candles.borderUpColor),N=>this.emitType(v.id,"candleBorderUpColor",N)),this.swatch(x("candleBorderDownColor",t.candles.borderDownColor),N=>this.emitType(v.id,"candleBorderDownColor",N))]),`symbol.style.${v.id}.borders`)),I.append(s(this.toggleRow("Wick",E("candleWickVisible",t.candles.wickVisible),N=>this.emitType(v.id,"candleWickVisible",N),[this.swatch(x("candleWickUpColor",t.candles.wickUpColor),N=>this.emitType(v.id,"candleWickUpColor",N)),this.swatch(x("candleWickDownColor",t.candles.wickDownColor),N=>this.emitType(v.id,"candleWickDownColor",N))]),`symbol.style.${v.id}.wick`)),I.append(s(this.numberRow("Spacing",t.series.spacing,.1,10,.1,N=>this.emit({series:{spacing:N}})),`symbol.style.${v.id}.spacing`)),a[v.id]=I,i.append(I);}l(t.series.style),i.append(s(this.sectionTitle("Animation"),"symbol.animation")),i.append(s(this.boolRow("Animate zoom",t.animations.zoom,v=>this.emit({animations:{zoom:v}}),this.hint("Glide the chart to each zoom step instead of jumping.")),"symbol.animation.zoom")),i.append(s(this.boolRow("Pan momentum",t.animations.pan,v=>this.emit({animations:{pan:v}}),this.hint("Keep gliding briefly after a drag release, and ease scroll-to-latest and keyboard pans.")),"symbol.animation.pan")),i.append(s(this.boolRow("Animate price scale",t.animations.autoscale,v=>this.emit({animations:{autoscale:v}}),this.hint("Glide the price scale to its new range while zooming or panning.")),"symbol.animation.autoscale")),i.append(s(this.boolRow("Animate price changes",t.priceScale.animateLastPrice,v=>this.emit({priceScale:{animateLastPrice:v}}),this.hint("Glide the live bar to each new price instead of snapping.")),"symbol.animation.price-changes")),i.append(s(this.boolRow("Reveal on load",t.animations.intro,v=>this.emit({animations:{intro:v}}),this.hint("Draw the candles in when a chart first loads. Takes effect on the next load.")),"symbol.animation.intro")),i.append(s(this.sectionTitle("Time zone"),"symbol.timezone")),i.append(s(this.selectRowLabeled("Time zone",md(t.timeScale.timezone),yI(t.timeScale.timezone),v=>this.emit({timeScale:{timezone:v}})),"symbol.timezone"));let m=v=>{for(let k of this.hostSections){if((k.placement??"after-symbol")!==v)continue;let x=dp(k);if(Mt(x,this.hiddenSettings))continue;let E=Sx(k.rows,x,this.hiddenSettings);if(E.length!==0){i.append(v==="symbol"?this.sectionTitle(k.title):this.section(k.title));for(let I of E)I.kind==="heading"?i.append(this.sectionTitle(I.label)):I.kind==="toggle"?i.append(this.boolRow(I.label,I.get(),N=>I.set(N))):I.kind==="color"?i.append(this.colorRow(I.label,I.get(),N=>I.set(N))):i.append(this.selectRowLabeled(I.label,I.get(),Lx(I.options),N=>I.set(N)));}}},f=v=>{for(let k of xt()){let x=k.settings;x&&(x.placement??"end")===v&&(Mt(`type:${k.id}`,this.hiddenSettings)||this.chartTypeSection(k.id,x,t,i));}};if(m("symbol"),f("after-symbol"),m("after-symbol"),i.append(s(this.section("Scales and lines"),"scales")),i.append(s(this.sectionTitle("Price scale"),"scales.price-scale")),i.append(s(this.selectRowLabeled("Mode",t.priceScale.log?"log":t.priceScale.mode,[["price","Regular"],["percent","Percent"],["indexed","Indexed to 100"],["log","Logarithmic"]],v=>this.emit({priceScale:v==="log"?{mode:"price",log:true}:{mode:v,log:false}})),"scales.price-scale.mode")),i.append(s(this.boolRow("Invert scale",t.priceScale.invert,v=>this.emit({priceScale:{invert:v}})),"scales.price-scale.invert")),i.append(s(this.separator(),"scales.price-scale")),i.append(s(this.boolRow("Last Price Line",t.priceScale.currentPriceLine,v=>this.emit({priceScale:{currentPriceLine:v}})),"scales.price-scale.last-price-line")),i.append(s(this.boolRow("Last price label",t.priceScale.priceLabel,v=>this.emit({priceScale:{priceLabel:v}})),"scales.price-scale.last-price-label")),i.append(s(this.boolRow("Countdown to bar close",t.priceScale.countdown,v=>this.emit({priceScale:{countdown:v}})),"scales.price-scale.countdown")),i.append(s(this.boolRow("Axis labels",t.priceScale.labelsVisible,v=>this.emit({priceScale:{labelsVisible:v}})),"scales.price-scale.axis-labels")),i.append(s(this.colorRow("Scale border color",t.priceScale.borderColor,v=>this.emit({priceScale:{borderColor:v}})),"scales.price-scale.border-color")),i.append(s(this.sectionTitle("Crosshair"),"scales.crosshair")),i.append(s(this.colorRow("Color",t.crosshair.color,v=>this.emit({crosshair:{color:v}})),"scales.crosshair.color")),i.append(s(this.numberRow("Width",t.crosshair.width,.5,8,.5,v=>this.emit({crosshair:{width:v}})),"scales.crosshair.width")),i.append(s(this.selectRowLabeled("Style",t.crosshair.style,[["solid","Solid"],["dashed","Dashed"],["dotted","Dotted"]],v=>this.emit({crosshair:{style:v}})),"scales.crosshair.style")),i.append(s(this.section("Canvas"),"canvas")),i.append(s(this.sectionTitle("Background & text"),"canvas.background")),i.append(s(this.colorRow("Background",t.layout.background,v=>this.emit({layout:{background:v}})),"canvas.background.color")),i.append(s(this.colorRow("Text color",t.layout.textColor,v=>this.emit({layout:{textColor:v}})),"canvas.background.text-color")),i.append(s(this.numberRow("Text size",t.layout.fontSize,6,32,1,v=>this.emit({layout:{fontSize:v}})),"canvas.background.text-size")),i.append(s(this.colorRow("Pane separator color",t.panes.separatorColor,v=>this.emit({panes:{separatorColor:v}})),"canvas.background.pane-separator")),i.append(s(this.sectionTitle("Grid"),"canvas.grid")),i.append(s(this.toggleRow("Vertical",t.grid.vertLines.visible,v=>this.emit({grid:{vertLines:{visible:v}}}),[this.swatch(t.grid.vertLines.color,v=>this.emit({grid:{vertLines:{color:v}}}))]),"canvas.grid.vertical")),i.append(s(this.toggleRow("Horizontal",t.grid.horzLines.visible,v=>this.emit({grid:{horzLines:{visible:v}}}),[this.swatch(t.grid.horzLines.color,v=>this.emit({grid:{horzLines:{color:v}}}))]),"canvas.grid.horizontal")),i.append(s(this.sectionTitle("Margins"),"canvas.margins")),i.append(s(this.numberRow("Top",t.margins.top,0,40,1,v=>this.emit({margins:{top:v}}),"%"),"canvas.margins.top")),i.append(s(this.numberRow("Bottom",t.margins.bottom,0,40,1,v=>this.emit({margins:{bottom:v}}),"%"),"canvas.margins.bottom")),i.append(s(this.numberRow("Right",t.margins.right,0,200,1,v=>this.emit({margins:{right:v}}),"bars"),"canvas.margins.right")),this.themeControl){let v=this.themeControl;i.append(s(this.sectionTitle("Theme"),"canvas.theme")),i.append(s(this.selectRow("Color theme",v.current==="dark"?"Dark":"Light",["Dark","Light"],k=>v.onSelect(k==="Dark"?"dark":"light")),"canvas.theme"));}if(this.markGroups.length>0){i.append(s(this.section("Events"),lp)),i.append(s(this.sectionTitle("Visible events"),fd));let v=new Map,k=lu(this.markGroups),x=()=>{for(let{group:E}of k){let I=v.get(E.id);!I||E.parent===void 0||I.classList.toggle("vela-sd-soft",!this.markGroupVisible(E.parent));}};for(let{group:E,depth:I}of k){let N=this.boolRow(E.label,this.markGroupOwnVisible(E.id),V=>{this.emit({marks:{groups:{[E.id]:V}}}),x();});I>0&&(N.classList.add("vela-sd-nested"),N.style.setProperty("--vela-sd-depth",String(I))),v.set(E.id,N),i.append(s(N,cp(E.id)));}x();}if(f("end"),m("end"),this.hiddenSettings.size>0){let v=false;for(let k of [...i.children]){if(k.dataset.sdTab!==void 0&&(v=k.dataset.sdId!==void 0&&Mt(k.dataset.sdId,this.hiddenSettings)),v||k.dataset.sdId!==void 0&&Mt(k.dataset.sdId,this.hiddenSettings)){k.remove();continue}for(let x of [...k.querySelectorAll("[data-sd-id]")])Mt(x.dataset.sdId,this.hiddenSettings)&&x.remove();}}let g=document.createElement("div");g.style.cssText=o?"display:flex;min-height:0;flex:1 1 auto;position:relative;overflow:hidden;":"display:flex;min-height:360px;max-height:calc(70vh - 100px);flex:1 1 auto;";let b=document.createElement("div");b.className="vela-sd-rail",b.style.cssText=o?"display:flex;flex-direction:column;gap:2px;padding:10px 8px;overflow-y:auto;":`flex:0 0 170px;display:flex;flex-direction:column;gap:2px;padding:10px 8px;border-right:1px solid ${bI};overflow-y:auto;`;let y=null;o&&(y=document.createElement("div"),y.className="vela-sd-railscrim",y.addEventListener("click",()=>this.toggleRail?.()),this.toggleRail=v=>{let k=v??!b.classList.contains("open");b.classList.toggle("open",k),y?.classList.toggle("open",k);});let w=document.createElement("div");w.className="vela-sd-pane",w.style.cssText=o?"flex:1;min-width:0;overflow-y:auto;overflow-anchor:none;padding:6px 14px calc(14px + env(safe-area-inset-bottom, 0px));":"flex:1;overflow-y:auto;overflow-anchor:none;padding:6px 18px 14px;";let S=[],M=null;for(let v of [...i.children]){let k=v.dataset.sdTab;if(k!==void 0){let x=document.createElement("div");x.style.display="none";let E=document.createElement("button");E.type="button",E.textContent=k,E.className="vela-sd-tab"+(v.dataset.sdSub!==void 0?" vela-sd-tab-sub":""),S.push({title:k,el:x,tab:E,style:v.dataset.sdStyle,visibility:v.dataset.sdVisibility}),M=x,v.remove();continue}M&&M.appendChild(v);}for(let v=S.length-1;v>=0;v--)S[v].el.childElementCount===0&&S.splice(v,1);this.syncTypeTabs=v=>{let k=false;S.forEach((x,E)=>{if(!x.style)return;let I=x.visibility==="always"||x.style===v||v==="heikinashi"&&x.style==="heikinashi";x.tab.style.display=I?"":"none",!I&&x.el.style.display==="block"&&(k=true);}),k&&C(0);};let C=v=>{S.forEach((k,x)=>{k.el.style.display=x===v?"block":"none",k.tab.classList.toggle("on",x===v);}),this.activeSection=S[v]?.title??null,o&&(e.titleEl.textContent=S[v]?.title??"Chart settings",this.toggleRail?.(false));};S.forEach((v,k)=>{v.tab.addEventListener("click",()=>C(k)),b.appendChild(v.tab),w.appendChild(v.el);}),this.tabs=S.map((v,k)=>({title:v.title,show:()=>C(k)}));let L=n!==void 0?S.findIndex(v=>v.title.toLowerCase()===n.toLowerCase()):S.findIndex(v=>v.style===t.series.style&&!v.tab.classList.contains("vela-sd-tab-sub"));return C(L>=0?L:0),this.syncTypeTabs?.(t.series.style),g.append(b,w),y&&g.append(y),e.body.appendChild(g),S.map(v=>v.el)}close(){Me(),Ic();let e=this.ui;this.ui=null,this.root=null,this.toggleRail=null,this.tabs=[];for(let t of this.hintTips)t();this.hintTips=[],e?.destroy();}destroy(){this.close(),this.onChange=null,this.onImport=null,this.config=null;}emitType(e,t,n){this.emit({chartTypes:{[e]:{[t]:n}}});}emit(e){this.onChange?.(e);}sectionTitle(e){return In(e)}chartTypeSection(e,t,n,o){let i=this.section(t.title);i.dataset.sdStyle=e,i.dataset.sdVisibility=t.visibility??"active",o.append(i);let s=n.chartTypes[e]??{},a={},l=h=>{for(let p of h)for(let m of Ii(p)){let f=s[m.key];a[m.key]=typeof f===m.type?f:m.defval;}};t.rows&&l(t.rows);for(let h of t.instances??[])l(h.rows);for(let h of t.subsections??[])l(h.rows);for(let h of t.instances??[])!h.enableKey||h.enableKey in a||(a[h.enableKey]=s[h.enableKey]===true);for(let h of t.subsections??[])!h.enableKey||h.enableKey in a||(a[h.enableKey]=s[h.enableKey]===true);let c=[],d=(h,p)=>{a[h]=p,this.emitType(e,h,p);for(let m of c)m();},u=`type:${e}`;if(t.instances&&t.instances.length>0){let h=t.instances.map(p=>({...p,rows:gd(p.rows,u,this.hiddenSettings)}));o.append(this.instancesBlock(e,h,a,d,c));}else if(t.rows){let h=gd(t.rows,u,this.hiddenSettings);t.layout==="grouped"?o.append(this.groupedRows(`${e}/rows`,h,a,d,c)):this.flatTypeRows(h,a,d,c,o);}for(let h of t.subsections??[]){if(Mt(`${u}.${sr(h.title)}`,this.hiddenSettings))continue;let p=gd(h.rows,u,this.hiddenSettings);if(p.length===0)continue;let m=this.section(h.title);m.dataset.sdStyle=e,m.dataset.sdVisibility=t.visibility??"active",m.dataset.sdSub="1",o.append(m),o.append(this.groupedRows(`${e}/${h.title}`,p,a,d,c,h.enableKey));}for(let h of c)h();}flatTypeRows(e,t,n,o,i){let s=[];for(let a of e){let l=a.kind==="heading"||a.kind==="header"?this.sectionTitle(a.label):this.typeRow(a,t,n,o);s.push({el:l,when:a.when}),i.append(l);}o.push(()=>{for(let a of s)a.el.classList.toggle("vela-sd-hide",!Pr(a.when,t));});}typeRow(e,t,n,o){let i=mo(e),s=[];for(let a of i.controls){let l=this.inlineControl(a,t,n,i.toggle!==void 0);if(a.kind!=="hint"&&o.push(()=>l.dispatchEvent(new Event("vela-sync"))),a.kind!=="hint"&&a.when){l.dataset.sdSelfGated="1";let c=a.when;o.push(()=>{l.style.display=Pr(c,t)?"":"none";});}s.push(l);}if(i.toggle){let a=i.toggle,l=this.toggleRow(i.label,t[a.key],c=>n(a.key,c),s,()=>t[a.key]===true);return o.push(()=>l.dispatchEvent(new Event("vela-sync"))),l}return this.rowWith(i.label,s)}inlineControl(e,t,n,o){if(e.kind==="hint"){let s=document.createElement("span");return s.textContent=e.text,s.style.cssText="color:var(--vela-fg-muted);",s}if(e.kind==="color")return de({kind:"color",theme:this.theme,get:()=>t[e.key],onChange:s=>n(e.key,s),title:e.label}).el;if(e.kind==="width"){let s=typeof t[e.key]=="number"?t[e.key]:e.defval;return de({kind:"width",theme:this.theme,get:()=>typeof t[e.key]=="number"?t[e.key]:s,onChange:a=>n(e.key,a),title:e.label}).el}if(e.kind==="select"){let s=typeof t[e.key]=="string"?t[e.key]:e.defval;return de({kind:"select",options:Lx(e.options).map(([a,l])=>({value:a,label:l})),value:s,fill:false,theme:this.theme,title:e.label,onChange:a=>n(e.key,a),sync:()=>typeof t[e.key]=="string"?t[e.key]:e.defval}).el}let i=typeof t[e.key]=="number"?t[e.key]:e.defval;return de({kind:"number",value:i,min:e.min,max:e.max,step:e.step??1,fill:false,commit:"live",clamp:e.placeholder!==void 0,steppers:true,compact:o,title:e.label,placeholder:e.placeholder,emptyValue:e.placeholder!==void 0?e.defval:void 0,onChange:s=>n(e.key,s),sync:()=>typeof t[e.key]=="number"?t[e.key]:e.defval}).el}instancesBlock(e,t,n,o,i){let s=document.createElement("div"),a=document.createElement("div");a.className="vela-sd-itabs",(t.length>1||t[0]?.enableKey!==void 0)&&s.append(a);let l=t.map((u,h)=>{let p=this.groupedRows(`${e}/#${h}`,u.rows,n,o,i);return s.append(p),p}),c=u=>!u.enableKey||n[u.enableKey]===true,d=()=>{let u=this.typeActiveInstance.get(e)??0;c(t[u]??t[0])||(u=0),this.typeActiveInstance.set(e,u),a.replaceChildren(),t.forEach((p,m)=>{if(!c(p))return;let f=document.createElement("button");f.type="button",f.className="vela-sd-itab"+(m===u?" on":"");let g=document.createElement("span");if(g.textContent=p.label,f.append(g),m===u&&p.enableKey){let b=document.createElement("span");b.className="vela-sd-ix",b.textContent="\u2715",b.title=`Remove ${p.label}`,b.addEventListener("click",y=>{y.stopPropagation(),this.typeActiveInstance.set(e,0),o(p.enableKey,false);}),f.append(b);}f.addEventListener("click",()=>{this.typeActiveInstance.set(e,m),d();}),a.append(f);});let h=t.findIndex(p=>!c(p));if(h>=0){let p=document.createElement("button");p.type="button",p.className="vela-sd-itab vela-sd-itab-add",p.textContent="+",p.title=`Add ${t[h].label}`,p.addEventListener("click",()=>{this.typeActiveInstance.set(e,h),o(t[h].enableKey,true);}),a.append(p);}l.forEach((p,m)=>p.classList.toggle("vela-sd-hide",m!==u));};return i.push(d),s}groupedRows(e,t,n,o,i,s){let a=document.createElement("div");a.className="vela-sd-struct";let l=document.createElement("div");l.className="vela-sd-toc";let c=document.createElement("div");c.dataset.sdRowsHost="1",c.style.cssText="flex:1 1 auto;min-width:0;",a.append(l,c);let d=[],u=[],h=[],p=-1;for(let f of t){if(f.kind==="heading"){p=u.length,u.push(f.label),h.push(f.when);continue}if(f.kind==="header"){d.push({el:this.sectionTitle(f.label),when:f.when,group:p,header:true}),c.append(d[d.length-1].el);continue}let g=this.typeRow(f,n,o,i),b=f.kind==="row"?f.toggle?.key:f.kind==="range"?void 0:f.key;d.push({el:g,when:f.when,group:p,key:b}),c.append(g);}let m=()=>{let f=u.map((w,S)=>Pr(h[S],n)&&d.some(M=>M.group===S&&!M.header&&Pr(M.when,n))),g=u.indexOf(this.typeActiveGroup.get(e)??"");(g<0||!f[g])&&(g=f.findIndex(Boolean)),g>=0&&this.typeActiveGroup.set(e,u[g]),l.replaceChildren(),u.forEach((w,S)=>{if(!f[S])return;let M=document.createElement("button");M.type="button",M.className="vela-sd-toc-btn"+(S===g?" on":""),M.textContent=w,M.addEventListener("click",()=>{this.typeActiveGroup.set(e,w),m();}),l.append(M);});let b=f.some(Boolean);l.classList.toggle("vela-sd-hide",!b),a.classList.toggle("no-toc",!b);let y=!s||n[s]===true;for(let w=0;wn?n():o,onChange:i=>{o=i,t(i);}}).el}rowWith(e,t){return Be({label:e,labelSize:"sm",control:t,className:"vela-sd-row"})}section(e){let t=document.createElement("div");return t.dataset.sdTab=e,t.style.display="none",t}group(){let e=document.createElement("div");return e.dataset.sdGroup="",e.style.cssText="display:contents;",e}colorRow(e,t,n){let o=t;return Be({label:e,labelSize:"sm",fit:true,className:"vela-sd-row",control:de({kind:"color",theme:this.theme,get:()=>o,onChange:i=>{o=i,n(i);}}).el})}boolRow(e,t,n,o){return this.toggleRow(e,t,n,[],void 0,o)}toggleRow(e,t,n,o,i,s){return Be({label:e,labelSize:"sm",bool:o.length===0,toggle:{checked:t,onChange:n,get:i},control:o,info:s,className:o.length===0?"vela-sd-bool":"vela-sd-row"})}hint(e){let{el:t,dispose:n}=Rl(e,{host:this.container,theme:()=>this.theme});return this.hintTips.push(n),t}numberRow(e,t,n,o,i,s,a){let l=[de({kind:"number",value:t,min:n,max:o,step:i,fill:false,commit:"live",steppers:true,onChange:s}).el];if(a){let c=document.createElement("span");c.textContent=a,c.style.cssText="color:var(--vela-fg-muted);",l.push(c);}return this.rowWith(e,l)}selectRowLabeled(e,t,n,o){return Be({label:e,labelSize:"sm",className:"vela-sd-row",control:de({kind:"select",options:n.map(([i,s])=>({value:i,label:s})),value:t,fill:false,theme:this.theme,onChange:o}).el})}selectRow(e,t,n,o){return this.selectRowLabeled(e,t,n.map(i=>[i,i]),o)}};function Lx(r){return r.map(e=>typeof e=="string"?[e,e]:e)}function yI(r){let e=sp.map(n=>[n.value,ap(n.value,n.label)]),t=md(r);return sp.some(n=>n.value===t)?e:[[t,ap(t,t)],...e]}var Gs=ca,$s=da;function Et(r,e){if(r instanceof Ge){if(!r.fillTriangles().length)return null;let t=r.valid();return r.style.fillColor??(t==null?r.style.lineColor:t?Gs:$s)}return r instanceof vt?r.style.fillColor??e.background:r.style.fillColor??null}var wI=4.5,up=_,xI=J(A,.55),SI=.7,Mx=Ym,CI=Km,Ex={selected:.3,hovered:.12};function hp(r){let e=new Set(r.selected);return r.dragged&&e.add(r.dragged),r.hovered&&e.add(r.hovered),r.mutedLabel&&e.delete(r.mutedLabel),e}var bd=class{constructor(){this.targets={};this.seriesLook={style:"candles",upColor:O,downColor:D,lineColor:O};}paintAll(e,t,n,o,i={}){this.targets=i;for(let s of t)s.visible&&this.paintClipped(e,s,n,()=>this.paintOne(e,s,n,o));this.targets={},this.paintHighlights(e,t,n,hp(i));}paintHighlights(e,t,n,o){if(o.size!==0)for(let i of t)i.visible&&o.has(i.id)&&this.paintClipped(e,i,n,()=>this.paintHandles(e,i.handlePoints(n)));}paintClipped(e,t,n,o){if(!n.paneRect){o();return}let i=n.paneRect(t.paneId);!i||i.height<=0||(e.save(),e.beginPath(),e.rect(0,i.top,n.width,i.height),e.clip(),o(),e.restore());}paintGhost(e,t,n,o){e.globalAlpha=SI,t instanceof yn||t instanceof gt?this.paintTimeSpanGhost(e,t,n):t instanceof ht?this.paintMagnifierGhost(e,t,n,o):this.paintOne(e,t,n,o),e.globalAlpha=1;}paintTimeSpanGhost(e,t,n){let o=t.anchors[0],i=t.anchors[1];if(!o)return;let s=t instanceof yn?t.reg?.midColor||A:A,a=u=>{let h=n.xOf(u);e.save(),e.strokeStyle=s,e.globalAlpha=.6*e.globalAlpha,e.lineWidth=1,e.setLineDash([4,4]),e.beginPath(),e.moveTo(h,0),e.lineTo(h,n.height),e.stroke(),e.restore();};a(o.time),i&&a(i.time);let l=n.yOf(o.price,t.paneId),c=i?n.yOf(i.price,t.paneId):null,d=[];l!=null&&d.push([n.xOf(o.time),l]),i&&c!=null&&(e.save(),e.strokeStyle=s,e.lineWidth=1,e.setLineDash([]),e.beginPath(),e.moveTo(n.xOf(o.time),l??c),e.lineTo(n.xOf(i.time),c),e.stroke(),e.restore(),d.push([n.xOf(i.time),c])),this.paintHandles(e,d);}paintMarquee(e,t){e.save(),e.fillStyle=J(up,.08),e.fillRect(t.x,t.y,t.w,t.h),e.strokeStyle=up,e.lineWidth=1,e.setLineDash([4,3]),e.strokeRect(t.x+.5,t.y+.5,t.w,t.h),e.restore();}paintSnapRing(e,t,n,o){e.setLineDash([]),e.globalAlpha=.9,e.beginPath(),e.arc(t,n,5.5,0,Math.PI*2),e.strokeStyle=o.textColor,e.lineWidth=1.5,e.stroke(),e.globalAlpha=1;}paintOne(e,t,n,o){if(t.type==="highlighter"&&t instanceof ve){this.paintHighlighter(e,t,n),this.paintLabel(e,t,n,o);return}if(t instanceof ve){if(this.paintSegments(e,t,n),t.type==="path"){let i=t.handlePoints(n);i.length>=2&&this.paintArrowhead(e,i[i.length-2],i[i.length-1],t.style);}this.paintLabel(e,t,n,o);return}if(t instanceof vr){this.paintArrowMark(e,t,n),this.paintLabel(e,t,n,o);return}if(t instanceof yr){this.paintGlyphStamp(e,t,n,o),this.paintLabel(e,t,n,o);return}if(t instanceof Ot){this.paintRadialFib(e,t,n,o),this.paintLabel(e,t,n,o);return}if(t instanceof Tr){this.paintFibSpiral(e,t,n),this.paintLabel(e,t,n,o);return}if(t instanceof Lr){this.paintDedekind(e,t,n),this.paintLabel(e,t,n,o);return}if(t instanceof dt){this.paintMachFigure(e,t,n,o),this.paintLabel(e,t,n,o);return}if(t instanceof kr){this.paintFibRatios(e,t,n,o),this.paintGannArcs(e,t,n),this.paintLabel(e,t,n,o);return}if(t instanceof Se){this.paintFibRatios(e,t,n,o),this.paintLabel(e,t,n,o);return}if(t instanceof Mr){this.paintMeasureBox(e,t,n,o);return}if(t instanceof yt){this.paintPosition(e,t,n,o);return}if(t instanceof yn){this.paintRegressionChannel(e,t,n,o),this.paintLabel(e,t,n,o);return}if(t instanceof br){this.paintAnchoredVwap(e,t,n),this.paintLabel(e,t,n,o);return}if(t instanceof gt){this.paintFixedRangeVp(e,t,n,o),this.paintLabel(e,t,n,o);return}if(t instanceof ht){this.paintMagnifier(e,t,n,o);return}if(t instanceof Ge){this.paintPattern(e,t,n,o);return}if(t instanceof fr){this.paintComment(e,t,n,o);return}if(t instanceof mr){this.paintPriceNote(e,t,n,o);return}if(t instanceof gr){this.paintSignpost(e,t,n,o);return}if(t instanceof jt){this.paintCallout(e,t,n,o);return}if(t instanceof hr){this.paintNote(e,t,n,o);return}if(t instanceof pr){this.paintPriceLabel(e,t,n,o);return}switch(t.type){case "hline":{let i=t.handlePoints(n);if(i.length===0)return;this.stroke(e,t.style,()=>{e.moveTo(0,i[0][1]),e.lineTo(n.width,i[0][1]);});break}case "trendline":case "arrow":{let i=t.handlePoints(n);if(i.length<2)return;this.stroke(e,t.style,()=>{e.moveTo(i[0][0],i[0][1]),e.lineTo(i[1][0],i[1][1]);}),t.style.arrowRight&&this.paintArrowhead(e,i[0],i[1],t.style),t.style.arrowLeft&&this.paintArrowhead(e,i[1],i[0],t.style);break}case "ellipse":{let i=t.handlePoints(n);if(i.length<2)return;let s=(i[0][0]+i[1][0])/2,a=(i[0][1]+i[1][1])/2,l=Math.abs(i[1][0]-i[0][0])/2,c=Math.abs(i[1][1]-i[0][1])/2;t.style.fillColor&&(e.save(),e.fillStyle=t.style.fillColor,e.beginPath(),e.ellipse(s,a,l,c,0,0,Math.PI*2),e.fill(),e.restore()),this.applyStroke(e,t.style),e.beginPath(),e.ellipse(s,a,l,c,0,0,Math.PI*2),e.stroke(),e.setLineDash([]);break}case "ray":{let i=t.handlePoints(n);if(i.length<2)return;let[s,a,l,c]=Jo(i[0][0],i[0][1],i[1][0],i[1][1],"right",n.width,n.height);this.stroke(e,t.style,()=>{e.moveTo(s,a),e.lineTo(l,c);});break}case "extendedline":{let i=t.handlePoints(n);if(i.length<2)return;let[s,a,l,c]=Jo(i[0][0],i[0][1],i[1][0],i[1][1],"both",n.width,n.height);this.stroke(e,t.style,()=>{e.moveTo(s,a),e.lineTo(l,c);});break}case "vline":{let i=t.handlePoints(n);if(i.length===0)return;this.stroke(e,t.style,()=>{e.moveTo(i[0][0],0),e.lineTo(i[0][0],n.height);});break}case "hray":{let i=t.handlePoints(n);if(i.length===0)return;this.stroke(e,t.style,()=>{e.moveTo(i[0][0],i[0][1]),e.lineTo(n.width,i[0][1]);});break}case "crossline":{let i=t.handlePoints(n);if(i.length===0)return;this.stroke(e,t.style,()=>{e.moveTo(0,i[0][1]),e.lineTo(n.width,i[0][1]),e.moveTo(i[0][0],0),e.lineTo(i[0][0],n.height);});break}case "infoline":this.paintInfoLine(e,t,n);break;case "trendangle":this.paintTrendAngle(e,t,n,o);break;case "circle":{let i=t.handlePoints(n);if(i.length<2)return;let s=i[0][0],a=i[0][1],l=Math.hypot(i[1][0]-s,i[1][1]-a);if(l<1)return;t.style.fillColor&&(e.save(),e.fillStyle=t.style.fillColor,e.beginPath(),e.arc(s,a,l,0,Math.PI*2),e.fill(),e.restore()),this.applyStroke(e,t.style),e.beginPath(),e.arc(s,a,l,0,Math.PI*2),e.stroke(),e.setLineDash([]);break}case "box":{let i=t.handlePoints(n);if(i.length<2)return;let s=Math.min(i[0][0],i[1][0]),a=Math.min(i[0][1],i[1][1]),l=Math.abs(i[1][0]-i[0][0]),c=Math.abs(i[1][1]-i[0][1]);t.style.fillColor&&(e.save(),e.fillStyle=t.style.fillColor,e.fillRect(s,a,l,c),e.restore()),this.applyStroke(e,t.style),e.strokeRect(s,a,l,c),e.setLineDash([]);break}}this.paintLabel(e,t,n,o);}paintLabel(e,t,n,o){let i=t.text;if(!i||!i.value||t.id===this.targets.mutedLabel)return;let s=kI(t,n);if(!s)return;let a=Ke(i.size);e.save(),s.rotate&&(e.translate(s.rotate.cx,s.rotate.cy),e.rotate(s.rotate.angle)),e.font=`${i.bold?"bold ":""}${i.italic?"italic ":""}${a}px ${o.fontFamily}`,e.textBaseline="top",e.textAlign=s.align,e.fillStyle=i.color??o.textColor;let l=mn(a),c=i.value.split(` +`);c.forEach((d,u)=>e.fillText(d,s.x,s.top+u*l)),t.type==="text"&&this.paintTextFrame(e,t.id,s.x,s.top,c,a,o),e.restore();}paintTextFrame(e,t,n,o,i,s,a){let l=this.targets,c=l.selected?.has(t)?Ex.selected:l.hovered===t?Ex.hovered:0;if(c===0)return;let d=mn(s),u=Math.max(8,...i.map(h=>e.measureText(h).width));e.save(),e.setLineDash([]),e.lineWidth=1,e.strokeStyle=J(a.textColor,c),Gt(e,n-Kr,o-(d-s)/2-Xr,u+Kr*2,i.length*d+Xr*2,4),e.stroke(),e.restore();}paintFibRatios(e,t,n,o){let i=t.entryLines(n);if(!i||i.length===0)return;for(let l of t.fillBands(n))e.save(),e.globalAlpha=.06*e.globalAlpha,e.fillStyle=l.color,e.fillRect(l.x,l.y,l.w,l.h),e.restore();e.textBaseline="middle";let s=`${Ke(t.numbersSize)}px ${o.fontFamily}`,a=`${Ke(t.labelsSize)}px ${o.fontFamily}`;for(let l of i)this.stroke(e,{...t.style,lineColor:l.color},()=>{e.moveTo(l.x1,l.y1),e.lineTo(l.x2,l.y2);}),e.fillStyle=l.color,e.font=s,e.textAlign=l.numberAlign,e.fillText(l.numberText,l.numberX,l.numberY),l.label&&(e.font=a,e.textAlign="center",e.fillText(l.label,l.labelX,l.labelY));e.textAlign="left",e.textBaseline="alphabetic";}paintRadialFib(e,t,n,o){let i=t.radial(n);if(i&&i.R0>=1){let s=`${Ke(t.numbersSize)}px ${o.fontFamily}`,a=(i.a0+i.a1)/2;e.textBaseline="middle";for(let l of t.levels){if(!l.enabled)continue;let c=i.R0*l.ratio;c<.5||(this.applyStroke(e,{...t.style,lineColor:l.color}),e.beginPath(),e.arc(i.cx,i.cy,c,i.a0,i.a1),e.stroke(),e.setLineDash([]),e.fillStyle=l.color,e.font=s,e.textAlign="left",e.fillText(String(l.ratio),i.cx+Math.cos(a)*c+3,i.cy+Math.sin(a)*c));}e.textBaseline="alphabetic",e.textAlign="left";}for(let s of t.boundingLines(n))this.stroke(e,t.style,()=>{e.moveTo(s[0],s[1]),e.lineTo(s[2],s[3]);});}paintGannArcs(e,t,n){let o=t.arcGeom(n);if(!o||Math.abs(o.bx)<1||Math.abs(o.py)<1)return;let i=24;for(let s of nu){this.applyStroke(e,{...t.style,lineColor:s.color}),e.beginPath();for(let a=0;a<=i;a+=1){let l=a/i*(Math.PI/2),c=o.ox+s.k*o.bx*Math.cos(l),d=o.oy+s.k*o.py*Math.sin(l);a===0?e.moveTo(c,d):e.lineTo(c,d);}e.stroke();}e.setLineDash([]);}paintFibSpiral(e,t,n){let o=t.spiralPoints(n);!o||o.length<2||this.stroke(e,t.style,()=>{e.moveTo(o[0][0],o[0][1]);for(let i=1;ie.fillText(f,s+l/2,m+g*p)),e.textAlign="left",e.textBaseline="alphabetic";}paintPosition(e,t,n,o){let i=t.layout(n);if(!i)return;let{x1:s,x2:a,ey:l,sy:c,ty:d}=i,u=a-s,h=(b,y,w)=>{e.save(),e.globalAlpha=.13*e.globalAlpha,e.fillStyle=w,e.fillRect(s,Math.min(b,y),u,Math.abs(y-b)),e.restore();};h(l,d,t.profitColor),h(l,c,t.lossColor);let p=(b,y)=>this.stroke(e,{...t.style,lineColor:y},()=>{e.moveTo(s,b),e.lineTo(a,b);});if(p(d,t.profitColor),p(c,t.lossColor),p(l,t.style.lineColor),!t.showText)return;let m=Ke(t.text?.size??"normal");e.fillStyle=t.text?.color??o.textColor,e.textAlign="center",e.textBaseline="middle",e.font=`${m}px ${o.fontFamily}`;let f=s+u/2,g=Math.min(l,c,d)-9;t.showHeader&&e.fillText(t.headerLabel(),f,t.showLossSize?g-Math.round(m*1.15):g),e.font=`${Math.max(10,m-1)}px ${o.fontFamily}`,t.showLossSize&&e.fillText(t.lossSizeLabel(),f,g),t.showTargetLabel&&e.fillText(t.targetLabel(),f,(l+d)/2),t.showStopLabel&&e.fillText(t.stopLabel(),f,(l+c)/2),e.textAlign="left",e.textBaseline="alphabetic";}paintRegressionChannel(e,t,n,o){let i=t.layout(n);if(!i)return;let s=t.reg,a=(c,d,u,h,p)=>{e.save(),e.fillStyle=c,e.beginPath(),e.moveTo(i.x0,d),e.lineTo(i.x1,u),e.lineTo(i.x1,p),e.lineTo(i.x0,h),e.closePath(),e.fill(),e.restore();};a(s.upperFill,i.midY0,i.midY1,i.upperY0,i.upperY1),a(s.lowerFill,i.midY0,i.midY1,i.lowerY0,i.lowerY1);let l=(c,d,u,h)=>this.stroke(e,{lineColor:c,lineWidth:t.style.lineWidth,lineStyle:d},()=>{e.moveTo(i.x0,u),e.lineTo(i.x1,h);});if(l(s.upperColor,s.upperStyle,i.upperY0,i.upperY1),l(s.lowerColor,s.lowerStyle,i.lowerY0,i.lowerY1),l(s.midColor,s.midStyle,i.midY0,i.midY1),i.showR2){let c=`R\xB2 ${Math.round(i.r2*100)}%`;e.font=`11px ${o.fontFamily}`;let d=e.measureText(c).width,u=5,h=4,p=d+u*2,m=i.x0-h-p,f=i.midY0-9;e.save(),e.globalAlpha=.9*e.globalAlpha,Gt(e,m,f-8,p,16,3),e.fillStyle=Mx,e.fill(),e.restore(),e.fillStyle=o.textColor,e.textAlign="left",e.textBaseline="middle",e.fillText(c,m+u,f),e.textBaseline="alphabetic";}}paintMagnifierGhost(e,t,n,o){let i=t.rect(n);i&&(e.save(),e.strokeStyle=t.style.lineColor||Ye(o.background),e.lineWidth=1,e.setLineDash([4,4]),e.strokeRect(Math.min(i.x1,i.x2),Math.min(i.y1,i.y2),Math.abs(i.x2-i.x1),Math.abs(i.y2-i.y1)),e.restore());}paintMagnifier(e,t,n,o){let i=t.rect(n),s=t.anchors[0],a=t.anchors[1];if(!i||!s||!a)return;let l=Math.min(i.x1,i.x2),c=Math.max(i.x1,i.x2),d=Math.min(i.y1,i.y2),u=Math.max(i.y1,i.y2),h=c-l,p=u-d;e.save(),e.globalAlpha=1,e.fillStyle=o.background,e.fillRect(l,d,h,p),e.restore();let m=Math.min(s.time,a.time),f=Math.max(s.time,a.time),g=n.barsBetween?n.barsBetween(m,f):0,b=g>0?(f-m)/g:0,y=n.seriesInRange&&b>0&&h>1&&p>1?n.seriesInRange(t.magnifier.timeframe,m,f+b):void 0,w=y?.state==="ready"||y?.state==="loading"?y.bars??[]:[];if(y&&(y.state==="ready"||y.state==="loading")&&w.length>0){let S=this.seriesLook,M=S.style!=="candles"?fo(S.style):null;M&&(w=M.full(w));let C=S.style==="bars"?"bars":S.style==="line"||S.style==="baseline"?"line":S.style==="area"?"area":"candles",L=(n.xOf(m+b)-n.xOf(m))/2;e.save(),e.beginPath(),e.rect(l,d,h,p),e.clip(),C==="line"||C==="area"?this.paintMagnifierLine(e,t,n,w,y.barMs,L,u,C==="area",t.magnifier.upColor||S.lineColor):this.paintMagnifierBars(e,t,n,w,y.barMs,L,l,c,C,t.magnifier.upColor||S.upColor,t.magnifier.downColor||S.downColor),e.restore();}else if(y){let S=y.state==="loading"?"Loading\u2026":y.state==="ready"?"No lower-timeframe data":y.reason==="too-wide"?"Area too wide for this timeframe":y.reason==="none-lower"?"No lower timeframe available":y.reason==="not-lower"?"Pick a timeframe below the chart":"No data source";this.paintMagnifierNotice(e,S,l,d,h,p,o);}if(e.save(),e.strokeStyle=t.style.lineColor||Ye(o.background),e.lineWidth=t.style.lineWidth||1,e.setLineDash(or(t.style.lineStyle,t.style.lineWidth||1)),e.strokeRect(l,d,h,p),e.restore(),h>44){let S=ki(y?.state==="ready"||y?.state==="loading"?y.timeframe:t.magnifier.timeframe),M=17,C=4,L=n.paneRect?.(t.paneId),v=L?L.top+L.height:n.height,x=u+C+M<=v?u+C:u-C-M;e.save(),e.font=`10px ${o.fontFamily}`;let E=e.measureText(S).width,N=E+12+11;Gt(e,l,x,N,M,3),e.fillStyle=o.background,e.fill(),e.strokeStyle=J(o.textColor,.28),e.lineWidth=1,e.setLineDash([]),e.stroke(),e.fillStyle=o.textColor,e.textAlign="left",e.textBaseline="middle",e.fillText(S,l+6,x+M/2+.5);let V=l+6+E+5,Z=x+M/2;e.strokeStyle=J(o.textColor,.7),e.lineWidth=1.2,e.beginPath(),e.moveTo(V,Z-1.5),e.lineTo(V+2.5,Z+1.5),e.lineTo(V+5,Z-1.5),e.stroke(),e.restore(),t.chipRect={x:l,y:x,w:N,h:M};}else t.chipRect=null;}paintMagnifierBars(e,t,n,o,i,s,a,l,c,d,u){e.setLineDash([]),e.lineWidth=1;for(let h of o){let p=n.xOf(h.time)-s,m=n.xOf(h.time+i)-s;if(ml)continue;let f=n.yOf(h.high,t.paneId),g=n.yOf(h.low,t.paneId),b=n.yOf(h.open,t.paneId),y=n.yOf(h.close,t.paneId);if(f==null||g==null||b==null||y==null)continue;let w=h.close>=h.open?d:u,S=m-p,M=(p+m)/2;if(e.strokeStyle=w,e.beginPath(),e.moveTo(M,f),e.lineTo(M,g),e.stroke(),!(S<3))if(c==="bars"){let C=Math.max(1,S*.35);e.beginPath(),e.moveTo(M-C,b),e.lineTo(M,b),e.moveTo(M,y),e.lineTo(M+C,y),e.stroke();}else {let C=Math.max(1,S*.7);e.fillStyle=w,e.fillRect(M-C/2,Math.min(b,y),C,Math.max(1,Math.abs(y-b)));}}}paintMagnifierLine(e,t,n,o,i,s,a,l,c){let d=[];for(let u of o){let h=n.yOf(u.close,t.paneId);h!=null&&d.push([n.xOf(u.time+i/2)-s,h]);}if(!(d.length<2)){if(l){e.beginPath(),e.moveTo(d[0][0],a);for(let[u,h]of d)e.lineTo(u,h);e.lineTo(d[d.length-1][0],a),e.closePath(),e.fillStyle=J(c,.15),e.fill();}e.setLineDash([]),e.lineWidth=1.5,e.strokeStyle=c,e.beginPath(),e.moveTo(d[0][0],d[0][1]);for(let u=1;u=a.vaFrom&&f<=a.vaTo,k=v?s.vaUpColor:s.upColor,x=v?s.vaDownColor:s.downColor,E=d===1?c:c-C;L>0&&(e.fillStyle=k,e.fillRect(E,S,L,M)),C-L>0&&(e.fillStyle=x,e.fillRect(E+L,S,C-L,M));}let h=t.style.lineWidth,p=(f,g,b,y)=>{!f||y==null||Px(g)||this.stroke(e,{lineColor:g,lineWidth:h,lineStyle:b},()=>{e.moveTo(i.x0,y),e.lineTo(i.x1,y);});};p(s.showVah,s.vahColor,s.vahStyle,i.vahY),p(s.showVal,s.valColor,s.valStyle,i.valY),p(s.showPoc,s.pocColor??Ye(o.background),s.pocStyle,i.pocY);let m=Math.max(1,h);if(s.showDevelopingPoc&&this.strokePolyline(e,i.developingPoc,{lineColor:s.developingPocColor,lineWidth:m,lineStyle:s.developingPocStyle}),s.showDevelopingVa){let f={lineColor:s.developingVaColor,lineWidth:m,lineStyle:s.developingVaStyle};this.strokePolyline(e,i.developingVaHigh,f),this.strokePolyline(e,i.developingVaLow,f);}}paintAnchoredVwap(e,t,n){let o=t.layout(n);if(!o)return;let i=t.vwap,s=t.style.lineWidth;if(o.upper.length>=2&&i.bandFill){e.save(),e.fillStyle=i.bandFill,e.beginPath(),e.moveTo(o.upper[0][0],o.upper[0][1]);for(let a=1;a=0;a-=1)e.lineTo(o.lower[a][0],o.lower[a][1]);e.closePath(),e.fill(),e.restore();}this.strokePolyline(e,o.upper,{lineColor:i.upperColor,lineWidth:s,lineStyle:i.upperStyle}),this.strokePolyline(e,o.lower,{lineColor:i.lowerColor,lineWidth:s,lineStyle:i.lowerStyle}),this.strokePolyline(e,o.mid,{lineColor:i.midColor,lineWidth:s,lineStyle:i.midStyle});}strokePolyline(e,t,n){t.length<2||Px(n.lineColor)||this.stroke(e,n,()=>{e.moveTo(t[0][0],t[0][1]);for(let o=1;oe.measureText(I).width)),f=9,g=6,b=mn(h),y=m+f*2,w=p.length*b+g*2,S=c-y/2,M=d-w/2,C=y/2,L=w/2,v=a-c,k=l-d,x=Math.min(i,y/2,w/2),E=null;if(Math.abs(v)>C||Math.abs(k)>L){let I=Math.max(6,Math.min(y,w)*.18);if(Math.abs(v)/C>=Math.abs(k)/L){let N=v>0?S+y:S,V=Math.max(M+x+I,Math.min(M+w-x-I,d+k*(N-c)/(v||1)));E={edge:v>0?"right":"left",at:V,apex:[a,l],half:I};}else {let N=k>0?M+w:M,V=Math.max(S+x+I,Math.min(S+y-x-I,c+v*(N-d)/(k||1)));E={edge:k>0?"bottom":"top",at:V,apex:[a,l],half:I};}}e.save(),e.fillStyle=Et(t,o)??o.background,Ax(e,S,M,y,w,x,E),e.fill(),e.restore(),this.applyStroke(e,t.style),Ax(e,S,M,y,w,x,E),e.stroke(),e.setLineDash([]),e.fillStyle=u?.color??Ye(Et(t,o)??o.background),e.textBaseline="top",e.textAlign="left",p.forEach((I,N)=>e.fillText(I,S+f,M+g+N*b));}paintTextPlate(e,t,n,o,i,s,a,l,c,d,u){e.save(),e.fillStyle=Et(t,n)??n.background,Gt(e,o,i,s,a,5),e.fill(),e.restore(),this.applyStroke(e,t.style),Gt(e,o,i,s,a,5),e.stroke(),e.setLineDash([]),e.fillStyle=t.text?.color??Ye(Et(t,n)??n.background),e.textBaseline="top",e.textAlign="left",l.forEach((h,p)=>e.fillText(h,o+d,i+u+p*c));}measureText(e,t,n,o){let i=t.text,s=Ke(i?.size??"normal");e.font=`${i?.bold?"bold ":""}${i?.italic?"italic ":""}${s}px ${n.fontFamily}`;let a=(i?.value||o).split(` +`),l=Math.max(8,...a.map(c=>e.measureText(c).width));return {lines:a,tw:l,fs:s,lh:mn(s)}}paintNote(e,t,n,o){let i=t.handlePoints(n);if(!i.length)return;let[s,a]=i[0],{lines:l,tw:c,lh:d}=this.measureText(e,t,o,"Note"),u=8,h=5;this.paintTextPlate(e,t,o,s,a,c+u*2,l.length*d+h*2,l,d,u,h);}paintPriceNote(e,t,n,o){let i=t.points(n),s=t.anchors[0];if(!i||!s)return;let[a,l]=i[0],[c,d]=i[1],u=Ix(s.price),h=t.text,p=Ke(h?.size??"normal");e.font=`${h?.bold?"bold ":""}${h?.italic?"italic ":""}${p}px ${o.fontFamily}`;let m=9,f=6,g=e.measureText(u).width+m*2,b=mn(p)+f*2,y=c-g/2,w=d-b/2;this.stroke(e,t.style,()=>{e.moveTo(a,l),e.lineTo(c,d);}),e.fillStyle=t.style.lineColor,e.beginPath(),e.arc(a,l,3,0,Math.PI*2),e.fill(),e.save(),e.fillStyle=Et(t,o)??o.background,Gt(e,y,w,g,b,5),e.fill(),e.restore(),this.applyStroke(e,t.style),Gt(e,y,w,g,b,5),e.stroke(),e.setLineDash([]),e.fillStyle=h?.color??Ye(Et(t,o)??o.background),e.textBaseline="middle",e.textAlign="center",e.fillText(u,c,d+.5);}paintSignpost(e,t,n,o){let i=t.points(n);if(!i)return;let[s,a]=i[0],[l,c]=i[1],{lines:d,tw:u,lh:h}=this.measureText(e,t,o,"Signpost"),p=9,m=6,f=u+p*2,g=d.length*h+m*2;this.stroke(e,t.style,()=>{e.moveTo(s,a),e.lineTo(l,c);}),e.fillStyle=t.style.lineColor,e.beginPath(),e.arc(s,a,3.5,0,Math.PI*2),e.fill(),this.paintTextPlate(e,t,o,l-f/2,c-g/2,f,g,d,h,p,m);}paintPriceLabel(e,t,n,o){let i=t.handlePoints(n),s=t.anchors[0];if(!i.length||!s)return;let[a,l]=i[0],c=Ix(s.price),d=t.text,u=Ke(d?.size??"normal");e.font=`${d?.bold?"bold ":""}${d?.italic?"italic ":""}${u}px ${o.fontFamily}`;let h=e.measureText(c).width,p=8,m=4,f=6,g=h+p*2,b=mn(u)+m*2,y=l-b/2,w=Et(t,o)??o.background;e.save(),e.fillStyle=w,e.beginPath(),e.moveTo(a,l),e.lineTo(a+f,l-5),e.lineTo(a+f,l+5),e.closePath(),e.fill(),Gt(e,a+f,y,g,b,4),e.fill(),e.restore(),this.applyStroke(e,t.style),Gt(e,a+f,y,g,b,4),e.stroke(),e.setLineDash([]),e.fillStyle=d?.color??Ye(w),e.textBaseline="middle",e.textAlign="left",e.fillText(c,a+f+p,l+.5);}paintPattern(e,t,n,o){let i=t.handlePoints(n);if(i.length<2)return;let s=t.valid(),a=Et(t,o)??t.style.lineColor,l=t.style.fillColor?1:.1;for(let[h,p,m]of t.fillTriangles()){let f=i[h],g=i[p],b=i[m];!f||!g||!b||(e.save(),e.globalAlpha=l*e.globalAlpha,e.fillStyle=a,e.beginPath(),e.moveTo(f[0],f[1]),e.lineTo(g[0],g[1]),e.lineTo(b[0],b[1]),e.closePath(),e.fill(),e.restore());}this.stroke(e,t.style,()=>{e.moveTo(i[0][0],i[0][1]);for(let h=1;h=2){let f=Jd(h[0],h[1],p[0],p[1],i[0][0],i[0][1],i[1][0],i[1][1])??h,g=Jd(h[0],h[1],p[0],p[1],i[m-2][0],i[m-2][1],i[m-1][0],i[m-1][1])??p;this.stroke(e,{...t.style,lineStyle:"dashed"},()=>{e.moveTo(f[0],f[1]),e.lineTo(g[0],g[1]);});}}let d=t.vertexLabels();if(e.fillStyle=o.textColor,e.font=`bold 12px ${o.fontFamily}`,e.textAlign="center",i.forEach((h,p)=>{let m=d[p];if(!m)return;let f=((i[p-1]?.[1]??h[1])+(i[p+1]?.[1]??h[1]))/2,g=h[1]<=f;e.textBaseline=g?"bottom":"top",e.fillText(m,h[0],g?h[1]-7:h[1]+7);}),t.legRatios()){e.font=`11px ${o.fontFamily}`,e.textAlign="left",e.textBaseline="middle";for(let h=2;h=2){let h=i[i.length-1],p=i[i.length-2],m=p?h[1]<=p[1]:false;e.font=`bold 12px ${o.fontFamily}`,e.fillStyle=s===false?$s:Gs,e.textAlign="center",e.textBaseline=m?"bottom":"top",e.fillText(`${u} ${s?"\u2713":"\u2717"}`,h[0],m?h[1]-22:h[1]+22);}e.textAlign="left",e.textBaseline="alphabetic";}paintHighlighter(e,t,n){let o=t.geometry(n);if(!o||o.segments.length===0)return;e.save(),e.strokeStyle=t.style.lineColor,e.lineWidth=t.style.lineWidth,e.lineCap="round",e.lineJoin="round",e.setLineDash([]),e.beginPath();let i=o.segments[0];e.moveTo(i[0],i[1]);for(let s of o.segments)e.lineTo(s[2],s[3]);e.stroke(),e.restore();}paintSegments(e,t,n){let o=t.geometry(n);if(o){if(o.fill&&o.fill.length>=3&&t.style.fillColor){e.save(),e.fillStyle=t.style.fillColor,e.beginPath(),e.moveTo(o.fill[0][0],o.fill[0][1]);for(let i=1;i{e.moveTo(i[0],i[1]),e.lineTo(i[2],i[3]);});}}paintInfoLine(e,t,n){let o=t.handlePoints(n);if(o.length<2)return;let[i,s]=o[0],[a,l]=o[1];this.stroke(e,t.style,()=>{e.moveTo(i,s),e.lineTo(a,l);});let c=t.anchors[0],d=t.anchors[1];if(!c||!d)return;let u=d.price-c.price,h=c.price!==0?u/c.price*100:0,p=n.barsBetween?Math.abs(Math.round(n.barsBetween(c.time,d.time))):0,m=u>=0?"+":"",f=`${m}${u.toFixed(2)} (${m}${h.toFixed(2)}%) ${p} bars`,g=(i+a)/2,b=(s+l)/2;e.font="11px monospace";let y=e.measureText(f).width+12,w=18,S=g-2,M=b-w-4;e.save(),e.globalAlpha=.9*e.globalAlpha,Gt(e,S,M,y,w,3),e.fillStyle=Mx,e.fill(),e.strokeStyle=CI,e.lineWidth=1,e.stroke(),e.restore(),e.fillStyle=u>=0?O:D,e.textAlign="left",e.textBaseline="middle",e.fillText(f,S+6,M+w/2),e.textBaseline="alphabetic";}paintTrendAngle(e,t,n,o){let i=t.handlePoints(n);if(i.length<2)return;let[s,a]=i[0],[l,c]=i[1];this.stroke(e,t.style,()=>{e.moveTo(s,a),e.lineTo(l,c);});let d=l-s,u=c-a,h=Math.atan2(-u,d),p=h*(180/Math.PI),m=Math.min(30,Math.hypot(d,u)*.3),f=t.style.lineColor;if(e.save(),e.globalAlpha=.4*e.globalAlpha,e.strokeStyle=f,e.lineWidth=1,e.setLineDash([4,4]),e.beginPath(),e.moveTo(s,a),e.lineTo(s+Math.max(Math.abs(d),m+20),a),e.stroke(),e.restore(),e.setLineDash([]),m>1){let g=-h;e.strokeStyle=f,e.lineWidth=1.5,e.beginPath(),e.arc(s,a,m,Math.min(0,g),Math.max(0,g)),e.stroke();}e.fillStyle=f,e.font=`11px ${o.fontFamily}`,e.textAlign="left",e.textBaseline="alphabetic",e.fillText(`${p.toFixed(1)}\xB0`,s+m+6,a+(u<0?-14:2));}paintArrowMark(e,t,n){let o=t.glyphPoints(n);if(!(!o||o.length<3)){e.save(),e.setLineDash([]),e.fillStyle=t.style.lineColor,e.beginPath(),e.moveTo(o[0][0],o[0][1]);for(let i=1;i{if(s&&s.edge===l){let[u,h]=s.apex;l==="top"?(r.lineTo(s.at-s.half,t),r.lineTo(u,h),r.lineTo(s.at+s.half,t)):l==="bottom"?(r.lineTo(s.at+s.half,t+o),r.lineTo(u,h),r.lineTo(s.at-s.half,t+o)):l==="right"?(r.lineTo(e+n,s.at-s.half),r.lineTo(u,h),r.lineTo(e+n,s.at+s.half)):(r.lineTo(e,s.at+s.half),r.lineTo(u,h),r.lineTo(e,s.at-s.half));}r.lineTo(c,d);};r.beginPath(),r.moveTo(e+i,t),a("top",e+n-i,t),r.arcTo(e+n,t,e+n,t+i,i),a("right",e+n,t+o-i),r.arcTo(e+n,t+o,e+n-i,t+o,i),a("bottom",e+i,t+o),r.arcTo(e,t+o,e,t+o-i,i),a("left",e,t+i),r.arcTo(e,t,e+i,t,i),r.closePath();}function TI(r){if(!Number.isFinite(r))return "";let e=Math.round(r*1e3)/1e3;return String(e)}function kI(r,e){let t=r.text;if(!t)return null;let n=r.handlePoints(e),o=t.value.split(` +`).length,i=mn(Ke(t.size));switch(r.type){case "text":return n[0]?{x:n[0][0]+2,top:n[0][1]+2,align:"left"}:null;case "hline":return n[0]?{x:n[0][0]+8,top:n[0][1]-4-i*o,align:"left"}:null;case "trendline":case "ray":case "extendedline":case "infoline":case "trendangle":{if(n.length<2)return null;let[s,a]=n[0],[l,c]=n[1];return {x:0,top:-6-i*o,align:"center",rotate:{angle:ex(s,a,l,c),cx:(s+l)/2,cy:(a+c)/2}}}case "box":return n.length<2?null:{x:(n[0][0]+n[1][0])/2,top:(n[0][1]+n[1][1])/2-i*o/2,align:"center"};default:return n[0]?{x:n[0][0],top:n[0][1],align:"left"}:null}}function ri(r,e,t,n,o=6){for(let i=r.length-1;i>=0;i-=1){let s=r[i];if(!s.visible)continue;let a=n.paneRect?.(s.paneId);if(!(a&&a.height<=0)&&s.hitTest(e,t,n,o))return s}return null}function pp(r,e){let t=[...r];return t.length<2?t:t.filter(n=>!e.find(o=>o.id===n)?.locked)}function Rx(r,e,t,n){return n&&e.size>=2&&e.has(r.id)?pp(e,t):r.locked?[]:[r.id]}var vd=3,LI=4,Dx=Math.PI/4,Ox=new Set(["trendline","ray","extendedline","infoline","trendangle","arrow"]),yd=class{constructor(e){this.deps=e;this.state={kind:"idle"};this.snapAt=null;}snapMarker(){return this.snapAt}placingMarkers(e){if(this.state.kind!=="placing")return null;let{draft:t}=this.state;if(t.placementMode()==="freehand")return null;let n=[];for(let o of t.anchors){let i=e.yOf(o.price,t.paneId);i!=null&&n.push([e.xOf(o.time),i]);}return n.length?n:null}resolve(e,t,n,o){let i=this.deps.projector().pxToPoint(e,t,n);if(o==="off")return this.snapAt=null,i;let s=this.deps.snap(i,n,o,{x:e,y:t}),a=s.time!==i.time||s.price!==i.price;return this.snapAt=a?{point:s,paneId:n}:null,s}snapCursor(e,t,n){let o=this.deps.projector(),i=o.paneIdAtY(t)??"price",s=this.resolve(e,t,i,n),a=o.yOf(s.price,i);return {x:o.xOf(s.time),y:a??t}}clearSnapMarker(){this.snapAt=null;}resolveAngleSnapped(e,t,n,o){let i=this.deps.projector(),s=i.xOf(e.time),a=i.yOf(e.price,t);if(this.snapAt=null,a==null)return i.pxToPoint(n,o,t);let l=Math.hypot(n-s,o-a);if(l<1)return i.pxToPoint(n,o,t);let c=Math.round(Math.atan2(o-a,n-s)/Dx)*Dx;return i.pxToPoint(s+l*Math.cos(c),a+l*Math.sin(c),t)}placingPivot(e){return Ox.has(e.type)?e.anchors[e.anchors.length-1]??null:null}claim(e,t){return this.deps.activeTool()!=null||this.state.kind!=="idle"?true:this.hitAt(e,t)!=null}cursorAt(e,t){return this.deps.activeTool()!=null?null:this.hitAt(e,t)?"pointer":null}isPlacing(){return this.state.kind==="placing"}isDragging(){return this.state.kind==="pressed"&&this.state.moved}activeDragId(){return this.state.kind==="pressed"&&this.state.moved?this.state.id:null}movingIds(){return this.state.kind!=="pressed"||!this.state.moved||this.state.clones?new Set:new Set([this.state.id,...this.state.riders.map(e=>e.id)])}pressedId(){return this.state.kind==="pressed"?this.state.id:null}dragClones(){return this.state.kind==="pressed"&&this.state.moved&&this.state.clones?this.state.clones.map(e=>e.d):null}marqueeRect(){if(this.state.kind!=="marquee")return null;let{x0:e,y0:t,x1:n,y1:o}=this.state;return {x:Math.min(e,n),y:Math.min(t,o),w:Math.abs(n-e),h:Math.abs(o-t)}}beginMarquee(e,t){return this.state.kind!=="idle"||this.deps.activeTool()!=null?false:(this.state={kind:"marquee",x0:e,y0:t,x1:e,y1:t},true)}down(e,t,n="off",o=false,i=false){let s=this.deps.projector();if(this.state.kind==="placing"){if(this.state.draft.placementMode()!=="click")return;let c=o?this.placingPivot(this.state.draft):null,d=c?this.resolveAngleSnapped(c,this.state.draft.paneId,e,t):this.resolve(e,t,this.state.draft.paneId,n);this.state.draft.anchors.push(this.placementAnchor(this.state.draft,d)),this.state.draft.anchors.length>=this.state.need?this.finalize():this.deps.changed();return}let a=this.deps.activeTool();if(a){let c=s.paneIdAtY(t)??"price",d=Wn(a,{paneId:c,anchors:[this.resolve(e,t,c,n)],style:this.deps.lastStyle()});if(!d)return;this.state={kind:"placing",draft:d,need:d.anchorSchema().max,cursor:null},d.placementMode()==="click"&&d.anchors.length>=this.state.need?this.finalize():this.deps.changed();return}let l=this.hitAt(e,t);if(l){if(o){this.deps.emit({kind:"select",ids:[l.id],additive:true});return}let c=l.hitHandle(e,t,s,6),d=[];if(c<0&&this.deps.selectedIds().has(l.id))for(let u of this.deps.selectedIds()){let h=u===l.id?null:this.byId(u);h&&!h.locked&&h.visible&&d.push({id:u,orig:mp(h)});}this.state={kind:"pressed",id:l.id,handle:c,orig:mp(l),px:e,py:t,moved:false,riders:d,mod:i,clones:null};}}bodyDelta(e,t,n){if(this.state.kind!=="pressed")return {dt:0,dp:0};let o=this.deps.projector(),i=o.pxToPoint(this.state.px,this.state.py,e),s=o.pxToPoint(t,n,e);return {dt:s.time-i.time,dp:s.price-i.price}}dragSources(e){if(this.state.kind!=="pressed")return [];let t=[{d:e,orig:this.state.orig}];for(let n of this.state.riders){let o=this.byId(n.id);o&&t.push({d:o,orig:n.orig});}return t}dragBody(e,t,n){if(this.state.kind==="pressed"){this.snapAt=null,this.state.mod&&!this.state.clones&&(this.state.clones=this.dragSources(e).flatMap(o=>{let i=wt(o.d.serialize());return i?[{d:i,orig:mp(i)}]:[]}));for(let o of this.state.clones??this.dragSources(e)){let{dt:i,dp:s}=this.bodyDelta(o.d.paneId,t,n);o.d.anchors=o.d.translateBody(i,s,o.orig);}}}move(e,t,n="off",o=false){if(this.state.kind==="idle"){let s=this.deps.activeTool(),a=this.snapAt!=null;s&&n!=="off"?this.resolve(e,t,this.deps.projector().paneIdAtY(t)??"price",n):this.snapAt=null,(this.snapAt!=null||a)&&this.deps.changed();return}if(this.state.kind==="placing"){if(this.state.draft.placementMode()==="freehand"){this.captureFreehand(e,t);return}let s=o?this.placingPivot(this.state.draft):null;this.state.cursor=s?this.resolveAngleSnapped(s,this.state.draft.paneId,e,t):this.resolve(e,t,this.state.draft.paneId,n),this.deps.changed();return}if(this.state.kind==="marquee"){this.state.x1=e,this.state.y1=t,this.deps.changed();return}if(this.state.kind!=="pressed")return;let i=this.byId(this.state.id);if(!(!i||i.locked)&&!(!this.state.moved&&Math.abs(e-this.state.px)<=vd&&Math.abs(t-this.state.py)<=vd)){if(this.state.moved=true,this.state.handle<0)this.dragBody(i,e,t);else {let s=i.anchors[this.state.handle];if(s){let a=o&&Ox.has(i.type)&&i.anchors.length===2?i.anchors[1-this.state.handle]:void 0,l=a?this.resolveAngleSnapped(a,i.paneId,e,t):this.resolve(e,t,i.paneId,n);EI(s,l,i.anchorSchema().slots[this.state.handle]?.free??"both");}i.constrainHandleDrag(this.state.handle);}this.deps.changed();}}up(e,t){if(this.snapAt=null,this.state.kind==="placing"){let c=this.state.draft.placementMode();c==="drag"?(this.state.cursor&&this.state.draft.anchors.push(this.state.cursor),this.state.draft.anchors.length>=this.state.draft.anchorSchema().min?this.finalize():this.discardPlacing()):c==="freehand"&&(this.state.draft.anchors.length>=this.state.draft.anchorSchema().min?this.finalize():this.discardPlacing());return}if(this.state.kind==="marquee"){let c=this.marqueeRect();this.state={kind:"idle"},(c.w>vd||c.h>vd)&&this.selectWithin(c),this.deps.changed();return}if(this.state.kind!=="pressed")return;let{id:n,moved:o,riders:i,mod:s,clones:a}=this.state;this.state={kind:"idle"};let l=this.byId(n);if(!o){s?this.deps.emit({kind:"select",ids:[n],additive:true}):this.deps.openSettings(n,e,t);return}if(a)this.deps.emit({kind:"clone",docs:a.map(c=>c.d.serialize())});else if(l){let c=[l.serialize()];for(let d of i){let u=this.byId(d.id);u&&c.push(u.serialize());}c.length>1?this.deps.emit({kind:"edit-many",docs:c}):this.deps.emit({kind:"edit",doc:c[0]});}this.deps.changed();}selectWithin(e){let t=this.deps.projector(),n=[...this.deps.selectedIds()];for(let o of this.deps.drawings()){if(!o.visible||n.includes(o.id))continue;let i=o.bounds(t);i&&MI(e,i)&&n.push(o.id);}n.length>this.deps.selectedIds().size&&this.deps.emit({kind:"select",ids:n});}cancel(){if(this.snapAt=null,this.state.kind==="placing"){let e=this.state.draft.type;return this.state={kind:"idle"},this.deps.emit({kind:"tool-finished",type:e}),this.deps.changed(),true}if(this.state.kind==="pressed"){if(this.state.moved&&!this.state.clones){let e=this.byId(this.state.id);if(e)for(let t of this.dragSources(e))t.d.anchors=t.orig.map(n=>({time:n.time,price:n.price}));}return this.state={kind:"idle"},this.deps.changed(),true}return this.state.kind==="marquee"?(this.state={kind:"idle"},this.deps.changed(),true):false}onToolCleared(){this.state.kind==="placing"&&(this.state={kind:"idle"},this.deps.changed());}ghost(){if(this.state.kind!=="placing")return null;let{draft:e,cursor:t}=this.state;return t?Wn(e.type,{paneId:e.paneId,anchors:[...e.anchors,this.placementAnchor(e,t)],style:e.style}):e.anchors.length>=1&&e.type==="hline"?e:null}placementAnchor(e,t){if(e.type!=="parallelchannel"||e.anchors.length!==2)return t;let n=e.anchors[0],o=e.anchors[1],i=o.time-n.time,s=i===0?n.price:n.price+(o.price-n.price)*(t.time-n.time)/i,a=t.price-s;return {time:(n.time+o.time)/2,price:(n.price+o.price)/2+a}}captureFreehand(e,t){if(this.state.kind!=="placing")return;this.snapAt=null;let n=this.state.draft,o=this.deps.projector(),i=n.anchors[n.anchors.length-1],s=i?o.xOf(i.time):NaN,a=i?o.yOf(i.price,n.paneId)??NaN:NaN;if(Math.hypot(e-s,t-a)>LI){if(n.anchors.length>=this.state.need){let l=n.anchors.length-1;n.anchors=n.anchors.filter((c,d)=>d%2===0||d===l);}n.anchors.push(o.pxToPoint(e,t,n.paneId));}this.state.cursor=o.pxToPoint(e,t,n.paneId),this.deps.changed();}finishPlacing(e){if(this.state.kind!=="placing")return false;let t=this.state.draft,n=t.anchorSchema();return t.placementMode()!=="click"||n.max<=n.min||(e&&t.anchors.length>n.min&&t.anchors.pop(),t.anchors.length=0)return o;return ri(this.deps.drawings(),e,t,n,6)}handleDrawings(){let e=new Set(this.deps.selectedIds()),t=this.deps.hoveredId();t&&e.add(t);let n=[];for(let o of e){let i=this.byId(o);i&&n.push(i);}return n}byId(e){return this.deps.drawings().find(t=>t.id===e)??null}};function mp(r){return r.anchors.map(e=>({time:e.time,price:e.price}))}function MI(r,e){return r.x<=e.x+e.w&&e.x<=r.x+r.w&&r.y<=e.y+e.h&&e.y<=r.y+r.h}function EI(r,e,t){(t==="both"||t==="x")&&(r.time=e.time),(t==="both"||t==="y")&&(r.price=e.price);}var PI=[{value:"price",label:"Price"},{value:"points",label:"Points"}],II=[{value:"right",label:"Right"},{value:"left",label:"Left"}],AI={position:"Position size",frvp:"Volume profile",levels:"Levels"},wd=class{constructor(e,t){this.host=e;this.ui=null;this.theme=t;}setTheme(e){this.theme=e;}isOpen(){return this.ui!=null}contains(e){return this.ui?.contains(e)===true}open(e,t,n){this.close();let o=t.resolve()??e,i=Qt(o.serialize()),s=Ms({variant:"inputs"});if(s.style.padding="16px 20px",s.style.overflowY="auto",s.style.overflowX="hidden",s.style.flex="1 1 auto",n==="position"&&o instanceof yt)this.buildPosition(s,o,t);else if(n==="frvp"&&o instanceof gt)this.buildFrvp(s,o,t);else if(n==="levels")this.buildLevels(s,o,t);else return;let a=new Pn({host:this.host,title:AI[n],modal:false,contained:true,align:"center",draggable:true,flush:true,className:"vela-dialog--form",closeOnEscape:false,footer:c=>{c.append(Nx("Cancel",false,()=>{t.restore?.(i),this.close();}),Nx("Ok",true,()=>this.close()));},onOpenChange:c=>{c||this.close();}});_e(a.panel,this.theme),a.body.appendChild(s);let l=c=>{if(!(c.target!==a.backdrop&&c.target!==a.positioner)){if(un()||Wr(c)){Me();return}this.close();}};a.backdrop.addEventListener("pointerdown",l),a.positioner.addEventListener("pointerdown",l),a.panel.addEventListener("keydown",c=>{c.key==="Escape"&&(c.preventDefault(),t.restore?.(i),this.close());}),this.ui=a,a.show();}close(){let e=this.ui;this.ui=null,e?.destroy();}destroy(){this.close();}buildPosition(e,t,n){let o=()=>{let p=n.resolve();return p instanceof yt?p:t},i=[],s=()=>i.forEach(p=>p()),a=p=>Math.round(p*1e8)/1e8,l=(p,m,f)=>{let g=de({kind:"number",value:a(o()[m]),min:f?.min,max:f?.max,step:f?.step,integer:f?.integer,fill:false,commit:"blur",onChange:b=>{n.patch({[m]:b}),s();}});i.push(()=>{document.activeElement!==g.el.querySelector("input")&&g.setValue?.(a(o()[m]));}),e.appendChild(Be({label:p,control:g.el}));},c=(p,m,f)=>{let g="price",b=()=>a(o().levelDisplayValue(f,g)),y=de({kind:"number",value:b(),fill:false,commit:"blur",onChange:S=>{n.patch({[m]:o().levelPriceFromDisplay(f,g,S)}),s();}}),w=de({kind:"select",options:PI,value:g,fill:false,theme:this.theme,onChange:S=>{g=S,y.setValue?.(b());}});i.push(()=>{document.activeElement!==y.el.querySelector("input")&&y.setValue?.(b());}),e.appendChild(Be({label:p,control:[y.el,w.el]}));};e.appendChild(In("Account",{variant:"inputs",first:true})),l("Risk %","riskPercent",{min:0,max:100,step:.1}),l("Account balance","accountBalance",{min:0,max:1e12,step:1,integer:true}),l("Position size","quantity"),e.appendChild(In("Levels",{variant:"inputs"}));let d=de({kind:"select",options:fl,value:o().direction,fill:false,theme:this.theme,onChange:p=>{n.patch({direction:p}),s();}});i.push(()=>d.setValue?.(o().direction)),e.appendChild(Be({label:"Direction",control:d.el})),l("Entry price","entryPrice"),c("Stop","stopPrice","stop"),c("Target","targetPrice","target"),e.appendChild(In("Display",{variant:"inputs"}));let u=[["Show text","showText"],["Show direction & ratio","showHeader"],["Show loss & size","showLossSize"],["Show target label","showTargetLabel"],["Show stop label","showStopLabel"],["Show level prices","showPrices"]];for(let[p,m]of u)e.appendChild(Be({label:p,bool:true,toggle:{checked:o()[m],onChange:f=>{n.patch({[m]:f}),s();},get:()=>o()[m]}}));let h=document.createElement("div");h.className="vela-field-span",h.style.cssText="opacity:0.7;font-size:11px;line-height:1.4;border-top:1px solid var(--vela-border);padding-top:6px;font-variant-numeric:tabular-nums;",i.push(()=>{let p=o();h.textContent=`${p.headerLabel()} \u2014 ${p.lossSizeLabel()}`;}),e.appendChild(h),s();}buildFrvp(e,t,n){let o=()=>{let d=n.resolve();return d instanceof gt?d.frvp:t.frvp},i=o(),s=(d,u,h,p,m,f=true)=>{e.appendChild(Be({label:d,control:de({kind:"number",value:i[u],min:h,max:p,step:m,integer:f,fill:false,commit:"blur",onChange:g=>n.patch({[`frvp.${u}`]:g})}).el}));};s("Rows","rows",1,500,1),s("Value Area","valueAreaPct",0,100,1),s("Width %","widthPct",0,100,1),e.appendChild(Be({label:"Anchor",control:de({kind:"select",options:II,value:i.anchor,fill:false,theme:this.theme,onChange:d=>n.patch({"frvp.anchor":d})}).el}));let a=(d,u)=>{e.appendChild(Be({label:d,fit:true,control:de({kind:"color",theme:this.theme,get:()=>o()[u],onChange:h=>n.patch({[`frvp.${u}`]:h})}).el}));};a("Up Volume","upColor"),a("Down Volume","downColor"),a("Value Area Up","vaUpColor"),a("Value Area Down","vaDownColor");let l=rt.map(d=>({value:d.value,label:d.label})),c=(d,u,h,p)=>{let m=document.createElement("div");m.className="vela-field-span",m.style.cssText="display:flex;align-items:center;gap:8px;";let f=de({kind:"switch",checked:!!i[u],onChange:S=>n.patch({[`frvp.${u}`]:S})}),g=document.createElement("span");g.className="vela-field-label",g.style.flex="1",g.textContent=d;let b=i[h]??Ye(this.theme.background),y=de({kind:"color",theme:this.theme,get:()=>b,onChange:S=>{b=S,n.patch({[`frvp.${h}`]:S});}}),w=de({kind:"select",options:l,value:i[p],fill:false,theme:this.theme,onChange:S=>n.patch({[`frvp.${p}`]:S})});m.append(f.el,g,y.el,w.el),e.appendChild(m);};c("VAH","showVah","vahColor","vahStyle"),c("VAL","showVal","valColor","valStyle"),c("POC","showPoc","pocColor","pocStyle"),c("Developing POC","showDevelopingPoc","developingPocColor","developingPocStyle"),c("Developing VA","showDevelopingVa","developingVaColor","developingVaStyle");}buildLevels(e,t,n){let o=t.editableLevels();if(!o)return;let i=t instanceof dt;if(i){let s=t;e.appendChild(Be({label:"Show ratio labels",bool:true,toggle:{checked:s.showRatios!==false,onChange:a=>n.patch({showRatios:a})}}));}if(t instanceof Cr){let s=t;e.appendChild(Be({label:"Reverse",bool:true,toggle:{checked:s.reverse,onChange:a=>n.patch({reverse:a})}}));}o.forEach((s,a)=>{let l=document.createElement("div");l.className="vela-field-span",l.style.cssText="display:flex;align-items:center;gap:8px;";let c=de({kind:"switch",checked:s.enabled,onChange:m=>n.patch({[`levels.${a}.enabled`]:m})}),d=s.color,u=de({kind:"color",theme:this.theme,get:()=>d,onChange:m=>{d=m,n.patch({[`levels.${a}.color`]:m});}}),h=s.ratio,p=de({kind:"number",value:h,min:0,step:.01,fill:i,compact:!i,commit:"blur",onChange:m=>{if(m<=0){p.setValue?.(h);return}h=m,n.patch({[`levels.${a}.ratio`]:m});}});if(i&&(p.el.style.flex="1"),l.append(c.el,u.el,p.el),!i){let m=de({kind:"text",value:s.label??"",fill:true,placeholder:"label\u2026",onChange:f=>n.patch({[`levels.${a}.label`]:f})});m.el.style.flex="1",m.el.style.minWidth="60px",l.appendChild(m.el);}e.appendChild(l);});}};function Nx(r,e,t){let n=document.createElement("button");return n.type="button",n.textContent=r,n.className=e?"vela-dialog-btn vela-dialog-btn-primary":"vela-dialog-btn",n.addEventListener("click",t),n}var $t=Symbol("mixed");function RI(r){let[e,...t]=r,n=new Set(e?.schema().fields.map(o=>o.path)??[]);for(let o of t){let i=new Set(o.schema().fields.map(s=>s.path));for(let s of n)i.has(s)||n.delete(s);}return n}function DI(r,e){let t=e(r[0]);return r.every(n=>e(n)===t)?t:$t}function OI(r,e){return [...new Set(r.map(e))]}var lr=30,NI=21,Fx="vela-drawing-popup-styles",Vx="4";function Bx(){if(typeof document>"u")return;let r=document.getElementById(Fx);if(r?.dataset.rev===Vx)return;let e=r??document.createElement("style");e.id=Fx,e.dataset.rev=Vx,e.textContent=` .vela-dpop-btn{background:transparent;color:var(--vela-fg-muted);transition:background var(--vela-dur-fast) ease,color var(--vela-dur-fast) ease;} .vela-dpop-btn:hover{background:var(--vela-hover-strong);color:var(--vela-fg-bright);} .vela-dpop-btn[data-active='1']{background:var(--vela-active);color:var(--vela-fg-bright);} @@ -926,7 +955,7 @@ ${Ir(".vela-sd-pane")} .vela-dpop-item[data-active='1']{background:var(--vela-active);} /* A finger needs a wider grab zone than a cursor \u2014 grow the move handle on touch-first devices (the glyph stays centered; only the hit target widens). */ -@media (pointer: coarse){.vela-dpop-grip{width:${ir+14}px !important;}}`,r||document.head.appendChild(e);}var bd=class{constructor(e,t,n=()=>0){this.host=e;this.chartBarMs=n;this.el=null;this.tipEl=null;this.textPanel=null;this.colorPop=null;this.colorOwner=null;this.menuPop=null;this.menuOwner=null;this.onClose=null;this.onOutside=e=>{let t=e.target;if(this.settingsDialog.isOpen()){if(this.settingsDialog.contains(t)||this.isOwnChrome(t))return;this.settingsDialog.close();return}if(this.isOwnChrome(t))return;let n=this.onClose;this.close(),n?.(e);};this.theme=t,this.settingsDialog=new gd(e,t);}lowerTimeframeOptions(){let e=this.chartBarMs();if(!(e>0))return [...Tr];let t=Tr.filter(n=>n.ms>0&&n.ms0?[Tr[0],...t]:[]}setTheme(e){this.theme=e,this.settingsDialog.setTheme(e);}isOpen(){return this.el!=null}contains(e){return e!=null&&(this.isOwnChrome(e)||this.settingsDialog.contains(e))}open(e,t,n,o){this.close();let i=e[0];if(!i)return;A0(),this.onClose=o??null;let s=this.theme,a=e.length>1,l=i.schema(),c=vI(e),d=v=>yI(e,v),u=v=>e.every(v),h=(v,k,x,E)=>this.colorButton(v,k,d(x),I=>n.patch({[E]:I}),void 0,wI(e,x)),p=a||l.textIsContent===true||!c.has("text.value"),m=document.createElement("div");m.className="vela-dpop",m.style.cssText=`position:absolute;z-index:22;background:${s.background};border:1px solid var(--vela-border);border-radius:var(--vela-radius-lg);box-shadow:var(--vela-shadow);color:${s.textColor};font:var(--vela-font-size-md) ${s.fontFamily};display:flex;flex-direction:column;pointer-events:auto;overflow:hidden;`,Be(m,s),m.addEventListener("pointerdown",v=>{v.target?.closest(".vela-select-trigger, .vela-color-field")||Me();});let f=document.createElement("div");if(f.style.cssText="display:flex;align-items:center;gap:2px;padding:4px;",f.appendChild(this.dragHandle()),c.has("glyph")){let v=d(k=>k.glyph??bi[0]);f.appendChild(this.dropdown("Icon",bi,v,k=>zI(k),k=>n.patch({glyph:k})));}if(c.has("size")){let v=d(k=>k.size??"normal");f.appendChild(this.dropdown("Icon size",Fa,v,k=>WI(k),k=>n.patch({size:k}),{label:zs}));}if(c.has("magnifier.timeframe")&&u(v=>v instanceof ht)){let v=x=>x,k=this.lowerTimeframeOptions();k.length>0&&f.appendChild(this.dropdown("Lower timeframe",k.map(x=>x.value),d(x=>v(x).magnifier.timeframe),()=>"",x=>n.patch({"magnifier.timeframe":x}),{label:x=>xi(String(x)),labelInTrigger:true})),f.appendChild(h("Up candles",or,x=>v(x).magnifier.upColor||s.upColor,"magnifier.upColor")),f.appendChild(h("Down candles",or,x=>v(x).magnifier.downColor||s.downColor,"magnifier.downColor"));}if(c.has("style.lineColor")&&f.appendChild(h("Line color",Kr,v=>v.style.lineColor||(v instanceof ht?Ye(this.theme.background):_),"style.lineColor")),c.has("style.lineWidth")){let v=I=>I.schema().fields.find(N=>N.path==="style.lineWidth"),k=v(i),x=d(I=>I.style.lineWidth);u(I=>{let N=v(I);return N?.kind==="number"&&(N.min??1)>1})&&k?.kind==="number"?f.appendChild(this.widthInput("Line width",x,k.min??1,k.max??60,k.step??1,I=>n.patch({"style.lineWidth":I}))):f.appendChild(this.dropdown("Line width",[1,2,3,4],x,I=>ei(I,"solid"),I=>n.patch({"style.lineWidth":I}),{label:I=>`${I}px`,labelInTrigger:true}));}c.has("style.lineStyle")&&f.appendChild(this.dropdown("Line style",rt.map(v=>v.value),d(v=>v.style.lineStyle),v=>ei(2,v),v=>n.patch({"style.lineStyle":v}),{label:Ws})),c.has("style.fillColor")&&f.appendChild(h("Fill",or,v=>Et(v,this.theme)??v.style.fillColor??_,"style.fillColor"));let g=c.has("frvp.rows")&&i instanceof gt,b=c.has("riskPercent")&&u(v=>v instanceof yt);if(b){let v=k=>k;f.appendChild(h("Profit zone",or,k=>v(k).profitColor,"profitColor")),f.appendChild(h("Loss zone",or,k=>v(k).lossColor,"lossColor"));}let y=v=>v.reg;if(c.has("reg.midColor")&&u(v=>y(v)!=null)){let v=x=>y(x),k=rt.map(x=>x.value);f.appendChild(h("Midline color",Kr,x=>v(x).midColor,"reg.midColor")),f.appendChild(this.dropdown("Midline style",k,d(x=>v(x).midStyle),x=>ei(2,x),x=>n.patch({"reg.midStyle":x}),{label:Ws})),f.appendChild(h("Upper line color",Kr,x=>v(x).upperColor,"reg.upperColor")),f.appendChild(this.dropdown("Upper line style",k,d(x=>v(x).upperStyle),x=>ei(2,x),x=>n.patch({"reg.upperStyle":x}),{label:Ws})),f.appendChild(h("Lower line color",Kr,x=>v(x).lowerColor,"reg.lowerColor")),f.appendChild(this.dropdown("Lower line style",k,d(x=>v(x).lowerStyle),x=>ei(2,x),x=>n.patch({"reg.lowerStyle":x}),{label:Ws})),f.appendChild(h("Upper fill",or,x=>v(x).upperFill,"reg.upperFill")),f.appendChild(h("Lower fill",or,x=>v(x).lowerFill,"reg.lowerFill")),f.appendChild(this.toggle("Show R\xB2",OI,d(x=>v(x).showR2),x=>n.patch({"reg.showR2":x})));}let w=v=>v.vwap;if(c.has("vwap.midColor")&&u(v=>w(v)!=null)){let v=E=>w(E),k=rt.map(E=>E.value),x=[.5,1,1.5,2,2.5,3,4,5];f.appendChild(h("VWAP color",Kr,E=>v(E).midColor,"vwap.midColor")),f.appendChild(this.dropdown("VWAP style",k,d(E=>v(E).midStyle),E=>ei(2,E),E=>n.patch({"vwap.midStyle":E}),{label:Ws})),f.appendChild(this.dropdown("Band multiplier",x,d(E=>v(E).multiplier),()=>NI,E=>n.patch({"vwap.multiplier":E}),{label:E=>`${E}\u03C3`,labelInTrigger:true})),f.appendChild(h("Upper band color",Kr,E=>v(E).upperColor,"vwap.upperColor")),f.appendChild(h("Lower band color",Kr,E=>v(E).lowerColor,"vwap.lowerColor")),f.appendChild(h("Band fill",or,E=>v(E).bandFill,"vwap.bandFill"));}if(c.has("maxCurvature")){let v=d(k=>k.maxCurvature??24);f.appendChild(this.dropdown("Max curvature",eu,v,()=>FI,k=>n.patch({maxCurvature:k}),{label:k=>`n=${k}`,labelInTrigger:true}));}if(c.has("mach")){let v=d(k=>k.mach??2);f.appendChild(this.dropdown("Mach number",nu,v,()=>BI,k=>n.patch({mach:k}),{label:k=>`M=${k}`,labelInTrigger:true}));}if(c.has("waveCount")){let v=d(k=>k.waveCount??6);f.appendChild(this.dropdown("Waves",tu,v,()=>VI,k=>n.patch({waveCount:k}),{label:k=>`${k}`,labelInTrigger:true}));}let C=v=>v;c.has("showPrice")&&f.appendChild(this.toggle("Show price",CI,d(v=>C(v).showPrice!==false),v=>n.patch({showPrice:v}))),c.has("showDate")&&f.appendChild(this.toggle("Show date",SI,d(v=>C(v).showDate!==false),v=>n.patch({showDate:v}))),c.has("text.color")&&p&&f.appendChild(h("Text color",dp,v=>v.text?.color||s.textColor,"text.color")),c.has("text.size")&&p&&f.appendChild(this.dropdown("Text size",Dt.map(v=>v.value),d(v=>v.text?.size??"normal"),v=>O0(v),v=>n.patch({"text.size":v}),{label:zs}));let M=!a&&c.has("text.value");c.has("text.bold")&&!M&&f.appendChild(this.toggle("Bold",R0,d(v=>!!v.text?.bold),v=>n.patch({"text.bold":v}))),c.has("text.italic")&&!M&&f.appendChild(this.toggle("Italic",D0,d(v=>!!v.text?.italic),v=>n.patch({"text.italic":v}))),M&&f.appendChild(this.iconBtn("Text",dp,()=>this.toggleTextPanel(i,n,!p)));let S=i.editableLevels();if(S&&u(v=>v.editableLevels()!=null&&!(v instanceof dt))){let v=x=>x,k=Dt.map(x=>x.value);f.appendChild(this.dropdown("Numbers size",k,d(x=>v(x).numbersSize??"small"),x=>$I(x),x=>n.patch({numbersSize:x}),{label:zs})),f.appendChild(this.dropdown("Label size",k,d(x=>v(x).labelsSize??"normal"),x=>O0(x),x=>n.patch({labelsSize:x}),{label:zs}));}f.appendChild(this.divider()),!a&&g&&f.appendChild(this.iconBtn("Settings",up,()=>this.settingsDialog.open(i,n,"frvp"))),!a&&b&&f.appendChild(this.iconBtn("Position size",up,()=>this.settingsDialog.open(i,n,"position"))),!a&&S&&f.appendChild(this.iconBtn("Levels",up,()=>this.settingsDialog.open(i,n,"levels"))),f.appendChild(this.toggle("Lock",TI,d(v=>v.locked),v=>n.setLocked(v),kI));let L=this.iconBtn("Delete",EI,()=>n.remove());L.style.color="var(--vela-danger)",f.appendChild(L),f.appendChild(this.kebabButton(n)),m.append(f),this.host.appendChild(m),this.el=m,m.addEventListener("mouseover",v=>{let k=v.target.closest("[data-tip]");k?this.showTip(k):this.hideTip();}),m.addEventListener("mouseleave",()=>this.hideTip()),this.position(t),setTimeout(()=>document.addEventListener("pointerdown",this.onOutside),0);}close(){document.removeEventListener("pointerdown",this.onOutside),this.closeColorPopover(),this.closeMenu(),this.hideTip(),this.settingsDialog.close(),this.el?.remove(),this.el=null,this.textPanel=null,this.onClose=null;}destroy(){this.close();}isOwnChrome(e){if(this.el?.contains(e)||this.colorPop?.el.contains(e)||this.menuPop?.el.contains(e))return true;let t=e instanceof Element?e:e.parentElement;if(!t)return false;let n=t.closest(".vela-popover");return n!=null&&this.host.contains(n)}toggleTextPanel(e,t,n){if(this.textPanel){this.textPanel.remove(),this.textPanel=null,this.reposition();return}let o=e.text,i=document.createElement("div");i.style.cssText="padding:6px;border-top:1px solid var(--vela-border);display:flex;flex-direction:column;gap:4px;";let s=new zr({value:o?.value??"",rows:1,size:"sm",autoGrow:true,maxLines:4,placeholder:"Label\u2026",onChange:l=>{t.patch({"text.value":l}),this.reposition();}});s.el.style.minWidth="220px",s.input.addEventListener("input",()=>{t.patch({"text.value":s.input.value}),this.reposition();}),s.input.addEventListener("keydown",l=>{if(l.stopPropagation(),l.key==="Escape"){l.preventDefault();let c=this.onClose;this.close(),c?.();}});let a=document.createElement("div");a.style.cssText="display:flex;align-items:center;justify-content:flex-start;gap:0;transform:scale(0.8);transform-origin:left center;",n&&a.append(this.colorButton("Text color",dp,o?.color||this.theme.textColor,l=>t.patch({"text.color":l}),14),this.dropdown("Text size",Dt.map(l=>l.value),o?.size??"normal",l=>GI(l),l=>t.patch({"text.size":l}),{label:zs})),a.append(this.toggle("Bold",R0,!!o?.bold,l=>t.patch({"text.bold":l})),this.toggle("Italic",D0,!!o?.italic,l=>t.patch({"text.italic":l}))),i.append(s.el,a),this.el?.appendChild(i),this.textPanel=i,this.reposition(),s.input.focus();}position(e){let t=this.el;if(!t)return;let n=this.host.getBoundingClientRect(),o=t.offsetWidth,i=t.offsetHeight,s=10,a=n.width/2-o/2,l=12;e&&(a=e.x+e.w/2-o/2,l=e.y-i-s,l<4&&(l=e.y+e.h+s)),t.style.left=`${Math.max(4,Math.min(a,n.width-o-4))}px`,t.style.top=`${Math.max(4,Math.min(l,n.height-i-4))}px`;}reposition(){let e=this.el;if(!e)return;let t=this.host.getBoundingClientRect(),n=e.offsetWidth,o=e.offsetHeight,i=parseFloat(e.style.left)||0,s=parseFloat(e.style.top)||0;e.style.left=`${Math.max(4,Math.min(i,t.width-n-4))}px`,e.style.top=`${Math.max(4,Math.min(s,t.height-o-4))}px`;}base(e){let t=document.createElement("button");return t.type="button",t.dataset.tip=e,t.className="vela-dpop-btn",t.style.cssText=`width:${ir}px;height:${ir}px;display:flex;align-items:center;justify-content:center;cursor:pointer;color:inherit;border:none;border-radius:5px;padding:0;`,t}iconBtn(e,t,n){let o=this.base(e);return o.innerHTML=On(t),o.addEventListener("click",n),o}dragHandle(){let e=document.createElement("button");return e.type="button",e.className="vela-dpop-grip",e.style.cssText=`width:${ir}px;height:${ir}px;display:flex;align-items:center;justify-content:center;background:transparent;border:none;padding:0;cursor:grab;touch-action:none;color:var(--vela-fg-faint);`,e.innerHTML=On(PI),e.addEventListener("pointerdown",t=>{let n=this.el;if(!n||t.button!==0)return;t.preventDefault(),t.stopPropagation(),this.hideTip(),this.closeColorPopover(),this.closeMenu();let o=this.host.getBoundingClientRect(),i=t.clientX,s=t.clientY,a=parseFloat(n.style.left)||0,l=parseFloat(n.style.top)||0;e.style.cursor="grabbing";try{e.setPointerCapture(t.pointerId);}catch{}let c=u=>{let h=n.offsetWidth,p=n.offsetHeight,m=a+(u.clientX-i),f=l+(u.clientY-s);n.style.left=`${Math.max(4,Math.min(m,o.width-h-4))}px`,n.style.top=`${Math.max(4,Math.min(f,o.height-p-4))}px`;},d=()=>{e.style.cursor="grab",window.removeEventListener("pointermove",c),window.removeEventListener("pointerup",d),window.removeEventListener("pointercancel",d);};window.addEventListener("pointermove",c),window.addEventListener("pointerup",d),window.addEventListener("pointercancel",d);}),e}kebabButton(e){let t=this.base("More");return t.innerHTML=On(II),t.addEventListener("pointerdown",n=>n.stopPropagation()),t.addEventListener("click",n=>{if(n.stopPropagation(),this.menuOwner===t){this.closeMenu();return}this.openActionMenu(t,[{icon:AI,label:"Duplicate",onClick:()=>e.duplicate()},{icon:LI,label:"Bring to front",onClick:()=>e.reorder("front")},{icon:MI,label:"Send to back",onClick:()=>e.reorder("back")},{icon:RI,label:"Reset settings",onClick:()=>e.resetSettings()}]);}),t}hostFloat(e,t){let n=this.theme,o=new qe({trigger:e,host:this.host,theme:n,position:"absolute",boundary:this.host,boundaryInset:4,viewportInset:0,gap:6,align:t.align??"start",zIndex:t.zIndex,onClose:()=>{this.menuPop===o&&(this.menuPop=null,this.menuOwner=null),this.colorPop===o&&(this.colorPop=null,this.colorOwner=null),t.onClose?.();}}),i=o.el;return i.style.background=n.background,i.style.border="1px solid var(--vela-border)",i.style.borderRadius="var(--vela-radius-lg)",i.style.boxShadow="var(--vela-shadow)",i.style.padding=t.padding,i.style.display="flex",i.style.flexDirection="column",i.style.gap="1px",i.style.color=n.textColor,i.style.font=`var(--vela-font-size-md) ${n.fontFamily}`,i.style.pointerEvents="auto",t.fill(i,o),o.show(),o}openMagnifierTimeframeMenu(e,t,n){A0(),Me();let o=this.lowerTimeframeOptions(),i=document.createElement("div");i.style.cssText=`position:absolute;left:${e.x}px;top:${e.y}px;width:${e.w}px;height:${e.h}px;pointer-events:none;`,this.host.appendChild(i),this.menuPop=this.hostFloat(i,{zIndex:26,padding:"4px",onClose:()=>i.remove(),fill:(s,a)=>{if(o.length===0){let l=document.createElement("div");l.style.cssText="padding:6px 10px;opacity:0.65;white-space:nowrap;",l.textContent="No lower timeframe available",s.appendChild(l);return}for(let l of o){let c=document.createElement("button");c.type="button",c.className="vela-dpop-item",c.dataset.active=l.value===t?"1":"0",c.style.cssText="display:flex;align-items:center;min-width:88px;padding:5px 10px;border:none;border-radius:5px;color:inherit;cursor:pointer;text-align:left;font:inherit;font-variant-numeric:tabular-nums;",c.textContent=l.label,c.addEventListener("click",d=>{d.stopPropagation(),a.hide(),n(l.value);}),s.appendChild(c);}}}),this.menuOwner=i;}openActionMenu(e,t){this.menuPop=this.hostFloat(e,{align:"end",zIndex:26,padding:"4px",fill:(n,o)=>{for(let i of t){let s=document.createElement("button");s.type="button",s.className="vela-dpop-item",s.style.cssText="display:flex;align-items:center;gap:9px;min-width:150px;padding:6px 9px;border:none;border-radius:5px;color:inherit;cursor:pointer;text-align:left;font:inherit;";let a=document.createElement("span");a.style.cssText="display:flex;flex:none;width:20px;justify-content:center;",a.innerHTML=On(i.icon,18);let l=document.createElement("span");l.textContent=i.label,l.style.cssText="flex:1;",s.append(a,l),s.addEventListener("click",c=>{c.stopPropagation(),o.hide(),i.onClick();}),n.appendChild(s);}}}),this.menuOwner=e;}showTip(e){let t=e.dataset.tip;if(!t){this.hideTip();return}let n=this.theme;if(!this.tipEl){let p=document.createElement("div");p.style.cssText=`position:absolute;z-index:27;pointer-events:none;white-space:nowrap;background:${n.textColor};color:${n.background};padding:3px 7px;border-radius:5px;font:var(--vela-font-size-sm) ${n.fontFamily};box-shadow:var(--vela-shadow);`,this.host.appendChild(p),this.tipEl=p;}let o=this.tipEl;o.textContent=t;let i=this.host.getBoundingClientRect(),s=e.getBoundingClientRect(),a=o.offsetWidth,l=o.offsetHeight,c=6,d=s.left-i.left+s.width/2-a/2;d=Math.max(4,Math.min(d,i.width-a-4));let u=s.top-i.top-l-c,h=u>=4?u:s.bottom-i.top+c;o.style.left=`${Math.round(d)}px`,o.style.top=`${Math.round(h)}px`;}hideTip(){this.tipEl?.remove(),this.tipEl=null;}toggle(e,t,n,o,i){let s=this.base(e),a=c=>{s.dataset.active=c===Gt?"mixed":c?"1":"0",s.innerHTML=On(i&&c===false?i:t);};a(n);let l=n;return s.addEventListener("click",()=>{l=l===Gt?true:!l,a(l),o(l);}),s}widthInput(e,t,n,o,i,s){let a=new Hr({value:t===Gt?n:t,min:n,max:o,step:i,integer:i>=1,size:"sm",fill:false,compact:true,commit:"blur",title:e,onChange:s});return t===Gt&&(a.input.value="",a.input.placeholder="\u2014"),a.el.dataset.tip=e,HI(a.el),a.el}dropdown(e,t,n,o,i,s={}){let a=this.base(e);a.style.width="auto",a.style.minWidth=`${ir}px`,a.style.padding="0 4px",a.style.gap="2px";let l=n,c=d=>{if(a.replaceChildren(),d===Gt){let p=document.createElement("span");p.textContent="\u2014",p.style.cssText="min-width:18px;text-align:center;opacity:0.85;",a.appendChild(p);}let u=d===Gt?"":o(d);if(u){let p=document.createElement("span");p.style.cssText="display:flex;",p.innerHTML=On(u),a.appendChild(p);}if(s.label&&s.labelInTrigger&&d!==Gt){let p=document.createElement("span");p.textContent=s.label(d),p.style.cssText="font-size:11px;opacity:0.85;font-variant-numeric:tabular-nums;",a.appendChild(p);}let h=document.createElement("span");h.style.cssText="display:flex;opacity:0.55;",h.innerHTML=On(DI,12),a.appendChild(h);};return c(l),a.addEventListener("pointerdown",d=>d.stopPropagation()),a.addEventListener("click",d=>{if(d.stopPropagation(),this.menuOwner===a){this.closeMenu();return}this.openMenu(a,t,l,o,s.label,u=>{l=u,c(u),i(u);});}),a}openMenu(e,t,n,o,i,s){this.menuPop=this.hostFloat(e,{zIndex:26,padding:"4px",fill:(a,l)=>{for(let c of t){let d=c===n,u=document.createElement("button");u.type="button",u.className="vela-dpop-item",u.dataset.active=d?"1":"0",u.style.cssText=`display:flex;align-items:center;gap:8px;${i?"min-width:118px;":""}padding:5px 8px;border:none;border-radius:5px;color:inherit;cursor:pointer;text-align:left;font:inherit;`;let h=o(c);if(h){let p=document.createElement("span");p.style.cssText="display:flex;flex:none;width:22px;justify-content:center;",p.innerHTML=On(h,18),u.appendChild(p);}if(i){let p=document.createElement("span");p.textContent=i(c),p.style.cssText="flex:1;font-variant-numeric:tabular-nums;",u.appendChild(p);}u.addEventListener("click",p=>{p.stopPropagation(),l.hide(),s(c);}),a.appendChild(u);}}}),this.menuOwner=e;}closeMenu(){this.menuPop?.hide();}colorButton(e,t,n,o,i=17,s=[]){let a=document.createElement("button");a.type="button",a.dataset.tip=e,a.className="vela-dpop-btn",a.style.cssText=`position:relative;width:${ir}px;height:${ir}px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;cursor:pointer;border-radius:5px;border:none;color:inherit;padding:0;`;let l=document.createElement("span");l.style.cssText="display:flex;",l.innerHTML=On(t,i);let c=document.createElement("span");c.style.cssText=`display:block;height:3px;width:${Math.round(i*.85)}px;border-radius:2px;background:${n===Gt?_I(s):n};`,a.append(l,c);let d=n;return a.addEventListener("pointerdown",u=>u.stopPropagation()),a.addEventListener("click",u=>{u.stopPropagation();let h=d===Gt?s[0]??_:d;this.toggleColorPopover(a,h,d===Gt?s:[],p=>{d=p,c.style.background=p,o(p);});}),a}toggleColorPopover(e,t,n,o){if(this.colorOwner===e){this.closeColorPopover();return}this.openColorPopover(e,t,n,o);}openColorPopover(e,t,n,o){let i=this.theme;this.colorPop=this.hostFloat(e,{zIndex:25,padding:"10px",fill:(s,a)=>{if(n.length>1){let l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:6px;padding-bottom:9px;border-bottom:1px solid var(--vela-border);";let c=document.createElement("span");c.textContent="In use",c.style.cssText="font:var(--vela-font-size-sm) inherit;opacity:0.7;margin-right:2px;",l.appendChild(c);for(let d of n){let u=document.createElement("button");u.type="button",u.dataset.tip=d,u.style.cssText=`width:18px;height:18px;border-radius:4px;border:1px solid var(--vela-border-strong);cursor:pointer;background:${d};padding:0;`,u.addEventListener("click",h=>{h.stopPropagation(),a.hide(),o(d);}),l.appendChild(u);}s.appendChild(l);}s.appendChild(ws(t,i,o));}}),this.colorOwner=e;}closeColorPopover(){this.colorPop?.hide();}divider(){let e=document.createElement("div");return e.style.cssText="width:1px;height:18px;margin:0 3px;background:var(--vela-border);",e}},Kr=ee("brush"),or=ee("bucket"),dp=ee("type"),CI=ee("price-delta"),SI=ee("date-delta"),TI=ee("lock"),kI=ee("unlock"),LI=ee("bring-front"),MI=ee("send-back"),EI=ee("trash"),R0=ee("bold"),D0=ee("italic"),PI=ee("grip"),II=ee("kebab"),AI=ee("clone"),RI=ee("reset"),up=ee("gear"),DI=ee("chevron-down"),OI=ee("r-squared"),NI=ee("bands"),FI=ee("dedekind"),VI=ee("sonic"),BI=ee("supersonic");function _I(r){let e=r.length>1?r:["var(--vela-fg-faint)","var(--vela-fg-muted)"],t=100/e.length;return `linear-gradient(90deg,${e.map((o,i)=>`${o} ${i*t}% ${(i+1)*t}%`).join(",")})`}function ei(r,e){let t=e==="dashed"?"5,3":e==="dotted"?"1.5,3":"";return B(``)}function HI(r){r.addEventListener("keydown",e=>e.stopPropagation());}function Gs(r,e,t=17,n=""){return jd(`${r}`)}function zI(r){return Gs(String(r),15)}function WI(r){return Gs("\u25CF",(hp[String(r)]??13)+4)}function GI(r){return Gs(String(r).charAt(0).toUpperCase(),15)}var hp={small:10,normal:13,large:16,huge:20};function $I(r){return Gs("12",(hp[String(r)]??13)-1,16.5,'font-weight="600"')}function O0(r){return Gs("T",(hp[String(r)]??13)+2)}function N0(r){return r.charAt(0).toUpperCase()+r.slice(1)}function zs(r){return Dt.find(e=>e.value===r)?.label??N0(String(r))}function Ws(r){return rt.find(e=>e.value===r)?.label??N0(String(r))}function On(r,e=xI){return r.replace("{},i=()=>{},s=()=>{},a=()=>{},l=()=>{},c={}){this.host=e;this.theme=t;this.onArm=n;this.onMagnet=o;this.onMeasure=i;this.onEraser=s;this.onToggleFavorite=a;this.onStayMode=l;this.def={groups:[]};this.active=null;this.lastUsed=new Map;this.favorites=new Set;this.shortcuts=new Map;this.starEls=new Map;this.flyout=null;this.flyoutOwnerId=null;this.flyoutCell=null;this.groupCells=new Map;this.groupIcons=new Map;this.cursorBtn=null;this.magnetCell=null;this.magnetIcon=null;this.magnetMode="off";this.lastMagnetOn="weak";this.measureBtn=null;this.measureActive=false;this.eraserBtn=null;this.eraserActive=false;this.stayBtn=null;this.stayActive=false;this.syncBtn=null;this.syncActive=false;this.collapseBtn=null;this.collapsed=false;this.visible=false;this.tipText=new WeakMap;this.tipDisposers=[];this.onOutside=e=>{let t=e.target;this.flyout&&!this.flyout.contains(t)&&!this.root.contains(t)&&this.closeFlyout();};this.borderOverride=c.borderColor??null,this.width=c.width??pp,this.dock=c.dock??"absolute",this.onCollapse=c.onCollapse??(()=>{}),this.onDrawingsSync=c.onDrawingsSync??null,UI(),this.root=document.createElement("div"),this.root.className="vela-dtb",this.styleRoot(),e.appendChild(this.root);}get borderColor(){return this.borderOverride??this.theme.borderColor}styleRoot(){let e=this.theme;Be(this.root,e);let t=this.collapsed?mp:this.width;this.root.dataset.collapsed=this.collapsed?"1":"";let n=this.dock==="absolute"?`position:absolute;left:0;top:0;height:100%;width:${t}px;z-index:21;`:`position:relative;height:100%;width:${t}px;flex:none;`;this.root.style.cssText=n+`display:${this.visible?"flex":"none"};flex-direction:column;gap:4px;padding:6px 0;box-sizing:border-box;background:${e.background};border-right:1px solid ${this.borderColor};color:var(--vela-fg-muted);pointer-events:auto;overflow-y:auto;overflow-x:hidden;`;}setDefinition(e){this.def=e;for(let t of e.groups){let n=t.tools[0];n&&!this.lastUsed.has(t.id)&&this.lastUsed.set(t.id,n.type);}this.rebuild();}setFavorites(e){this.favorites=new Set(e);for(let[t,n]of this.starEls)this.paintStar(n,t);}setShortcuts(e){this.shortcuts=new Map(Object.entries(e));}paintStar(e,t){let n=this.favorites.has(t);e.classList.toggle("vela-fav",n),e.setAttribute("aria-label",n?"Remove from favorites":"Add to favorites"),e.setAttribute("aria-pressed",n?"true":"false"),e.innerHTML=yd(n?nA:tA);}setVisible(e){this.visible=e,this.root.style.display=e?"flex":"none";}setActiveTool(e){if(this.active=e,e){let t=this.def.groups.find(n=>n.tools.some(o=>o.type===e));t&&(this.lastUsed.set(t.id,e),this.paintGroupIcon(t));}this.closeFlyout(),this.highlight();}setTheme(e){this.theme=e,this.styleRoot(),this.rebuild();}destroy(){this.closeFlyout();for(let e of this.tipDisposers.splice(0))e();this.root.remove();}rebuild(){for(let e of this.tipDisposers.splice(0))e();this.root.replaceChildren(),this.groupCells.clear(),this.groupIcons.clear(),this.cursorBtn=this.makeButton(YI,"Cursor",()=>this.onCursorClick()),this.root.appendChild(this.cursorBtn),this.def.groups.length>0&&this.root.appendChild(this.divider());for(let e of this.def.groups){let t=this.makeGroupCell(e);this.root.appendChild(t),this.paintGroupIcon(e);}this.root.appendChild(this.divider()),this.measureBtn=this.makeButton(KI,"Measure",()=>this.onMeasure()),this.root.appendChild(this.measureBtn),this.eraserBtn=this.makeButton(QI,"Eraser (click/drag to delete)",()=>this.onEraser()),this.root.appendChild(this.eraserBtn),this.root.appendChild(this.makeMagnetCell()),this.stayBtn=this.makeButton(qI,"Stay in drawing mode",()=>this.toggleStay()),this.root.appendChild(this.stayBtn),this.onDrawingsSync&&(this.syncBtn=this.makeButton(ZI,"Sync drawings on all charts",()=>this.toggleDrawingsSync()),this.root.appendChild(this.syncBtn)),this.collapseBtn=this.makeButton(B0,"Collapse toolbar",()=>this.toggleCollapsed()),this.collapseBtn.classList.add("vela-dtb-collapse"),this.root.appendChild(this.collapseBtn),this.paintMeasure(),this.paintEraser(),this.paintMagnet(),this.paintStay(),this.paintDrawingsSync(),this.paintCollapse(),this.highlight();}toggleCollapsed(){this.collapsed=!this.collapsed,this.closeFlyout(),this.styleRoot(),this.paintCollapse(),this.onCollapse(this.collapsed);}paintCollapse(){let e=this.collapseBtn;if(!e)return;let t=this.collapsed?"Expand toolbar":"Collapse toolbar";e.innerHTML=vd(this.collapsed?XI:B0,12),e.setAttribute("aria-label",t),this.tipText.set(e,t);}makeCell(e,t){let n=document.createElement("div");n.className="vela-dtb-cell";let o=document.createElement("button");o.type="button",o.className="vela-dtb-icon",o.setAttribute("aria-label",e),t.iconSvg&&(o.innerHTML=vd(t.iconSvg)),o.addEventListener("click",t.onIcon),n.appendChild(o);let i=null;if(t.multi&&t.onArrow){let s=t.onArrow;i=document.createElement("button"),i.type="button",i.className="vela-dtb-arrow",i.setAttribute("aria-label",`${e} \u2014 more`),i.innerHTML=rA(JI),i.addEventListener("click",a=>{a.stopPropagation(),s();}),n.appendChild(i);}return this.tipDisposers.push(tn(n,{host:this.host,theme:()=>this.theme,text:()=>this.tipText.get(n)??e,placement:"right"})),{cell:n,icon:o,arrow:i}}makeGroupCell(e){let t=e.tools.length>1,{cell:n,icon:o}=this.makeCell(e.label,{multi:t,onIcon:()=>this.onGroupIconClick(e),onArrow:t?()=>this.onArrowClick(e):void 0});return this.groupCells.set(e.id,n),this.groupIcons.set(e.id,o),n}makeMagnetCell(){let{cell:e,icon:t}=this.makeCell("Magnet snap",{iconSvg:jI,multi:true,onIcon:()=>this.toggleMagnet(),onArrow:()=>this.onMagnetArrowClick()});return this.magnetCell=e,this.magnetIcon=t,e}onCursorClick(){this.measureActive&&this.onMeasure(),this.eraserActive&&this.onEraser(),this.onArm(null);}onGroupIconClick(e){let t=this.lastUsed.get(e.id)??e.tools[0]?.type;t&&this.onArm(t);}onArrowClick(e){let t=this.flyoutOwnerId===e.id;this.closeFlyout(),t||this.openGroupFlyout(e);}toggleMagnet(){this.applyMagnet(this.magnetMode==="off"?this.lastMagnetOn:"off");}onMagnetArrowClick(){let e=this.flyoutOwnerId===F0;this.closeFlyout(),e||this.openMagnetFlyout();}applyMagnet(e){this.magnetMode=e,e!=="off"&&(this.lastMagnetOn=e),this.onMagnet(e),this.paintMagnet(),this.highlight();}setMagnetMode(e){this.magnetMode=e,e!=="off"&&(this.lastMagnetOn=e),this.paintMagnet(),this.highlight();}setMeasureActive(e){this.measureActive=e,this.paintMeasure(),this.highlight();}paintMeasure(){let e=this.measureBtn;e&&(e.dataset.active=this.measureActive?"1":"");}setEraserActive(e){this.eraserActive=e,this.paintEraser(),this.highlight();}paintEraser(){let e=this.eraserBtn;e&&(e.dataset.active=this.eraserActive?"1":"");}paintMagnet(){let e=this.magnetCell,t=this.magnetIcon;if(!e||!t)return;let n=this.magnetMode==="off"?"Off":this.magnetMode==="weak"?"Weak":"Strong";this.tipText.set(e,`Magnet snap: ${n}`);let o=this.magnetMode!=="off";e.dataset.active=o?"1":"",t.style.opacity=o?"1":"0.5";}toggleStay(){this.stayActive=!this.stayActive,this.onStayMode(this.stayActive),this.paintStay();}setStayMode(e){this.stayActive=e,this.paintStay();}paintStay(){let e=this.stayBtn;e&&(e.dataset.active=this.stayActive?"1":"",e.style.opacity=this.stayActive?"1":"0.5");}toggleDrawingsSync(){this.syncActive=!this.syncActive,this.onDrawingsSync?.(this.syncActive),this.paintDrawingsSync();}setDrawingsSyncMode(e){this.syncActive=e,this.paintDrawingsSync();}paintDrawingsSync(){let e=this.syncBtn;e&&(e.dataset.active=this.syncActive?"1":"",e.style.opacity=this.syncActive?"1":"0.5");}beginFlyout(e,t){let n=this.theme,o=document.createElement("div");o.className="vela-dtb-flyout",o.style.cssText=`position:absolute;z-index:23;display:flex;flex-direction:column;gap:2px;padding:4px;border-radius:0 8px 8px 0;background:var(--vela-surface-elev);border:1px solid ${this.borderColor};border-left:none;box-shadow:var(--vela-shadow);pointer-events:auto;overflow-y:auto;overscroll-behavior:contain;`,Be(o,n),this.host.appendChild(o);let i=t.getBoundingClientRect(),s=this.root.getBoundingClientRect(),a=this.host.getBoundingClientRect(),l=i.top-a.top;return o.style.left=`${s.right-a.left-1}px`,o.style.top=`${l}px`,o.style.maxHeight=`${Math.max(120,a.height-l-8)}px`,this.flyout=o,this.flyoutOwnerId=e,this.flyoutCell=t,t.classList.add("vela-open"),this.highlight(),document.addEventListener("pointerdown",this.onOutside),o}openGroupFlyout(e){let t=this.groupCells.get(e.id);if(!t)return;let n=this.beginFlyout(e.id,t),o=e.sections??[{label:"",tools:e.tools}];for(let i=0;i0&&n.appendChild(this.flyoutSeparator()),n.appendChild(this.flyoutHeader(s.label)));for(let a of s.tools)n.appendChild(this.makeFlyoutItem({icon:a.icon,label:a.label,selected:a.type===this.active,shortcut:this.shortcuts.get(a.type),onSelect:()=>this.onArm(a.type),favorite:{type:a.type,toggle:()=>this.onToggleFavorite(a.type,!this.favorites.has(a.type))}}));}}openMagnetFlyout(){let e=this.magnetCell;if(!e)return;let t=this.beginFlyout(F0,e);t.appendChild(this.flyoutHeader("Magnet"));let n=[["off","Off"],["weak","Weak"],["strong","Strong"]];for(let[o,i]of n)t.appendChild(this.makeFlyoutItem({label:i,selected:o===this.magnetMode,onSelect:()=>{this.applyMagnet(o),this.closeFlyout();}}));}flyoutHeader(e){let t=this.theme,n=document.createElement("div");return n.textContent=e.toUpperCase(),n.style.cssText=`padding:6px 12px 2px 8px;font:var(--vela-font-size-sm) ${t.fontFamily};font-weight:600;letter-spacing:0.04em;color:var(--vela-fg-muted);user-select:none;`,n}flyoutSeparator(){let e=document.createElement("div");return e.style.cssText=`height:1px;margin:4px 8px;background:${this.borderColor};`,e}makeFlyoutItem(e){let t=this.theme,n=document.createElement("button");if(n.type="button",n.className="vela-dtb-item",n.setAttribute("aria-label",e.label),n.style.cssText=`display:flex;align-items:center;gap:8px;padding:5px 10px 5px 8px;cursor:pointer;color:${t.textColor};border-radius:var(--vela-radius-sm);font:13px ${t.fontFamily};white-space:nowrap;min-width:148px;`,e.icon){let s=document.createElement("span");s.style.cssText="width:18px;height:18px;display:flex;align-items:center;justify-content:center;flex:none;",s.innerHTML=yd(e.icon),n.appendChild(s);}let o=document.createElement("span");o.textContent=e.label,o.style.cssText="flex:1 1 auto;text-align:left;",n.appendChild(o);let i=document.createElement("span");if(i.style.cssText="width:14px;height:14px;display:flex;align-items:center;justify-content:center;flex:none;",e.selected&&(i.innerHTML=yd(eA)),n.appendChild(i),e.shortcut){let s=document.createElement("span");s.className="vela-dtb-hint",s.textContent=e.shortcut,s.style.cssText=`flex:none;font:var(--vela-font-size-md) ${t.fontFamily};color:var(--vela-fg-muted);`,n.appendChild(s);}if(e.favorite){let s=document.createElement("span");s.className="vela-dtb-star",s.setAttribute("role","button"),this.paintStar(s,e.favorite.type),this.starEls.set(e.favorite.type,s);for(let a of ["pointerdown","pointerup","mousedown","mouseup"])s.addEventListener(a,l=>l.stopPropagation());s.addEventListener("click",a=>{a.stopPropagation(),a.preventDefault(),e.favorite.toggle();}),n.appendChild(s);}return n.addEventListener("click",s=>{s.stopPropagation(),e.onSelect();}),n}closeFlyout(){this.starEls.clear(),this.flyout&&(this.flyout.remove(),this.flyout=null,this.flyoutCell?.classList.remove("vela-open"),this.flyoutCell=null,this.flyoutOwnerId=null,document.removeEventListener("pointerdown",this.onOutside),this.highlight());}paintGroupIcon(e){let t=this.groupIcons.get(e.id);if(!t)return;let n=this.lastUsed.get(e.id)??e.tools[0]?.type,o=e.tools.find(s=>s.type===n)??e.tools[0];t.innerHTML=vd(o?.icon??"");let i=this.groupCells.get(e.id);i&&this.tipText.set(i,o?.label??e.label);}highlight(){let e=this.active?this.def.groups.find(t=>t.tools.some(n=>n.type===this.active)):null;for(let[t,n]of this.groupCells){let o=t===e?.id;n.dataset.active=o?"1":"";}this.cursorBtn&&(this.cursorBtn.dataset.active=this.active==null&&!this.measureActive&&!this.eraserActive?"1":""),this.paintMeasure(),this.paintEraser(),this.paintMagnet(),this.paintStay();}makeButton(e,t,n){let o=document.createElement("button");return o.type="button",o.className="vela-dtb-btn",o.setAttribute("aria-label",t),this.tipText.set(o,t),e&&(o.innerHTML=vd(e)),this.tipDisposers.push(tn(o,{host:this.host,theme:()=>this.theme,text:()=>this.tipText.get(o)??t,placement:"right"})),o.addEventListener("click",n),o}divider(){let e=document.createElement("div");return e.style.cssText=`width:24px;height:1px;margin:2px auto;flex:none;background:${this.borderColor};`,e}},F0="__magnet__",V0="vela-drawing-toolbar-styles";function UI(){if(typeof document>"u")return;let r=document.getElementById(V0);r||(r=document.createElement("style"),r.id=V0,document.head.appendChild(r)),r.textContent=` +@media (pointer: coarse){.vela-dpop-grip{width:${lr+14}px !important;}}`,r||document.head.appendChild(e);}var xd=class{constructor(e,t,n=()=>0){this.host=e;this.chartBarMs=n;this.el=null;this.tipEl=null;this.textPanel=null;this.colorPop=null;this.colorOwner=null;this.menuPop=null;this.menuOwner=null;this.onClose=null;this.onOutside=e=>{let t=e.target;if(this.settingsDialog.isOpen()){if(this.settingsDialog.contains(t)||this.isOwnChrome(t))return;this.settingsDialog.close();return}if(this.isOwnChrome(t))return;let n=this.onClose;this.close(),n?.(e);};this.theme=t,this.settingsDialog=new wd(e,t);}lowerTimeframeOptions(){let e=this.chartBarMs();if(!(e>0))return [...Er];let t=Er.filter(n=>n.ms>0&&n.ms0?[Er[0],...t]:[]}setTheme(e){this.theme=e,this.settingsDialog.setTheme(e);}isOpen(){return this.el!=null}contains(e){return e!=null&&(this.isOwnChrome(e)||this.settingsDialog.contains(e))}open(e,t,n,o){this.close();let i=e[0];if(!i)return;Bx(),this.onClose=o??null;let s=this.theme,a=e.length>1,l=i.schema(),c=RI(e),d=v=>DI(e,v),u=v=>e.every(v),h=(v,k,x,E)=>this.colorButton(v,k,d(x),I=>n.patch({[E]:I}),void 0,OI(e,x)),p=a||l.textIsContent===true||!c.has("text.value"),m=document.createElement("div");m.className="vela-dpop",m.style.cssText=`position:absolute;z-index:22;background:${s.background};border:1px solid var(--vela-border);border-radius:var(--vela-radius-lg);box-shadow:var(--vela-shadow);color:${s.textColor};font:var(--vela-font-size-md) ${s.fontFamily};display:flex;flex-direction:column;pointer-events:auto;overflow:hidden;`,_e(m,s),m.addEventListener("pointerdown",v=>{v.target?.closest(".vela-select-trigger, .vela-color-field")||Me();});let f=document.createElement("div");if(f.style.cssText="display:flex;align-items:center;gap:2px;padding:4px;",f.appendChild(this.dragHandle()),c.has("glyph")){let v=d(k=>k.glyph??xi[0]);f.appendChild(this.dropdown("Icon",xi,v,k=>tA(k),k=>n.patch({glyph:k})));}if(c.has("size")){let v=d(k=>k.size??"normal");f.appendChild(this.dropdown("Icon size",Ha,v,k=>nA(k),k=>n.patch({size:k}),{label:Us}));}if(c.has("magnifier.timeframe")&&u(v=>v instanceof ht)){let v=x=>x,k=this.lowerTimeframeOptions();k.length>0&&f.appendChild(this.dropdown("Lower timeframe",k.map(x=>x.value),d(x=>v(x).magnifier.timeframe),()=>"",x=>n.patch({"magnifier.timeframe":x}),{label:x=>ki(String(x)),labelInTrigger:true})),f.appendChild(h("Up candles",ar,x=>v(x).magnifier.upColor||s.upColor,"magnifier.upColor")),f.appendChild(h("Down candles",ar,x=>v(x).magnifier.downColor||s.downColor,"magnifier.downColor"));}if(c.has("style.lineColor")&&f.appendChild(h("Line color",Zr,v=>v.style.lineColor||(v instanceof ht?Ye(this.theme.background):_),"style.lineColor")),c.has("style.lineWidth")){let v=I=>I.schema().fields.find(N=>N.path==="style.lineWidth"),k=v(i),x=d(I=>I.style.lineWidth);u(I=>{let N=v(I);return N?.kind==="number"&&(N.min??1)>1})&&k?.kind==="number"?f.appendChild(this.widthInput("Line width",x,k.min??1,k.max??60,k.step??1,I=>n.patch({"style.lineWidth":I}))):f.appendChild(this.dropdown("Line width",[1,2,3,4],x,I=>oi(I,"solid"),I=>n.patch({"style.lineWidth":I}),{label:I=>`${I}px`,labelInTrigger:true}));}c.has("style.lineStyle")&&f.appendChild(this.dropdown("Line style",rt.map(v=>v.value),d(v=>v.style.lineStyle),v=>oi(2,v),v=>n.patch({"style.lineStyle":v}),{label:Ys})),c.has("style.fillColor")&&f.appendChild(h("Fill",ar,v=>Et(v,this.theme)??v.style.fillColor??_,"style.fillColor"));let g=c.has("frvp.rows")&&i instanceof gt,b=c.has("riskPercent")&&u(v=>v instanceof yt);if(b){let v=k=>k;f.appendChild(h("Profit zone",ar,k=>v(k).profitColor,"profitColor")),f.appendChild(h("Loss zone",ar,k=>v(k).lossColor,"lossColor"));}let y=v=>v.reg;if(c.has("reg.midColor")&&u(v=>y(v)!=null)){let v=x=>y(x),k=rt.map(x=>x.value);f.appendChild(h("Midline color",Zr,x=>v(x).midColor,"reg.midColor")),f.appendChild(this.dropdown("Midline style",k,d(x=>v(x).midStyle),x=>oi(2,x),x=>n.patch({"reg.midStyle":x}),{label:Ys})),f.appendChild(h("Upper line color",Zr,x=>v(x).upperColor,"reg.upperColor")),f.appendChild(this.dropdown("Upper line style",k,d(x=>v(x).upperStyle),x=>oi(2,x),x=>n.patch({"reg.upperStyle":x}),{label:Ys})),f.appendChild(h("Lower line color",Zr,x=>v(x).lowerColor,"reg.lowerColor")),f.appendChild(this.dropdown("Lower line style",k,d(x=>v(x).lowerStyle),x=>oi(2,x),x=>n.patch({"reg.lowerStyle":x}),{label:Ys})),f.appendChild(h("Upper fill",ar,x=>v(x).upperFill,"reg.upperFill")),f.appendChild(h("Lower fill",ar,x=>v(x).lowerFill,"reg.lowerFill")),f.appendChild(this.toggle("Show R\xB2",XI,d(x=>v(x).showR2),x=>n.patch({"reg.showR2":x})));}let w=v=>v.vwap;if(c.has("vwap.midColor")&&u(v=>w(v)!=null)){let v=E=>w(E),k=rt.map(E=>E.value),x=[.5,1,1.5,2,2.5,3,4,5];f.appendChild(h("VWAP color",Zr,E=>v(E).midColor,"vwap.midColor")),f.appendChild(this.dropdown("VWAP style",k,d(E=>v(E).midStyle),E=>oi(2,E),E=>n.patch({"vwap.midStyle":E}),{label:Ys})),f.appendChild(this.dropdown("Band multiplier",x,d(E=>v(E).multiplier),()=>jI,E=>n.patch({"vwap.multiplier":E}),{label:E=>`${E}\u03C3`,labelInTrigger:true})),f.appendChild(h("Upper band color",Zr,E=>v(E).upperColor,"vwap.upperColor")),f.appendChild(h("Lower band color",Zr,E=>v(E).lowerColor,"vwap.lowerColor")),f.appendChild(h("Band fill",ar,E=>v(E).bandFill,"vwap.bandFill"));}if(c.has("maxCurvature")){let v=d(k=>k.maxCurvature??24);f.appendChild(this.dropdown("Max curvature",ru,v,()=>qI,k=>n.patch({maxCurvature:k}),{label:k=>`n=${k}`,labelInTrigger:true}));}if(c.has("mach")){let v=d(k=>k.mach??2);f.appendChild(this.dropdown("Mach number",iu,v,()=>QI,k=>n.patch({mach:k}),{label:k=>`M=${k}`,labelInTrigger:true}));}if(c.has("waveCount")){let v=d(k=>k.waveCount??6);f.appendChild(this.dropdown("Waves",ou,v,()=>ZI,k=>n.patch({waveCount:k}),{label:k=>`${k}`,labelInTrigger:true}));}let S=v=>v;c.has("showPrice")&&f.appendChild(this.toggle("Show price",FI,d(v=>S(v).showPrice!==false),v=>n.patch({showPrice:v}))),c.has("showDate")&&f.appendChild(this.toggle("Show date",VI,d(v=>S(v).showDate!==false),v=>n.patch({showDate:v}))),c.has("text.color")&&p&&f.appendChild(h("Text color",fp,v=>v.text?.color||s.textColor,"text.color")),c.has("text.size")&&p&&f.appendChild(this.dropdown("Text size",Dt.map(v=>v.value),d(v=>v.text?.size??"normal"),v=>zx(v),v=>n.patch({"text.size":v}),{label:Us}));let M=!a&&c.has("text.value");c.has("text.bold")&&!M&&f.appendChild(this.toggle("Bold",_x,d(v=>!!v.text?.bold),v=>n.patch({"text.bold":v}))),c.has("text.italic")&&!M&&f.appendChild(this.toggle("Italic",Hx,d(v=>!!v.text?.italic),v=>n.patch({"text.italic":v}))),M&&f.appendChild(this.iconBtn("Text",fp,()=>this.toggleTextPanel(i,n,!p)));let C=i.editableLevels();if(C&&u(v=>v.editableLevels()!=null&&!(v instanceof dt))){let v=x=>x,k=Dt.map(x=>x.value);f.appendChild(this.dropdown("Numbers size",k,d(x=>v(x).numbersSize??"small"),x=>oA(x),x=>n.patch({numbersSize:x}),{label:Us})),f.appendChild(this.dropdown("Label size",k,d(x=>v(x).labelsSize??"normal"),x=>zx(x),x=>n.patch({labelsSize:x}),{label:Us}));}f.appendChild(this.divider()),!a&&g&&f.appendChild(this.iconBtn("Settings",gp,()=>this.settingsDialog.open(i,n,"frvp"))),!a&&b&&f.appendChild(this.iconBtn("Position size",gp,()=>this.settingsDialog.open(i,n,"position"))),!a&&C&&f.appendChild(this.iconBtn("Levels",gp,()=>this.settingsDialog.open(i,n,"levels"))),f.appendChild(this.toggle("Lock",BI,d(v=>v.locked),v=>n.setLocked(v),_I));let L=this.iconBtn("Delete",WI,()=>n.remove());L.style.color="var(--vela-danger)",f.appendChild(L),f.appendChild(this.kebabButton(n)),m.append(f),this.host.appendChild(m),this.el=m,m.addEventListener("mouseover",v=>{let k=v.target.closest("[data-tip]");k?this.showTip(k):this.hideTip();}),m.addEventListener("mouseleave",()=>this.hideTip()),this.position(t),setTimeout(()=>document.addEventListener("pointerdown",this.onOutside),0);}close(){document.removeEventListener("pointerdown",this.onOutside),this.closeColorPopover(),this.closeMenu(),this.hideTip(),this.settingsDialog.close(),this.el?.remove(),this.el=null,this.textPanel=null,this.onClose=null;}destroy(){this.close();}isOwnChrome(e){if(this.el?.contains(e)||this.colorPop?.el.contains(e)||this.menuPop?.el.contains(e))return true;let t=e instanceof Element?e:e.parentElement;if(!t)return false;let n=t.closest(".vela-popover");return n!=null&&this.host.contains(n)}toggleTextPanel(e,t,n){if(this.textPanel){this.textPanel.remove(),this.textPanel=null,this.reposition();return}let o=(t.resolve()??e).text,i=document.createElement("div");i.style.cssText="padding:6px;border-top:1px solid var(--vela-border);display:flex;flex-direction:column;gap:4px;";let s=new Ur({value:o?.value??"",rows:1,size:"sm",autoGrow:true,maxLines:4,placeholder:"Label\u2026",onChange:l=>{t.patch({"text.value":l}),this.reposition();}});s.el.style.minWidth="220px",s.input.addEventListener("input",()=>{t.patch({"text.value":s.input.value}),this.reposition();}),s.input.addEventListener("keydown",l=>{if(l.stopPropagation(),l.key==="Escape"){l.preventDefault();let c=this.onClose;this.close(),c?.();}});let a=document.createElement("div");a.style.cssText="display:flex;align-items:center;justify-content:flex-start;gap:0;transform:scale(0.8);transform-origin:left center;",n&&a.append(this.colorButton("Text color",fp,o?.color||this.theme.textColor,l=>t.patch({"text.color":l}),14),this.dropdown("Text size",Dt.map(l=>l.value),o?.size??"normal",l=>rA(l),l=>t.patch({"text.size":l}),{label:Us})),a.append(this.toggle("Bold",_x,!!o?.bold,l=>t.patch({"text.bold":l})),this.toggle("Italic",Hx,!!o?.italic,l=>t.patch({"text.italic":l}))),i.append(s.el,a),this.el?.appendChild(i),this.textPanel=i,this.reposition(),s.input.focus();}position(e){let t=this.el;if(!t)return;let n=this.host.getBoundingClientRect(),o=t.offsetWidth,i=t.offsetHeight,s=10,a=n.width/2-o/2,l=12;e&&(a=e.x+e.w/2-o/2,l=e.y-i-s,l<4&&(l=e.y+e.h+s)),t.style.left=`${Math.max(4,Math.min(a,n.width-o-4))}px`,t.style.top=`${Math.max(4,Math.min(l,n.height-i-4))}px`;}reposition(){let e=this.el;if(!e)return;let t=this.host.getBoundingClientRect(),n=e.offsetWidth,o=e.offsetHeight,i=parseFloat(e.style.left)||0,s=parseFloat(e.style.top)||0;e.style.left=`${Math.max(4,Math.min(i,t.width-n-4))}px`,e.style.top=`${Math.max(4,Math.min(s,t.height-o-4))}px`;}base(e){let t=document.createElement("button");return t.type="button",t.dataset.tip=e,t.className="vela-dpop-btn",t.style.cssText=`width:${lr}px;height:${lr}px;display:flex;align-items:center;justify-content:center;cursor:pointer;color:inherit;border:none;border-radius:5px;padding:0;`,t}iconBtn(e,t,n){let o=this.base(e);return o.innerHTML=On(t),o.addEventListener("click",n),o}dragHandle(){let e=document.createElement("button");return e.type="button",e.className="vela-dpop-grip",e.style.cssText=`width:${lr}px;height:${lr}px;display:flex;align-items:center;justify-content:center;background:transparent;border:none;padding:0;cursor:grab;touch-action:none;color:var(--vela-fg-faint);`,e.innerHTML=On(GI),e.addEventListener("pointerdown",t=>{let n=this.el;if(!n||t.button!==0)return;t.preventDefault(),t.stopPropagation(),this.hideTip(),this.closeColorPopover(),this.closeMenu();let o=this.host.getBoundingClientRect(),i=t.clientX,s=t.clientY,a=parseFloat(n.style.left)||0,l=parseFloat(n.style.top)||0;e.style.cursor="grabbing";try{e.setPointerCapture(t.pointerId);}catch{}let c=u=>{let h=n.offsetWidth,p=n.offsetHeight,m=a+(u.clientX-i),f=l+(u.clientY-s);n.style.left=`${Math.max(4,Math.min(m,o.width-h-4))}px`,n.style.top=`${Math.max(4,Math.min(f,o.height-p-4))}px`;},d=()=>{e.style.cursor="grab",window.removeEventListener("pointermove",c),window.removeEventListener("pointerup",d),window.removeEventListener("pointercancel",d);};window.addEventListener("pointermove",c),window.addEventListener("pointerup",d),window.addEventListener("pointercancel",d);}),e}kebabButton(e){let t=this.base("More");return t.innerHTML=On($I),t.addEventListener("pointerdown",n=>n.stopPropagation()),t.addEventListener("click",n=>{if(n.stopPropagation(),this.menuOwner===t){this.closeMenu();return}this.openActionMenu(t,[{icon:UI,label:"Duplicate",onClick:()=>e.duplicate()},{icon:HI,label:"Bring to front",onClick:()=>e.reorder("front")},{icon:zI,label:"Send to back",onClick:()=>e.reorder("back")},{icon:YI,label:"Reset settings",onClick:()=>e.resetSettings()}]);}),t}hostFloat(e,t){let n=this.theme,o=new qe({trigger:e,host:this.host,theme:n,position:"absolute",boundary:this.host,boundaryInset:4,viewportInset:0,gap:6,align:t.align??"start",zIndex:t.zIndex,onClose:()=>{this.menuPop===o&&(this.menuPop=null,this.menuOwner=null),this.colorPop===o&&(this.colorPop=null,this.colorOwner=null),t.onClose?.();}}),i=o.el;return i.style.background=n.background,i.style.border="1px solid var(--vela-border)",i.style.borderRadius="var(--vela-radius-lg)",i.style.boxShadow="var(--vela-shadow)",i.style.padding=t.padding,i.style.display="flex",i.style.flexDirection="column",i.style.gap="1px",i.style.color=n.textColor,i.style.font=`var(--vela-font-size-md) ${n.fontFamily}`,i.style.pointerEvents="auto",t.fill(i,o),o.show(),o}openMagnifierTimeframeMenu(e,t,n){Bx(),Me();let o=this.lowerTimeframeOptions(),i=document.createElement("div");i.style.cssText=`position:absolute;left:${e.x}px;top:${e.y}px;width:${e.w}px;height:${e.h}px;pointer-events:none;`,this.host.appendChild(i),this.menuPop=this.hostFloat(i,{zIndex:26,padding:"4px",onClose:()=>i.remove(),fill:(s,a)=>{if(o.length===0){let l=document.createElement("div");l.style.cssText="padding:6px 10px;opacity:0.65;white-space:nowrap;",l.textContent="No lower timeframe available",s.appendChild(l);return}for(let l of o){let c=document.createElement("button");c.type="button",c.className="vela-dpop-item",c.dataset.active=l.value===t?"1":"0",c.style.cssText="display:flex;align-items:center;min-width:88px;padding:5px 10px;border:none;border-radius:5px;color:inherit;cursor:pointer;text-align:left;font:inherit;font-variant-numeric:tabular-nums;",c.textContent=l.label,c.addEventListener("click",d=>{d.stopPropagation(),a.hide(),n(l.value);}),s.appendChild(c);}}}),this.menuOwner=i;}openActionMenu(e,t){this.menuPop=this.hostFloat(e,{align:"end",zIndex:26,padding:"4px",fill:(n,o)=>{for(let i of t){let s=document.createElement("button");s.type="button",s.className="vela-dpop-item",s.style.cssText="display:flex;align-items:center;gap:9px;min-width:150px;padding:6px 9px;border:none;border-radius:5px;color:inherit;cursor:pointer;text-align:left;font:inherit;";let a=document.createElement("span");a.style.cssText="display:flex;flex:none;width:20px;justify-content:center;",a.innerHTML=On(i.icon,18);let l=document.createElement("span");l.textContent=i.label,l.style.cssText="flex:1;",s.append(a,l),s.addEventListener("click",c=>{c.stopPropagation(),o.hide(),i.onClick();}),n.appendChild(s);}}}),this.menuOwner=e;}showTip(e){let t=e.dataset.tip;if(!t){this.hideTip();return}let n=this.theme;if(!this.tipEl){let p=document.createElement("div");p.style.cssText=`position:absolute;z-index:27;pointer-events:none;white-space:nowrap;background:${n.textColor};color:${n.background};padding:3px 7px;border-radius:5px;font:var(--vela-font-size-sm) ${n.fontFamily};box-shadow:var(--vela-shadow);`,this.host.appendChild(p),this.tipEl=p;}let o=this.tipEl;o.textContent=t;let i=this.host.getBoundingClientRect(),s=e.getBoundingClientRect(),a=o.offsetWidth,l=o.offsetHeight,c=6,d=s.left-i.left+s.width/2-a/2;d=Math.max(4,Math.min(d,i.width-a-4));let u=s.top-i.top-l-c,h=u>=4?u:s.bottom-i.top+c;o.style.left=`${Math.round(d)}px`,o.style.top=`${Math.round(h)}px`;}hideTip(){this.tipEl?.remove(),this.tipEl=null;}toggle(e,t,n,o,i){let s=this.base(e),a=c=>{s.dataset.active=c===$t?"mixed":c?"1":"0",s.innerHTML=On(i&&c===false?i:t);};a(n);let l=n;return s.addEventListener("click",()=>{l=l===$t?true:!l,a(l),o(l);}),s}widthInput(e,t,n,o,i,s){let a=new $r({value:t===$t?n:t,min:n,max:o,step:i,integer:i>=1,size:"sm",fill:false,compact:true,commit:"blur",title:e,onChange:s});return t===$t&&(a.input.value="",a.input.placeholder="\u2014"),a.el.dataset.tip=e,eA(a.el),a.el}dropdown(e,t,n,o,i,s={}){let a=this.base(e);a.style.width="auto",a.style.minWidth=`${lr}px`,a.style.padding="0 4px",a.style.gap="2px";let l=n,c=d=>{if(a.replaceChildren(),d===$t){let p=document.createElement("span");p.textContent="\u2014",p.style.cssText="min-width:18px;text-align:center;opacity:0.85;",a.appendChild(p);}let u=d===$t?"":o(d);if(u){let p=document.createElement("span");p.style.cssText="display:flex;",p.innerHTML=On(u),a.appendChild(p);}if(s.label&&s.labelInTrigger&&d!==$t){let p=document.createElement("span");p.textContent=s.label(d),p.style.cssText="font-size:11px;opacity:0.85;font-variant-numeric:tabular-nums;",a.appendChild(p);}let h=document.createElement("span");h.style.cssText="display:flex;opacity:0.55;",h.innerHTML=On(KI,12),a.appendChild(h);};return c(l),a.addEventListener("pointerdown",d=>d.stopPropagation()),a.addEventListener("click",d=>{if(d.stopPropagation(),this.menuOwner===a){this.closeMenu();return}this.openMenu(a,t,l,o,s.label,u=>{l=u,c(u),i(u);});}),a}openMenu(e,t,n,o,i,s){this.menuPop=this.hostFloat(e,{zIndex:26,padding:"4px",fill:(a,l)=>{for(let c of t){let d=c===n,u=document.createElement("button");u.type="button",u.className="vela-dpop-item",u.dataset.active=d?"1":"0",u.style.cssText=`display:flex;align-items:center;gap:8px;${i?"min-width:118px;":""}padding:5px 8px;border:none;border-radius:5px;color:inherit;cursor:pointer;text-align:left;font:inherit;`;let h=o(c);if(h){let p=document.createElement("span");p.style.cssText="display:flex;flex:none;width:22px;justify-content:center;",p.innerHTML=On(h,18),u.appendChild(p);}if(i){let p=document.createElement("span");p.textContent=i(c),p.style.cssText="flex:1;font-variant-numeric:tabular-nums;",u.appendChild(p);}u.addEventListener("click",p=>{p.stopPropagation(),l.hide(),s(c);}),a.appendChild(u);}}}),this.menuOwner=e;}closeMenu(){this.menuPop?.hide();}colorButton(e,t,n,o,i=17,s=[]){let a=document.createElement("button");a.type="button",a.dataset.tip=e,a.className="vela-dpop-btn",a.style.cssText=`position:relative;width:${lr}px;height:${lr}px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;cursor:pointer;border-radius:5px;border:none;color:inherit;padding:0;`;let l=document.createElement("span");l.style.cssText="display:flex;",l.innerHTML=On(t,i);let c=document.createElement("span");c.style.cssText=`display:block;height:3px;width:${Math.round(i*.85)}px;border-radius:2px;background:${n===$t?JI(s):n};`,a.append(l,c);let d=n;return a.addEventListener("pointerdown",u=>u.stopPropagation()),a.addEventListener("click",u=>{u.stopPropagation();let h=d===$t?s[0]??_:d;this.toggleColorPopover(a,h,d===$t?s:[],p=>{d=p,c.style.background=p,o(p);});}),a}toggleColorPopover(e,t,n,o){if(this.colorOwner===e){this.closeColorPopover();return}this.openColorPopover(e,t,n,o);}openColorPopover(e,t,n,o){let i=this.theme;this.colorPop=this.hostFloat(e,{zIndex:25,padding:"10px",fill:(s,a)=>{if(n.length>1){let l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:6px;padding-bottom:9px;border-bottom:1px solid var(--vela-border);";let c=document.createElement("span");c.textContent="In use",c.style.cssText="font:var(--vela-font-size-sm) inherit;opacity:0.7;margin-right:2px;",l.appendChild(c);for(let d of n){let u=document.createElement("button");u.type="button",u.dataset.tip=d,u.style.cssText=`width:18px;height:18px;border-radius:4px;border:1px solid var(--vela-border-strong);cursor:pointer;background:${d};padding:0;`,u.addEventListener("click",h=>{h.stopPropagation(),a.hide(),o(d);}),l.appendChild(u);}s.appendChild(l);}s.appendChild(Ts(t,i,o));}}),this.colorOwner=e;}closeColorPopover(){this.colorPop?.hide();}divider(){let e=document.createElement("div");return e.style.cssText="width:1px;height:18px;margin:0 3px;background:var(--vela-border);",e}},Zr=ee("brush"),ar=ee("bucket"),fp=ee("type"),FI=ee("price-delta"),VI=ee("date-delta"),BI=ee("lock"),_I=ee("unlock"),HI=ee("bring-front"),zI=ee("send-back"),WI=ee("trash"),_x=ee("bold"),Hx=ee("italic"),GI=ee("grip"),$I=ee("kebab"),UI=ee("clone"),YI=ee("reset"),gp=ee("gear"),KI=ee("chevron-down"),XI=ee("r-squared"),jI=ee("bands"),qI=ee("dedekind"),ZI=ee("sonic"),QI=ee("supersonic");function JI(r){let e=r.length>1?r:["var(--vela-fg-faint)","var(--vela-fg-muted)"],t=100/e.length;return `linear-gradient(90deg,${e.map((o,i)=>`${o} ${i*t}% ${(i+1)*t}%`).join(",")})`}function oi(r,e){let t=e==="dashed"?"5,3":e==="dotted"?"1.5,3":"";return B(``)}function eA(r){r.addEventListener("keydown",e=>e.stopPropagation());}function Ks(r,e,t=17,n=""){return Qd(`${r}`)}function tA(r){return Ks(String(r),15)}function nA(r){return Ks("\u25CF",(bp[String(r)]??13)+4)}function rA(r){return Ks(String(r).charAt(0).toUpperCase(),15)}var bp={small:10,normal:13,large:16,huge:20};function oA(r){return Ks("12",(bp[String(r)]??13)-1,16.5,'font-weight="600"')}function zx(r){return Ks("T",(bp[String(r)]??13)+2)}function Wx(r){return r.charAt(0).toUpperCase()+r.slice(1)}function Us(r){return Dt.find(e=>e.value===r)?.label??Wx(String(r))}function Ys(r){return rt.find(e=>e.value===r)?.label??Wx(String(r))}function On(r,e=NI){return r.replace("{},i=()=>{},s=()=>{},a=()=>{},l=()=>{},c={}){this.host=e;this.theme=t;this.onArm=n;this.onMagnet=o;this.onMeasure=i;this.onEraser=s;this.onToggleFavorite=a;this.onStayMode=l;this.def={groups:[]};this.active=null;this.lastUsed=new Map;this.favorites=new Set;this.shortcuts=new Map;this.starEls=new Map;this.flyout=null;this.flyoutOwnerId=null;this.flyoutCell=null;this.exitingFlyouts=new Map;this.groupCells=new Map;this.groupIcons=new Map;this.cursorBtn=null;this.magnetCell=null;this.magnetIcon=null;this.magnetMode="off";this.lastMagnetOn="weak";this.measureBtn=null;this.measureActive=false;this.eraserBtn=null;this.eraserActive=false;this.stayBtn=null;this.stayActive=false;this.syncBtn=null;this.syncActive=false;this.collapseBtn=null;this.collapsed=false;this.visible=false;this.tipText=new WeakMap;this.tipDisposers=[];this.onOutside=e=>{let t=e.target;this.flyout&&!this.flyout.contains(t)&&!this.root.contains(t)&&this.closeFlyout();};this.borderOverride=c.borderColor??null,this.width=c.width??yp,this.dock=c.dock??"absolute",this.onCollapse=c.onCollapse??(()=>{}),this.onDrawingsSync=c.onDrawingsSync??null,sA(),this.root=document.createElement("div"),this.root.className="vela-dtb",this.styleRoot(),e.appendChild(this.root);}get borderColor(){return this.borderOverride??this.theme.borderColor}styleRoot(){let e=this.theme;_e(this.root,e);let t=this.collapsed?wp:this.width;this.root.dataset.collapsed=this.collapsed?"1":"";let n=this.dock==="absolute"?`position:absolute;left:0;top:0;height:100%;width:${t}px;z-index:21;`:`position:relative;height:100%;width:${t}px;flex:none;`;this.root.style.cssText=n+`display:${this.visible?"flex":"none"};flex-direction:column;gap:4px;padding:6px 0;box-sizing:border-box;background:${e.background};border-right:1px solid ${this.borderColor};color:var(--vela-fg-muted);pointer-events:auto;overflow-y:auto;overflow-x:hidden;`;}setDefinition(e){this.def=e;for(let t of e.groups){let n=t.tools[0];n&&!this.lastUsed.has(t.id)&&this.lastUsed.set(t.id,n.type);}this.rebuild();}setFavorites(e){this.favorites=new Set(e);for(let[t,n]of this.starEls)this.paintStar(n,t);}setShortcuts(e){this.shortcuts=new Map(Object.entries(e));}paintStar(e,t){let n=this.favorites.has(t);e.classList.toggle("vela-fav",n),e.setAttribute("aria-label",n?"Remove from favorites":"Add to favorites"),e.setAttribute("aria-pressed",n?"true":"false"),e.innerHTML=vp(n?bA:gA);}setVisible(e){this.visible=e,this.root.style.display=e?"flex":"none";}setActiveTool(e){if(this.active=e,e){let t=this.def.groups.find(n=>n.tools.some(o=>o.type===e));t&&(this.lastUsed.set(t.id,e),this.paintGroupIcon(t));}this.closeFlyout(),this.highlight();}setTheme(e){this.theme=e,this.styleRoot(),this.rebuild();}destroy(){this.closeFlyout();for(let{exit:e}of [...this.exitingFlyouts.values()])e.finish();for(let e of this.tipDisposers.splice(0))e();this.root.remove();}rebuild(){for(let e of this.tipDisposers.splice(0))e();this.root.replaceChildren(),this.groupCells.clear(),this.groupIcons.clear(),this.cursorBtn=this.makeButton(aA,"Cursor",()=>this.onCursorClick()),this.root.appendChild(this.cursorBtn),this.def.groups.length>0&&this.root.appendChild(this.divider());for(let e of this.def.groups){let t=this.makeGroupCell(e);this.root.appendChild(t),this.paintGroupIcon(e);}this.root.appendChild(this.divider()),this.measureBtn=this.makeButton(lA,"Measure",()=>this.onMeasure()),this.root.appendChild(this.measureBtn),this.eraserBtn=this.makeButton(pA,"Eraser (click/drag to delete)",()=>this.onEraser()),this.root.appendChild(this.eraserBtn),this.root.appendChild(this.makeMagnetCell()),this.stayBtn=this.makeButton(uA,"Stay in drawing mode",()=>this.toggleStay()),this.root.appendChild(this.stayBtn),this.onDrawingsSync&&(this.syncBtn=this.makeButton(hA,"Sync drawings on all charts",()=>this.toggleDrawingsSync()),this.root.appendChild(this.syncBtn)),this.collapseBtn=this.makeButton(Ux,"Collapse toolbar",()=>this.toggleCollapsed()),this.collapseBtn.classList.add("vela-dtb-collapse"),this.root.appendChild(this.collapseBtn),this.paintMeasure(),this.paintEraser(),this.paintMagnet(),this.paintStay(),this.paintDrawingsSync(),this.paintCollapse(),this.highlight();}toggleCollapsed(){this.collapsed=!this.collapsed,this.closeFlyout(),this.styleRoot(),this.paintCollapse(),this.onCollapse(this.collapsed);}paintCollapse(){let e=this.collapseBtn;if(!e)return;let t=this.collapsed?"Expand toolbar":"Collapse toolbar";e.innerHTML=Sd(this.collapsed?cA:Ux,12),e.setAttribute("aria-label",t),this.tipText.set(e,t);}makeCell(e,t){let n=document.createElement("div");n.className="vela-dtb-cell";let o=document.createElement("button");o.type="button",o.className="vela-dtb-icon",o.setAttribute("aria-label",e),t.iconSvg&&(o.innerHTML=Sd(t.iconSvg)),o.addEventListener("click",t.onIcon),n.appendChild(o);let i=null;if(t.multi&&t.onArrow){let s=t.onArrow;i=document.createElement("button"),i.type="button",i.className="vela-dtb-arrow",i.setAttribute("aria-label",`${e} \u2014 more`),i.innerHTML=vA(mA),i.addEventListener("click",a=>{a.stopPropagation(),s();}),n.appendChild(i);}return this.tipDisposers.push(nn(n,{host:this.host,theme:()=>this.theme,text:()=>this.tipText.get(n)??e,placement:"right"})),{cell:n,icon:o,arrow:i}}makeGroupCell(e){let t=e.tools.length>1,{cell:n,icon:o}=this.makeCell(e.label,{multi:t,onIcon:()=>this.onGroupIconClick(e),onArrow:t?()=>this.onArrowClick(e):void 0});return this.groupCells.set(e.id,n),this.groupIcons.set(e.id,o),n}makeMagnetCell(){let{cell:e,icon:t}=this.makeCell("Magnet snap",{iconSvg:dA,multi:true,onIcon:()=>this.toggleMagnet(),onArrow:()=>this.onMagnetArrowClick()});return this.magnetCell=e,this.magnetIcon=t,e}onCursorClick(){this.measureActive&&this.onMeasure(),this.eraserActive&&this.onEraser(),this.onArm(null);}onGroupIconClick(e){let t=this.lastUsed.get(e.id)??e.tools[0]?.type;t&&this.onArm(t);}onArrowClick(e){let t=this.flyoutOwnerId===e.id;this.closeFlyout(),t||this.openGroupFlyout(e);}toggleMagnet(){this.applyMagnet(this.magnetMode==="off"?this.lastMagnetOn:"off");}onMagnetArrowClick(){let e=this.flyoutOwnerId===Gx;this.closeFlyout(),e||this.openMagnetFlyout();}applyMagnet(e){this.magnetMode=e,e!=="off"&&(this.lastMagnetOn=e),this.onMagnet(e),this.paintMagnet(),this.highlight();}setMagnetMode(e){this.magnetMode=e,e!=="off"&&(this.lastMagnetOn=e),this.paintMagnet(),this.highlight();}setMeasureActive(e){this.measureActive=e,this.paintMeasure(),this.highlight();}paintMeasure(){let e=this.measureBtn;e&&(e.dataset.active=this.measureActive?"1":"");}setEraserActive(e){this.eraserActive=e,this.paintEraser(),this.highlight();}paintEraser(){let e=this.eraserBtn;e&&(e.dataset.active=this.eraserActive?"1":"");}paintMagnet(){let e=this.magnetCell,t=this.magnetIcon;if(!e||!t)return;let n=this.magnetMode==="off"?"Off":this.magnetMode==="weak"?"Weak":"Strong";this.tipText.set(e,`Magnet snap: ${n}`);let o=this.magnetMode!=="off";e.dataset.active=o?"1":"",t.style.opacity=o?"1":"0.5";}toggleStay(){this.stayActive=!this.stayActive,this.onStayMode(this.stayActive),this.paintStay();}setStayMode(e){this.stayActive=e,this.paintStay();}paintStay(){let e=this.stayBtn;e&&(e.dataset.active=this.stayActive?"1":"",e.style.opacity=this.stayActive?"1":"0.5");}toggleDrawingsSync(){this.syncActive=!this.syncActive,this.onDrawingsSync?.(this.syncActive),this.paintDrawingsSync();}setDrawingsSyncMode(e){this.syncActive=e,this.paintDrawingsSync();}paintDrawingsSync(){let e=this.syncBtn;e&&(e.dataset.active=this.syncActive?"1":"",e.style.opacity=this.syncActive?"1":"0.5");}beginFlyout(e,t){let n=this.theme,o=this.exitingFlyouts.get(e);o&&(this.exitingFlyouts.delete(e),o.exit.cancel(),o.fly.replaceChildren());let i=o?.fly??document.createElement("div");i.className="vela-dtb-flyout",i.style.cssText=`position:absolute;z-index:23;display:flex;flex-direction:column;gap:2px;padding:4px;border-radius:var(--vela-radius-md);background:var(--vela-surface);border:1px solid ${this.borderOverride??"var(--vela-border-strong)"};box-shadow:var(--vela-shadow);pointer-events:auto;overflow-y:auto;overscroll-behavior:contain;`,_e(i,n),this.host.appendChild(i);let s=t.getBoundingClientRect(),a=this.root.getBoundingClientRect(),l=this.host.getBoundingClientRect(),c=s.top-l.top;return i.style.left=`${a.right-l.left+iA}px`,i.style.top=`${c}px`,i.style.maxHeight=`${Math.max(120,l.height-c-8)}px`,this.flyout=i,this.flyoutOwnerId=e,this.flyoutCell=t,t.classList.add("vela-open"),this.highlight(),document.addEventListener("pointerdown",this.onOutside),i}openGroupFlyout(e){let t=this.groupCells.get(e.id);if(!t)return;let n=this.beginFlyout(e.id,t),o=e.sections??[{label:"",tools:e.tools}],i=o.some(s=>s.tools.some(a=>!!a.icon));for(let s=0;s0&&n.appendChild(this.flyoutSeparator()),n.appendChild(this.flyoutHeader(a.label)));for(let l of a.tools)n.appendChild(this.makeFlyoutItem({icon:l.icon,badge:i,label:l.label,selected:l.type===this.active,shortcut:this.shortcuts.get(l.type),onSelect:()=>this.onArm(l.type),favorite:{type:l.type,toggle:()=>this.onToggleFavorite(l.type,!this.favorites.has(l.type))}}));}Vt(n,true,"menu",t);}openMagnetFlyout(){let e=this.magnetCell;if(!e)return;let t=this.beginFlyout(Gx,e);t.appendChild(this.flyoutHeader("Magnet"));let n=[["off","Off"],["weak","Weak"],["strong","Strong"]];for(let[o,i]of n)t.appendChild(this.makeFlyoutItem({label:i,selected:o===this.magnetMode,onSelect:()=>{this.applyMagnet(o),this.closeFlyout();}}));Vt(t,true,"menu",e);}flyoutHeader(e){let t=this.theme,n=document.createElement("div");return n.textContent=e.toUpperCase(),n.style.cssText=`padding:6px 12px 2px 8px;font:var(--vela-font-size-sm) ${t.fontFamily};font-weight:600;letter-spacing:0.04em;color:var(--vela-fg-muted);user-select:none;`,n}flyoutSeparator(){let e=document.createElement("div");return e.style.cssText=`height:1px;margin:4px 8px;background:${this.borderColor};`,e}makeFlyoutItem(e){let t=this.theme,n=document.createElement("button");n.type="button",n.className="vela-dtb-item",n.setAttribute("aria-label",e.label);let o=e.badge===true||!!e.icon,i=o?"gap:10px;padding:4px 10px 4px 6px;":"gap:8px;padding:5px 10px 5px 8px;";if(n.style.cssText=`display:flex;align-items:center;${i}cursor:pointer;color:${t.textColor};border-radius:var(--vela-radius-sm);font:13px ${t.fontFamily};white-space:nowrap;min-width:148px;`,e.selected&&(n.dataset.selected="1"),o){let l=document.createElement("span");l.className="vela-dtb-badge",e.icon&&(l.innerHTML=e.icon),n.appendChild(l);}let s=document.createElement("span");s.textContent=e.label,s.style.cssText="flex:1 1 auto;text-align:left;",n.appendChild(s);let a=document.createElement("span");if(a.style.cssText="width:14px;height:14px;display:flex;align-items:center;justify-content:center;flex:none;",e.selected&&(a.innerHTML=vp(fA)),n.appendChild(a),e.shortcut){let l=document.createElement("span");l.className="vela-dtb-hint",l.textContent=e.shortcut,l.style.cssText=`flex:none;font:var(--vela-font-size-md) ${t.fontFamily};color:var(--vela-fg-muted);`,n.appendChild(l);}if(e.favorite){let l=document.createElement("span");l.className="vela-dtb-star",l.setAttribute("role","button"),this.paintStar(l,e.favorite.type),this.starEls.set(e.favorite.type,l);for(let c of ["pointerdown","pointerup","mousedown","mouseup"])l.addEventListener(c,d=>d.stopPropagation());l.addEventListener("click",c=>{c.stopPropagation(),c.preventDefault(),e.favorite.toggle();}),n.appendChild(l);}return n.addEventListener("click",l=>{l.stopPropagation(),e.onSelect();}),n}closeFlyout(){this.starEls.clear();let e=this.flyout;if(e){this.flyout=null,Vt(e,false,"menu",this.flyoutCell);let t=this.flyoutOwnerId??"",n=Kn(e,()=>{this.exitingFlyouts.get(t)?.fly===e&&this.exitingFlyouts.delete(t),e.remove();});n&&this.exitingFlyouts.set(t,{fly:e,exit:n}),this.flyoutCell?.classList.remove("vela-open"),this.flyoutCell=null,this.flyoutOwnerId=null,document.removeEventListener("pointerdown",this.onOutside),this.highlight();}}paintGroupIcon(e){let t=this.groupIcons.get(e.id);if(!t)return;let n=this.lastUsed.get(e.id)??e.tools[0]?.type,o=e.tools.find(s=>s.type===n)??e.tools[0];t.innerHTML=Sd(o?.icon??"");let i=this.groupCells.get(e.id);i&&this.tipText.set(i,o?.label??e.label);}highlight(){let e=this.active?this.def.groups.find(t=>t.tools.some(n=>n.type===this.active)):null;for(let[t,n]of this.groupCells){let o=t===e?.id;n.dataset.active=o?"1":"";}this.cursorBtn&&(this.cursorBtn.dataset.active=this.active==null&&!this.measureActive&&!this.eraserActive?"1":""),this.paintMeasure(),this.paintEraser(),this.paintMagnet(),this.paintStay();}makeButton(e,t,n){let o=document.createElement("button");return o.type="button",o.className="vela-dtb-btn",o.setAttribute("aria-label",t),this.tipText.set(o,t),e&&(o.innerHTML=Sd(e)),this.tipDisposers.push(nn(o,{host:this.host,theme:()=>this.theme,text:()=>this.tipText.get(o)??t,placement:"right"})),o.addEventListener("click",n),o}divider(){let e=document.createElement("div");return e.style.cssText=`width:24px;height:1px;margin:2px auto;flex:none;background:${this.borderColor};`,e}},Gx="__magnet__",$x="vela-drawing-toolbar-styles";function sA(){if(typeof document>"u")return;let r=document.getElementById($x);r||(r=document.createElement("style"),r.id=$x,document.head.appendChild(r)),r.textContent=` .vela-dtb-hit{width:22px;height:22px;display:flex;align-items:center;justify-content:center;border-radius:var(--vela-radius-md);transition:background var(--vela-dur-fast) ease,color var(--vela-dur-fast) ease;} .vela-dtb-hit--arrow{width:11px;height:22px;} .vela-dtb-btn{position:relative;width:100%;height:30px;flex:none;display:flex;align-items:center;justify-content:center;cursor:pointer;color:inherit;background:transparent;border:none;padding:0;transition:color var(--vela-dur-fast) ease;} @@ -950,6 +979,11 @@ ${Ir(".vela-sd-pane")} .vela-dtb[data-collapsed='1'] .vela-dtb-collapse .vela-dtb-hit{width:14px;} .vela-dtb-item{background:transparent;border:none;transition:background var(--vela-dur-fast) ease;} .vela-dtb-item:hover{background:var(--vela-hover-strong);} +.vela-dtb-badge{width:24px;height:24px;padding:3px;box-sizing:border-box;display:flex;align-items:center;justify-content:center;flex:none;border-radius:var(--vela-radius-md);background:var(--vela-hover);border:1px solid var(--vela-border);color:var(--vela-fg-muted);transition:background var(--vela-dur-fast) ease,border-color var(--vela-dur-fast) ease,color var(--vela-dur-fast) ease;} +.vela-dtb-badge:empty{background:transparent;border-color:transparent;} +.vela-dtb-badge svg{width:100%;height:100%;} +.vela-dtb-item:hover .vela-dtb-badge:not(:empty){background:var(--vela-active);color:var(--vela-fg-bright);} +.vela-dtb-item[data-selected='1'] .vela-dtb-badge:not(:empty){background:color-mix(in srgb,var(--vela-fg-bright) 83%,var(--vela-surface));border-color:color-mix(in srgb,var(--vela-fg-bright) 40%,transparent);color:var(--vela-surface);} .vela-dtb-star{width:26px;height:22px;margin:-3px -5px -3px 0;padding:3px 5px;box-sizing:border-box;display:flex;align-items:center;justify-content:center;flex:none;opacity:0;color:inherit;border-radius:var(--vela-radius-sm);transition:opacity .1s ease,color .1s ease,background .1s ease;} .vela-dtb-star svg{width:16px;height:16px;} .vela-dtb-item:hover .vela-dtb-star{opacity:.55;} @@ -963,11 +997,11 @@ ${Ir(".vela-sd-pane")} .vela-dtb-flyout::-webkit-scrollbar-button{display:none;width:0;height:0;} .vela-dtb-flyout::-webkit-scrollbar-track,.vela-dtb-flyout::-webkit-scrollbar-track-piece,.vela-dtb-flyout::-webkit-scrollbar-corner{background:transparent;} .vela-dtb-flyout::-webkit-scrollbar-thumb{background:var(--vela-scroll);border-radius:var(--vela-radius-sm);} -.vela-dtb-flyout::-webkit-scrollbar-thumb:hover{background:var(--vela-fg-muted);}`;}var YI=ee("cursor"),KI=ee("ruler"),B0=ee("chevrons-left"),XI=ee("chevrons-right"),jI=ee("magnet"),qI=ee("pen-lock"),ZI=ee("pen-sync"),QI=ee("eraser"),JI=ee("chevron-right"),eA=ee("check"),tA=ee("star"),nA=ee("star-filled");function yd(r){return r.replace("${yd(r)}`:""}function vd(r,e=18){return `${_0(r,e)}`}function rA(r){return `${_0(r,11)}`}function H0(r){return `${r>=0?"+":""}${r.toFixed(2)}`}var oA=O,iA=D,sA=3,wd=class{constructor(){this.state="idle";this.start=null;this.end=null;this.pressX=0;this.pressY=0;}isActive(){return this.state!=="idle"}isFinished(){return this.state==="finished"}down(e,t,n=e,o=t){if(this.state==="measuring"){this.end={x:n,y:o},this.state="finished";return}this.start={x:n,y:o},this.end={x:n,y:o},this.pressX=e,this.pressY=t,this.state="measuring";}move(e,t){this.state==="measuring"&&(this.end={x:e,y:t});}up(e,t,n=e,o=t){this.state==="measuring"&&Math.hypot(e-this.pressX,t-this.pressY)>sA&&(this.end={x:n,y:o},this.state="finished");}points(){return !this.start||!this.end?null:{start:this.start,end:this.end}}clear(){this.state="idle",this.start=null,this.end=null;}paint(e,t,n){if(!this.start||!this.end)return;let{x:o,y:i}=this.start,{x:s,y:a}=this.end,l=t.paneIdAtY(i)??t.paneIdAtY(a);if(!l)return;let c=t.pxToPoint(o,i,l),d=t.pxToPoint(s,a,l),u=d.price-c.price,h=c.price!==0?u/c.price*100:0,p=t.barsBetween?Math.round(t.barsBetween(c.time,d.time)):null,m=u>=0,f=m?oA:iA,g=Math.min(o,s),b=Math.max(o,s),y=Math.min(i,a),w=Math.max(i,a),C=(o+s)/2,M=(i+a)/2;e.save(),e.globalAlpha=.12,e.fillStyle=f,e.fillRect(g,y,b-g,w-y),e.globalAlpha=1,e.strokeStyle=f,e.lineWidth=1,e.setLineDash([4,4]),e.beginPath(),e.moveTo(C,i),e.lineTo(C,a),e.moveTo(o,M),e.lineTo(s,M),e.stroke(),e.setLineDash([]);let S=m?y:w,L=m?1:-1;e.fillStyle=f,e.beginPath(),e.moveTo(C,S),e.lineTo(C-5,S+L*7),e.lineTo(C+5,S+L*7),e.closePath(),e.fill(),e.restore(),this.paintLabel(e,t,n,C,y,w,f,[`${H0(u)} (${H0(h)}%)`,p!=null?`${p} bars \xB7 ${wi(d.time-c.time)}`:wi(d.time-c.time)]);}paintLabel(e,t,n,o,i,s,a,l){e.save(),e.font=`12px ${n.fontFamily}`;let c=Math.max(...l.map(f=>e.measureText(f).width))+16,d=16,u=l.length*d+8,h=s+8;h+u>t.height&&(h=i-u-8);let p=o-c/2;e.fillStyle=n.background,e.strokeStyle=a,e.lineWidth=1,e.beginPath(),e.roundRect(p,h,c,u,4),e.fill(),e.stroke(),e.fillStyle=n.textColor,e.textAlign="center",e.textBaseline="middle",l.forEach((f,g)=>e.fillText(f,o,h+8+d/2+g*d)),e.restore();}};function z0(r,e){if(e.editingText)return null;if(r.ctrlKey||r.metaKey)switch(r.key.toLowerCase()){case "z":return r.shiftKey?{kind:"redo"}:{kind:"undo"};case "y":return {kind:"redo"};case "c":return e.hasSelection?{kind:"copy"}:null;case "v":return {kind:"paste"};case "d":return e.hasSelection?{kind:"duplicate"}:null;default:return null}if(r.key==="Delete"||r.key==="Backspace")return e.hasTarget?{kind:"delete"}:null;if(e.hasSelection){let n=r.shiftKey?10:1;switch(r.key){case "ArrowLeft":return {kind:"nudge",dx:-n,dy:0};case "ArrowRight":return {kind:"nudge",dx:n,dy:0};case "ArrowUp":return {kind:"nudge",dx:0,dy:-n};case "ArrowDown":return {kind:"nudge",dx:0,dy:n}}}return null}function W0(r){let e=r;return !e||!e.tagName?false:e.tagName==="INPUT"||e.tagName==="TEXTAREA"||e.isContentEditable===true}var G0="Enter Text",aA=8,fp=1;function gp(r){return r instanceof Xt||r instanceof bn}var lA={};function $0(r,e){return e.length===0||r>e[e.length-1]?null:e.find(t=>t>=r)}var xd=class{constructor(e,t,n,o){this.toolbarHost=e;this.overlayHost=t;this.canvas=n;this.deps=o;this.ctx=null;this.drawings=[];this.sliced=new Set;this.sliceCache=new Map;this.lastBounds=new Map;this.selectedIds=new Set;this.hoveredId=null;this.activeTool=null;this.intentCb=null;this.externalGhost=null;this.seriesGw=null;this.seriesGwUnsub=null;this.lastDraftKey=null;this.measure=new wd;this.toolbarVisible=false;this.toolbarCollapsed=false;this.mobileLayout=false;this.historyChords=true;this.measureMode=false;this.eraserMode=false;this.erasing=false;this.textEditor=null;this.painter=new pd;this.popupMulti=false;this.onPopupDismissed=e=>{if(e&&(e.shiftKey||e.ctrlKey||e.metaKey))return;let t=this.interaction.pressedId();t&&this.selectedIds.has(t)||this.clearSelection();};this.ctx=n.getContext("2d"),this.popup=new bd(t,o.theme(),()=>o.chartBarMs()),this.toolbar=new $s(e,o.theme(),i=>this.emit({kind:"arm",type:i}),i=>{this.deps.setSnapMode(i),this.emit({kind:"snap-mode",mode:i});},()=>this.withModeIntent(()=>this.toggleMeasure()),()=>this.withModeIntent(()=>this.toggleEraser()),(i,s)=>this.emit({kind:"favorite",type:i,on:s}),i=>this.emit({kind:"stay-mode",on:i}),{onCollapse:i=>{this.toolbarCollapsed=i,this.syncToolbarGutter();}}),this.interaction=new fd({projector:()=>this.deps.projector(),activeTool:()=>this.activeTool,drawings:()=>this.drawings,hoveredId:()=>this.hoveredId,selectedIds:()=>this.selectedIds,emit:i=>this.emit(i),changed:()=>{this.invalidateSlices(),this.render();},openSettings:(i,s,a)=>this.openSettingsById(i,s,a),snap:(i,s,a,l)=>this.deps.snap(i,s,a,l),lastStyle:()=>this.activeToolStyle});}setToolbar(e){this.toolbar.setDefinition(e);}showToolbar(e){this.toolbarVisible=e,this.toolbar.setVisible(e&&!this.mobileLayout),this.syncToolbarGutter();}setLayoutMode(e){this.mobileLayout=e==="mobile",this.toolbar.setVisible(this.toolbarVisible&&!this.mobileLayout),this.syncToolbarGutter();}syncToolbarGutter(){let e=this.toolbarVisible&&!this.mobileLayout;this.deps.setToolbarGutter(e?this.toolbarCollapsed?mp:pp:0);}setSeriesGateway(e){this.seriesGwUnsub?.(),this.seriesGw=e,this.seriesGwUnsub=e.onUpdate(()=>{this.invalidateSlices(),this.render(),this.deps.requestDataPaint();});}get seriesGateway(){return this.seriesGw}setExternalGhost(e){this.externalGhost=e?wt(e):null,this.render();}syncDrawings(e){this.drawings=e.map(t=>wt(t)).filter(t=>t!=null),this.textEditor&&!this.editedDrawing(this.textEditor.id)&&this.closeTextEditor(),this.invalidateSlices(),this.render(),this.deps.requestScaleUpdate();}stackRange(e){let t=this.deps.seriesBoundaries(e);return {front:Math.max(0,...t),back:Math.min(0,...t),price:this.deps.priceZ(e)??void 0}}priceRangeForPane(e,t,n){let o=1/0,i=-1/0;for(let s of this.drawings){if(!s.visible||s.paneId!==e)continue;let a=s.timeExtent();if(a&&(a.maxn))continue;let l=s.priceRange();l&&(l.mini&&(i=l.max));}return o<=i?{min:o,max:i}:null}setActiveTool(e,t){e!=null&&(this.finishTextEditor(true),this.withModeIntent(()=>{this.measureMode&&this.exitMeasure(),this.eraserMode&&this.exitEraser();})),this.activeTool=e,this.activeToolStyle=t,this.toolbar.setActiveTool(e),e==null?this.interaction.onToolCleared():this.clearSelection(),this.render();}setFavorites(e){this.toolbar.setFavorites(e);}setToolShortcuts(e){this.toolbar.setShortcuts(e);}setSnapMode(e){this.deps.setSnapMode(e),this.toolbar.setMagnetMode(e);}setStayMode(e){this.toolbar.setStayMode(e);}setMode(e){this.withModeIntent(()=>{e==="measure"?this.measureMode||this.toggleMeasure():e==="eraser"?this.eraserMode||this.toggleEraser():(this.measureMode&&this.exitMeasure(),this.eraserMode&&this.exitEraser());});}modeOf(){return this.measureMode?"measure":this.eraserMode?"eraser":null}withModeIntent(e){let t=this.modeOf();e();let n=this.modeOf();n!==t&&this.emit({kind:"mode",mode:n});}setSelection(e){this.selectedIds=new Set(e),e.length>=2?this.openSettingsForSelection(e):this.popupMulti&&(this.popupMulti=false,this.popup.close(),e.length===1&&this.openSettingsById(e[0],0,0)),this.render();}openSettings(e){this.openSettingsById(e,0,0);}onDrawingIntent(e){return this.intentCb=e,()=>{this.intentCb===e&&(this.intentCb=null);}}claim(e,t){return this.measureMode||this.eraserMode||this.magnifierChipAt(e,t)?true:this.interaction.claim(e,t)}magnifierChipAt(e,t){for(let n=this.drawings.length-1;n>=0;n-=1){let o=this.drawings[n];if(!(o instanceof ht)||!o.visible||o.locked)continue;let i=o.chipRect;if(i&&e>=i.x&&e<=i.x+i.w&&t>=i.y&&t<=i.y+i.h)return o}return null}openMagnifierChipMenu(e){let t=e.chipRect;if(!t)return;let n=e.id;this.popup.openMagnifierTimeframeMenu(t,e.magnifier.timeframe,o=>{let i=this.drawings.find(s=>s.id===n);i instanceof ht&&(i.applySettings({"magnifier.timeframe":o}),this.render(),this.emit({kind:"edit",doc:i.serialize()}));});}deleteAt(e,t,n=false){let o=Jo(this.drawings,e,t,this.deps.projector(),6);if(!o)return false;let i=k0(o,this.selectedIds,this.drawings,n);return i.length===0?false:(this.popup.close(),this.emit({kind:"delete",ids:i}),true)}beginMeasureAt(e,t,n="off"){if(this.measureMode||this.eraserMode||this.activeTool!=null)return false;this.withModeIntent(()=>this.toggleMeasure());let o=this.interaction.snapCursor(e,t,n);return this.measure.down(e,t,o.x,o.y),this.render(),true}clearTransient(){this.textEditor&&this.finishTextEditor(true),this.measure.isFinished()&&(this.measure.clear(),this.render());}beginMarqueeAt(e,t){return this.measureMode||this.eraserMode||!this.interaction.beginMarquee(e,t)?false:(this.render(),true)}pointerDown(e,t,n="off",o=false,i=false){if(this.eraserMode){this.erasing=true,this.deleteAt(e,t);return}if(this.measureMode){let s=this.interaction.snapCursor(e,t,n);this.measure.down(e,t,s.x,s.y),this.measure.isFinished()&&this.withModeIntent(()=>this.exitMeasure(false)),this.render();return}if(this.activeTool==null){let s=this.magnifierChipAt(e,t);if(s){this.openMagnifierChipMenu(s);return}}this.interaction.down(e,t,n,o,i);}pointerMove(e,t,n="off",o=false,i=false){if(this.eraserMode){this.erasing&&this.deleteAt(e,t);return}if(this.measureMode){let s=this.interaction.snapCursor(e,t,n);this.measure.move(s.x,s.y),this.render();return}this.interaction.move(e,t,n,o),this.updateHover(e,t,i);}updateHover(e,t,n=false){let o=null;!n&&this.activeTool==null&&!this.interaction.isPlacing()&&!this.interaction.isDragging()&&(o=Jo(this.drawings,e,t,this.deps.projector(),6)?.id??null),o!==this.hoveredId&&(this.hoveredId=o,this.render());}pointerUp(e,t,n="off"){if(this.eraserMode){this.erasing=false;return}if(this.measureMode){let i=this.interaction.snapCursor(e,t,n);this.measure.up(e,t,i.x,i.y),this.measure.isFinished()&&this.withModeIntent(()=>this.exitMeasure(false)),this.render();return}let o=this.interaction.isDragging()?this.interaction.pressedId():null;this.interaction.up(e,t),o&&this.selectedIds.has(o)&&!this.popup.isOpen()&&(this.selectedIds.size>=2?this.openSettingsForSelection(this.selectionIds()):this.openSettingsById(o,e,t));}toggleMeasure(){if(this.measureMode){this.exitMeasure();return}this.eraserMode&&this.exitEraser(),this.measure.clear(),this.measureMode=true,this.emit({kind:"arm",type:null}),this.clearSelection(),this.toolbar.setMeasureActive(true),this.render();}toggleEraser(){if(this.eraserMode){this.exitEraser();return}this.measureMode&&this.exitMeasure(),this.eraserMode=true,this.erasing=false,this.emit({kind:"arm",type:null}),this.clearSelection(),this.toolbar.setEraserActive(true),this.render();}exitEraser(){this.eraserMode=false,this.erasing=false,this.toolbar.setEraserActive(false),this.render();}exitMeasure(e=true){this.measureMode=false,this.interaction.clearSnapMarker(),e&&this.measure.clear(),this.toolbar.setMeasureActive(false),this.render();}editTextInline(e){let t=this.editedDrawing(e);if(!t)return;this.closeTextEditor();let n=t.text?.value??"",o=this.inlineEditorCss(t,n);if(!o)return;let i=document.createElement("textarea");i.value=n,i.placeholder=G0,i.spellcheck=false,i.style.cssText=o;let s=()=>{this.editedDrawing(e)?.applySettings({"text.value":i.value}),this.render();};i.addEventListener("input",s),i.addEventListener("pointerdown",a=>a.stopPropagation()),i.addEventListener("keydown",a=>{if(a.stopPropagation(),a.key==="Enter"&&!a.ctrlKey&&!a.metaKey){a.preventDefault();let l=i.selectionStart;i.setRangeText(` -`,l,i.selectionEnd,"end"),s();}else a.key==="Enter"?(a.preventDefault(),this.finishTextEditor(true)):a.key==="Escape"&&(a.preventDefault(),this.finishTextEditor(false));}),i.addEventListener("blur",a=>{this.popup.contains(a.relatedTarget)?this.storeText(i.value):this.finishTextEditor(true);}),this.overlayHost.appendChild(i),this.textEditor={el:i,id:e,initial:n,stored:n},i.focus(),i.setSelectionRange(i.value.length,i.value.length);}storeText(e){let t=this.textEditor,n=t&&this.editedDrawing(t.id);!t||!n||(n.applySettings({"text.value":e}),e!==t.stored&&(t.stored=e,this.emit({kind:"edit",doc:n.serialize()})));}editedDrawing(e){let t=this.drawings.find(n=>n.id===e);return gp(t)?t:null}finishTextEditor(e){let t=this.textEditor;if(!t)return;let n=e?t.el.value:t.initial;this.closeTextEditor();let o=this.editedDrawing(t.id);o&&(o.applySettings({"text.value":n}),this.render(),o instanceof bn&&n.trim()===""?(this.clearSelection(),this.emit({kind:"delete",ids:[o.id]})):n!==t.stored&&this.emit({kind:"edit",doc:o.serialize()}));}inlineEditorCss(e,t){let n=this.deps.projector(),o=this.deps.theme(),i=e.text,s=Ke(i?.size??"normal"),a=`${i?.italic?"italic ":""}${i?.bold?"bold ":""}${s}px ${o.fontFamily}`,l="position:absolute;z-index:24;box-sizing:border-box;resize:none;overflow:hidden;margin:0;outline:none;pointer-events:auto;text-align:left;";if(e instanceof Xt){let p=e.box(n);if(!p)return null;let m=e.style.fillColor??o.background;return l+`left:${Math.round(p.x)}px;top:${Math.round(p.y)}px;width:${Math.round(p.w)}px;height:${Math.round(p.h)}px;padding:5px 8px;border-radius:5px;border:1px solid ${e.style.lineColor??o.borderColor};background:${Sh(m,o.background,Qn(m).alpha)};color:${i?.color??o.textColor};font:${a};`}let c=e.handlePoints(n)[0];if(!c)return null;let d=pn(s),u=(t||G0).split(` -`),h=Math.ceil(this.measureTextWidth(u,a))+aA;return l+`left:${Math.round(c[0]+2)-Gr}px;top:${Math.round(c[1]+2-(d-s)/2)-$r}px;width:${h+Gr*2}px;height:${u.length*d+$r*2}px;padding:${$r-fp}px ${Gr-fp}px;border:${fp}px solid ${J(o.textColor,.3)};border-radius:4px;background:transparent;color:${i?.color??o.textColor};font:${a};line-height:${d}px;white-space:pre;`}measureTextWidth(e,t){let n=this.ctx;if(!n)return 120;let o=n.font;n.font=t;let i=Math.max(8,...e.map(s=>n.measureText(s).width));return n.font=o,i}layoutTextEditor(){let e=this.textEditor;if(!e)return;let t=this.editedDrawing(e.id),n=t&&this.inlineEditorCss(t,e.el.value);n&&(e.el.style.cssText=n);}closeTextEditor(){let e=this.textEditor;e&&(this.textEditor=null,e.el.remove(),this.render());}cursorAt(e,t){return this.eraserMode||this.activeTool==null&&this.magnifierChipAt(e,t)?"pointer":this.interaction.cursorAt(e,t)}cancelPlacement(){return this.measureMode||this.eraserMode?(this.withModeIntent(()=>this.measureMode?this.exitMeasure():this.exitEraser()),true):this.interaction.isPlacing()?(this.interaction.cancel(),this.activeTool!=null&&this.emit({kind:"arm",type:null}),true):this.activeTool!=null?(this.emit({kind:"arm",type:null}),true):false}dblClick(e,t){if(this.interaction.finishPlacing(true))return true;let n=Jo(this.drawings,e,t,this.deps.projector(),6);return gp(n)?(this.editTextInline(n.id),true):n!=null}handleKey(e){if(e.key==="Escape")return this.textEditor?(this.finishTextEditor(false),true):this.popup.isOpen()?(this.clearSelection(),true):this.interaction.cancel()?true:this.measureMode?(this.withModeIntent(()=>this.exitMeasure()),true):this.selectedIds.size?(this.clearSelection(),true):false;if(e.key==="Enter"&&this.interaction.finishPlacing(false))return true;let t=z0(e,{hasSelection:this.selectedIds.size>0,hasTarget:this.selectedIds.size>0||this.hoveredId!=null,editingText:W0(e.target)});if(!t)return false;switch(t.kind){case "undo":if(!this.historyChords)return false;this.emit({kind:"undo"});break;case "redo":if(!this.historyChords)return false;this.emit({kind:"redo"});break;case "copy":this.emit({kind:"copy",ids:this.selectionIds()});break;case "paste":this.emit({kind:"paste"});break;case "duplicate":this.emit({kind:"duplicate",ids:this.selectionIds()});break;case "delete":{let n=this.selectedIds.size?this.deletableSelection():this.hoveredId?[this.hoveredId]:[];n.length&&(this.popup.close(),this.emit({kind:"delete",ids:n}));break}case "nudge":this.nudgeSelection(t.dx,t.dy);break}return true}selectionIds(){return [...this.selectedIds]}deletableSelection(){return lp(this.selectedIds,this.drawings)}nudgeSelection(e,t){let n=this.deps.projector(),o=[];for(let i of this.drawings){if(!this.selectedIds.has(i.id)||i.locked)continue;let s=i.anchors.map(l=>{let c=n.yOf(l.price,i.paneId);return c==null?{time:l.time,price:l.price}:n.pxToPoint(n.xOf(l.time)+e,c+t,i.paneId)}),a=i.serialize();a.anchors=s,o.push(a);}o.length===1?this.emit({kind:"edit",doc:o[0]}):o.length>1&&this.emit({kind:"edit-many",docs:o});}setTheme(e){this.popup.setTheme(e),this.toolbar.setTheme(e),this.render();}onResize(){this.finishTextEditor(true),this.popup.close(),this.render();}isInterleaved(e){return $0(e.zIndex,this.lastBounds.get(e.paneId)??[])!==null}invalidateSlices(){(this.sliced.size>0||this.drawings.some(e=>this.isInterleaved(e)))&&this.deps.requestDataPaint();}prepareSlices(e){this.sliced.clear(),this.lastBounds=new Map(e.map(a=>[a,this.deps.seriesBoundaries(a)]));let t=new Map,n=this.deps.dpr(),o=this.deps.projector(),i=this.deps.theme(),s=new Map;for(let a of this.drawings){if(!a.visible)continue;let l=$0(a.zIndex,this.lastBounds.get(a.paneId)??[]);if(l===null)continue;let c=`${a.paneId}|${l}`,d=s.get(c);d?d.drawings.push(a):s.set(c,{paneId:a.paneId,beforeZ:l,drawings:[a]}),this.sliced.add(a.id);}for(let[a,{paneId:l,beforeZ:c,drawings:d}]of s){let u=this.sliceCache.get(a);u||(u=document.createElement("canvas"),this.sliceCache.set(a,u)),(u.width!==this.canvas.width||u.height!==this.canvas.height)&&(u.width=this.canvas.width,u.height=this.canvas.height);let h=u.getContext("2d");if(!h)continue;h.setTransform(n,0,0,n,0,0),h.clearRect(0,0,u.width/n,u.height/n),this.painter.seriesLook=this.deps.seriesLook(),this.painter.paintAll(h,d,o,i,lA);let p=t.get(l)??[];p.push({beforeZ:c,canvas:u}),t.set(l,p);}for(let a of [...this.sliceCache.keys()])s.has(a)||this.sliceCache.delete(a);for(let a of t.values())a.sort((l,c)=>l.beforeZ-c.beforeZ);return t}render(){let e=this.ctx;if(!e)return;let t=this.deps.dpr();e.setTransform(t,0,0,t,0,0),e.clearRect(0,0,this.canvas.width/t,this.canvas.height/t);let n=this.deps.projector(),o=this.textEditor?this.editedDrawing(this.textEditor.id):null,i={selected:this.selectedIds,hovered:this.hoveredId,dragged:this.interaction.activeDragId(),mutedLabel:o instanceof bn?o.id:null};this.painter.seriesLook=this.deps.seriesLook(),this.painter.paintAll(e,this.drawings.filter(h=>!this.isInterleaved(h)),n,this.deps.theme(),i),this.painter.paintHighlights(e,this.drawings.filter(h=>this.isInterleaved(h)),n,ap(i));let s=this.interaction.dragClones();s&&this.painter.paintAll(e,s,n,this.deps.theme(),{selected:new Set(s.map(h=>h.id))}),this.layoutTextEditor();let a=this.interaction.ghost();if(a&&this.painter.paintGhost(e,a,n,this.deps.theme()),this.externalGhost&&this.painter.paintGhost(e,this.externalGhost,n,this.deps.theme()),this.emitDraft(a),this.activeTool&&!a){let h=Nt(this.activeTool)?.placementHint;h&&this.painter.paintPlacementHint(e,h,this.deps.theme(),n.width,n.height);}let l=this.interaction.placingMarkers(n);l&&this.painter.paintHandles(e,l);let c=this.interaction.snapMarker(),d=c?n.yOf(c.point.price,c.paneId):null;c&&d!=null&&this.painter.paintSnapRing(e,n.xOf(c.point.time),d,this.deps.theme()),this.measure.isActive()&&this.measure.paint(e,n,this.deps.theme());let u=this.interaction.marqueeRect();u&&this.painter.paintMarquee(e,u);}destroy(){this.closeTextEditor(),this.popup.destroy(),this.toolbar.destroy(),this.seriesGwUnsub?.(),this.seriesGwUnsub=null,this.seriesGw=null,this.intentCb=null,this.drawings=[];}clearSelection(){this.popup.close(),this.selectedIds.size&&this.emit({kind:"select",ids:[]}),this.render();}emitEdits(e){let t=e.map(n=>n.serialize());t.length===1?this.emit({kind:"edit",doc:t[0]}):t.length>1&&this.emit({kind:"edit-many",docs:t});}openSettingsForSelection(e){let t=()=>e.map(s=>this.drawings.find(a=>a.id===s)).filter(s=>s!=null),n=t();if(n.length<2)return;let o=this.deps.projector(),i=null;for(let s of n){let a=s.bounds(o);if(a)if(!i)i={...a};else {let l=Math.max(i.x+i.w,a.x+a.w),c=Math.max(i.y+i.h,a.y+a.h);i.x=Math.min(i.x,a.x),i.y=Math.min(i.y,a.y),i.w=l-i.x,i.h=c-i.y;}}this.popupMulti=true,this.emit({kind:"settings",id:n[0].id}),this.popup.open(n,i,{resolve:()=>t()[0]??null,patch:s=>{let a=t();for(let l of a)l.applySettings(s);this.render(),this.emitEdits(a);},setLocked:s=>{let a=t();for(let l of a)l.locked=s;this.emitEdits(a);},reorder:s=>{for(let a of t())this.emit({kind:"reorder",id:a.id,to:s});},duplicate:()=>{this.popup.close(),this.emit({kind:"duplicate",ids:t().map(s=>s.id)});},resetSettings:()=>{let s=t();for(let a of s)ml(a);this.render(),this.emitEdits(s),this.openSettingsForSelection(e);},remove:()=>{let s=t().filter(a=>!a.locked).map(a=>a.id);s.length!==0&&(this.popup.close(),this.emit({kind:"delete",ids:s}));}},this.onPopupDismissed);}openSettingsById(e,t,n){let o=this.drawings.find(a=>a.id===e);if(!o)return;let i=()=>this.drawings.find(a=>a.id===e);this.popupMulti=false,this.emit({kind:"select",ids:[e]}),this.emit({kind:"settings",id:e});let s=o.bounds(this.deps.projector());this.popup.open([o],s,{resolve:()=>i()??null,patch:a=>{let l=i();l&&(l.applySettings(a),this.render(),this.emit({kind:"edit",doc:l.serialize()}));},setLocked:a=>{let l=i();l&&(l.locked=a,this.emit({kind:"edit",doc:l.serialize()}));},reorder:a=>this.emit({kind:"reorder",id:e,to:a}),duplicate:()=>{this.finishTextEditor(true),this.popup.close(),this.emit({kind:"duplicate",ids:[e]});},resetSettings:()=>{let a=i();a&&(ml(a),this.render(),this.emit({kind:"edit",doc:a.serialize()}),this.openSettingsById(e,0,0));},restore:a=>{let l=i();l&&(a.style&&(l.style={...a.style}),a.text!==void 0&&(l.text=a.text?{...a.text}:void 0),a.props!==void 0&&l.applyProps(a.props),this.render(),this.emit({kind:"edit",doc:a}));},remove:()=>{this.closeTextEditor(),this.popup.close(),this.emit({kind:"delete",ids:[e]});}},this.onPopupDismissed);}deselect(){this.clearSelection();}emitDraft(e){let t=e?JSON.stringify({t:e.type,p:e.paneId,a:e.anchors,s:e.style,x:e.text}):null;t!==this.lastDraftKey&&(this.lastDraftKey=t,this.intentCb?.({kind:"draft",doc:e?e.serialize():null}));}emit(e){if(e.kind==="create"){e.doc.text&&e.doc.text.color===void 0&&(e.doc.text={...e.doc.text,color:Ye(this.deps.theme().background)});let t=new Set(this.drawings.map(n=>n.id));this.intentCb?.(e),setTimeout(()=>{let n=this.drawings.find(o=>!t.has(o.id));n&&(this.openSettingsById(n.id,0,0),gp(n)&&this.editTextInline(n.id));},0);return}if(e.kind==="clone"){let t=new Set(this.drawings.map(o=>o.id));this.intentCb?.(e);let n=this.drawings.filter(o=>!t.has(o.id));n.length===1&&this.openSettingsById(n[0].id,0,0);return}this.intentCb?.(e);}};var bp={auto:13,tiny:10,small:11,normal:13,large:16,huge:20};function vp(r){return typeof r=="number"?r>0?r:bp.auto:bp[r]??bp.auto}function U0(r){return r.cells.some(e=>e?.some(t=>t!=null&&!t.merged))}function Y0(r){let e=new Map,t=new Set;for(let n of r.merges){e.set(`${n.startRow}:${n.startCol}`,{cs:n.endCol-n.startCol+1,rs:n.endRow-n.startRow+1});for(let o=n.startRow;o<=n.endRow;o+=1)for(let i=n.startCol;i<=n.endCol;i+=1)(o!==n.startRow||i!==n.startCol)&&t.add(`${o}:${i}`);}for(let n=0;n0?e.frameWidth:0,{x:s,y:a}=dA(e.position,o.w+2*i,o.h+2*i,t),l=s+i,c=a+i;e.bgColor&&(r.fillStyle=e.bgColor,r.fillRect(l,c,o.w,o.h)),i>0&&e.frameColor&&(r.strokeStyle=e.frameColor,r.lineWidth=i,r.strokeRect(s+i/2,a+i/2,o.w+i,o.h+i));let d=[0];for(let m of o.colW)d.push(d[d.length-1]+m);let u=[0];for(let m of o.rowH)u.push(u[u.length-1]+m);let h=r.textBaseline,p=r.textAlign;r.textBaseline="middle";for(let m of o.boxes){let f=l+d[m.c],g=c+u[m.r],b=d[m.c+m.cs]-d[m.c],y=u[m.r+m.rs]-u[m.r],w=m.cell;w.bgColor&&(r.fillStyle=w.bgColor,r.fillRect(f,g,b,y));let C=w.text??"";if(C.length>0){let M=vp(w.textSize);r.font=X0(w,M,t.theme),r.fillStyle=w.textColor??t.theme.textColor;let S=C.split(` -`),L=S.length*M*xp,v=w.vAlign==="top"?g+wp:w.vAlign==="bottom"?g+y-wp-L:g+(y-L)/2,k=w.hAlign==="left"?f+yp:w.hAlign==="right"?f+b-yp:f+b/2;r.textAlign=w.hAlign,S.forEach((x,E)=>r.fillText(x,k,v+(E+.5)*M*xp));}w.tooltip&&n.push({left:f,top:g,right:f+b,bottom:g+y,text:w.tooltip});}if(r.textBaseline=h,r.textAlign=p,e.borderColor&&e.borderWidth>0){r.strokeStyle=e.borderColor,r.lineWidth=e.borderWidth;let m=new Set;r.beginPath();let f=(g,b,y,w)=>{let C=`${g},${b},${y},${w}`;m.has(C)||(m.add(C),r.moveTo(g,b),r.lineTo(y,w));};for(let g of o.boxes){let b=Math.round(l+d[g.c]),y=Math.round(l+d[g.c+g.cs]),w=Math.round(c+u[g.r]),C=Math.round(c+u[g.r+g.rs]);f(b,w,y,w),f(b,C,y,C),f(b,w,b,C),f(y,w,y,C);}r.stroke();}}function cA(r,e,t){let{span:n,omit:o}=Y0(e),i=new Array(e.columns).fill(0),s=new Array(e.rows).fill(0),a=[];for(let h=0;h{let p=vp(h.textSize);r.font=X0(h,p,t.theme);let m=(h.text??"").split(` -`),f=0;for(let y of m)f=Math.max(f,r.measureText(y).width);let g=Math.ceil(f)+2*yp,b=Math.ceil(m.length*p*xp)+2*wp;return h.width&&(g=Math.max(g,h.width/100*t.plotWidth)),h.height&&(b=Math.max(b,h.height/100*t.paneHeight)),{w:g,h:b}},c=[];for(let h of a){let{w:p,h:m}=l(h.cell);h.cs===1&&(i[h.c]=Math.max(i[h.c],p)),h.rs===1&&(s[h.r]=Math.max(s[h.r],m)),(h.cs>1||h.rs>1)&&c.push({box:h,w:p,h:m});}for(let{box:h,w:p,h:m}of c){if(h.cs>1){let f=0;for(let g=h.c;gf)for(let g=h.c;g1){let f=0;for(let g=h.r;gf)for(let g=h.r;gt>r)??1/0}var Sd=class{constructor(){this.drawScene=new qo({timeToLogical:()=>0,barAt:()=>null,theme:{}});this.sliceCache=new Map;this.tips=[];}prepare(e,t,n,o){this.tips=[];let i=new Map;if(o.width===0||o.height===0)return this.sliceCache.clear(),i;this.drawScene.setDeps({timeToLogical:d=>t.timeToLogical(d),barAt:d=>{let u=e.bars[Math.round(d)];return u?{high:u.high,low:u.low}:null},theme:n});let s=t.dpr,a=t.width,l=new Map,c=(d,u,h)=>{let p=`${d}|${u}`,m=l.get(p);m?m.entries.push(h):l.set(p,{paneId:d,beforeZ:u,entries:[h]});};for(let d of e.orderedPanes()){if(d.collapsed)continue;let u=e.seriesBoundaries(d.id);for(let h of e.orderedIndicatorsForPane(d.id)){let p=Zo(h,false),m=(h.tables??[]).filter(y=>!y.overlay);if(Xh(p)&&m.length===0)continue;let f=e.scaleFor(h,d),g=f===d.scale?d:{...d,scale:f},b=uA(e.zOf(h.id),u);c(d.id,b,{set:p,tables:m,pane:g,indexOffset:e.offsetOf(h.id)});}if(d.kind==="price")for(let h of e.indicators.values()){let p=Zo(h,true),m=(h.tables??[]).filter(f=>f.overlay===true);Xh(p)&&m.length===0||c(d.id,1/0,{set:p,tables:m,pane:d,indexOffset:e.offsetOf(h.id)});}}for(let[d,{paneId:u,beforeZ:h,entries:p}]of l){let m=this.sliceCache.get(d);m||(m=document.createElement("canvas"),this.sliceCache.set(d,m)),(m.width!==o.width||m.height!==o.height)&&(m.width=o.width,m.height=o.height);let f=m.getContext("2d");if(!f)continue;f.setTransform(s,0,0,s,0,0),f.clearRect(0,0,m.width/s,m.height/s);for(let b of p)this.paintEntry(f,b,t,a,n);let g=i.get(u)??[];g.push({beforeZ:h,canvas:m}),i.set(u,g);}for(let d of [...this.sliceCache.keys()])l.has(d)||this.sliceCache.delete(d);for(let d of i.values())d.sort((u,h)=>u.beforeZ-h.beforeZ);return i}paintEntry(e,t,n,o,i){let{pane:s}=t,a=[];e.save(),e.translate(0,s.bounds.top),e.beginPath(),e.rect(0,0,o,s.bounds.height),e.clip(),this.drawScene.setSet(t.set,t.indexOffset),this.drawScene.render(e,o,s.bounds.height,l=>n.logicalToX(l),l=>n.priceToY(l,s.scale,s.bounds)-s.bounds.top),a.push(...this.drawScene.labelTipRegions());for(let l of t.tables)K0(e,l,{paneHeight:s.bounds.height,plotWidth:o,theme:i},a);e.restore();for(let l of a)this.tips.push({...l,top:l.top+s.bounds.top,bottom:l.bottom+s.bounds.top});}labelTooltipAt(e,t){for(let n=this.tips.length-1;n>=0;n-=1){let o=this.tips[n];if(e>=o.left&&e<=o.right&&t>=o.top&&t<=o.bottom)return o.text}return null}};function j0(r,e){let t=new Map;for(let[n,o]of r)t.set(n,[...o]);for(let[n,o]of e)t.set(n,[...t.get(n)??[],...o]);for(let n of t.values())n.sort((o,i)=>o.beforeZ-i.beforeZ);return t}function q0(r,e,t,n,o){return {xOf:i=>r.timeToX(i),yOf:(i,s)=>{let a=e(s);return a?r.priceToY(i,a.scale,a.bounds):null},pxToPoint:(i,s,a)=>{let l=e(a),c=r.logicalToTime(r.xToLogical(i)),d=l?r.yToPrice(s,l.scale,l.bounds):0;return {time:c,price:d}},paneIdAtY:t,paneRect:i=>{let s=e(i);return s?{top:s.bounds.top,height:s.collapsed?0:s.bounds.height}:null},barsBetween:(i,s)=>Math.abs(r.timeToLogical(s)-r.timeToLogical(i)),barsInRange:n?(i,s)=>n(i,s):void 0,seriesInRange:o,width:r.width,height:r.height}}function Td(r,e,t,n,o,i,s=false,a=()=>0,l=Nh){let c=1/0,d=-1/0,u=g=>{g!=null&&Number.isFinite(g)&&(gd&&(d=g));};if(t)for(let g=n;g<=o;g+=1){let b=e[g];b&&(u(b.high),u(b.low));}for(let g of r){let b=a(g.id);for(let y of g.series)y.overlay!==true&&Z0(y,n,o,b,u);for(let y of g.priceLines)u(y.price);}if(i&&(u(i.min),u(i.max)),c===1/0||d===-1/0)return {min:0,max:1};if(c===d){let g=Math.abs(c)*.1||1;return {min:c-g,max:d+g,log:s&&c-g>0}}let h=Math.max(.1,1-(l.top+l.bottom)/100),p=l.top/100/h,m=l.bottom/100/h;if(s&&c>0){let g=Math.log(c),b=Math.log(d),y=b-g;return {min:Math.exp(g-y*m),max:Math.exp(b+y*p),log:true}}let f=d-c;return {min:c-f*m,max:d+f*p}}function Z0(r,e,t,n,o){if(ta(r)){if(r.kind==="candle"||r.kind==="bar")for(let i=e;i<=t;i+=1){let s=r.bars[i-n];s&&(o(s.high),o(s.low));}else if(Ge(r)){for(let i=e;i<=t;i+=1)o(r.points[i-n]?.value);r.kind==="histogram"||r.kind==="columns"?o(r.style?.base??0):r.style?.base!=null&&o(r.style.base);}}}function Q0(r,e,t,n=()=>0){let o=1/0,i=-1/0,s=a=>{a!=null&&Number.isFinite(a)&&(ai&&(i=a));};for(let a of r){let l=n(a.id);for(let c of a.series)c.overlay===true&&Z0(c,e,t,l,s);}return o===1/0?null:{min:o,max:i}}function J0(r,e,t,n){if(t<=0&&n<=0)return r;let o=e-t-n;if(!(o>=8))return r;if(r.log&&r.min>0&&r.max>r.min){let s=Math.log(r.min),a=Math.log(r.max),l=(a-s)/o;return {...r,min:Math.exp(s-n*l),max:Math.exp(a+t*l)}}if(r.max<=r.min)return r;let i=(r.max-r.min)/o;return {...r,min:r.min-n*i,max:r.max+t*i}}var hA=new Set(["a","abbr","b","blockquote","br","code","dd","del","div","dl","dt","em","h1","h2","h3","h4","h5","h6","hr","i","img","ins","kbd","li","mark","ol","p","pre","q","s","small","span","strong","sub","sup","table","tbody","td","tfoot","th","thead","tr","u","ul"]),pA=new Set(["script","style","iframe","frame","frameset","object","embed","applet","form","input","textarea","button","select","option","link","meta","base","svg","math","template","noscript","audio","video","canvas","dialog","head","title"]),mA={a:new Set(["href"]),img:new Set(["src","alt","width","height"]),td:new Set(["colspan","rowspan"]),th:new Set(["colspan","rowspan"]),ol:new Set(["start"])},fA=new Set(["javascript","vbscript","data","file","blob"]);function gA(r){let e=r.toLowerCase();return pA.has(e)?"drop":hA.has(e)?"keep":"unwrap"}function bA(r,e){let t=e.toLowerCase();return t.startsWith("on")||t==="style"?false:t==="title"?true:mA[r.toLowerCase()]?.has(t)??false}function vA(r,e=false){let t="";for(let i of r)i.charCodeAt(0)>32&&(t+=i);let n=/^([a-z][a-z0-9+.-]*):/i.exec(t),o=n?n[1].toLowerCase():null;return o!==null&&fA.has(o)||e&&o!=="http"&&o!=="https"?null:t}var yA=1,wA=3;function ex(r,e){let t=e.createElement("template");t.innerHTML=r;let n=e.createDocumentFragment();return Cp(t.content,n,e),n}function Cp(r,e,t){for(let n of Array.from(r.childNodes)){if(n.nodeType===wA){e.appendChild(t.createTextNode(n.textContent??""));continue}if(n.nodeType!==yA)continue;let o=n,i=o.tagName.toLowerCase(),s=gA(i);if(s==="drop")continue;if(s==="unwrap"){Cp(o,e,t);continue}let a=t.createElement(i);for(let l of Array.from(o.attributes)){let c=l.name.toLowerCase();if(!bA(i,c))continue;let d=l.value;if(c==="href"||c==="src"){let u=vA(d,c==="src");if(u===null)continue;d=u;}a.setAttribute(c,d);}i==="a"&&(a.setAttribute("target","_blank"),a.setAttribute("rel","noopener noreferrer")),Cp(o,a,t),e.appendChild(a);}}var xA="vela-marks-popover",CA=` +.vela-dtb-flyout::-webkit-scrollbar-thumb:hover{background:var(--vela-fg-muted);}`;}var aA=ee("cursor"),lA=ee("ruler"),Ux=ee("chevrons-left"),cA=ee("chevrons-right"),dA=ee("magnet"),uA=ee("pen-lock"),hA=ee("pen-sync"),pA=ee("eraser"),mA=ee("chevron-right"),fA=ee("check"),gA=ee("star"),bA=ee("star-filled");function vp(r){return r.replace("${vp(r)}`:""}function Sd(r,e=18){return `${Yx(r,e)}`}function vA(r){return `${Yx(r,11)}`}function Kx(r){return `${r>=0?"+":""}${r.toFixed(2)}`}var yA=O,wA=D,xA=3,Cd=class{constructor(){this.state="idle";this.start=null;this.end=null;this.pressX=0;this.pressY=0;}isActive(){return this.state!=="idle"}isFinished(){return this.state==="finished"}down(e,t,n=e,o=t){if(this.state==="measuring"){this.end={x:n,y:o},this.state="finished";return}this.start={x:n,y:o},this.end={x:n,y:o},this.pressX=e,this.pressY=t,this.state="measuring";}move(e,t){this.state==="measuring"&&(this.end={x:e,y:t});}up(e,t,n=e,o=t){this.state==="measuring"&&Math.hypot(e-this.pressX,t-this.pressY)>xA&&(this.end={x:n,y:o},this.state="finished");}points(){return !this.start||!this.end?null:{start:this.start,end:this.end}}clear(){this.state="idle",this.start=null,this.end=null;}paint(e,t,n){if(!this.start||!this.end)return;let{x:o,y:i}=this.start,{x:s,y:a}=this.end,l=t.paneIdAtY(i)??t.paneIdAtY(a);if(!l)return;let c=t.pxToPoint(o,i,l),d=t.pxToPoint(s,a,l),u=d.price-c.price,h=c.price!==0?u/c.price*100:0,p=t.barsBetween?Math.round(t.barsBetween(c.time,d.time)):null,m=u>=0,f=m?yA:wA,g=Math.min(o,s),b=Math.max(o,s),y=Math.min(i,a),w=Math.max(i,a),S=(o+s)/2,M=(i+a)/2;e.save(),e.globalAlpha=.12,e.fillStyle=f,e.fillRect(g,y,b-g,w-y),e.globalAlpha=1,e.strokeStyle=f,e.lineWidth=1,e.setLineDash([4,4]),e.beginPath(),e.moveTo(S,i),e.lineTo(S,a),e.moveTo(o,M),e.lineTo(s,M),e.stroke(),e.setLineDash([]);let C=m?y:w,L=m?1:-1;e.fillStyle=f,e.beginPath(),e.moveTo(S,C),e.lineTo(S-5,C+L*7),e.lineTo(S+5,C+L*7),e.closePath(),e.fill(),e.restore(),this.paintLabel(e,t,n,S,y,w,f,[`${Kx(u)} (${Kx(h)}%)`,p!=null?`${p} bars \xB7 ${Ti(d.time-c.time)}`:Ti(d.time-c.time)]);}paintLabel(e,t,n,o,i,s,a,l){e.save(),e.font=`12px ${n.fontFamily}`;let c=Math.max(...l.map(f=>e.measureText(f).width))+16,d=16,u=l.length*d+8,h=s+8;h+u>t.height&&(h=i-u-8);let p=o-c/2;e.fillStyle=n.background,e.strokeStyle=a,e.lineWidth=1,e.beginPath(),e.roundRect(p,h,c,u,4),e.fill(),e.stroke(),e.fillStyle=n.textColor,e.textAlign="center",e.textBaseline="middle",l.forEach((f,g)=>e.fillText(f,o,h+8+d/2+g*d)),e.restore();}};function Xx(r,e){if(e.editingText)return null;if(r.ctrlKey||r.metaKey)switch(r.key.toLowerCase()){case "z":return r.shiftKey?{kind:"redo"}:{kind:"undo"};case "y":return {kind:"redo"};case "c":return e.hasSelection?{kind:"copy"}:null;case "v":return {kind:"paste"};case "d":return e.hasSelection?{kind:"duplicate"}:null;default:return null}if(r.key==="Delete"||r.key==="Backspace")return e.hasTarget?{kind:"delete"}:null;if(e.hasSelection){let n=r.shiftKey?10:1;switch(r.key){case "ArrowLeft":return {kind:"nudge",dx:-n,dy:0};case "ArrowRight":return {kind:"nudge",dx:n,dy:0};case "ArrowUp":return {kind:"nudge",dx:0,dy:-n};case "ArrowDown":return {kind:"nudge",dx:0,dy:n}}}return null}function jx(r){let e=r;return !e||!e.tagName?false:e.tagName==="INPUT"||e.tagName==="TEXTAREA"||e.isContentEditable===true}var qx="Enter Text",SA=8,xp=1;function Sp(r){return r instanceof jt||r instanceof vn}var CA={};function Zx(r,e){return e.length===0||r>e[e.length-1]?null:e.find(t=>t>=r)}var Td=class{constructor(e,t,n,o){this.toolbarHost=e;this.overlayHost=t;this.canvas=n;this.deps=o;this.ctx=null;this.drawings=[];this.sliced=new Set;this.lifted=new Set;this.sliceCache=new Map;this.lastBounds=new Map;this.selectedIds=new Set;this.hoveredId=null;this.activeTool=null;this.intentCb=null;this.externalGhost=null;this.seriesGw=null;this.seriesGwUnsub=null;this.lastDraftKey=null;this.measure=new Cd;this.toolbarVisible=false;this.toolbarCollapsed=false;this.mobileLayout=false;this.historyChords=true;this.measureMode=false;this.eraserMode=false;this.erasing=false;this.textEditor=null;this.painter=new bd;this.popupMulti=false;this.onPopupDismissed=e=>{if(e&&(e.shiftKey||e.ctrlKey||e.metaKey))return;let t=this.interaction.pressedId();t&&this.selectedIds.has(t)||this.clearSelection();};this.ctx=n.getContext("2d"),this.popup=new xd(t,o.theme(),()=>o.chartBarMs()),this.toolbar=new Xs(e,o.theme(),i=>this.emit({kind:"arm",type:i}),i=>{this.deps.setSnapMode(i),this.emit({kind:"snap-mode",mode:i});},()=>this.withModeIntent(()=>this.toggleMeasure()),()=>this.withModeIntent(()=>this.toggleEraser()),(i,s)=>this.emit({kind:"favorite",type:i,on:s}),i=>this.emit({kind:"stay-mode",on:i}),{onCollapse:i=>{this.toolbarCollapsed=i,this.syncToolbarGutter();}}),this.interaction=new yd({projector:()=>this.deps.projector(),activeTool:()=>this.activeTool,drawings:()=>this.drawings,hoveredId:()=>this.hoveredId,selectedIds:()=>this.selectedIds,emit:i=>this.emit(i),changed:()=>{this.syncLift(),this.render();},openSettings:(i,s,a)=>this.openSettingsById(i,s,a),snap:(i,s,a,l)=>this.deps.snap(i,s,a,l),lastStyle:()=>this.activeToolStyle});}setToolbar(e){this.toolbar.setDefinition(e);}showToolbar(e){this.toolbarVisible=e,this.toolbar.setVisible(e&&!this.mobileLayout),this.syncToolbarGutter();}setLayoutMode(e){this.mobileLayout=e==="mobile",this.toolbar.setVisible(this.toolbarVisible&&!this.mobileLayout),this.syncToolbarGutter();}syncToolbarGutter(){let e=this.toolbarVisible&&!this.mobileLayout;this.deps.setToolbarGutter(e?this.toolbarCollapsed?wp:yp:0);}setSeriesGateway(e){this.seriesGwUnsub?.(),this.seriesGw=e,this.seriesGwUnsub=e.onUpdate(()=>{this.invalidateSlices(),this.render(),this.deps.requestDataPaint();});}get seriesGateway(){return this.seriesGw}setExternalGhost(e){this.externalGhost=e?wt(e):null,this.render();}syncDrawings(e){this.drawings=e.map(t=>wt(t)).filter(t=>t!=null),this.textEditor&&!this.editedDrawing(this.textEditor.id)&&this.closeTextEditor(),this.invalidateSlices(),this.render(),this.deps.requestScaleUpdate();}stackRange(e){let t=this.deps.seriesBoundaries(e);return {front:Math.max(0,...t),back:Math.min(0,...t),price:this.deps.priceZ(e)??void 0}}priceRangeForPane(e,t,n){let o=1/0,i=-1/0;for(let s of this.drawings){if(!s.visible||s.paneId!==e)continue;let a=s.timeExtent();if(a&&(a.maxn))continue;let l=s.priceRange();l&&(l.mini&&(i=l.max));}return o<=i?{min:o,max:i}:null}setActiveTool(e,t){e!=null&&(this.finishTextEditor(true),this.withModeIntent(()=>{this.measureMode&&this.exitMeasure(),this.eraserMode&&this.exitEraser();})),this.activeTool=e,this.activeToolStyle=t,this.toolbar.setActiveTool(e),e==null?this.interaction.onToolCleared():this.clearSelection(),this.render();}setFavorites(e){this.toolbar.setFavorites(e);}setToolShortcuts(e){this.toolbar.setShortcuts(e);}setSnapMode(e){this.deps.setSnapMode(e),this.toolbar.setMagnetMode(e);}setStayMode(e){this.toolbar.setStayMode(e);}setMode(e){this.withModeIntent(()=>{e==="measure"?this.measureMode||this.toggleMeasure():e==="eraser"?this.eraserMode||this.toggleEraser():(this.measureMode&&this.exitMeasure(),this.eraserMode&&this.exitEraser());});}modeOf(){return this.measureMode?"measure":this.eraserMode?"eraser":null}withModeIntent(e){let t=this.modeOf();e();let n=this.modeOf();n!==t&&this.emit({kind:"mode",mode:n});}setSelection(e){this.selectedIds=new Set(e),e.length>=2?this.openSettingsForSelection(e):this.popupMulti&&(this.popupMulti=false,this.popup.close(),e.length===1&&this.openSettingsById(e[0],0,0)),this.render();}openSettings(e){this.openSettingsById(e,0,0);}onDrawingIntent(e){return this.intentCb=e,()=>{this.intentCb===e&&(this.intentCb=null);}}claim(e,t){return this.measureMode||this.eraserMode||this.magnifierChipAt(e,t)?true:this.interaction.claim(e,t)}magnifierChipAt(e,t){for(let n=this.drawings.length-1;n>=0;n-=1){let o=this.drawings[n];if(!(o instanceof ht)||!o.visible||o.locked)continue;let i=o.chipRect;if(i&&e>=i.x&&e<=i.x+i.w&&t>=i.y&&t<=i.y+i.h)return o}return null}openMagnifierChipMenu(e){let t=e.chipRect;if(!t)return;let n=e.id;this.popup.openMagnifierTimeframeMenu(t,e.magnifier.timeframe,o=>{let i=this.drawings.find(s=>s.id===n);i instanceof ht&&(i.applySettings({"magnifier.timeframe":o}),this.render(),this.emit({kind:"edit",doc:i.serialize()}));});}deleteAt(e,t,n=false){let o=ri(this.drawings,e,t,this.deps.projector(),6);if(!o)return false;let i=Rx(o,this.selectedIds,this.drawings,n);return i.length===0?false:(this.popup.close(),this.emit({kind:"delete",ids:i}),true)}beginMeasureAt(e,t,n="off"){if(this.measureMode||this.eraserMode||this.activeTool!=null)return false;this.withModeIntent(()=>this.toggleMeasure());let o=this.interaction.snapCursor(e,t,n);return this.measure.down(e,t,o.x,o.y),this.render(),true}clearTransient(){this.textEditor&&this.finishTextEditor(true),this.measure.isFinished()&&(this.measure.clear(),this.render());}beginMarqueeAt(e,t){return this.measureMode||this.eraserMode||!this.interaction.beginMarquee(e,t)?false:(this.render(),true)}pointerDown(e,t,n="off",o=false,i=false){if(this.eraserMode){this.erasing=true,this.deleteAt(e,t);return}if(this.measureMode){let s=this.interaction.snapCursor(e,t,n);this.measure.down(e,t,s.x,s.y),this.measure.isFinished()&&this.withModeIntent(()=>this.exitMeasure(false)),this.render();return}if(this.activeTool==null){let s=this.magnifierChipAt(e,t);if(s){this.openMagnifierChipMenu(s);return}}this.interaction.down(e,t,n,o,i);}pointerMove(e,t,n="off",o=false,i=false){if(this.eraserMode){this.erasing&&this.deleteAt(e,t);return}if(this.measureMode){let s=this.interaction.snapCursor(e,t,n);this.measure.move(s.x,s.y),this.render();return}this.interaction.move(e,t,n,o),this.updateHover(e,t,i);}updateHover(e,t,n=false){let o=null;!n&&this.activeTool==null&&!this.interaction.isPlacing()&&!this.interaction.isDragging()&&(o=ri(this.drawings,e,t,this.deps.projector(),6)?.id??null),o!==this.hoveredId&&(this.hoveredId=o,this.render());}clearHover(){this.hoveredId!=null&&(this.hoveredId=null,this.render());}pointerUp(e,t,n="off"){if(this.eraserMode){this.erasing=false;return}if(this.measureMode){let i=this.interaction.snapCursor(e,t,n);this.measure.up(e,t,i.x,i.y),this.measure.isFinished()&&this.withModeIntent(()=>this.exitMeasure(false)),this.render();return}let o=this.interaction.isDragging()?this.interaction.pressedId():null;this.interaction.up(e,t),o&&this.selectedIds.has(o)&&!this.popup.isOpen()&&(this.selectedIds.size>=2?this.openSettingsForSelection(this.selectionIds()):this.openSettingsById(o,e,t));}toggleMeasure(){if(this.measureMode){this.exitMeasure();return}this.eraserMode&&this.exitEraser(),this.measure.clear(),this.measureMode=true,this.emit({kind:"arm",type:null}),this.clearSelection(),this.toolbar.setMeasureActive(true),this.render();}toggleEraser(){if(this.eraserMode){this.exitEraser();return}this.measureMode&&this.exitMeasure(),this.eraserMode=true,this.erasing=false,this.emit({kind:"arm",type:null}),this.clearSelection(),this.toolbar.setEraserActive(true),this.render();}exitEraser(){this.eraserMode=false,this.erasing=false,this.toolbar.setEraserActive(false),this.render();}exitMeasure(e=true){this.measureMode=false,this.interaction.clearSnapMarker(),e&&this.measure.clear(),this.toolbar.setMeasureActive(false),this.render();}editTextInline(e){let t=this.editedDrawing(e);if(!t)return;this.closeTextEditor();let n=t.text?.value??"",o=this.inlineEditorCss(t,n);if(!o)return;let i=document.createElement("textarea");i.value=n,i.placeholder=qx,i.spellcheck=false,i.style.cssText=o;let s=()=>{this.editedDrawing(e)?.applySettings({"text.value":i.value}),this.render();};i.addEventListener("input",s),i.addEventListener("pointerdown",a=>a.stopPropagation()),i.addEventListener("keydown",a=>{if(a.stopPropagation(),a.key==="Enter"&&!a.ctrlKey&&!a.metaKey){a.preventDefault();let l=i.selectionStart;i.setRangeText(` +`,l,i.selectionEnd,"end"),s();}else a.key==="Enter"?(a.preventDefault(),this.finishTextEditor(true)):a.key==="Escape"&&(a.preventDefault(),this.finishTextEditor(false));}),i.addEventListener("blur",a=>{this.popup.contains(a.relatedTarget)?this.storeText(i.value):this.finishTextEditor(true);}),this.overlayHost.appendChild(i),this.textEditor={el:i,id:e,initial:n,stored:n},i.focus(),i.setSelectionRange(i.value.length,i.value.length);}storeText(e){let t=this.textEditor,n=t&&this.editedDrawing(t.id);!t||!n||(n.applySettings({"text.value":e}),e!==t.stored&&(t.stored=e,this.emit({kind:"edit",doc:n.serialize()})));}editedDrawing(e){let t=this.drawings.find(n=>n.id===e);return Sp(t)?t:null}finishTextEditor(e){let t=this.textEditor;if(!t)return;let n=e?t.el.value:t.initial;this.closeTextEditor();let o=this.editedDrawing(t.id);o&&(o.applySettings({"text.value":n}),this.render(),o instanceof vn&&n.trim()===""?(this.clearSelection(),this.emit({kind:"delete",ids:[o.id]})):n!==t.stored&&this.emit({kind:"edit",doc:o.serialize()}));}inlineEditorCss(e,t){let n=this.deps.projector(),o=this.deps.theme(),i=e.text,s=Ke(i?.size??"normal"),a=`${i?.italic?"italic ":""}${i?.bold?"bold ":""}${s}px ${o.fontFamily}`,l="position:absolute;z-index:24;box-sizing:border-box;resize:none;overflow:hidden;margin:0;outline:none;pointer-events:auto;text-align:left;";if(e instanceof jt){let p=e.box(n);if(!p)return null;let m=e.style.fillColor??o.background;return l+`left:${Math.round(p.x)}px;top:${Math.round(p.y)}px;width:${Math.round(p.w)}px;height:${Math.round(p.h)}px;padding:5px 8px;border-radius:5px;border:1px solid ${e.style.lineColor??o.borderColor};background:${Mh(m,o.background,Jn(m).alpha)};color:${i?.color??o.textColor};font:${a};`}let c=e.handlePoints(n)[0];if(!c)return null;let d=mn(s),u=(t||qx).split(` +`),h=Math.ceil(this.measureTextWidth(u,a))+SA;return l+`left:${Math.round(c[0]+2)-Kr}px;top:${Math.round(c[1]+2-(d-s)/2)-Xr}px;width:${h+Kr*2}px;height:${u.length*d+Xr*2}px;padding:${Xr-xp}px ${Kr-xp}px;border:${xp}px solid ${J(o.textColor,.3)};border-radius:4px;background:transparent;color:${i?.color??o.textColor};font:${a};line-height:${d}px;white-space:pre;`}measureTextWidth(e,t){let n=this.ctx;if(!n)return 120;let o=n.font;n.font=t;let i=Math.max(8,...e.map(s=>n.measureText(s).width));return n.font=o,i}layoutTextEditor(){let e=this.textEditor;if(!e)return;let t=this.editedDrawing(e.id),n=t&&this.inlineEditorCss(t,e.el.value);n&&(e.el.style.cssText=n);}closeTextEditor(){let e=this.textEditor;e&&(this.textEditor=null,e.el.remove(),this.render());}cursorAt(e,t){return this.eraserMode||this.activeTool==null&&this.magnifierChipAt(e,t)?"pointer":this.interaction.cursorAt(e,t)}cancelPlacement(){return this.measureMode||this.eraserMode?(this.withModeIntent(()=>this.measureMode?this.exitMeasure():this.exitEraser()),true):this.interaction.isPlacing()?(this.interaction.cancel(),this.activeTool!=null&&this.emit({kind:"arm",type:null}),true):this.activeTool!=null?(this.emit({kind:"arm",type:null}),true):false}dblClick(e,t){if(this.interaction.finishPlacing(true))return true;let n=ri(this.drawings,e,t,this.deps.projector(),6);return Sp(n)?(this.editTextInline(n.id),true):n!=null}handleKey(e){if(e.key==="Escape")return this.textEditor?(this.finishTextEditor(false),true):this.popup.isOpen()?(this.clearSelection(),true):this.interaction.cancel()?true:this.measureMode?(this.withModeIntent(()=>this.exitMeasure()),true):this.selectedIds.size?(this.clearSelection(),true):false;if(e.key==="Enter"&&this.interaction.finishPlacing(false))return true;let t=Xx(e,{hasSelection:this.selectedIds.size>0,hasTarget:this.selectedIds.size>0||this.hoveredId!=null,editingText:jx(e.target)});if(!t)return false;switch(t.kind){case "undo":if(!this.historyChords)return false;this.emit({kind:"undo"});break;case "redo":if(!this.historyChords)return false;this.emit({kind:"redo"});break;case "copy":this.emit({kind:"copy",ids:this.selectionIds()});break;case "paste":this.emit({kind:"paste"});break;case "duplicate":this.emit({kind:"duplicate",ids:this.selectionIds()});break;case "delete":{let n=this.selectedIds.size?this.deletableSelection():this.hoveredId?[this.hoveredId]:[];n.length&&(this.popup.close(),this.emit({kind:"delete",ids:n}));break}case "nudge":this.nudgeSelection(t.dx,t.dy);break}return true}selectionIds(){return [...this.selectedIds]}deletableSelection(){return pp(this.selectedIds,this.drawings)}nudgeSelection(e,t){let n=this.deps.projector(),o=[];for(let i of this.drawings){if(!this.selectedIds.has(i.id)||i.locked)continue;let s=i.anchors.map(l=>{let c=n.yOf(l.price,i.paneId);return c==null?{time:l.time,price:l.price}:n.pxToPoint(n.xOf(l.time)+e,c+t,i.paneId)}),a=i.serialize();a.anchors=s,o.push(a);}o.length===1?this.emit({kind:"edit",doc:o[0]}):o.length>1&&this.emit({kind:"edit-many",docs:o});}setTheme(e){this.popup.setTheme(e),this.toolbar.setTheme(e),this.render();}onResize(){this.finishTextEditor(true),this.popup.close(),this.render();}isInterleaved(e){return Zx(e.zIndex,this.lastBounds.get(e.paneId)??[])!==null}syncLift(){let e=this.interaction.movingIds(),t=e.size===this.lifted.size;if(t)for(let n of e)this.lifted.has(n)||(t=false);t||(this.lifted=new Set(e),this.invalidateSlices());}invalidateSlices(){(this.sliced.size>0||this.drawings.some(e=>this.isInterleaved(e)))&&this.deps.requestDataPaint();}prepareSlices(e){this.sliced.clear(),this.lastBounds=new Map(e.map(a=>[a,this.deps.seriesBoundaries(a)]));let t=new Map,n=this.deps.dpr(),o=this.deps.projector(),i=this.deps.theme(),s=new Map;for(let a of this.drawings){if(!a.visible||this.lifted.has(a.id))continue;let l=Zx(a.zIndex,this.lastBounds.get(a.paneId)??[]);if(l===null)continue;let c=`${a.paneId}|${l}`,d=s.get(c);d?d.drawings.push(a):s.set(c,{paneId:a.paneId,beforeZ:l,drawings:[a]}),this.sliced.add(a.id);}for(let[a,{paneId:l,beforeZ:c,drawings:d}]of s){let u=this.sliceCache.get(a);u||(u=document.createElement("canvas"),this.sliceCache.set(a,u)),(u.width!==this.canvas.width||u.height!==this.canvas.height)&&(u.width=this.canvas.width,u.height=this.canvas.height);let h=u.getContext("2d");if(!h)continue;h.setTransform(n,0,0,n,0,0),h.clearRect(0,0,u.width/n,u.height/n),this.painter.seriesLook=this.deps.seriesLook(),this.painter.paintAll(h,d,o,i,CA);let p=t.get(l)??[];p.push({beforeZ:c,canvas:u}),t.set(l,p);}for(let a of [...this.sliceCache.keys()])s.has(a)||this.sliceCache.delete(a);for(let a of t.values())a.sort((l,c)=>l.beforeZ-c.beforeZ);return t}render(){let e=this.ctx;if(!e)return;let t=this.deps.dpr();e.setTransform(t,0,0,t,0,0),e.clearRect(0,0,this.canvas.width/t,this.canvas.height/t);let n=this.deps.projector(),o=this.textEditor?this.editedDrawing(this.textEditor.id):null,i={selected:this.selectedIds,hovered:this.hoveredId,dragged:this.interaction.activeDragId(),mutedLabel:o instanceof vn?o.id:null};this.painter.seriesLook=this.deps.seriesLook();let s=p=>!this.isInterleaved(p)||this.lifted.has(p.id);this.painter.paintAll(e,this.drawings.filter(s),n,this.deps.theme(),i),this.painter.paintHighlights(e,this.drawings.filter(p=>!s(p)),n,hp(i));let a=this.interaction.dragClones();a&&this.painter.paintAll(e,a,n,this.deps.theme(),{selected:new Set(a.map(p=>p.id))}),this.layoutTextEditor();let l=this.interaction.ghost();if(l&&this.painter.paintGhost(e,l,n,this.deps.theme()),this.externalGhost&&this.painter.paintGhost(e,this.externalGhost,n,this.deps.theme()),this.emitDraft(l),this.activeTool&&!l){let p=Nt(this.activeTool)?.placementHint;p&&this.painter.paintPlacementHint(e,p,this.deps.theme(),n.width,n.height);}let c=this.interaction.placingMarkers(n);c&&this.painter.paintHandles(e,c);let d=this.interaction.snapMarker(),u=d?n.yOf(d.point.price,d.paneId):null;d&&u!=null&&this.painter.paintSnapRing(e,n.xOf(d.point.time),u,this.deps.theme()),this.measure.isActive()&&this.measure.paint(e,n,this.deps.theme());let h=this.interaction.marqueeRect();h&&this.painter.paintMarquee(e,h);}destroy(){this.closeTextEditor(),this.popup.destroy(),this.toolbar.destroy(),this.seriesGwUnsub?.(),this.seriesGwUnsub=null,this.seriesGw=null,this.intentCb=null,this.drawings=[];}clearSelection(){this.popup.close(),this.selectedIds.size&&this.emit({kind:"select",ids:[]}),this.render();}emitEdits(e){let t=e.map(n=>n.serialize());t.length===1?this.emit({kind:"edit",doc:t[0]}):t.length>1&&this.emit({kind:"edit-many",docs:t});}openSettingsForSelection(e){let t=()=>e.map(s=>this.drawings.find(a=>a.id===s)).filter(s=>s!=null),n=t();if(n.length<2)return;let o=this.deps.projector(),i=null;for(let s of n){let a=s.bounds(o);if(a)if(!i)i={...a};else {let l=Math.max(i.x+i.w,a.x+a.w),c=Math.max(i.y+i.h,a.y+a.h);i.x=Math.min(i.x,a.x),i.y=Math.min(i.y,a.y),i.w=l-i.x,i.h=c-i.y;}}this.popupMulti=true,this.emit({kind:"settings",id:n[0].id}),this.popup.open(n,i,{resolve:()=>t()[0]??null,patch:s=>{let a=t();for(let l of a)l.applySettings(s);this.render(),this.emitEdits(a);},setLocked:s=>{let a=t();for(let l of a)l.locked=s;this.emitEdits(a);},reorder:s=>{for(let a of t())this.emit({kind:"reorder",id:a.id,to:s});},duplicate:()=>{this.popup.close(),this.emit({kind:"duplicate",ids:t().map(s=>s.id)});},resetSettings:()=>{let s=t();for(let a of s)bl(a);this.render(),this.emitEdits(s),this.openSettingsForSelection(e);},remove:()=>{let s=t().filter(a=>!a.locked).map(a=>a.id);s.length!==0&&(this.popup.close(),this.emit({kind:"delete",ids:s}));}},this.onPopupDismissed);}openSettingsById(e,t,n){let o=this.drawings.find(a=>a.id===e);if(!o)return;let i=()=>this.drawings.find(a=>a.id===e);this.popupMulti=false,this.emit({kind:"select",ids:[e]}),this.emit({kind:"settings",id:e});let s=o.bounds(this.deps.projector());this.popup.open([o],s,{resolve:()=>i()??null,patch:a=>{let l=i();l&&(l.applySettings(a),this.render(),this.emit({kind:"edit",doc:l.serialize()}));},setLocked:a=>{let l=i();l&&(l.locked=a,this.emit({kind:"edit",doc:l.serialize()}));},reorder:a=>this.emit({kind:"reorder",id:e,to:a}),duplicate:()=>{this.finishTextEditor(true),this.popup.close(),this.emit({kind:"duplicate",ids:[e]});},resetSettings:()=>{let a=i();a&&(bl(a),this.render(),this.emit({kind:"edit",doc:a.serialize()}),this.openSettingsById(e,0,0));},restore:a=>{let l=i();l&&(a.style&&(l.style={...a.style}),a.text!==void 0&&(l.text=a.text?{...a.text}:void 0),a.props!==void 0&&l.applyProps(a.props),this.render(),this.emit({kind:"edit",doc:a}));},remove:()=>{this.closeTextEditor(),this.popup.close(),this.emit({kind:"delete",ids:[e]});}},this.onPopupDismissed);}deselect(){this.clearSelection();}emitDraft(e){let t=e?JSON.stringify({t:e.type,p:e.paneId,a:e.anchors,s:e.style,x:e.text}):null;t!==this.lastDraftKey&&(this.lastDraftKey=t,this.intentCb?.({kind:"draft",doc:e?e.serialize():null}));}emit(e){if(e.kind==="create"){e.doc.text&&e.doc.text.color===void 0&&(e.doc.text={...e.doc.text,color:Ye(this.deps.theme().background)});let t=new Set(this.drawings.map(n=>n.id));this.intentCb?.(e),setTimeout(()=>{let n=this.drawings.find(o=>!t.has(o.id));n&&(this.openSettingsById(n.id,0,0),Sp(n)&&this.editTextInline(n.id));},0);return}if(e.kind==="clone"){let t=new Set(this.drawings.map(o=>o.id));this.intentCb?.(e);let n=this.drawings.filter(o=>!t.has(o.id));n.length===1&&this.openSettingsById(n[0].id,0,0);return}this.intentCb?.(e);}};var Cp={auto:13,tiny:10,small:11,normal:13,large:16,huge:20};function Tp(r){return typeof r=="number"?r>0?r:Cp.auto:Cp[r]??Cp.auto}function Qx(r){return r.cells.some(e=>e?.some(t=>t!=null&&!t.merged))}function Jx(r){let e=new Map,t=new Set;for(let n of r.merges){e.set(`${n.startRow}:${n.startCol}`,{cs:n.endCol-n.startCol+1,rs:n.endRow-n.startRow+1});for(let o=n.startRow;o<=n.endRow;o+=1)for(let i=n.startCol;i<=n.endCol;i+=1)(o!==n.startRow||i!==n.startCol)&&t.add(`${o}:${i}`);}for(let n=0;n0?e.frameWidth:0,{x:s,y:a}=kA(e.position,o.w+2*i,o.h+2*i,t),l=s+i,c=a+i;e.bgColor&&(r.fillStyle=e.bgColor,r.fillRect(l,c,o.w,o.h)),i>0&&e.frameColor&&(r.strokeStyle=e.frameColor,r.lineWidth=i,r.strokeRect(s+i/2,a+i/2,o.w+i,o.h+i));let d=[0];for(let m of o.colW)d.push(d[d.length-1]+m);let u=[0];for(let m of o.rowH)u.push(u[u.length-1]+m);let h=r.textBaseline,p=r.textAlign;r.textBaseline="middle";for(let m of o.boxes){let f=l+d[m.c],g=c+u[m.r],b=d[m.c+m.cs]-d[m.c],y=u[m.r+m.rs]-u[m.r],w=m.cell;w.bgColor&&(r.fillStyle=w.bgColor,r.fillRect(f,g,b,y));let S=w.text??"";if(S.length>0){let M=Tp(w.textSize);r.font=t0(w,M,t.theme),r.fillStyle=w.textColor??t.theme.textColor;let C=S.split(` +`),L=C.length*M*Mp,v=w.vAlign==="top"?g+Lp:w.vAlign==="bottom"?g+y-Lp-L:g+(y-L)/2,k=w.hAlign==="left"?f+kp:w.hAlign==="right"?f+b-kp:f+b/2;r.textAlign=w.hAlign,C.forEach((x,E)=>r.fillText(x,k,v+(E+.5)*M*Mp));}w.tooltip&&n.push({left:f,top:g,right:f+b,bottom:g+y,text:w.tooltip});}if(r.textBaseline=h,r.textAlign=p,e.borderColor&&e.borderWidth>0){r.strokeStyle=e.borderColor,r.lineWidth=e.borderWidth;let m=new Set;r.beginPath();let f=(g,b,y,w)=>{let S=`${g},${b},${y},${w}`;m.has(S)||(m.add(S),r.moveTo(g,b),r.lineTo(y,w));};for(let g of o.boxes){let b=Math.round(l+d[g.c]),y=Math.round(l+d[g.c+g.cs]),w=Math.round(c+u[g.r]),S=Math.round(c+u[g.r+g.rs]);f(b,w,y,w),f(b,S,y,S),f(b,w,b,S),f(y,w,y,S);}r.stroke();}}function TA(r,e,t){let{span:n,omit:o}=Jx(e),i=new Array(e.columns).fill(0),s=new Array(e.rows).fill(0),a=[];for(let h=0;h{let p=Tp(h.textSize);r.font=t0(h,p,t.theme);let m=(h.text??"").split(` +`),f=0;for(let y of m)f=Math.max(f,r.measureText(y).width);let g=Math.ceil(f)+2*kp,b=Math.ceil(m.length*p*Mp)+2*Lp;return h.width&&(g=Math.max(g,h.width/100*t.plotWidth)),h.height&&(b=Math.max(b,h.height/100*t.paneHeight)),{w:g,h:b}},c=[];for(let h of a){let{w:p,h:m}=l(h.cell);h.cs===1&&(i[h.c]=Math.max(i[h.c],p)),h.rs===1&&(s[h.r]=Math.max(s[h.r],m)),(h.cs>1||h.rs>1)&&c.push({box:h,w:p,h:m});}for(let{box:h,w:p,h:m}of c){if(h.cs>1){let f=0;for(let g=h.c;gf)for(let g=h.c;g1){let f=0;for(let g=h.r;gf)for(let g=h.r;gt>r)??1/0}var Ld=class{constructor(){this.drawScene=new ei({timeToLogical:()=>0,barAt:()=>null,theme:{}});this.sliceCache=new Map;this.tips=[];}prepare(e,t,n,o){this.tips=[];let i=new Map;if(o.width===0||o.height===0)return this.sliceCache.clear(),i;this.drawScene.setDeps({timeToLogical:d=>t.timeToLogical(d),barAt:d=>{let u=e.bars[Math.round(d)];return u?{high:u.high,low:u.low}:null},theme:n});let s=t.dpr,a=t.width,l=new Map,c=(d,u,h)=>{let p=`${d}|${u}`,m=l.get(p);m?m.entries.push(h):l.set(p,{paneId:d,beforeZ:u,entries:[h]});};for(let d of e.orderedPanes()){if(d.collapsed)continue;let u=e.seriesBoundaries(d.id);for(let h of e.orderedIndicatorsForPane(d.id)){let p=ti(h,false),m=(h.tables??[]).filter(y=>!y.overlay);if(Jh(p)&&m.length===0)continue;let f=e.scaleFor(h,d),g=f===d.scale?d:{...d,scale:f},b=LA(e.zOf(h.id),u);c(d.id,b,{set:p,tables:m,pane:g,indexOffset:e.offsetOf(h.id)});}if(d.kind==="price")for(let h of e.indicators.values()){let p=ti(h,true),m=(h.tables??[]).filter(f=>f.overlay===true);Jh(p)&&m.length===0||c(d.id,1/0,{set:p,tables:m,pane:d,indexOffset:e.offsetOf(h.id)});}}for(let[d,{paneId:u,beforeZ:h,entries:p}]of l){let m=this.sliceCache.get(d);m||(m=document.createElement("canvas"),this.sliceCache.set(d,m)),(m.width!==o.width||m.height!==o.height)&&(m.width=o.width,m.height=o.height);let f=m.getContext("2d");if(!f)continue;f.setTransform(s,0,0,s,0,0),f.clearRect(0,0,m.width/s,m.height/s);for(let b of p)this.paintEntry(f,b,t,a,n);let g=i.get(u)??[];g.push({beforeZ:h,canvas:m}),i.set(u,g);}for(let d of [...this.sliceCache.keys()])l.has(d)||this.sliceCache.delete(d);for(let d of i.values())d.sort((u,h)=>u.beforeZ-h.beforeZ);return i}paintEntry(e,t,n,o,i){let{pane:s}=t,a=[];e.save(),e.translate(0,s.bounds.top),e.beginPath(),e.rect(0,0,o,s.bounds.height),e.clip(),this.drawScene.setSet(t.set,t.indexOffset),this.drawScene.render(e,o,s.bounds.height,l=>n.logicalToX(l),l=>n.priceToY(l,s.scale,s.bounds)-s.bounds.top),a.push(...this.drawScene.labelTipRegions());for(let l of t.tables)e0(e,l,{paneHeight:s.bounds.height,plotWidth:o,theme:i},a);e.restore();for(let l of a)this.tips.push({...l,top:l.top+s.bounds.top,bottom:l.bottom+s.bounds.top});}labelTooltipAt(e,t){for(let n=this.tips.length-1;n>=0;n-=1){let o=this.tips[n];if(e>=o.left&&e<=o.right&&t>=o.top&&t<=o.bottom)return o.text}return null}};function n0(r,e){let t=new Map;for(let[n,o]of r)t.set(n,[...o]);for(let[n,o]of e)t.set(n,[...t.get(n)??[],...o]);for(let n of t.values())n.sort((o,i)=>o.beforeZ-i.beforeZ);return t}function r0(r,e,t,n,o){return {xOf:i=>r.timeToX(i),yOf:(i,s)=>{let a=e(s);return a?r.priceToY(i,a.scale,a.bounds):null},pxToPoint:(i,s,a)=>{let l=e(a),c=r.logicalToTime(r.xToLogical(i)),d=l?r.yToPrice(s,l.scale,l.bounds):0;return {time:c,price:d}},paneIdAtY:t,paneRect:i=>{let s=e(i);return s?{top:s.bounds.top,height:s.collapsed?0:s.bounds.height}:null},barsBetween:(i,s)=>Math.abs(r.timeToLogical(s)-r.timeToLogical(i)),barsInRange:n?(i,s)=>n(i,s):void 0,seriesInRange:o,width:r.width,height:r.height}}function Md(r,e,t,n,o,i,s=false,a=()=>0,l=Hh){let c=1/0,d=-1/0,u=g=>{g!=null&&Number.isFinite(g)&&(gd&&(d=g));};if(t)for(let g=n;g<=o;g+=1){let b=e[g];b&&(u(b.high),u(b.low));}for(let g of r){let b=a(g.id);for(let y of g.series)y.overlay!==true&&o0(y,n,o,b,u);for(let y of g.priceLines)u(y.price);}if(i&&(u(i.min),u(i.max)),c===1/0||d===-1/0)return {min:0,max:1};if(d-c<=Math.max(Math.abs(c),Math.abs(d))*1e-12){let g=(c+d)/2,b=Math.abs(g)*.1||1;return {min:g-b,max:g+b,log:s&&g-b>0}}let h=Math.max(.1,1-(l.top+l.bottom)/100),p=l.top/100/h,m=l.bottom/100/h;if(s&&c>0){let g=Math.log(c),b=Math.log(d),y=b-g;return {min:Math.exp(g-y*m),max:Math.exp(b+y*p),log:true}}let f=d-c;return {min:c-f*m,max:d+f*p}}function o0(r,e,t,n,o){if(ia(r)){if(r.kind==="candle"||r.kind==="bar")for(let i=e;i<=t;i+=1){let s=r.bars[i-n];s&&(o(s.high),o(s.low));}else if($e(r)){for(let i=e;i<=t;i+=1)o(r.points[i-n]?.value);r.kind==="histogram"||r.kind==="columns"?o(r.style?.base??0):r.style?.base!=null&&o(r.style.base);}}}function i0(r,e,t,n=()=>0){let o=1/0,i=-1/0,s=a=>{a!=null&&Number.isFinite(a)&&(ai&&(i=a));};for(let a of r){let l=n(a.id);for(let c of a.series)c.overlay===true&&o0(c,e,t,l,s);}return o===1/0?null:{min:o,max:i}}function s0(r,e,t,n){if(t<=0&&n<=0)return r;let o=e-t-n;if(!(o>=8))return r;if(r.log&&r.min>0&&r.max>r.min){let s=Math.log(r.min),a=Math.log(r.max),l=(a-s)/o;return {...r,min:Math.exp(s-n*l),max:Math.exp(a+t*l)}}if(r.max<=r.min)return r;let i=(r.max-r.min)/o;return {...r,min:r.min-n*i,max:r.max+t*i}}var MA=new Set(["a","abbr","b","blockquote","br","code","dd","del","div","dl","dt","em","h1","h2","h3","h4","h5","h6","hr","i","img","ins","kbd","li","mark","ol","p","pre","q","s","small","span","strong","sub","sup","table","tbody","td","tfoot","th","thead","tr","u","ul"]),EA=new Set(["script","style","iframe","frame","frameset","object","embed","applet","form","input","textarea","button","select","option","link","meta","base","svg","math","template","noscript","audio","video","canvas","dialog","head","title"]),PA={a:new Set(["href"]),img:new Set(["src","alt","width","height"]),td:new Set(["colspan","rowspan"]),th:new Set(["colspan","rowspan"]),ol:new Set(["start"])},IA=new Set(["javascript","vbscript","data","file","blob"]);function AA(r){let e=r.toLowerCase();return EA.has(e)?"drop":MA.has(e)?"keep":"unwrap"}function RA(r,e){let t=e.toLowerCase();return t.startsWith("on")||t==="style"?false:t==="title"?true:PA[r.toLowerCase()]?.has(t)??false}function DA(r,e=false){let t="";for(let i of r)i.charCodeAt(0)>32&&(t+=i);let n=/^([a-z][a-z0-9+.-]*):/i.exec(t),o=n?n[1].toLowerCase():null;return o!==null&&IA.has(o)||e&&o!=="http"&&o!=="https"?null:t}var OA=1,NA=3;function a0(r,e){let t=e.createElement("template");t.innerHTML=r;let n=e.createDocumentFragment();return Ep(t.content,n,e),n}function Ep(r,e,t){for(let n of Array.from(r.childNodes)){if(n.nodeType===NA){e.appendChild(t.createTextNode(n.textContent??""));continue}if(n.nodeType!==OA)continue;let o=n,i=o.tagName.toLowerCase(),s=AA(i);if(s==="drop")continue;if(s==="unwrap"){Ep(o,e,t);continue}let a=t.createElement(i);for(let l of Array.from(o.attributes)){let c=l.name.toLowerCase();if(!RA(i,c))continue;let d=l.value;if(c==="href"||c==="src"){let u=DA(d,c==="src");if(u===null)continue;d=u;}a.setAttribute(c,d);}i==="a"&&(a.setAttribute("target","_blank"),a.setAttribute("rel","noopener noreferrer")),Ep(o,a,t),e.appendChild(a);}}var FA="vela-marks-popover",VA=` .vela-marks-panel { padding: 0; gap: 0; min-width: 220px; max-width: 320px; max-height: 320px; overflow-y: auto; overscroll-behavior: contain; } .vela-marks-section { display: flex; flex-direction: column; gap: 8px; padding: 10px 12px; } .vela-marks-section + .vela-marks-section { border-top: 1px solid var(--vela-border); } @@ -983,7 +1017,7 @@ ${Ir(".vela-sd-pane")} .vela-marks-html td, .vela-marks-html th { padding: 2px 6px; border: 1px solid var(--vela-border); } .vela-marks-html pre, .vela-marks-html code { font-family: var(--vela-font-mono, monospace); font-size: 0.92em; } .vela-marks-loading, .vela-marks-error { color: var(--vela-fg-muted); font-style: italic; } -`,kd=class{constructor(e){this.deps=e;this.pop=null;this.openKey=null;this.generation=0;this.pressKey=null;this.onPress=()=>{if(this.openKey===null)return;this.pressKey=this.openKey;let e=this.deps.plot.ownerDocument,t=()=>{setTimeout(()=>this.pressKey=null,0);};e.addEventListener("pointerup",t,{capture:true,once:true}),e.addEventListener("pointercancel",t,{capture:true,once:true});};let t=e.plot.ownerDocument;he(us,hs,t),he(xA,CA,t),this.anchor=t.createElement("div"),this.anchor.className="vela-marks-anchor",Object.assign(this.anchor.style,{position:"absolute",pointerEvents:"none",left:"0",top:"0",width:"0",height:"0"}),e.plot.appendChild(this.anchor),t.addEventListener("pointerdown",this.onPress,true);}get key(){return this.openKey}open(e,t){if(this.pressKey===e.key)return;this.close(),this.place(t);let n=++this.generation;this.openKey=e.key,this.pop=new qe({trigger:this.anchor,host:this.deps.host(),theme:this.deps.theme(),gap:8,align:"center",fadeMs:120,className:"vela-marks-pop",content:o=>this.build(o,e,n),onClose:()=>{this.generation===n&&(this.openKey=null,this.pop=null,this.deps.onOpenChange?.(null));}}),this.pop.show(),this.deps.onOpenChange?.(e.key);}track(e){if(this.pop){if(!e){this.close();return}this.place(e),this.pop.reposition();}}close(){let e=this.pop,t=this.openKey!==null;this.pop=null,this.openKey=null,this.generation++,e?.destroy(),t&&this.deps.onOpenChange?.(null);}destroy(){this.close(),this.deps.plot.ownerDocument.removeEventListener("pointerdown",this.onPress,true),this.anchor.remove();}place(e){Object.assign(this.anchor.style,{left:`${e.x-e.size/2}px`,top:`${e.y-e.size/2}px`,width:`${e.size}px`,height:`${e.size}px`});}build(e,t,n){let o=e.ownerDocument,i=o.createElement("div");i.className="vela-callout-panel vela-marks-panel";let s=[];for(let a of t.marks){let l=o.createElement("section");if(l.className="vela-marks-section",a.title){let d=o.createElement("div");d.className="vela-callout-title",d.textContent=a.title,l.appendChild(d);}let c=a.content;if(typeof c=="function"){let d=o.createElement("div");d.className="vela-marks-loading",d.textContent="Loading\u2026",l.appendChild(d),s.push({el:l,resolve:()=>this.resolveLazy(c,d,n)});}else c!==void 0&&this.renderContent(l,c);l.childElementCount>0&&i.appendChild(l);}e.appendChild(i),s.length>0&&SA(i,s);}resolveLazy(e,t,n){let o;try{o=Promise.resolve(e());}catch(i){o=Promise.reject(i instanceof Error?i:new Error(String(i)));}o.then(i=>{if(n!==this.generation)return;let s=t.parentElement;s&&(t.remove(),this.renderContent(s,i),this.pop?.reposition());},()=>{n===this.generation&&(t.className="vela-marks-error",t.textContent="Couldn\u2019t load this entry.");});}renderContent(e,t){let n=e.ownerDocument;if(!(!t||typeof t!="object")){if("text"in t){let o=n.createElement("div");o.className="vela-callout-text",o.textContent=String(t.text),e.appendChild(o);return}if("html"in t){let o=n.createElement("div");o.className="vela-marks-html",o.appendChild(ex(String(t.html),n)),e.appendChild(o);return}if("panel"in t&&t.panel&&Array.isArray(t.panel.items)){let o=null;for(let i of t.panel.items)if(!(!i||typeof i!="object")){if(i.type==="button"){o||(o=n.createElement("div"),o.className="vela-callout-actions",e.appendChild(o));let s=n.createElement("button");s.type="button",s.className="vela-callout-btn"+(i.primary?" vela-callout-btn-primary":""),s.textContent=i.label,s.addEventListener("click",()=>{i.run(),i.close!==false&&this.close();}),o.appendChild(s);continue}if(o=null,i.type==="text"){let s=n.createElement("div");s.className="vela-callout-text",s.textContent=i.text,e.appendChild(s);}else if(i.type==="field"){let s=n.createElement("div");s.className="vela-marks-field";let a=n.createElement("span");a.className="vela-marks-field-label",a.textContent=i.label;let l=n.createElement("span");l.className="vela-marks-field-value",l.textContent=i.value,s.append(a,l),e.appendChild(s);}}}}}};function SA(r,e){if(typeof IntersectionObserver>"u"){for(let n of e)n.resolve();return}let t=new IntersectionObserver(n=>{for(let o of n){if(!o.isIntersecting)continue;let i=e.find(s=>s.el===o.target);i&&(t.unobserve(o.target),i.resolve());}},{root:r});for(let n of e)t.observe(n.el);}function tx(r,e){if(r.log&&r.min>0&&r.max>r.min){let o=Math.log(r.min),i=Math.log(r.max),s=(o+i)/2,a=(i-o)/2*e;return {min:Math.exp(s-a),max:Math.exp(s+a),log:true}}let t=(r.min+r.max)/2,n=(r.max-r.min)/2*e;return {min:t-n,max:t+n,log:r.log}}function nx(r,e,t){if(t<=0)return {...r};if(r.log&&r.min>0&&r.max>r.min){let o=Math.log(r.min),i=Math.log(r.max),s=(i-o)*e/t;return {min:Math.exp(o+s),max:Math.exp(i+s),log:true}}let n=(r.max-r.min)*e/t;return {min:r.min+n,max:r.max+n,log:r.log}}function rx(r,e,t=24){let{combinedTop:n,combinedHeight:o,combinedWeight:i,startBoundaryY:s}=r,a=Math.min(t,o/2),l=n+a,c=n+o-a,u=Math.max(l,Math.min(c,s+e))-n,h=o>0?i*(u/o):i/2;return {above:h,below:i-h}}function TA(r,e,t,n){let o=Math.max(t,r),i=Math.min(n,e);return i>o?{x:o,width:i-o}:null}function kA(r){return Math.ceil(r)-.5}var Ld=class{constructor(){this.canvas=null;this.ctx=null;}mount(e){this.canvas=e,this.ctx=e.getContext("2d");}destroy(){this.canvas=null,this.ctx=null;}render(e,t,n,o){let i=this.ctx,s=this.canvas;if(!i||!s)return;let a=t.dpr;i.setTransform(a,0,0,a,0,0),i.clearRect(0,0,s.width/a,s.height/a);let l=t.barCount;if(l===0)return;let c=t.visibleLogicalRange();Math.min(l-1,Math.ceil(c.to))0){let i=Math.max(0,n.logicalToX(-0.5)),s=Math.min(n.width,n.logicalToX(n.barCount-.5));this.drawHighlightSet(e,o,n,i,s,true);}this.drawHighlightSet(e,t.highlights,n,0,n.width,false);}drawHighlightSet(e,t,n,o,i,s){let a=l=>s?n.logicalToX(kA(n.timeToLogical(l))):n.timeToX(l);for(let l of t){let c=TA(a(l.from),a(l.to),o,i);c&&(e.fillStyle=l.color,e.fillRect(c.x,0,c.width,n.height));}}drawGrid(e,t,n,o,i,s){let a=t.orderedPanes(),{gridVert:l,gridHorz:c}=t.style,d=l.color??o.gridColor,u=c.color??o.gridColor;if(e.lineWidth=1,t.showGrid&&l.visible){e.globalAlpha=s,e.strokeStyle=d;let h=n.visibleTimeRange(),p=Is((h.from+h.to)/2,t.timezone);e.beginPath();for(let m of od(h.from,h.to,8,p)){let f=Math.round(n.timeToX(m.time))+.5;f<0||f>i||(e.moveTo(f,0),e.lineTo(f,n.height));}e.stroke();}for(let h of a)if(t.showGrid&&c.visible&&!h.collapsed){e.globalAlpha=s,e.strokeStyle=u;let p=Dn(t,h);e.beginPath();for(let m of Fs(h.scale,h.bounds.height,p,void 0,h.axisFormat)){let f=Math.round(n.priceToY(m.price,h.scale,h.bounds))+.5;fh.bounds.top+h.bounds.height||(e.moveTo(0,f),e.lineTo(i,f));}e.stroke();}e.globalAlpha=1;}};function ox(r,e,t,n){let{i0:o,i1:i,xOf:s,halfW:a,bottomY:l,maxH:c,maxVol:d}=t;if(!(d<=0||c<=0)){r.globalAlpha=.5;for(let u=o;u<=i;u+=1){let h=e[u],p=h?.volume;if(h==null||p==null||!(p>0))continue;let m=Math.max(1,p/d*c);r.fillStyle=h.close>=h.open?n.up:n.down,r.fillRect(s(u)-a,l-m,a*2,m);}r.globalAlpha=1;}}var Sp=.96;function LA(r){return Math.max(.5,Math.floor(r*.7)/2)}var Md=class{constructor(){this.canvas=null;this.ctx=null;}mount(e){this.canvas=e,this.ctx=e.getContext("2d");}destroy(){this.canvas=null,this.ctx=null;}render(e){let t=this.ctx,n=this.canvas;if(!t||!n)return;let{bars:o,data:i,visible:s,coords:a,bounds:l,fillPane:c}=e,d=a.dpr;if(t.setTransform(d,0,0,d,0,0),t.clearRect(0,0,n.width/d,n.height/d),!i||!s||o.length===0||l.height<=0)return;let u=a.visibleLogicalRange(),h=Math.max(0,Math.floor(u.from)),p=Math.min(o.length-1,Math.ceil(u.to));if(h>p)return;let m=0;for(let f=h;f<=p;f+=1){let g=o[f]?.volume;g!=null&&g>m&&(m=g);}m<=0||(t.save(),t.beginPath(),t.rect(0,l.top,a.width,l.height),t.clip(),ox(t,o,{i0:h,i1:p,xOf:f=>a.logicalToX(f),halfW:LA(a.bodySpacing()),bottomY:l.top+l.height,maxH:l.height*(c?Sp:i.heightFrac),maxVol:m},{up:i.upColor,down:i.downColor}),t.restore());}};function ix(r,e){return e==null?r:r==null?{...e}:{candleBodyScale:Tp(r.candleBodyScale,e.candleBodyScale),candleBodyAlpha:Tp(r.candleBodyAlpha,e.candleBodyAlpha),gridAlpha:Tp(r.gridAlpha,e.gridAlpha)}}function Tp(r,e){return r==null?e:e==null?r:Math.min(r,e)}var kp=new Map;function MA(r){kp.set(r.id,r);}function EA(r){kp.delete(r);}function Lp(){return [...kp.values()]}function sx(r,e){let t=r.map(i=>({id:i.id,key:i.ownerZ??(i.placement==="below-data"?-1/0:e)}));t.sort((i,s)=>i.key-s.key);let n=[],o=[];for(let i of t)(i.key{if(this.openKey===null)return;this.pressKey=this.openKey;let e=this.deps.plot.ownerDocument,t=()=>{setTimeout(()=>this.pressKey=null,0);};e.addEventListener("pointerup",t,{capture:true,once:true}),e.addEventListener("pointercancel",t,{capture:true,once:true});};let t=e.plot.ownerDocument;he(fs,gs,t),he(FA,VA,t),this.anchor=t.createElement("div"),this.anchor.className="vela-marks-anchor",Object.assign(this.anchor.style,{position:"absolute",pointerEvents:"none",left:"0",top:"0",width:"0",height:"0"}),e.plot.appendChild(this.anchor),t.addEventListener("pointerdown",this.onPress,true);}get key(){return this.openKey}open(e,t){if(this.pressKey===e.key)return;this.close(),this.place(t);let n=++this.generation;this.openKey=e.key,this.pop=new qe({trigger:this.anchor,host:this.deps.host(),theme:this.deps.theme(),gap:8,align:"center",fadeMs:120,className:"vela-marks-pop",content:o=>this.build(o,e,n),onClose:()=>{this.generation===n&&(this.openKey=null,this.pop=null,this.deps.onOpenChange?.(null));}}),this.pop.show(),this.deps.onOpenChange?.(e.key);}track(e){if(this.pop){if(!e){this.close();return}this.place(e),this.pop.reposition();}}close(){let e=this.pop,t=this.openKey!==null;this.pop=null,this.openKey=null,this.generation++,e?.destroy(),t&&this.deps.onOpenChange?.(null);}destroy(){this.close(),this.deps.plot.ownerDocument.removeEventListener("pointerdown",this.onPress,true),this.anchor.remove();}place(e){Object.assign(this.anchor.style,{left:`${e.x-e.size/2}px`,top:`${e.y-e.size/2}px`,width:`${e.size}px`,height:`${e.size}px`});}build(e,t,n){let o=e.ownerDocument,i=o.createElement("div");i.className="vela-callout-panel vela-marks-panel";let s=[];for(let a of t.marks){let l=o.createElement("section");if(l.className="vela-marks-section",a.title){let d=o.createElement("div");d.className="vela-callout-title",d.textContent=a.title,l.appendChild(d);}let c=a.content;if(typeof c=="function"){let d=o.createElement("div");d.className="vela-marks-loading",d.textContent="Loading\u2026",l.appendChild(d),s.push({el:l,resolve:()=>this.resolveLazy(c,d,n)});}else c!==void 0&&this.renderContent(l,c);l.childElementCount>0&&i.appendChild(l);}e.appendChild(i),s.length>0&&BA(i,s);}resolveLazy(e,t,n){let o;try{o=Promise.resolve(e());}catch(i){o=Promise.reject(i instanceof Error?i:new Error(String(i)));}o.then(i=>{if(n!==this.generation)return;let s=t.parentElement;s&&(t.remove(),this.renderContent(s,i),this.pop?.reposition());},()=>{n===this.generation&&(t.className="vela-marks-error",t.textContent="Couldn\u2019t load this entry.");});}renderContent(e,t){let n=e.ownerDocument;if(!(!t||typeof t!="object")){if("text"in t){let o=n.createElement("div");o.className="vela-callout-text",o.textContent=String(t.text),e.appendChild(o);return}if("html"in t){let o=n.createElement("div");o.className="vela-marks-html",o.appendChild(a0(String(t.html),n)),e.appendChild(o);return}if("panel"in t&&t.panel&&Array.isArray(t.panel.items)){let o=null;for(let i of t.panel.items)if(!(!i||typeof i!="object")){if(i.type==="button"){o||(o=n.createElement("div"),o.className="vela-callout-actions",e.appendChild(o));let s=n.createElement("button");s.type="button",s.className="vela-callout-btn"+(i.primary?" vela-callout-btn-primary":""),s.textContent=i.label,s.addEventListener("click",()=>{i.run(),i.close!==false&&this.close();}),o.appendChild(s);continue}if(o=null,i.type==="text"){let s=n.createElement("div");s.className="vela-callout-text",s.textContent=i.text,e.appendChild(s);}else if(i.type==="field"){let s=n.createElement("div");s.className="vela-marks-field";let a=n.createElement("span");a.className="vela-marks-field-label",a.textContent=i.label;let l=n.createElement("span");l.className="vela-marks-field-value",l.textContent=i.value,s.append(a,l),e.appendChild(s);}}}}}};function BA(r,e){if(typeof IntersectionObserver>"u"){for(let n of e)n.resolve();return}let t=new IntersectionObserver(n=>{for(let o of n){if(!o.isIntersecting)continue;let i=e.find(s=>s.el===o.target);i&&(t.unobserve(o.target),i.resolve());}},{root:r});for(let n of e)t.observe(n.el);}function l0(r,e){if(r.log&&r.min>0&&r.max>r.min){let o=Math.log(r.min),i=Math.log(r.max),s=(o+i)/2,a=(i-o)/2*e;return {min:Math.exp(s-a),max:Math.exp(s+a),log:true}}let t=(r.min+r.max)/2,n=(r.max-r.min)/2*e;return {min:t-n,max:t+n,log:r.log}}function c0(r,e,t){if(t<=0)return {...r};if(r.log&&r.min>0&&r.max>r.min){let o=Math.log(r.min),i=Math.log(r.max),s=(i-o)*e/t;return {min:Math.exp(o+s),max:Math.exp(i+s),log:true}}let n=(r.max-r.min)*e/t;return {min:r.min+n,max:r.max+n,log:r.log}}function d0(r,e,t=24){let{combinedTop:n,combinedHeight:o,combinedWeight:i,startBoundaryY:s}=r,a=Math.min(t,o/2),l=n+a,c=n+o-a,u=Math.max(l,Math.min(c,s+e))-n,h=o>0?i*(u/o):i/2;return {above:h,below:i-h}}function _A(r,e,t,n){let o=Math.max(t,r),i=Math.min(n,e);return i>o?{x:o,width:i-o}:null}function HA(r){return Math.ceil(r)-.5}var Pd=class{constructor(e=new ir){this.axisTicks=e;this.canvas=null;this.ctx=null;}mount(e){this.canvas=e,this.ctx=e.getContext("2d");}destroy(){this.canvas=null,this.ctx=null;}render(e,t,n,o){let i=this.ctx,s=this.canvas;if(!i||!s)return;let a=t.dpr;i.setTransform(a,0,0,a,0,0),i.clearRect(0,0,s.width/a,s.height/a);let l=t.barCount;if(l===0)return;let c=t.visibleLogicalRange();Math.min(l-1,Math.ceil(c.to))0){let i=Math.max(0,n.logicalToX(-0.5)),s=Math.min(n.width,n.logicalToX(n.barCount-.5));this.drawHighlightSet(e,o,n,i,s,true);}this.drawHighlightSet(e,t.highlights,n,0,n.width,false);}drawHighlightSet(e,t,n,o,i,s){let a=l=>s?n.logicalToX(HA(n.timeToLogical(l))):n.timeToX(l);for(let l of t){let c=_A(a(l.from),a(l.to),o,i);c&&(e.fillStyle=l.color,e.fillRect(c.x,0,c.width,n.height));}}drawGrid(e,t,n,o,i,s){let a=t.orderedPanes(),{gridVert:l,gridHorz:c}=t.style,d=l.color??o.gridColor,u=c.color??o.gridColor;if(e.lineWidth=1,t.showGrid&&l.visible){e.globalAlpha=s,e.strokeStyle=d;let h=n.visibleTimeRange(),p=Os((h.from+h.to)/2,t.timezone);e.beginPath();for(let m of ld(h.from,h.to,8,p)){let f=Math.round(n.timeToX(m.time))+.5;f<0||f>i||(e.moveTo(f,0),e.lineTo(f,n.height));}e.stroke();}for(let h of a)if(t.showGrid&&c.visible&&!h.collapsed){e.globalAlpha=s,e.strokeStyle=u,e.beginPath();for(let p of this.axisTicks.ticksFor(t,h,n)){let m=Math.round(n.priceToY(p.price,h.scale,h.bounds))+.5;mh.bounds.top+h.bounds.height||(e.moveTo(0,m),e.lineTo(i,m));}e.stroke();}e.globalAlpha=1;}};function u0(r,e,t,n){let{i0:o,i1:i,xOf:s,halfW:a,bottomY:l,maxH:c,maxVol:d}=t;if(!(d<=0||c<=0)){r.globalAlpha=.5;for(let u=o;u<=i;u+=1){let h=e[u],p=h?.volume;if(h==null||p==null||!(p>0))continue;let m=Math.max(1,p/d*c);r.fillStyle=h.close>=h.open?n.up:n.down,r.fillRect(s(u)-a,l-m,a*2,m);}r.globalAlpha=1;}}var Pp=.96;function zA(r){return Math.max(.5,Math.floor(r*.7)/2)}var Id=class{constructor(){this.canvas=null;this.ctx=null;}mount(e){this.canvas=e,this.ctx=e.getContext("2d");}destroy(){this.canvas=null,this.ctx=null;}render(e){let t=this.ctx,n=this.canvas;if(!t||!n)return;let{bars:o,data:i,visible:s,coords:a,bounds:l,fillPane:c}=e,d=a.dpr;if(t.setTransform(d,0,0,d,0,0),t.clearRect(0,0,n.width/d,n.height/d),!i||!s||o.length===0||l.height<=0)return;let u=a.visibleLogicalRange(),h=Math.max(0,Math.floor(u.from)),p=Math.min(o.length-1,Math.ceil(u.to));if(h>p)return;let m=0;for(let f=h;f<=p;f+=1){let g=o[f]?.volume;g!=null&&g>m&&(m=g);}m<=0||(t.save(),t.beginPath(),t.rect(0,l.top,a.width,l.height),t.clip(),u0(t,o,{i0:h,i1:p,xOf:f=>a.logicalToX(f),halfW:zA(a.bodySpacing()),bottomY:l.top+l.height,maxH:l.height*(c?Pp:i.heightFrac),maxVol:m},{up:i.upColor,down:i.downColor}),t.restore());}};function h0(r,e){return e==null?r:r==null?{...e}:{candleBodyScale:Ip(r.candleBodyScale,e.candleBodyScale),candleBodyAlpha:Ip(r.candleBodyAlpha,e.candleBodyAlpha),gridAlpha:Ip(r.gridAlpha,e.gridAlpha)}}function Ip(r,e){return r==null?e:e==null?r:Math.min(r,e)}var Ap=new Map;function WA(r){Ap.set(r.id,r);}function GA(r){Ap.delete(r);}function Rp(){return [...Ap.values()]}function p0(r,e){let t=r.map(i=>({id:i.id,key:i.ownerZ??(i.placement==="below-data"?-1/0:e)}));t.sort((i,s)=>i.key-s.key);let n=[],o=[];for(let i of t)(i.key.001:true}function hx(r,e,t){let n=r.borderTopLeftRadius,o=parseFloat(n)||0,i=n.endsWith("%")?o/100*Math.min(e,t):o;return Math.max(0,Math.min(i,Math.min(e,t)/2))}function Pp(r,e,t,n,o,i){r.beginPath(),i>0&&typeof r.roundRect=="function"?r.roundRect(e,t,n,o,i):r.rect(e,t,n,o);}function RA(r){try{let e=r.ownerDocument.createElement("canvas");e.width=1,e.height=1;let t=e.getContext("2d");return t?(t.drawImage(r,0,0,1,1),e.toDataURL(),!0):!1}catch{return false}}function Pd(r,e,t){let n=e.ownerDocument.defaultView;if(!n)return;r.save(),r.scale(t.dpr,t.dpr);let o=(c,d,u)=>{let h=c.textContent?.replace(/\s+/g," ").trim();if(!h)return;let p=c.ownerDocument.createRange();p.selectNodeContents(c);let m=p.getBoundingClientRect();m.width<=0||m.height<=0||(r.globalAlpha=u,r.fillStyle=d.color,r.font=`${d.fontStyle} ${d.fontWeight} ${d.fontSize} ${d.fontFamily}`,r.textBaseline="middle",r.textAlign="left",r.fillText(h,m.left-t.left,m.top-t.top+m.height/2));},i=(c,d,u)=>{if(!c.complete||c.naturalWidth<=0||!RA(c))return;let h=c.getBoundingClientRect();if(h.width<=0||h.height<=0)return;let p=h.left-t.left,m=h.top-t.top;r.save(),r.globalAlpha=u,Pp(r,p,m,h.width,h.height,hx(d,h.width,h.height)),r.clip(),r.drawImage(c,p,m,h.width,h.height),r.restore();},s=(c,d)=>{for(let u of c.children){if(u.hasAttribute("transform"))continue;let h=u.tagName.toLowerCase();if(h==="g"){s(u,d);continue}let p=b=>parseFloat(u.getAttribute(b)??"0")||0,m=null;if(h==="path"){let b=u.getAttribute("d");b&&(m=new Path2D(b));}else if(h==="circle")m=new Path2D,m.arc(p("cx"),p("cy"),p("r"),0,Math.PI*2);else if(h==="ellipse")m=new Path2D,m.ellipse(p("cx"),p("cy"),p("rx"),p("ry"),0,0,Math.PI*2);else if(h==="rect")m=new Path2D,m.rect(p("x"),p("y"),p("width"),p("height"));else if(h==="line")m=new Path2D,m.moveTo(p("x1"),p("y1")),m.lineTo(p("x2"),p("y2"));else if(h==="polyline"||h==="polygon"){let b=(u.getAttribute("points")??"").trim().split(/[\s,]+/).map(Number);if(b.length<4||b.some(Number.isNaN))continue;m=new Path2D,m.moveTo(b[0],b[1]);for(let y=2;y+10&&(r.globalAlpha=d*(parseFloat(f.strokeOpacity)||1),r.strokeStyle=f.stroke,r.lineWidth=g,(f.strokeLinecap==="round"||f.strokeLinecap==="square"||f.strokeLinecap==="butt")&&(r.lineCap=f.strokeLinecap),(f.strokeLinejoin==="round"||f.strokeLinejoin==="bevel"||f.strokeLinejoin==="miter")&&(r.lineJoin=f.strokeLinejoin),r.stroke(m));}},a=(c,d)=>{let u=c.getBoundingClientRect();if(u.width<=0||u.height<=0)return;let h=n.getComputedStyle(c);if(h.display==="none"||h.visibility==="hidden")return;let p=d*(parseFloat(h.opacity)||1);if(p<=.001)return;let m=c.viewBox.baseVal,f=m&&m.width>0?m.width:u.width,g=m&&m.height>0?m.height:u.height;r.save(),r.translate(u.left-t.left,u.top-t.top),r.scale(u.width/f,u.height/g),m&&r.translate(-m.x,-m.y),s(c,p),r.restore();},l=(c,d)=>{let u=n.getComputedStyle(c);if(u.display==="none"||u.visibility==="hidden")return;let h=d*(parseFloat(u.opacity)||1);if(h<=.001)return;let p=c.getBoundingClientRect();if(p.width>0&&p.height>0){let m=p.left-t.left,f=p.top-t.top,g=hx(u,p.width,p.height);Ed(u.backgroundColor)&&(r.globalAlpha=h,r.fillStyle=u.backgroundColor,Pp(r,m,f,p.width,p.height,g),r.fill());let b=parseFloat(u.borderTopWidth)||0;b>0&&u.borderTopStyle!=="none"&&Ed(u.borderTopColor)&&(r.globalAlpha=h,r.strokeStyle=u.borderTopColor,r.lineWidth=b,Pp(r,m+b/2,f+b/2,p.width-b,p.height-b,Math.max(0,g-b/2)),r.stroke());}for(let m of c.childNodes)m.nodeType===3?o(m,u,h):m instanceof n.HTMLImageElement?i(m,n.getComputedStyle(m),h):m instanceof n.SVGSVGElement?a(m,h):m instanceof n.HTMLElement&&l(m,h);};e instanceof n.HTMLElement&&l(e,1),r.restore();}function px(r,e,t,n,o){let i=Math.max(0,e),s=Math.min(r.length-1,t);if(i>s)return null;let a=1/0,l=-1/0;for(let w=i;w<=s;w+=1){let C=r[w];C.volume!=null&&C.volume>0&&(C.lowl&&(l=C.high));}if(!Number.isFinite(a))return null;let c=l>a?Math.max(1,Math.round(n)):1,d=l>a?(l-a)/c:1,u=Array.from({length:c},(w,C)=>({price:a+C*d,up:0,down:0}));for(let w=i;w<=s;w+=1){let C=r[w],M=C.volume;if(!(M!=null&&M>0))continue;let S=C.close>=C.open?"up":"down",L=C.high-C.low;if(L<=0){let x=Ip(Math.floor((C.low-a)/d),c);u[x][S]+=M;continue}let v=Ip(Math.floor((C.low-a)/d),c),k=Ip(Math.floor((C.high-a)/d-1e-9),c);for(let x=v;x<=k;x+=1){let E=a+x*d,I=Math.min(C.high,E+d)-Math.max(C.low,E);I>0&&(u[x][S]+=M*I/L);}}let h=0,p=0,m=0;for(let w=0;wp&&(p=C,m=w);}if(p<=0)return null;let f=h*Math.min(1,Math.max(0,o)),g=m,b=m,y=p;for(;y0||b0?u[g-1].up+u[g-1].down:-1,C=bw?(b+=1,y+=C):(g-=1,y+=w);}return {rows:u,rowH:d,min:a,maxTotal:p,poc:m,vaFrom:g,vaTo:b}}function Ip(r,e){return r<0?0:r>=e?e-1:r}function mx(r,e,t,n){let{rows:o,rowH:i,maxTotal:s,poc:a,vaFrom:l,vaTo:c}=e,{rightX:d,maxW:u,yOf:h}=t;if(!(s<=0||u<=0)){for(let p=0;p=l&&p<=c?.62:.28,w>0&&(r.fillStyle=n.upColor,r.fillRect(d-y,g,w,b)),y-w>0&&(r.fillStyle=n.downColor,r.fillRect(d-y+w,g,y-w,b));}if(n.showPoc){let p=o[a],m=h(p.price+i),f=Math.max(1,h(p.price)-m-1);r.globalAlpha=.9,r.strokeStyle=n.pocColor,r.lineWidth=1,r.strokeRect(d-u+.5,m+.5,u-1,f);}r.globalAlpha=1;}}var Id=class{constructor(){this.canvas=null;this.ctx=null;this.memoKey="";this.memo=null;}mount(e){this.canvas=e,this.ctx=e.getContext("2d");}destroy(){this.canvas=null,this.ctx=null,this.memoKey="",this.memo=null;}render(e){let t=this.ctx,n=this.canvas;if(!t||!n)return;let{bars:o,data:i,visible:s,coords:a,scale:l,bounds:c,theme:d}=e,u=a.dpr;if(t.setTransform(u,0,0,u,0,0),t.clearRect(0,0,n.width/u,n.height/u),!i||!s||o.length===0||c.height<=0)return;let h=a.visibleLogicalRange(),p=Math.max(0,Math.floor(h.from)),m=Math.min(o.length-1,Math.ceil(h.to));if(p>m)return;let f=o[m],g=`${p}:${m}:${o.length}:${f.high}:${f.low}:${f.close}:${f.volume??0}:${i.rows}:${i.valueAreaFrac}`;g!==this.memoKey&&(this.memoKey=g,this.memo=px(o,p,m,i.rows,i.valueAreaFrac));let b=this.memo;b&&(t.save(),t.beginPath(),t.rect(0,c.top,a.width,c.height),t.clip(),mx(t,b,{rightX:a.width,maxW:a.width*i.widthFrac,yOf:y=>a.priceToY(y,l,c)},{upColor:i.upColor,downColor:i.downColor,showPoc:i.showPoc,pocColor:d.textColor}),t.restore());}};var Xe="price",VA=8,BA="rgba(0,0,0,0)",Ad=64,_A=56,wx=26,ti=22,Us=26,Ap=24,HA=5,zA="0 2px 8px rgba(0,0,0,0.4)",WA=12,kx=12,xx=Ad+kx,Rp=ti+14,GA=120,$A=2,UA=6,Cx=350,YA=.02,KA=220;function Dp(){return typeof performance<"u"?performance.now():Date.now()}var XA=.004,jA=.2,qA=4,Ys=class{constructor(e){this.capabilities=uw;this.surfaceBackground=en.background;this.surfaceTextColor=en.textColor;this.toolbarGutter=0;this.mountContainer=null;this.userDrawings=null;this.backdropRenderer=new Ld;this.volumeRenderer=new Md;this.extLayers=[];this.layerOrderSig="";this.attributionEl=null;this.attributionEnabled=true;this.attributionHtml=null;this.vpvrRenderer=new Id;this.resizeObserver=null;this.dprMedia=null;this.plotDeviceSize=null;this.coords=new Uc;this.scene=new Qc;this.backendMode="auto";this.glowAmount=0;this.chrome=new ad;this.indicatorSlices=new Sd;this.labelTooltip=null;this.markPopover=null;this.marksExpandedBy="hover";this.markPulseRaf=null;this.markClickCbs=new Set;this.crosshairLayer=new cd;this.hostClock=null;this.ownClock=null;this.countdownUnsub=null;this.symbolPicker=null;this.indicatorTitlesOn=true;this.indicatorValuesOn=true;this.legendActionsProvider=null;this.legendCalloutsProvider=null;this.legendOverviewAction=null;this.keyboard=null;this.keyboardEnabled=true;this.historyChordsEnabled=true;this.liveRegion=null;this.animZoom=new er(70);this.animPan=new er(110);this.animScroll=new er(130);this.animAutoscale=new er(80);this.animLiveBar=new er(90,0);this.candleUp=O;this.candleDown=D;this.intro={style:"settle",duration:650};this.introOnStyle="settle";this.introPlayed=false;this.introRaf=null;this.loadingEl=null;this.modelAlpha=1;this.targetBarSpacing=0;this.zoomAnchorLogical=0;this.zoomAnchorX=0;this.zoomAnchorMode="right";this.panVelocity=0;this.bars=[];this.didInitialFit=false;this.paintedData=false;this.skeletonClockMs=0;this.candleBodyAlpha=1;this.candleStructureAlpha=1;this.lastPointer=null;this.volumeActive=false;this.volumeHidden=false;this.vpvrActive=false;this.vpvrHidden=false;this.liveEaseTime=0;this.liveEaseHigh=0;this.liveEaseLow=0;this.liveEaseClose=0;this.axisDragEnabled=true;this.scaleDragHolder=null;this.scaleDragHeight=0;this.scaleDragStart=null;this.paneResizeEnabled=true;this.resizeAbove=null;this.resizeBelow=null;this.resizeSplitStart=null;this.hoverSeparatorY=null;this.maximizedPaneId=null;this.rightAxisW=Ad;this.paneControls=null;this.axisScaleButtons=null;this.paneActionCbs=new Set;this.hoverLogical=null;this.settingsDialog=null;this.hiddenSettings=[];this.dialogHost=null;this.settingsButton=null;this.settingsEnabled=false;this.scrollButton=null;this.pointerNearScrollBtn=false;this.scrollTargetRO=null;this.scrollBtnBottomPx=Rp;this.scrollBtnRightPx=xx;this.layoutMode="desktop";this.viewportCbs=new Set;this.crosshairCbs=new Set;this.chartTypeSettingsCbs=new Set;this.configChangedCbs=new Set;this.themeSelectCbs=new Set;this.factoryConfig=null;this.hostSettingsSections=[];this.clickCbs=new Set;this.axisLongPressCbs=new Set;this.inputChangeCbs=new Set;this.removeIndicatorCbs=new Set;this.toggleVisibleCbs=new Set;this.moveIndicatorCbs=new Set;this.priceStyleCbs=new Set;this.name="native";this.features=["logScale","currentPriceLine","priceLabel","countdown","upColor","downColor","glow","animZoom","animPan","animScroll","animAutoscale","animLiveBar","intro","zoomAnchor","axisDrag","paneResize","candleZOrder","candleVisible","seriesOrder","highlights","sessionZones","gridlines","axisLabels","scaleMode","invertScale","paneScales","autoScale","timezone","keyboard","historyChords","priceStyle","priceBaseline","baselinePrice","settings","attribution","dialogHost","tradeMarkers","marks","indicatorTitles","indicatorValues","crosshairOverride"];this.onScrollProximityMove=e=>{if(!this.scrollButton||!this.plot)return;let t=this.plot.getBoundingClientRect(),n=t.width-this.scrollBtnRightPx-Us/2,o=t.height-this.scrollBtnBottomPx-Us/2,i=Math.hypot(e.clientX-t.left-n,e.clientY-t.top-o)<=GA;i!==this.pointerNearScrollBtn&&(this.pointerNearScrollBtn=i,this.updateScrollToRealtimeButton());};this.onScrollProximityLeave=()=>{this.pointerNearScrollBtn&&(this.pointerNearScrollBtn=false,this.updateScrollToRealtimeButton());};this.onDprChange=()=>{this.watchDpr(),this.resize();};this.externalCross=null;this.snapMode="off";e&&(this.scene.showPriceLine=e.currentPriceLine,this.scene.logScale=e.logScale,this.backendMode=e.nativeBackend,this.animZoom.set(e.animZoom),this.animPan.set(e.animPan),this.animScroll.set(e.animScroll),this.animAutoscale.set(e.animAutoscale),this.animLiveBar.set(e.animLiveBar),this.setIntro(e.animIntro),this.glowAmount=e.glow,this.candleUp=e.upColor,this.candleDown=e.downColor,this.scene.priceStyle=e.priceStyle,this.scene.basePainting=Fh(e.priceStyle),this.scene.candleOverride=Hc(e.priceStyle,this.scene.style.chartTypes)),this.theme=this.deriveTheme(en);}applyFeature(e,t){switch(e){case "logScale":if(t&&typeof t=="object"){let n=t;this.setPaneLog(n.pane??Xe,!!n.value);return}this.scene.logScale=!!t;break;case "currentPriceLine":this.scene.showPriceLine=!!t;break;case "priceLabel":this.scene.showPriceLabel=!!t;break;case "countdown":this.scene.showCountdown=!!t,this.syncCountdownTimer();break;case "upColor":this.candleUp=String(t),this.theme&&(this.theme=this.deriveTheme(this.theme));break;case "downColor":this.candleDown=String(t),this.theme&&(this.theme=this.deriveTheme(this.theme));break;case "glow":this.glowAmount=Number(t)||0,this.backend&&"glow"in this.backend&&(this.backend.glow=this.glowAmount);break;case "animZoom":this.animZoom.set(Yt(t,70));return;case "animPan":{let n=Yt(t,110);this.animPan.set(n),this.animScroll.toggle(n>0);return}case "animScroll":this.animScroll.set(Yt(t,130));return;case "animAutoscale":this.animAutoscale.set(Yt(t,80));return;case "animLiveBar":this.animLiveBar.set(Ud(t));return;case "intro":{this.setIntro(Yd(t)),this.intro.style&&this.playIntro();return}case "zoomAnchor":this.zoomAnchorMode=t==="right"?"right":"cursor",this.input&&(this.input.rightEdgeZoom=this.zoomAnchorMode==="right");return;case "axisDrag":this.axisDragEnabled=!!t,this.input&&(this.input.axisDrag=this.axisDragEnabled);return;case "paneResize":this.paneResizeEnabled=!!t,this.input&&(this.input.paneResize=this.paneResizeEnabled);return;case "candleZOrder":this.scene.candleZ=Number(t)||0;break;case "candleVisible":this.scene.candlesHidden=t===false;break;case "seriesOrder":this.applySeriesOrder(t);break;case "highlights":this.scene.highlights=eR(t);break;case "sessionZones":this.scene.sessionZones=tR(t);break;case "gridlines":this.scene.showGrid=!!t;break;case "axisLabels":this.scene.showAxisLabels=!!t;break;case "scaleMode":if(t&&typeof t=="object"){let n=t;this.setPaneScaleMode(n.pane??Xe,Sx(n.mode));return}this.scene.scaleMode=Sx(t);break;case "invertScale":if(t&&typeof t=="object"){let n=t;this.setPaneInvert(n.pane??Xe,!!n.value);return}this.scene.invertScale=!!t;break;case "autoScale":for(let n of this.scene.panes.values())n.manualScale=t?null:{...n.scale};break;case "timezone":this.scene.timezone=typeof t=="string"&&t?t:"UTC";break;case "priceStyle":this.setPriceStyle(nR(t)?t:"candles");break;case "priceBaseline":this.scene.baselineValue=t==null?null:Number(t);break;case "tradeMarkers":this.scene.tradeMarkers=Bw(this.scene.tradeMarkers,t);break;case "marks":this.scene.marks=Uw(this.scene.marks,t),this.markPopover?.close();break;case "crosshairOverride":this.scene.crosshairOverride=bw(t);break;case "keyboard":this.setKeyboardEnabled(!!t);return;case "historyChords":this.historyChordsEnabled=!!t,this.userDrawings&&(this.userDrawings.historyChords=this.historyChordsEnabled);return;case "settings":this.setSettingsEnabled(!!t);return;case "indicatorTitles":this.indicatorTitlesOn=t!==false,this.inputsUI?.setTitlesVisible(this.indicatorTitlesOn);return;case "indicatorValues":this.indicatorValuesOn=t!==false,this.inputsUI?.setValuesVisible(this.indicatorValuesOn);return;case "attribution":this.attributionHtml=typeof t=="string"&&t.trim()?t:null,this.attributionEnabled=this.attributionHtml!==null||!!t,this.rebuildAttribution();return;case "dialogHost":this.dialogHost=t instanceof HTMLElement?t:null,this.settingsDialog?.close(),this.settingsDialog=null,this.inputsUI?.setDialogHost(this.dialogHost);return;default:return}this.scheduler?.invalidate(4);}readFeature(e){switch(e){case "logScale":return this.scene.logScale;case "currentPriceLine":return this.scene.showPriceLine;case "priceLabel":return this.scene.showPriceLabel;case "countdown":return this.scene.showCountdown;case "upColor":return this.candleUp;case "downColor":return this.candleDown;case "glow":return this.glowAmount;case "animZoom":return this.animZoom.tau;case "animPan":return this.animPan.tau;case "animScroll":return this.animScroll.tau;case "animAutoscale":return this.animAutoscale.tau;case "animLiveBar":return this.animLiveBar.tau;case "intro":return this.intro.style;case "zoomAnchor":return this.zoomAnchorMode;case "axisDrag":return this.input?this.input.axisDrag:this.axisDragEnabled;case "paneResize":return this.input?this.input.paneResize:this.paneResizeEnabled;case "candleZOrder":return this.scene.candleZ;case "candleVisible":return !this.scene.candlesHidden;case "seriesOrder":return this.scene.indicatorZOrder();case "highlights":return this.scene.highlights;case "sessionZones":return this.scene.sessionZones;case "gridlines":return this.scene.showGrid;case "axisLabels":return this.scene.showAxisLabels;case "scaleMode":return this.scene.scaleMode;case "invertScale":return this.scene.invertScale;case "paneScales":return this.paneScaleInfos();case "autoScale":{let t=this.scene.orderedPanes().find(n=>n.kind==="price");return t?t.manualScale==null:true}case "timezone":return this.scene.timezone;case "priceStyle":return this.scene.priceStyle;case "priceBaseline":return this.scene.baselineValue;case "baselinePrice":{let t=this.scene.panes.get(Xe);return t?this.scene.baselinePriceFor(t.scale):this.scene.baselineValue}case "tradeMarkers":return {...this.scene.tradeMarkers,colors:{...this.scene.tradeMarkers.colors}};case "marks":return {visible:this.scene.marks.visible,groups:{...this.scene.marks.groups}};case "crosshairOverride":return this.scene.crosshairOverride?{...this.scene.crosshairOverride}:null;case "keyboard":return this.keyboardEnabled;case "historyChords":return this.historyChordsEnabled;case "settings":return this.settingsEnabled;case "indicatorTitles":return this.indicatorTitlesOn;case "indicatorValues":return this.indicatorValuesOn;case "attribution":return this.attributionHtml??this.attributionEnabled;case "dialogHost":return this.dialogHost??void 0;default:return}}setNativeData(e,t){e==="volume"?(this.scene.volumeLayer=t??null,this.scheduler?.invalidate(3)):e==="vpvr"?(this.scene.vpvrLayer=t??null,this.scheduler?.invalidate(3)):e.endsWith("-pending")?(this.scene.nativePending.set(e.slice(0,-8),t??[]),this.scheduler?.invalidate(3)):(this.scene.nativeData.set(e,t),this.scheduler?.invalidate(3));}setIndicatorStatus(e,t){this.inputsUI.setStatus(e.id,t);}setLoading(e){if(!e||!this.wrapper){this.loadingEl?.remove(),this.loadingEl=null;return}if(this.loadingEl)return;let t=this.wrapper.ownerDocument,n=t.createElement("div");n.className="vela-loading",Object.assign(n.style,{position:"absolute",inset:"0",display:"flex",alignItems:"center",justifyContent:"center",gap:"7px",pointerEvents:"none"});for(let o=0;o<3;o+=1){let i=t.createElement("span");Object.assign(i.style,{width:"7px",height:"7px",borderRadius:"50%",background:this.chromeTheme().textColor,opacity:"0.15"}),i.animate([{opacity:.12},{opacity:.55}],{duration:800,iterations:1/0,direction:"alternate",easing:"ease-in-out",delay:-o*260}),n.appendChild(i);}this.wrapper.appendChild(n),this.loadingEl=n;}setPricePrecision(e){let t=typeof e=="number"&&e>0?e:void 0;t!==this.scene.priceMintick&&(this.scene.priceMintick=t,this.scheduler?.invalidate(4));}getConfig(){let e=this.scene.style,t=Object.fromEntries(Object.entries(e.chartTypes).map(([o,i])=>[o,{...i}])),n=this.theme;return {version:Oh,chartTypes:t,layout:{background:n.background,textColor:n.textColor,fontFamily:n.fontFamily,fontSize:e.fontSize},grid:{vertLines:{visible:e.gridVert.visible,color:e.gridVert.color??n.gridColor},horzLines:{visible:e.gridHorz.visible,color:e.gridHorz.color??n.gridColor}},crosshair:{color:e.crosshair.color??n.textColor,width:e.crosshair.width,style:e.crosshair.style,opacity:e.crosshair.opacity,labelBackground:e.crosshair.labelBackground??n.textColor},priceScale:{mode:this.scene.scaleMode,log:this.scene.logScale,invert:this.scene.invertScale,borderColor:e.borderColor??n.borderColor,labelsVisible:this.scene.showAxisLabels,currentPriceLine:this.scene.showPriceLine,priceLabel:this.scene.showPriceLabel,countdown:this.scene.showCountdown,animateLastPrice:this.animLiveBar.on},animations:{zoom:this.animZoom.on,pan:this.animPan.on,autoscale:this.animAutoscale.on,intro:this.intro.style!==false},panes:{separatorColor:e.separatorColor??n.borderColor},margins:{...e.margins},trades:{visible:this.scene.tradeMarkers.visible,labels:this.scene.tradeMarkers.labels,qty:this.scene.tradeMarkers.qty,longColor:this.scene.tradeMarkers.colors.long,shortColor:this.scene.tradeMarkers.colors.short,exitColor:this.scene.tradeMarkers.colors.exit},timeScale:{timezone:this.scene.timezone},marks:{visible:this.scene.marks.visible,groups:{...this.scene.marks.groups}},candles:{upColor:this.candleUp,downColor:this.candleDown,bodyVisible:e.candle.bodyVisible,borderVisible:e.candle.borderVisible,borderUpColor:e.candle.borderUpColor??this.candleUp,borderDownColor:e.candle.borderDownColor??this.candleDown,wickVisible:e.candle.wickVisible,wickUpColor:e.candle.wickUpColor??this.candleUp,wickDownColor:e.candle.wickDownColor??this.candleDown},bars:{upColor:e.bars.upColor??this.candleUp,downColor:e.bars.downColor??this.candleDown},line:{color:e.line.color??this.candleUp,width:e.line.width},stacking:{candles:this.scene.candleZ,series:Object.fromEntries(this.scene.indicatorZOrder().map(({id:o,z:i})=>[o,i]))},area:(()=>{let o=e.area.lineColor??this.candleUp;return {lineColor:o,width:e.area.width,topColor:e.area.topColor??o,bottomColor:e.area.bottomColor??BA}})(),baseline:(()=>{let o=e.baseline.topLineColor??Ho,i=e.baseline.bottomLineColor??zo;return {topLineColor:o,bottomLineColor:i,topFillColor:e.baseline.topFillColor??J(o,An),topFillColor2:e.baseline.topFillColor2??J(o,Rn),bottomFillColor:e.baseline.bottomFillColor??J(i,An),bottomFillColor2:e.baseline.bottomFillColor2??J(i,Rn),width:e.baseline.width,baselineLevel:e.baseline.baselineLevel}})(),series:{style:this.scene.priceStyle,baseline:this.scene.baselineValue,spacing:this.coords.spacingScale},sessions:{premarketColor:e.sessions.premarketColor,postmarketColor:e.sessions.postmarketColor,extendedColor:e.sessions.extendedColor}}}applyConfig(e){let t=ww(this.getConfig(),e),n=this.scene.style;for(let[d,u]of Object.entries(t.chartTypes))if(JSON.stringify(n.chartTypes[d])!==JSON.stringify(u)){this.scene.nativeData.set(`${d}-settings`,{...u});for(let h of this.chartTypeSettingsCbs)h(d,{...u});}n.chartTypes=Object.fromEntries(Object.entries(t.chartTypes).map(([d,u])=>[d,{...u}]));let o=e&&typeof e=="object"?e.layout:void 0,i=o&&typeof o=="object"?o.textColor:void 0,s=typeof i=="string"&&i.trim().length>0,a=this.theme,l={textColor:t.layout.textColor,gridColor:a.gridColor,borderColor:a.borderColor};if(!s&&bt(t.layout.textColor)===bt(t.layout.background)){let d=bt(t.layout.background)?en:Ei;l={textColor:d.textColor,gridColor:d.gridColor,borderColor:d.borderColor};}this.theme={...this.theme,background:t.layout.background,textColor:l.textColor,gridColor:l.gridColor,borderColor:l.borderColor,fontFamily:t.layout.fontFamily},n.fontSize=t.layout.fontSize;let c=(d,u,h)=>d===null&&u===h?null:u;n.gridVert={visible:t.grid.vertLines.visible,color:c(n.gridVert.color,t.grid.vertLines.color,a.gridColor)},n.gridHorz={visible:t.grid.horzLines.visible,color:c(n.gridHorz.color,t.grid.horzLines.color,a.gridColor)},n.crosshair={color:t.crosshair.color,width:t.crosshair.width,style:t.crosshair.style,opacity:t.crosshair.opacity,labelBackground:t.crosshair.labelBackground},this.scene.scaleMode=t.priceScale.mode,this.scene.logScale=t.priceScale.log,this.scene.invertScale=t.priceScale.invert,n.borderColor=c(n.borderColor,t.priceScale.borderColor,a.borderColor),this.scene.showAxisLabels=t.priceScale.labelsVisible,this.scene.showPriceLine=t.priceScale.currentPriceLine,this.scene.showPriceLabel=t.priceScale.priceLabel,this.scene.showCountdown=t.priceScale.countdown,this.syncCountdownTimer(),this.animLiveBar.toggle(t.priceScale.animateLastPrice),this.animZoom.toggle(t.animations.zoom),this.animPan.toggle(t.animations.pan),this.animScroll.toggle(t.animations.pan),this.animAutoscale.toggle(t.animations.autoscale),this.intro={style:t.animations.intro?this.introOnStyle:false,duration:this.intro.duration||650},n.separatorColor=c(n.separatorColor,t.panes.separatorColor,a.borderColor),t.margins.right!==n.margins.right&&this.coords.barCount>0&&this.applyViewport({barSpacing:this.coords.getViewport().barSpacing,rightOffset:t.margins.right}),n.margins={...t.margins},this.scene.tradeMarkers={visible:t.trades.visible,labels:t.trades.labels,qty:t.trades.qty,colors:{long:t.trades.longColor,short:t.trades.shortColor,exit:t.trades.exitColor}},this.scene.timezone=t.timeScale.timezone,this.scene.marks={visible:t.marks.visible,groups:{...t.marks.groups}},this.candleUp=t.candles.upColor,this.candleDown=t.candles.downColor,n.candle={bodyVisible:t.candles.bodyVisible,borderVisible:t.candles.borderVisible,borderUpColor:t.candles.borderUpColor,borderDownColor:t.candles.borderDownColor,wickVisible:t.candles.wickVisible,wickUpColor:t.candles.wickUpColor,wickDownColor:t.candles.wickDownColor},this.scene.candleZ=t.stacking.candles;for(let[d,u]of Object.entries(t.stacking.series))this.scene.setIndicatorZ(d,u);n.bars={upColor:t.bars.upColor,downColor:t.bars.downColor},n.line={color:t.line.color,width:t.line.width},n.area={lineColor:t.area.lineColor,width:t.area.width,topColor:t.area.topColor,bottomColor:t.area.bottomColor},n.baseline={topLineColor:t.baseline.topLineColor,bottomLineColor:t.baseline.bottomLineColor,topFillColor:t.baseline.topFillColor,topFillColor2:t.baseline.topFillColor2,bottomFillColor:t.baseline.bottomFillColor,bottomFillColor2:t.baseline.bottomFillColor2,width:t.baseline.width,baselineLevel:t.baseline.baselineLevel},n.sessions={premarketColor:t.sessions.premarketColor,postmarketColor:t.sessions.postmarketColor,extendedColor:t.sessions.extendedColor},this.setPriceStyle(t.series.style),this.scene.candleOverride=Hc(this.scene.priceStyle,n.chartTypes),this.scene.baselineValue=t.series.baseline,this.coords.setPitchScale(t.series.spacing),this.coords.setViewport(this.clampViewport(this.coords.getViewport().barSpacing,this.coords.getViewport().rightOffset)),this.targetBarSpacing=this.coords.getViewport().barSpacing,this.theme=this.deriveTheme(this.theme),this.wrapper&&(Be(this.wrapper,this.chromeTheme()),this.applyBackground()),this.inputsUI?.setTheme(this.theme),this.paneControls?.setTheme(this.theme),this.axisScaleButtons?.setTheme(this.theme),this.userDrawings?.setTheme(this.chromeTheme()),this.refreshScrollButtonTheme(),this.refreshAttributionColor(),this.scheduler?.invalidate(4);for(let d of this.configChangedCbs)d();}applySeriesOrder(e){if(!e||typeof e!="object")return;let t=e;typeof t.id=="string"&&(typeof t.z=="number"?this.scene.setIndicatorZ(t.id,t.z):t.to==="front"?this.scene.bringIndicatorToFront(t.id):t.to==="back"&&this.scene.sendIndicatorToBack(t.id));}setSettingsEnabled(e){this.settingsEnabled=e,e?(this.plot&&!this.settingsButton&&(this.settingsButton=this.makeSettingsButton(),this.plot.appendChild(this.settingsButton)),this.settingsButton&&(this.settingsButton.style.display="flex"),this.plot&&!this.settingsDialog&&(this.settingsDialog=new Bs(this.dialogHost??this.plot,this.theme))):(this.settingsButton?.style.setProperty("display","none"),this.settingsDialog?.close());}makeSettingsButton(){let e=document.createElement("button");return e.type="button",e.title="Chart settings",e.innerHTML=Re("gear",14),Object.assign(e.style,{position:"absolute",bottom:`${ti+10}px`,right:`${Ad+10}px`,zIndex:"6",width:"26px",height:"26px",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",borderRadius:"50%",border:`1px solid ${this.theme.borderColor}`,background:this.theme.background,color:this.theme.textColor,fontSize:"14px",lineHeight:"1",opacity:"0.75",pointerEvents:"auto",padding:"0"}),e.addEventListener("mouseenter",()=>e.style.opacity="1"),e.addEventListener("mouseleave",()=>e.style.opacity="0.75"),e.addEventListener("click",()=>this.toggleSettingsDialog()),e}openSettingsDialog(e){!this.settingsDialog&&this.plot&&(this.settingsDialog=new Bs(this.dialogHost??this.plot,this.theme),this.settingsDialog.setLayoutMode(this.layoutMode)),this.toggleSettingsDialog(e);}syncThemeControl(){this.settingsDialog?.setThemeControl(bt(this.surfaceBackground)?"dark":"light",e=>{for(let t of this.themeSelectCbs)t(e);});}toggleSettingsDialog(e){if(this.settingsDialog){if(e!==void 0&&this.settingsDialog.isOpen()){this.settingsDialog.showSection(e);return}this.settingsDialog.setTheme(this.theme),this.settingsDialog.setHostSections(this.hostSettingsSections),this.settingsDialog.setMarkGroups(this.markGroupsForEventsTab(),t=>Zc(this.scene.marks,t,this.scene.markGroups),t=>bl(this.scene.marks.groups,t,this.scene.markGroups)),this.settingsDialog.setHiddenSettings(this.hiddenSettings),this.syncThemeControl(),this.settingsDialog.toggle(this.getConfig(),t=>this.applyConfig(t),t=>this.applyConfig(t),()=>{this.factoryConfig&&this.applyConfig(this.factoryResetDocument(this.factoryConfig)),this.settingsDialog?.refresh(this.getConfig());},e);}}factoryResetDocument(e){let t=yw(e,this.scene.priceStyle),n={...t.marks.groups};for(let o of this.markGroupsInUse())n[o.id]=o.visible!==false;return {...t,marks:{...t.marks,groups:n}}}closeDialogs(){this.inputsUI?.closeOpenDialog(),this.settingsDialog?.close();}makeScrollToRealtimeButton(){let e=document.createElement("button");return e.type="button",e.title="Scroll to most recent bar (Alt+Shift+\u2192)",e.setAttribute("aria-label","Scroll to most recent bar"),e.innerHTML=this.scrollButtonIcon(),Object.assign(e.style,{position:"absolute",bottom:`${Rp}px`,right:`${xx}px`,zIndex:"6",width:`${Us}px`,height:`${Us}px`,boxSizing:"border-box",display:"none",alignItems:"center",justifyContent:"center",cursor:"pointer",borderRadius:`${HA}px`,border:`1px solid ${this.theme.borderColor}`,boxShadow:zA,background:this.scrollButtonSurface(),color:this.theme.textColor,lineHeight:"0",opacity:"0.85",pointerEvents:"auto",padding:"0"}),e.addEventListener("mouseenter",()=>e.style.opacity="1"),e.addEventListener("mouseleave",()=>e.style.opacity="0.85"),e.addEventListener("click",()=>this.scrollToRealtime()),e}scrollButtonIcon(){return Re("chevrons-right",WA)}scrollButtonSurface(){return J(this.theme.background,.5)}refreshScrollButtonTheme(){this.scrollButton&&(this.scrollButton.style.background=this.scrollButtonSurface(),this.scrollButton.style.color=this.theme.textColor,this.scrollButton.style.borderColor=this.theme.borderColor);}updateScrollToRealtimeButton(){let e=this.scrollButton;if(!e)return;let t=this.coords.barCount>0&&this.coords.getViewport().rightOffset<0;if(this.layoutMode==="mobile"){e.style.display=t?"flex":"none";return}e.style.display=t&&this.pointerNearScrollBtn?"flex":"none";}scrollToRealtime(){this.coords.barCount!==0&&this.glideRightOffset(this.scene.style.margins.right);}glideRightOffset(e){let t=this.coords.getViewport();if(!this.animScroll.on){this.applyViewport({barSpacing:t.barSpacing,rightOffset:e});return}this.panVelocity=0,this.targetBarSpacing=t.barSpacing,this.scrollTargetRO=e,this.animator.start();}screenshotCanvas(){if(!this.dataCanvas)return null;this.computeScales(),this.paintData();let e=document.createElement("canvas");e.width=this.dataCanvas.width,e.height=this.dataCanvas.height;let t=e.getContext("2d");if(!t)return null;t.fillStyle=this.theme.background,t.fillRect(0,0,e.width,e.height);let n=this.plot?.getBoundingClientRect(),o=n&&n.width>0?{left:n.left,top:n.top,dpr:e.width/n.width}:null,i=[...this.mountContainer?.querySelectorAll("[data-vela-screenshot]")??[]];if(o)for(let s of i)s.getAttribute("data-vela-screenshot")==="under"&&Pd(t,s,o);for(let s of [...this.canvasPile(),this.chromeCanvas,this.drawingsCanvas])s&&s.width>0&&s.height>0&&t.drawImage(s,0,0);if(o){for(let s of this.plot?.querySelectorAll("[data-vela-pane]")??[])Pd(t,s,o);for(let s of i)s.getAttribute("data-vela-screenshot")!=="under"&&Pd(t,s,o);}return e}screenshot(){return this.screenshotCanvas()?.toDataURL("image/png")??null}playIntro(){this.introRaf!=null&&cancelAnimationFrame(this.introRaf),this.introRaf=null;let{style:e,duration:t}=this.intro,n=this.bars,o=n.length;if(o===0||!e)return;this.computeScales();for(let a of this.scene.panes.values())a.scale={...a.scaleTarget};this.modelAlpha=0;let i=performance.now(),s=a=>{let l=Math.min(1,(a-i)/t);this.scene.bars=l>=1?n:n.map((c,d)=>this.revealCandle(c,d,l,o,e)),this.paintData(),l<1?this.introRaf=requestAnimationFrame(s):(this.scene.bars=n,this.fadeInModels());};this.introRaf=requestAnimationFrame(s);}fadeInModels(){let e=Math.min(Cx,this.intro.duration||Cx),t=performance.now(),n=o=>{this.modelAlpha=Math.min(1,(o-t)/e),this.paintData(),this.modelAlpha<1?this.introRaf=requestAnimationFrame(n):(this.modelAlpha=1,this.introRaf=null);};this.introRaf=requestAnimationFrame(n);}revealCandle(e,t,n,o,i){let a=Math.max(0,Math.min(1,(n-t/Math.max(1,o-1)*.55)/.44999999999999996)),l;if(i==="settle"){let u=a-1;l=1+(1.70158+1)*u*u*u+1.70158*u*u;}else {let d=1-a;l=1-d*d*d;}let c=e.open;return {...e,high:c+(e.high-c)*l,low:c+(e.low-c)*l,close:c+(e.close-c)*l}}deriveTheme(e){return {...e,upColor:this.candleUp,downColor:this.candleDown}}chromeTheme(){return {...this.theme,background:this.surfaceBackground,textColor:this.surfaceTextColor,borderColor:bt(this.surfaceBackground)?en.borderColor:Ei.borderColor}}axisSurface(){return {background:this.theme.background,textColor:this.theme.textColor}}mount(e,t){this.mountContainer=e,this.publishGutters(),this.theme=this.deriveTheme(t),this.surfaceBackground=t.background,this.surfaceTextColor=t.textColor,this.wrapper=document.createElement("div"),Object.assign(this.wrapper.style,{position:"relative",width:"100%",height:"100%",overflow:"hidden",cursor:"crosshair",userSelect:"none",webkitUserSelect:"none"}),Be(this.wrapper,this.chromeTheme()),this.backdropCanvas=document.createElement("canvas"),Object.assign(this.backdropCanvas.style,{position:"absolute",inset:"0",width:"100%",height:"100%",pointerEvents:"none"}),this.volumeCanvas=document.createElement("canvas"),Object.assign(this.volumeCanvas.style,{position:"absolute",inset:"0",width:"100%",height:"100%",pointerEvents:"none"}),this.dataCanvas=this.createGeometryBackend(),this.vpvrCanvas=document.createElement("canvas"),Object.assign(this.vpvrCanvas.style,{position:"absolute",inset:"0",width:"100%",height:"100%",pointerEvents:"none"}),this.chromeCanvas=document.createElement("canvas"),Object.assign(this.chromeCanvas.style,{position:"absolute",inset:"0",width:"100%",height:"100%",pointerEvents:"none"}),this.drawingsCanvas=document.createElement("canvas"),Object.assign(this.drawingsCanvas.style,{position:"absolute",inset:"0",width:"100%",height:"100%",pointerEvents:"none"}),this.cursorCanvas=document.createElement("canvas"),Object.assign(this.cursorCanvas.style,{position:"absolute",inset:"0",width:"100%",height:"100%",pointerEvents:"none"}),this.overlayRoot=document.createElement("div"),Object.assign(this.overlayRoot.style,{position:"absolute",inset:"0",pointerEvents:"none"}),this.plot=document.createElement("div"),Object.assign(this.plot.style,{position:"absolute",top:"0",right:"0",bottom:"0",left:"0"}),this.extLayers=Lp().map(i=>({def:i,instance:i.create(),canvas:this.createLayerCanvas(),channel:i.id,owner:null}));let n=this.extLayers.filter(i=>i.def.placement==="below-data").map(i=>i.canvas),o=this.extLayers.filter(i=>i.def.placement!=="below-data").map(i=>i.canvas);this.plot.append(this.backdropCanvas,...n,this.dataCanvas,this.volumeCanvas,this.vpvrCanvas,...o,this.chromeCanvas,this.drawingsCanvas,this.cursorCanvas,this.overlayRoot),this.layerOrderSig="",this.wrapper.appendChild(this.plot),this.factoryConfig=this.getConfig(),this.attributionEl=this.buildAttributionEl(),this.attributionEnabled||(this.attributionEl.style.display="none"),this.positionAttribution(),this.wrapper.appendChild(this.attributionEl),e.appendChild(this.wrapper),this.applyBackground(),this.backdropRenderer.mount(this.backdropCanvas),this.volumeRenderer.mount(this.volumeCanvas),this.vpvrRenderer.mount(this.vpvrCanvas);for(let i of this.extLayers)i.instance.mount(i.canvas);for(let i of this.scene.indicators.values())this.ensureInstanceLayer(i);this.chrome.mount(this.chromeCanvas),this.crosshairLayer.mount(this.cursorCanvas),this.coords.setViewport($c()),this.scene.ensurePane(Xe,"price",0,3),this.scheduler=new Yc(i=>this.renderFrame(i)),this.animator=new Kc(i=>this.animTick(i)),this.targetBarSpacing=this.coords.getViewport().barSpacing,this.input=new Xc({getCoords:()=>this.coords,apply:i=>this.applyViewport(i),zoomTo:(i,s,a)=>this.zoomTo(i,s,a),fling:i=>this.fling(i),onPointerMove:(i,s)=>this.handlePointerMove(i,s),onClick:(i,s)=>{this.handleMarkClick(i,s)||(this.userDrawings?.deselect(),this.handleClick(i));},onAxisLongPress:(i,s,a)=>{for(let l of this.axisLongPressCbs)l({axis:i,x:s,y:a});},beginPriceScale:(i,s)=>this.beginPriceScale(i,s),priceScaleBy:i=>this.priceScaleBy(i),beginPricePan:i=>this.beginPricePan(i),pricePanBy:i=>this.pricePanBy(i),resetPriceScale:(i,s)=>this.resetPriceScale(i,s),dataDblClick:(i,s)=>this.dataDblClick(i,s),paneSeparatorAt:i=>this.paneSeparatorAt(i),beginPaneResize:i=>this.beginPaneResize(i),paneResizeBy:i=>this.paneResizeBy(i),resetPaneSize:i=>this.resetPaneSize(i),resetView:()=>this.resetView(),drawingsClaim:(i,s)=>this.userDrawings?.claim(i,s)??false,drawingsMeasureStart:(i,s,a)=>this.userDrawings?.beginMeasureAt(i,s,a)??false,drawingsMarqueeStart:(i,s)=>this.userDrawings?.beginMarqueeAt(i,s)??false,drawingsDeleteAt:(i,s)=>this.userDrawings?.deleteAt(i,s,true)??false,drawingsCancelPlacement:()=>this.userDrawings?.cancelPlacement()??false,drawingsSnapMode:()=>this.snapMode,drawingsPointerDown:(i,s,a,l,c)=>this.userDrawings?.pointerDown(i,s,a,l,c),drawingsPointerMove:(i,s,a,l,c)=>this.userDrawings?.pointerMove(i,s,a,l,c),drawingsPointerUp:(i,s,a)=>this.userDrawings?.pointerUp(i,s,a),drawingsCursor:(i,s)=>this.userDrawings?.cursorAt(i,s)??(this.chrome.markGlyphAt(i,s)?"pointer":null),drawingsDblClick:(i,s)=>this.userDrawings?.dblClick(i,s)??false,drawingsClearTransient:()=>this.userDrawings?.clearTransient()}),this.input.rightEdgeZoom=this.zoomAnchorMode==="right",this.input.axisDrag=this.axisDragEnabled,this.input.paneResize=this.paneResizeEnabled,this.input.attach(this.dataCanvas),this.settingsEnabled&&this.setSettingsEnabled(true),this.syncCountdownTimer(),this.scrollButton=this.makeScrollToRealtimeButton(),this.plot.appendChild(this.scrollButton),this.plot.addEventListener("pointermove",this.onScrollProximityMove),this.plot.addEventListener("pointerleave",this.onScrollProximityLeave),this.labelTooltip=new ld(this.plot,{theme:()=>this.chromeTheme(),lookup:(i,s)=>this.indicatorSlices.labelTooltipAt(i,s)??this.chrome.markTooltipAt(i,s,this.markGroupsInUse())}),this.markPopover=new kd({plot:this.plot,host:()=>this.dialogHost??this.plot,theme:()=>this.chromeTheme(),onOpenChange:i=>{this.scene.marksActiveKey=i,this.scheduler?.invalidate(2);}}),this.chrome.setMarkIconReady(()=>this.scheduler?.invalidate(2)),this.userDrawings=new xd(this.wrapper,this.plot,this.drawingsCanvas,{projector:()=>this.drawingProjector(),dpr:()=>this.coords.dpr,theme:()=>this.theme,requestScaleUpdate:()=>this.scheduler.invalidate(3),seriesBoundaries:i=>this.scene.seriesBoundaries(i),priceZ:i=>i===Xe?this.scene.candleZ:null,requestDataPaint:()=>this.scheduler.invalidate(3),seriesLook:()=>{let i=this.scene.style,s=Go(i.candle,this.scene.candleOverride,this.theme.upColor,this.theme.downColor),a=i.bars.upColor??this.theme.upColor,l=i.bars.downColor??this.theme.downColor,c=this.scene.priceStyle;return {style:c,upColor:c==="bars"?a:s.up,downColor:c==="bars"?l:s.down,lineColor:c==="area"?i.area.lineColor??this.theme.upColor:i.line.color??this.theme.upColor}},chartBarMs:()=>this.coords.barInterval,snap:(i,s,a,l)=>this.snapToCandle(i,s,a,l),setSnapMode:i=>this.setSnapMode(i),setToolbarGutter:i=>this.setToolbarGutter(i)}),this.userDrawings.historyChords=this.historyChordsEnabled,this.layoutMode==="mobile"&&(this.mountContainer?.setAttribute("data-vela-layout",this.layoutMode),this.userDrawings.setLayoutMode(this.layoutMode),this.scrollButton&&(this.scrollButton.style.width=`${Ap}px`,this.scrollButton.style.height=`${Ap}px`)),this.keyboard=new jc({panByBars:i=>this.panByBars(i),zoomByStep:i=>this.zoomByStep(i),stepCrosshair:i=>this.stepCrosshair(i),jumpToEdge:i=>this.focusBar(i==="first"?0:this.coords.barCount-1),resetView:()=>this.resetView(),scrollToRealtime:()=>this.scrollToRealtime(),clearCrosshair:()=>this.handlePointerMove(null,null),preempt:i=>this.userDrawings?.handleKey(i)??false}),this.setKeyboardEnabled(this.keyboardEnabled),this.inputsUI=new Nc(this.plot,t,i=>this.paneBoundsFor(i)),this.inputsUI.setLayoutMode(this.layoutMode),this.inputsUI.setTitlesVisible(this.indicatorTitlesOn),this.inputsUI.setValuesVisible(this.indicatorValuesOn),this.inputsUI.setDialogHost(this.dialogHost),this.inputsUI.setSymbolPicker(this.symbolPicker),this.inputsUI.setLegendActions(this.legendActionsProvider),this.inputsUI.setLegendCallouts(this.legendCalloutsProvider),this.inputsUI.setLegendOverviewAction(this.legendOverviewAction),this.inputsUI.setOnChange(i=>{for(let s of this.inputChangeCbs)s({indicatorId:i.indicatorId,key:i.key,value:i.value,...i.kind?{kind:i.kind}:{}});}),this.inputsUI.setOnRemove(i=>{for(let s of this.removeIndicatorCbs)s(i);}),this.inputsUI.setOnToggleVisible((i,s)=>{for(let a of this.toggleVisibleCbs)a(i,s);}),this.inputsUI.setMoveApi({panes:()=>this.scene.orderedPanes().map((i,s)=>({id:i.id,kind:i.kind,label:i.kind==="price"?"Main chart":this.paneMasterTitle(i.id)??`Pane ${s}`,top:i.bounds.top,height:i.bounds.height})),move:(i,s)=>{for(let a of this.moveIndicatorCbs)a(i,s);}}),this.paneControls=new Fc(this.plot,t,{panes:()=>this.paneControlViews(),rightAxis:()=>this.rightAxisW,onMove:(i,s)=>this.movePaneLocal(i,s),onToggleCollapse:i=>{let s=this.scene.panes.get(i);if(!s)return;let a=!s.collapsed;s.collapsed=a,this.afterPaneLayoutChange(),this.emitPaneAction({type:"collapse",paneId:i,collapsed:a});},onToggleMaximize:i=>{let s=this.maximizedPaneId!==i;this.maximizedPaneId=s?i:null,this.afterPaneLayoutChange(),this.emitPaneAction({type:"maximize",paneId:i,maximized:s});}}),this.paneControls.setSuspended(this.layoutMode==="mobile"),this.axisScaleButtons=new Vc(this.plot,t,{panes:()=>this.axisScaleViews(),rightAxis:()=>this.rightAxisW,onToggleAuto:i=>this.togglePaneAuto(i),onToggleLog:i=>{let s=this.scene.panes.get(i);s&&this.setPaneLog(i,!Ko(this.scene,s));}}),this.resizeObserver=new ResizeObserver(i=>{for(let s of i){if(s.target!==this.plot)continue;let a=s.devicePixelContentBoxSize?.[0];a&&(this.plotDeviceSize={width:a.inlineSize,height:a.blockSize});}this.resize();}),this.resizeObserver.observe(this.wrapper);try{this.resizeObserver.observe(this.plot,{box:"device-pixel-content-box"});}catch{}this.watchDpr(),this.syncSize();}makeDataCanvas(){let e=document.createElement("canvas");return Object.assign(e.style,{position:"absolute",inset:"0",width:"100%",height:"100%"}),e}createGeometryBackend(){if((this.backendMode==="auto"||this.backendMode==="webgl2")&&hw()){let n=this.makeDataCanvas(),o=new Gc;if(o.glow=this.glowAmount,o.onNeedsRedraw=()=>this.scheduler?.invalidate(4),o.onContextFailed=()=>this.swapToCanvas2dFallback(),o.mount(n),o.ok)return this.backend=o,n;o.destroy();}let e=this.makeDataCanvas(),t=new Ps;return t.mount(e),this.backend=t,e}swapToCanvas2dFallback(){if(this.backend.kind==="canvas2d")return;let e=this.dataCanvas;this.input?.detach(),this.backend.destroy();let t=this.makeDataCanvas(),n=new Ps;n.mount(t),this.backend=n,e.replaceWith(t),this.dataCanvas=t,this.input?.attach(t),this.syncSize();}watchDpr(){typeof window.matchMedia=="function"&&(this.dprMedia?.removeEventListener("change",this.onDprChange),this.dprMedia=window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`),this.dprMedia.addEventListener("change",this.onDprChange,{once:true}));}setTheme(e){this.theme=this.deriveTheme(e),this.surfaceBackground=e.background,this.surfaceTextColor=e.textColor,this.wrapper&&Be(this.wrapper,this.chromeTheme()),this.applyBackground(),this.inputsUI.setTheme(e),this.paneControls?.setTheme(this.theme),this.axisScaleButtons?.setTheme(this.theme),this.settingsDialog?.refreshConfig(this.getConfig()),this.syncThemeControl(),this.settingsDialog?.setTheme(this.theme),this.settingsButton&&(this.settingsButton.style.background=this.theme.background,this.settingsButton.style.color=this.theme.textColor,this.settingsButton.style.borderColor=this.theme.borderColor),this.refreshScrollButtonTheme(),this.userDrawings?.setTheme(this.chromeTheme()),this.refreshAttributionColor(),this.scheduler.invalidate(4);}resize(){this.syncSize();}setWallClock(e){e!==this.hostClock&&(this.hostClock=e,this.countdownUnsub!=null&&(this.countdownUnsub(),this.countdownUnsub=null),this.syncCountdownTimer());}syncCountdownTimer(){if(this.scene.showCountdown){if(this.countdownUnsub==null){let e=this.hostClock??this.ownClock??(this.ownClock=new _i);this.countdownUnsub=e.onTick(()=>{this.scene.showCountdown&&this.scene.bars.length>0&&this.scheduler?.invalidate(2);});}}else this.countdownUnsub!=null&&(this.countdownUnsub(),this.countdownUnsub=null);}destroy(){this.introRaf!=null&&cancelAnimationFrame(this.introRaf),this.loadingEl?.remove(),this.loadingEl=null,this.countdownUnsub!=null&&(this.countdownUnsub(),this.countdownUnsub=null),this.scheduler?.destroy(),this.animator?.stop(),this.input?.detach(),this.keyboard?.detach(),this.keyboard=null,this.liveRegion=null,this.inputsUI?.destroy(),this.paneControls?.destroy(),this.axisScaleButtons?.destroy(),this.resizeObserver?.disconnect(),this.resizeObserver=null,this.dprMedia?.removeEventListener("change",this.onDprChange),this.dprMedia=null,this.userDrawings?.destroy(),this.userDrawings=null,this.settingsDialog?.destroy(),this.settingsDialog=null,this.settingsButton?.remove(),this.settingsButton=null,this.plot?.removeEventListener("pointermove",this.onScrollProximityMove),this.plot?.removeEventListener("pointerleave",this.onScrollProximityLeave),this.labelTooltip?.destroy(),this.labelTooltip=null,this.markPopover?.destroy(),this.markPopover=null,this.chrome.setMarkIconReady(null),this.markPulseRaf!==null&&cancelAnimationFrame(this.markPulseRaf),this.markPulseRaf=null,this.scrollButton?.remove(),this.scrollButton=null;for(let e of this.extLayers)e.instance.destroy?.();this.extLayers=[],this.backdropRenderer.destroy(),this.volumeRenderer.destroy(),this.vpvrRenderer.destroy(),this.backend.destroy(),this.chrome.destroy(),this.crosshairLayer.destroy(),this.attributionEl?.remove(),this.attributionEl=null,this.mountContainer?.style.removeProperty("--vela-toolbar-gutter"),this.mountContainer?.style.removeProperty("--vela-scale-gutter"),this.mountContainer?.style.removeProperty("--vela-bottom-gutter"),this.mountContainer?.style.removeProperty("--vela-price-pane-top"),this.mountContainer?.style.removeProperty("--vela-price-pane-bottom"),this.mountContainer=null,this.wrapper?.remove();}setBars(e,t){this.introRaf!=null&&(cancelAnimationFrame(this.introRaf),this.introRaf=null,this.modelAlpha=1),this.liveEaseTime=0;let n=this.bars,o=n[0]?.time;this.bars=rR(e),this.scene.bars=this.bars,this.coords.setBars(this.bars.map(s=>s.time));for(let s of this.scene.indicators.values())this.refreshAnchorOffset(s);if(t?.preserveView===true&&o!=null&&this.bars.length>0){let s=this.bars[0].time,a=0;if(s!==o){let l=this.bars.findIndex(c=>c.time===o);if(l>0)a=l;else {let c=n.findIndex(d=>d.time===s);c>0&&(a=-c);}}a!==0&&(this.zoomAnchorLogical+=a,this.hoverLogical!=null&&(this.hoverLogical+=a));}let i=t?.preserveView===true&&this.didInitialFit;if(this.coords.width>0&&!i&&(this.didInitialFit?this.reframeKeepZoom():this.fitContent(),this.didInitialFit=true),!this.introPlayed&&this.bars.length>0&&(this.introPlayed=true,this.intro.style)){this.playIntro();return}this.scheduler.invalidate(4);}updateBar(e){let t=this.bars.length,n=this.bars[t-1];if(n&&e.time===n.time)this.bars[t-1]=e,!this.animLiveBar.on||this.liveEaseTime!==e.time?this.syncLiveEase(e):this.animator.start();else if(!n||e.time>n.time){let o=this.coords.getViewport(),i=t>0&&o.rightOffset<0&&this.scrollTargetRO===null;this.bars.push(e),this.syncLiveEase(e),this.coords.barInterval>0?this.coords.appendBar(e.time):this.coords.setBars(this.bars.map(s=>s.time)),i&&this.coords.setViewport({...o,rightOffset:o.rightOffset-1});}else return;this.scene.bars=this.bars,this.scheduler.invalidate(4);}setIntro(e){this.intro=e,e.style&&(this.introOnStyle=e.style);}syncLiveEase(e){this.liveEaseTime=e.time,this.liveEaseHigh=e.high,this.liveEaseLow=e.low,this.liveEaseClose=e.close;}easeLiveBar(e){let t=this.bars[this.bars.length-1];if(!t||this.liveEaseTime!==t.time)return false;let n=Math.max(1e-9,Math.abs(t.close)*1e-6),o=this.animLiveBar.tau,i=Lt(this.liveEaseHigh,t.high,e,o),s=Lt(this.liveEaseLow,t.low,e,o),a=Lt(this.liveEaseClose,t.close,e,o),l=Math.abs(i-t.high)>n||Math.abs(s-t.low)>n||Math.abs(a-t.close)>n;return this.liveEaseHigh=l?i:t.high,this.liveEaseLow=l?s:t.low,this.liveEaseClose=l?a:t.close,l}ensurePane(e){this.scene.ensurePane(e.id,e.kind,e.order,e.heightWeight??(e.kind==="price"?3:1)),this.layoutPanes(),this.paneControls?.refresh(),this.scheduler.invalidate(4);}removePane(e){e!==Xe&&(this.scene.removePane(e),this.maximizedPaneId===e&&(this.maximizedPaneId=null),this.refreshAxisWidth(),this.layoutPanes(),this.paneControls?.refresh(),this.scheduler.invalidate(4));}setIndicatorPane(e,t,n){let o=this.scene.indicators.get(e.id);o&&(o.paneId=t,o.ownScale=n?.ownScale===true,o.ownScale||this.scene.dropIndicatorScale(e.id),this.inputsUI.setPane(e.id,t),this.refreshAnchorOffset(o),this.refreshAxisWidth(),this.layoutPanes(),this.paneControls?.refresh(),this.scheduler.invalidate(4));}orderPanes(e){this.scene.orderPanes(e),this.layoutPanes(),this.paneControls?.refresh(),this.scheduler.invalidate(4);}setPaneCollapsed(e,t){let n=this.scene.panes.get(e);!n||n.collapsed===t||(n.collapsed=t,this.layoutPanes(),this.paneControls?.refresh(),this.scheduler.invalidate(4));}setPaneMaximized(e){e!==null&&!this.scene.panes.has(e)&&(e=null),this.maximizedPaneId=e,this.layoutPanes(),this.paneControls?.refresh(),this.scheduler.invalidate(4);}onPaneAction(e){return this.paneActionCbs.add(e),()=>this.paneActionCbs.delete(e)}emitPaneAction(e){for(let t of this.paneActionCbs)t(e);}onMoveIndicator(e){return this.moveIndicatorCbs.add(e),()=>this.moveIndicatorCbs.delete(e)}maxOwnScaleColumns(){let e=0;for(let t of this.scene.panes.values()){let n=this.scene.ownScaleIndicatorsForPane(t.id).length;n>e&&(e=n);}return e}refreshAxisWidth(){let e=Ad+_A*this.maxOwnScaleColumns();return e===this.rightAxisW?false:(this.rightAxisW=e,this.publishGutters(),this.coords.width>0&&this.syncSize(),true)}refreshAnchorOffset(e){let t=e.anchorTime;if(t==null||this.bars.length===0){this.scene.setAnchorOffset(e.id,0);return}let n=this.bars[0].time;if(t===n){this.scene.setAnchorOffset(e.id,0);return}if(t>1;this.bars[a].time>=t?(s=a,i=a-1):o=a+1;}if(s>=this.bars.length||this.bars[s].time!==t){console.warn(`[vela] indicator "${e.id}" anchorTime matches no chart bar \u2014 rendering unanchored`),this.scene.setAnchorOffset(e.id,0);return}this.scene.setAnchorOffset(e.id,s);}mountIndicator(e){return this.scene.indicators.set(e.id,e),this.refreshAnchorOffset(e),e.native&&this.extLayers.some(t=>t.def.id===e.native.type)?this.scene.assignIndicatorZTop(e.id):this.scene.assignIndicatorZ(e.id),this.ensureInstanceLayer(e),e.legend!==false&&this.inputsUI.upsert(e.id,e.shorttitle??e.title,e.inputs,e.inputValues,e.paneId,{native:!!e.native,...e.props?{props:e.props,propValues:e.propValues??{}}:{}}),e.native?.type==="volume"?(this.volumeActive=true,this.volumeHidden=false):e.native?.type==="vpvr"&&(this.vpvrActive=true,this.vpvrHidden=false),e.ownScale&&this.refreshAxisWidth(),this.paneControls?.refresh(),this.scheduler.invalidate(4),{id:e.id}}updateIndicator(e,t){let n=this.scene.indicators.get(e.id);if(n){if(t.kind==="value"&&t.anchorTime!==void 0){let o=t.anchorTime??void 0;o!==n.anchorTime&&(n.anchorTime=o,this.refreshAnchorOffset(n));}QA(n,t),this.scheduler.invalidate(3);}}removeIndicator(e){let t=this.scene.indicators.get(e.id)?.native?.type;t==="volume"?(this.volumeActive=false,this.volumeHidden=false,this.scene.volumeLayer=null):t==="vpvr"&&(this.vpvrActive=false,this.vpvrHidden=false,this.scene.vpvrLayer=null),this.scene.indicators.delete(e.id),this.dropInstanceLayer(e.id),this.scene.forgetIndicatorZ(e.id),this.scene.forgetAnchorOffset(e.id),this.scene.dropIndicatorScale(e.id),this.inputsUI.remove(e.id),this.refreshAxisWidth(),this.paneControls?.refresh(),this.scheduler.invalidate(4);}setIndicatorInputs(e,t,n){this.inputsUI.setValues(e.id,t,n);}setSymbolPicker(e){this.symbolPicker=e,this.inputsUI?.setSymbolPicker(e);}setLegendActions(e){this.legendActionsProvider=e,this.inputsUI?.setLegendActions(e);}setLegendCallouts(e){this.legendCalloutsProvider=e,this.inputsUI?.setLegendCallouts(e);}setLegendOverviewAction(e){this.legendOverviewAction=e,this.inputsUI?.setLegendOverviewAction(e);}openIndicatorSettings(e){this.inputsUI?.openSettingsFor(e);}setIndicatorVisible(e,t){let n=this.scene.indicators.get(e.id)?.native?.type;if(n==="volume"||n==="vpvr"){n==="volume"?this.volumeHidden=!t:this.vpvrHidden=!t,this.inputsUI.setVisible(e.id,t),this.scheduler.invalidate(4);return}t||this.scene.indicators.delete(e.id),this.inputsUI.setVisible(e.id,t),this.scheduler.invalidate(4);}onInputChange(e){return this.inputChangeCbs.add(e),()=>this.inputChangeCbs.delete(e)}onToggleIndicatorVisible(e){return this.toggleVisibleCbs.add(e),()=>this.toggleVisibleCbs.delete(e)}onPriceStyleChange(e){return this.priceStyleCbs.add(e),()=>this.priceStyleCbs.delete(e)}setPriceStyle(e){if(e!==this.scene.priceStyle){this.scene.priceStyle=e,this.scene.basePainting=Fh(e),this.scene.candleOverride=Hc(e,this.scene.style.chartTypes);for(let t of this.priceStyleCbs)t(e);}}onRemoveIndicator(e){return this.removeIndicatorCbs.add(e),()=>this.removeIndicatorCbs.delete(e)}setLayoutMode(e){if(e!==this.layoutMode){if(this.layoutMode=e,this.mountContainer?.setAttribute("data-vela-layout",e),this.userDrawings?.setLayoutMode(e),this.settingsDialog?.setLayoutMode(e),this.inputsUI?.setLayoutMode(e),this.paneControls?.setSuspended(e==="mobile"),this.scrollButton){let t=e==="mobile"?Ap:Us;this.scrollButton.style.width=`${t}px`,this.scrollButton.style.height=`${t}px`;}this.updateScrollToRealtimeButton();}}setSettingsSections(e){this.hostSettingsSections=e,this.settingsDialog?.setHostSections(e);}setSettingsVisibility(e){this.hiddenSettings=[...e.hidden??[]],this.settingsDialog?.setHiddenSettings(this.hiddenSettings);}listSettingsIds(){return g0(this.hostSettingsSections,this.markGroupsInUse())}onChartTypeSettingsChange(e){return this.chartTypeSettingsCbs.add(e),()=>this.chartTypeSettingsCbs.delete(e)}onConfigChanged(e){return this.configChangedCbs.add(e),()=>this.configChangedCbs.delete(e)}onThemeSelect(e){return this.themeSelectCbs.add(e),()=>this.themeSelectCbs.delete(e)}onCrosshairMove(e){return this.crosshairCbs.add(e),()=>this.crosshairCbs.delete(e)}onClick(e){return this.clickCbs.add(e),()=>this.clickCbs.delete(e)}onAxisLongPress(e){return this.axisLongPressCbs.add(e),()=>this.axisLongPressCbs.delete(e)}setTimelineMarks(e,t){this.scene.timelineMarks=e,this.scene.markGroups=t,this.scene.marksExpandedStack=null,this.markPopover?.close(),this.scheduler?.invalidate(2);}onMarkClick(e){return this.markClickCbs.add(e),()=>this.markClickCbs.delete(e)}markGroupsInUse(){return a0(this.scene.timelineMarks,this.scene.markGroups)}markGroupsForEventsTab(){let e=new Set(this.scene.markGroups.map(t=>t.id));return this.markGroupsInUse().map(t=>t.parent!==void 0&&!e.has(t.parent)?{...t,parent:void 0}:t)}onViewportChange(e){return this.viewportCbs.add(e),()=>this.viewportCbs.delete(e)}getVisibleRange(){let e=this.coords.barCount;if(e===0||this.coords.width===0)return null;let t=this.coords.visibleLogicalRange(),n=Math.max(0,Math.ceil(t.from)),o=Math.min(e-1,Math.floor(t.to));return os*.001?(n=hn(Lt(n,s,e,this.animZoom.tau)),o=this.anchoredRightOffset(n),i=true):n!==s&&(n=s,o=this.anchoredRightOffset(n));let a=YA/Math.max(1e-6,n*this.coords.spacingScale);if(Math.abs(this.panVelocity)>a){o+=this.panVelocity*e;let c=this.animPan.tau;this.panVelocity=c>0?this.panVelocity*Math.exp(-e/c):0,Math.abs(this.panVelocity)<=a?this.panVelocity=0:i=true;}if(this.scrollTargetRO!=null){let c=this.scrollTargetRO,d=Lt(o,c,e,this.animScroll.tau);Math.abs(d-c)<.001?(o=c,this.scrollTargetRO=null):(o=d,i=true);}let l=this.clampViewport(n,o);return l.barSpacing!==n&&(this.targetBarSpacing=l.barSpacing),this.scrollTargetRO!=null&&l.rightOffset!==o&&(this.scrollTargetRO=l.rightOffset),this.coords.setViewport(l),this.computeScales(),this.easeScales(e)&&(i=true),this.easeLiveBar(e)&&(i=true),this.skeletonClockMs+=e,this.paintData(),this.crosshairLayer.render(this.scene,this.coords,this.theme,this.hoverSeparatorY,this.externalCrossPx()),this.updateLegendValues(),this.emitViewportChange(),i}easeScales(e){let t=false,n=this.animAutoscale.tau;for(let o of this.scene.panes.values()){let i=o.scaleTarget,s=o.scale;if(i.log&&s.min>0&&i.min>0){let d=Math.log(i.min),u=Math.log(i.max),h=Math.max(1e-9,Math.abs(u-d)),p=Lt(Math.log(s.min),d,e,n),m=Lt(Math.log(s.max),u,e,n);Math.abs(p-d)<=h*.001&&Math.abs(m-u)<=h*.001?o.scale={min:i.min,max:i.max,log:true}:(t=true,o.scale={min:Math.exp(p),max:Math.exp(m),log:true});continue}let a=Math.max(1e-9,Math.abs(i.max-i.min)),l=Lt(s.min,i.min,e,n),c=Lt(s.max,i.max,e,n);Math.abs(l-i.min)<=a*.001&&Math.abs(c-i.max)<=a*.001?(l=i.min,c=i.max):t=true,o.scale={min:l,max:c,log:i.log};}for(let o of this.scene.indicatorScales.values()){let i=o.scaleTarget,s=o.scale,a=Math.max(1e-9,Math.abs(i.max-i.min)),l=Lt(s.min,i.min,e,n),c=Lt(s.max,i.max,e,n);Math.abs(l-i.min)<=a*.001&&Math.abs(c-i.max)<=a*.001?(l=i.min,c=i.max):t=true,o.scale={min:l,max:c};}return t}emitViewportChange(){this.updateScrollToRealtimeButton();let e=this.getVisibleRange();if(e)for(let t of this.viewportCbs)t(e);}handlePointerMove(e,t){if(e===null||t===null||this.coords.barCount===0){this.scene.crosshair=null,this.hoverSeparatorY=null,this.lastPointer=null,this.marksExpandedBy==="hover"&&this.setMarksExpanded(null),this.setMarkHover(null),this.scheduler.invalidate(1),this.hoverLogical=null;let p={time:null,price:null,paneKind:null,values:new Map,ohlc:null};for(let m of this.crosshairCbs)m(p);return}let n=e>=0&&t>=0&&e<=this.coords.width&&t<=this.coords.height;this.scene.crosshair=n?{x:e,y:t}:null,this.lastPointer=n?{x:e,y:t}:null,this.hoverSeparatorY=e>=0&&t>=0&&t<=this.coords.height?this.separatorHoverY(t):null,this.scheduler.invalidate(1),this.setMarksExpanded(n?this.chrome.markStackAt(e,t):null),this.setMarkHover(n?this.chrome.markGlyphAt(e,t)?.cluster.key??null:null);let o=Math.round(this.coords.xToLogical(e)),i=o>=0&&o=0&&ta.id),time:i.time,...n.cluster.group!==void 0?{group:n.cluster.group}:{}};for(let a of this.markClickCbs)a(s);return o.some(a=>a.content!==void 0)?this.markPopover?.open(n.cluster,{x:n.x,y:n.y,size:n.size}):(this.scene.marksFlash={key:n.cluster.key,until:Dp()+KA},this.syncMarkPulse()),true}trackMarkPopover(){let e=this.markPopover?.key;if(!e)return;let t=this.chrome.markGlyphByKey(e);this.markPopover.track(t&&!(t.decked&&t.depth!==0)?{x:t.x,y:t.y,size:t.size}:null);}setMarkHover(e){this.scene.marksHoverKey!==e&&(this.scene.marksHoverKey=e,this.scene.marksHoverSince=Dp(),this.scheduler?.invalidate(2),this.syncMarkPulse());}syncMarkPulse(){if(this.markPulseRaf!==null||typeof requestAnimationFrame!="function")return;let e=()=>{this.markPulseRaf=null;let t=Dp();this.scene.marksFlash&&this.scene.marksFlash.until<=t&&(this.scene.marksFlash=null),this.scheduler?.invalidate(2),(this.scene.marksHoverKey!==null&&t-this.scene.marksHoverSince=t.bounds.top&&e<=t.bounds.top+t.bounds.height)return t;return null}nearestPaneToY(e){let t=null,n=1/0;for(let o of this.scene.panes.values()){let i=e=o+64&&i.length>0){let s=Math.floor((e-o-64)/56),a=i[s];if(a)return {holder:this.scene.ensureIndicatorScale(a.id,n.scaleTarget),height:n.bounds.height}}return {holder:n,height:n.bounds.height}}beginPriceScale(e,t){let n=this.resolveScaleHolder(e,t);n&&(this.scaleDragHolder=n.holder,this.scaleDragHeight=n.height,this.scaleDragStart={...n.holder.scale},n.holder.manualScale={...n.holder.scale},this.axisScaleButtons?.reposition(),this.scheduler.invalidate(4));}priceScaleBy(e){let t=this.scaleDragHolder,n=this.scaleDragStart;!t||!n||this.setManualScale(t,tx(n,Math.exp(e*XA)));}beginPricePan(e){let t=this.paneNodeAtY(e);return !t||!t.manualScale?false:(this.scaleDragHolder=t,this.scaleDragHeight=t.bounds.height,this.scaleDragStart={...t.scale},true)}pricePanBy(e){let t=this.scaleDragHolder,n=this.scaleDragStart;!t||!n||this.setManualScale(t,nx(n,e,this.scaleDragHeight));}resetPriceScale(e,t){let n=this.resolveScaleHolder(e,t);n&&(n.holder.manualScale=null,this.axisScaleButtons?.reposition(),this.scheduler.invalidate(4));}dataDblClick(e,t){let n=this.paneNodeAtY(t)??this.nearestPaneToY(t);if(!n)return;let o=this.maximizedPaneId!==n.id;this.maximizedPaneId=o?n.id:null,this.afterPaneLayoutChange(),this.emitPaneAction({type:"maximize",paneId:n.id,maximized:o});}resetView(){this.fitContent(),this.scheduler.invalidate(4),this.emitViewportChange();}setManualScale(e,t){e.manualScale=t,e.scale={...t},e.scaleTarget={...t},e.initialized=true,this.scheduler.invalidate(4);}afterPaneLayoutChange(){this.layoutPanes(),this.paneControls?.refresh(),this.scheduler.invalidate(4);}paneControlViews(){let e=this.scene.orderedPanes();return e.map((t,n)=>({id:t.id,kind:t.kind,collapsed:t.collapsed,maximized:this.maximizedPaneId===t.id,top:t.bounds.top,height:t.bounds.height,index:n,count:e.length}))}movePaneLocal(e,t){let n=this.scene.orderedPanes(),o=n.findIndex(l=>l.id===e);if(o<0)return;let i=t==="up"?o-1:o+1;if(i<1||i>=n.length)return;let s=n.map(l=>l.id),a=s[o];s[o]=s[i],s[i]=a,this.scene.orderPanes(s),this.afterPaneLayoutChange(),this.emitPaneAction({type:"move",paneId:e,dir:t});}paneSeparatorAt(e){return this.separatorPaneIndexAt(e)!==null}separatorHoverY(e){if(!this.paneResizeEnabled)return null;let t=this.separatorPaneIndexAt(e);return t===null?null:this.scene.orderedPanes()[t].bounds.top}separatorPaneIndexAt(e){let t=this.scene.orderedPanes();for(let n=1;na-i&&(l+=n-(a-i)),l!==o.rightOffset&&this.applyViewport({barSpacing:o.barSpacing,rightOffset:l});let c=this.scene.orderedPanes().find(u=>u.kind==="price")??this.scene.orderedPanes()[0]??null,d=this.scene.crosshair?.y??(c?c.bounds.top+c.bounds.height/2:this.coords.height/2);this.handlePointerMove(this.coords.logicalToX(n),d),this.announceBar(n);}announceBar(e){if(!this.liveRegion)return;let t=this.bars[e],n=this.dataWindowPricePane(),o=this.dataWindowOHLC(t,n),i=[];t&&i.push(JA(t.time,this.scene.timezone)),o&&i.push(`Open ${o.o}, High ${o.h}, Low ${o.l}, Close ${o.c}`);for(let s of this.dataWindowGroups(e,n))for(let a of s.rows)i.push(`${a.label} ${a.value}`);this.liveRegion.textContent=i.join(". ");}getDataWindowReadout(){let e=this.bars.length;if(e===0)return {date:"",time:"",ohlc:null,groups:[]};let t=this.hoverLogical!=null?this.hoverLogical:e-1,n=this.bars[t],o=this.dataWindowPricePane(),i=n?Lx(n.time,this.scene.timezone):{date:"",time:""};return {date:i.date,time:i.time,ohlc:this.dataWindowOHLC(n,o),groups:this.dataWindowGroups(t,o)}}dataWindowPricePane(){return this.scene.orderedPanes().find(e=>e.kind==="price")??null}dataWindowFmt(e,t){return t?rd(t.scale,t.bounds.height,e,this.scene.priceMintick):String(e)}dataWindowOHLC(e,t){return e?{o:this.dataWindowFmt(e.open,t),h:this.dataWindowFmt(e.high,t),l:this.dataWindowFmt(e.low,t),c:this.dataWindowFmt(e.close,t),vol:e.volume!=null?Tx(e.volume):void 0,up:e.close>=e.open}:null}dataWindowGroups(e,t){let n=[];for(let o of this.scene.indicators.values()){let i=this.readoutRowsFor(o,e,t,"dataWindow");i.length&&n.push({name:o.title,rows:i});}return n}readoutRowsFor(e,t,n,o){if(e.native?.type==="volume")return this.volumeReadoutRows(e,t);let i=(e.paneId?this.scene.panes.get(e.paneId):null)??n,s=this.scene.offsetOf(e.id),a=[];for(let l of e.series){if(!Rt(l,o))continue;let c,d;if(l.kind==="candle"||l.kind==="bar")c=l.bars[t-s]?.close,d=l.style?.up??this.theme.upColor;else if(Ge(l))c=l.points[t-s]?.value,d=l.points[t-s]?.color??l.style.color;else continue;c==null||!Number.isFinite(c)||a.push({label:l.title||e.title,value:this.dataWindowFmt(c,i),color:d});}return a}volumeReadoutRows(e,t){if(this.volumeHidden)return [];let n=this.bars[t],o=n?.volume;if(n==null||o==null||!Number.isFinite(o))return [];let i=this.scene.volumeLayer,s=n.close>=n.open?i?.upColor??this.theme.upColor:i?.downColor??this.theme.downColor;return [{label:e.title,value:Tx(o),color:s}]}updateLegendValues(){if(!this.inputsUI)return;let e=this.bars.length,t=new Map;if(e>0){let n=this.hoverLogical!=null?this.hoverLogical:e-1,o=this.dataWindowPricePane();for(let i of this.scene.indicators.values())t.set(i.id,this.readoutRowsFor(i,n,o,"legend").map(s=>({value:s.value,color:s.color})));}this.inputsUI.setPlotValues(t);}renderFrame(e){this.animator.active||(zh(e)?(this.computeScales(),this.paintData()):Pw(e)&&this.paintedData&&(this.chrome.prepare(this.scene,this.coords,this.theme),this.chrome.render(this.scene,this.coords,this.theme,this.axisSurface()),this.trackMarkPopover()),this.crosshairLayer.render(this.scene,this.coords,this.theme,this.hoverSeparatorY,this.externalCrossPx()),!zh(e)&&this.paintedData&&this.repaintCursorLayers(),this.updateLegendValues());}repaintCursorLayers(){let e=this.scene.panes.get(Xe);if(!e)return;let t=typeof performance<"u"?performance.now():Date.now();for(let n of this.extLayers){if(!n.def.repaintOnCursor)continue;let o=this.layerPane(n)??e;o.collapsed||this.layerHiddenWithCandles(n)||(n.instance.render(this.extLayerArgs(n,o.scale,o.bounds,t)),this.animZoom.on&&n.instance.animating?.()&&this.animator.start());}}clearLayerCanvas(e){e.width===0||e.height===0||e.getContext("2d")?.clearRect(0,0,e.width,e.height);}extLayerArgs(e,t,n,o){return {bars:this.scene.bars,data:this.scene.nativeData.get(e.channel),settings:this.scene.nativeData.get(`${e.def.id}-settings`)??{},pending:this.scene.nativePending.get(e.channel)??[],coords:this.coords,scale:t,bounds:n,theme:this.theme,priceStyle:this.scene.priceStyle,nowMs:o,cursor:this.lastPointer}}paintData(){this.syncLayerCanvasOrder(),this.stampScaleInvert(),this.backend.modelAlpha=this.modelAlpha,this.backend.candleBodyAlpha=this.candleBodyAlpha,this.backend.candleStructureAlpha=this.candleStructureAlpha;let e=1,t=1;this.backend.candleBodyScale=t;let n=this.scene.panes.get(Xe);if(n){let a=this.nativeLayerPane("volume")??n;this.volumeRenderer.render({bars:this.scene.bars,data:this.scene.volumeLayer,visible:this.volumeActive&&!this.volumeHidden&&!a.collapsed,coords:this.coords,bounds:a.bounds,fillPane:a.kind!=="price"}),this.vpvrRenderer.render({bars:this.scene.bars,data:this.scene.vpvrLayer,visible:this.vpvrActive&&!this.vpvrHidden,coords:this.coords,scale:n.scale,bounds:n.bounds,theme:this.theme});let l=typeof performance<"u"?performance.now():Date.now(),c=null;for(let d of this.extLayers){let u=this.layerPane(d)??n;if(u.collapsed||this.layerHiddenWithCandles(d)){this.clearLayerCanvas(d.canvas);continue}let h=this.extLayerArgs(d,u.scale,u.bounds,l);d.instance.render(h),u===n&&(c=ix(c,d.instance.modulateBase?.(h)??null)),this.animZoom.on&&d.instance.animating?.()&&this.animator.start();}c&&(c.candleBodyScale!=null&&(this.backend.candleBodyScale=Op(c.candleBodyScale)||.01),c.candleBodyAlpha!=null&&(this.backend.candleBodyAlpha=Op(c.candleBodyAlpha)*this.candleBodyAlpha),c.gridAlpha!=null&&(e=Op(c.gridAlpha)));}let o=this.bars.length-1,i=o>=0?this.bars[o]:void 0,s=!!i&&this.liveEaseTime===i.time&&(i.high!==this.liveEaseHigh||i.low!==this.liveEaseLow||i.close!==this.liveEaseClose);s&&i&&(this.bars[o]={...i,high:this.liveEaseHigh,low:this.liveEaseLow,close:this.liveEaseClose}),this.scene.drawingSlices=j0(this.indicatorSlices.prepare(this.scene,this.coords,this.theme,this.dataCanvas),this.userDrawings?.prepareSlices(this.scene.orderedPanes().map(a=>a.id))??new Map),this.backdropRenderer.render(this.scene,this.coords,this.theme,e),this.backend.render(this.scene,this.coords,this.theme),this.chrome.render(this.scene,this.coords,this.theme,this.axisSurface()),this.trackMarkPopover(),this.userDrawings?.render(),s&&i&&(this.bars[o]=i),this.paintedData=true;}drawingProjector(){return q0(this.coords,e=>{let t=this.scene.panes.get(e);return t?{scale:t.scale,bounds:t.bounds,collapsed:t.collapsed}:null},e=>this.paneNodeAtY(e)?.id??null,(e,t)=>this.barsInTimeRange(e,t),this.userDrawings?.seriesGateway?(e,t,n)=>this.userDrawings.seriesGateway.seriesInRange(e,t,n):void 0)}barsInTimeRange(e,t){let n=Math.min(e,t),o=Math.max(e,t),i=[];for(let s of this.bars)if(!(s.timeo)break;i.push(s);}return i}get userDrawingsPort(){return this.userDrawings??void 0}focus(){this.dataCanvas?.focus({preventScroll:true});}setExternalCrosshair(e,t=null){let n=e==null?null:{time:e,price:t},o=this.externalCross;!n&&!o||n&&o&&o.time===n.time&&o.price===n.price||(this.externalCross=n,this.scheduler.invalidate(1));}externalCrossPx(){let e=this.externalCross;if(!e||this.coords.barCount===0)return null;let t=Math.floor(this.coords.timeToLogical(e.time));if(!(t=0&&n>=0&&n<=this.coords.width,i=null;if(e.price!=null){let s=this.scene.orderedPanes().find(a=>a.kind==="price");s&&(i=this.coords.priceToY(e.price,s.scale,s.bounds),(!Number.isFinite(i)||is.bounds.top+s.bounds.height)&&(i=null));}return {x:n,y:i,time:this.coords.logicalToTime(Math.max(t,0)),price:i!=null?e.price:null,line:o}}setSnapMode(e){this.snapMode=e;}snapToCandle(e,t,n="strong",o){if(n==="off")return e;let i=this.bars.length;if(i===0)return e;let s=Math.max(0,Math.min(i-1,Math.round(this.coords.timeToLogical(e.time)))),a=this.bars[s];if(!a)return e;let l;if(t!==Xe)l={time:a.time,price:e.price};else {let c=a.open;for(let d of [a.high,a.low,a.close])Math.abs(d-e.price)VA)return e}return l}computeScales(){let e=this.coords.barCount;if(e===0)return;let t=this.coords.visibleLogicalRange(),n=Math.max(0,Math.floor(t.from)),o=Math.min(e-1,Math.ceil(t.to));if(oc.kind==="price")??null;this.chrome.prepare(this.scene,this.coords,this.theme);let a=this.animator.active,l=this.scene.style.margins;for(let c of i){if(c.manualScale){c.scaleTarget=c.manualScale,c.scale={...c.manualScale},c.initialized=true;continue}let u=this.scene.indicatorsForPane(c.id).filter(m=>m.ownScale!==true),h=this.chrome.paneDrawingsRange(u,this.scene,c===s,t);if(c===s){let m=Q0(this.scene.indicators.values(),n,o,f=>this.scene.offsetOf(f));m&&(h=h?{min:Math.min(h.min,m.min),max:Math.max(h.max,m.max)}:m);}let p=c.kind==="price"&&(!this.scene.candlesHidden||this.priceLayersAnchoredToBars(u)||!this.paneHasMeasurableContent(u,h));if(c.scaleTarget=Td(u,this.bars,p,n,o,h,Ko(this.scene,c),m=>this.scene.offsetOf(m),l),c.percentBaseline=c.kind==="price"?this.bars[n]?.close??0:this.firstVisibleValue(u,n),c.axisFormat=void 0,c.axisBands=void 0,this.volumeOwnsPane(c,u)){let m=this.maxVisibleVolume(n,o);m>0&&(c.scaleTarget={min:0,max:m/Sp},c.axisFormat="volume");}else if(this.layerNativesOwnPane(c,u)&&(c.scaleTarget=Td([],this.bars,true,n,o,h,Ko(this.scene,c),m=>this.scene.offsetOf(m),l),c.percentBaseline=this.bars[n]?.close??0,u.every(m=>m.paneAxis!=null))){c.axisFormat="none";let m=u.find(f=>typeof f.paneAxis=="object");c.axisBands=m?m.paneAxis.bands:void 0;}if(c===s&&this.scene.tradeMarkers.visible&&c.bounds.height>0){let m=this.tradesScaleHints(t);if(m){let f=c.scaleTarget,g={...f,min:Math.min(f.min,m.min),max:Math.max(f.max,m.max)};c.scaleTarget=J0(g,c.bounds.height,m.abovePx,m.belowPx);}}(!a||!c.initialized)&&(c.scale={...c.scaleTarget},c.initialized=true);for(let m of this.scene.ownScaleIndicatorsForPane(c.id)){let f=this.scene.ensureIndicatorScale(m.id,c.scaleTarget);if(f.manualScale){f.scaleTarget=f.manualScale,f.scale={...f.manualScale},f.initialized=true;continue}let g=this.chrome.paneDrawingsRange([m],this.scene,false,t);f.scaleTarget=Td([m],this.bars,false,n,o,g,false,b=>this.scene.offsetOf(b),l),(!a||!f.initialized)&&(f.scale={...f.scaleTarget},f.initialized=true);}}}tradesScaleHints(e){let t=null,n={timeToLogical:o=>this.coords.timeToLogical(o),barAt:o=>{let i=this.bars[Math.round(o)];return i?{high:i.high,low:i.low}:null}};for(let o of this.scene.indicators.values()){if(!o.trades?.length)continue;let i=Ww(o.trades,this.scene.tradeMarkers,n,e.from,e.to,this.scene.style.fontSize);i&&(t=t?{min:Math.min(t.min,i.min),max:Math.max(t.max,i.max),abovePx:Math.max(t.abovePx,i.abovePx),belowPx:Math.max(t.belowPx,i.belowPx)}:i);}return t}fitContent(){let e=this.coords.barCount,t=this.coords.width;if(e<=0||t<=0)return;this.animator?.stop(),this.panVelocity=0;for(let s of this.scene.panes.values())s.manualScale=null;for(let s of this.scene.indicatorScales.values())s.manualScale=null;let n=Math.min(e,200),o=this.scene.style.margins.right,i=this.clampViewport(t/((n+o)*this.coords.spacingScale),o);this.coords.setViewport(i),this.targetBarSpacing=i.barSpacing;}reframeKeepZoom(){this.animator?.stop(),this.panVelocity=0;for(let t of this.scene.panes.values())t.manualScale=null;for(let t of this.scene.indicatorScales.values())t.manualScale=null;let e={barSpacing:hn(this.coords.getViewport().barSpacing),rightOffset:this.scene.style.margins.right};this.coords.setViewport(e),this.targetBarSpacing=e.barSpacing;}paneBoundsFor(e){let t=this.scene.panes.get(e);return {top:t?.bounds.top??0,height:t?.bounds.height??0,rightAxis:this.rightAxisW}}paneMasterTitle(e){let t=this.scene.orderedIndicatorsForPane(e);return (t.find(o=>o.ownScale!==true)??t[0])?.title||null}nativeLayerPane(e){for(let t of this.scene.indicators.values())if(t.native?.type===e)return this.scene.panes.get(t.paneId??Xe)??null;return null}createLayerCanvas(){let e=document.createElement("canvas");return Object.assign(e.style,{position:"absolute",inset:"0",width:"100%",height:"100%",pointerEvents:"none"}),e}ensureInstanceLayer(e){let t=e.native?.channel;if(!t||!this.plot||this.extLayers.some(s=>s.owner===e.id))return;let n=this.extLayers.find(s=>s.owner===null&&s.def.id===e.native.type);if(!n)return;let o=this.createLayerCanvas();o.width=this.dataCanvas.width,o.height=this.dataCanvas.height,o.style.width=this.dataCanvas.style.width||"100%",o.style.height=this.dataCanvas.style.height||"100%";let i={def:n.def,instance:n.def.create(),canvas:o,channel:t,owner:e.id};this.extLayers.push(i),this.plot.insertBefore(o,this.chromeCanvas),i.instance.mount(o);}dropInstanceLayer(e){let t=this.extLayers.findIndex(o=>o.owner===e);if(t<0)return;let[n]=this.extLayers.splice(t,1);n.instance.destroy?.(),n.canvas.remove();}layerOwner(e){if(e.owner!==null)return this.scene.indicators.get(e.owner)??null;for(let t of this.scene.indicators.values())if(t.native?.type===e.def.id&&!t.native.channel)return t;return null}layerPane(e){let t=this.layerOwner(e),n=t?t.paneId??Xe:Xe;return this.scene.panes.get(n)??null}orderedLayerCanvases(){let e=new Map(this.extLayers.map(o=>[o.channel,o.canvas])),{below:t,above:n}=sx(this.extLayers.map(o=>{let i=this.layerOwner(o);return {id:o.channel,placement:o.def.placement==="below-data"?"below-data":"above-data",ownerZ:i?this.scene.zOf(i.id):null}}),this.scene.candleZ);return {below:t.map(o=>e.get(o)),above:n.map(o=>e.get(o))}}canvasPile(){let{below:e,above:t}=this.orderedLayerCanvases();return [this.backdropCanvas,...e,this.dataCanvas,this.volumeCanvas,this.vpvrCanvas,...t]}syncLayerCanvasOrder(){if(this.extLayers.length===0||!this.plot)return;let{below:e,above:t}=this.orderedLayerCanvases(),n=[...e.map(o=>this.extLayers.find(i=>i.canvas===o).channel),"|",...t.map(o=>this.extLayers.find(i=>i.canvas===o).channel)].join(",");if(n!==this.layerOrderSig){this.layerOrderSig=n;for(let o of e)this.plot.insertBefore(o,this.dataCanvas);for(let o of t)this.plot.insertBefore(o,this.chromeCanvas);}}volumeOwnsPane(e,t){return e.kind==="price"||!this.volumeActive||this.volumeHidden||!this.scene.volumeLayer||this.nativeLayerPane("volume")!==e?false:t.every(n=>n.native?.type==="volume")}layerNativesOwnPane(e,t){return e.kind==="price"||t.length===0?false:t.every(n=>n.series.length===0&&!!n.native&&this.extLayers.some(o=>o.def.id===n.native.type))}layerHiddenWithCandles(e){return this.scene.candlesHidden&&e.owner===null&&e.def.id===this.scene.priceStyle}priceLayersAnchoredToBars(e){return e.some(t=>t.series.length===0&&!!t.native&&this.extLayers.some(n=>n.def.id===t.native.type))}paneHasMeasurableContent(e,t){return t?true:e.some(n=>n.priceLines.length>0||n.series.some(o=>o.overlay!==true))}paneScaleInfos(){return this.scene.orderedPanes().map(e=>({id:e.id,kind:e.kind,top:e.bounds.top,height:e.bounds.height,mode:Yh(this.scene,e),log:Ko(this.scene,e),invert:Kh(this.scene,e)}))}axisScaleViews(){return this.scene.orderedPanes().map(e=>({id:e.id,top:e.bounds.top,height:e.bounds.height,collapsed:e.collapsed,auto:e.manualScale==null,log:Ko(this.scene,e)}))}togglePaneAuto(e){let t=this.scene.panes.get(e);t&&(t.manualScale=t.manualScale==null?{...t.scale}:null,this.scheduler?.invalidate(4));}setPaneScaleMode(e,t){if(e===Xe)this.scene.scaleMode=t;else {let n=this.scene.panes.get(e);if(!n)return;n.scaleMode=t;}this.scheduler?.invalidate(4);}setPaneLog(e,t){let n=e===Xe?this.scene.orderedPanes().find(o=>o.kind==="price"):this.scene.panes.get(e);if(e===Xe)this.scene.logScale=t;else {if(!n)return;n.logScale=t;}n?.manualScale&&(n.manualScale.log=t),this.scheduler?.invalidate(4);}setPaneInvert(e,t){if(e===Xe)this.scene.invertScale=t;else {let n=this.scene.panes.get(e);if(!n)return;n.invert=t;}this.scheduler?.invalidate(4);}stampScaleInvert(){for(let e of this.scene.panes.values()){let t=Kh(this.scene,e);e.scale.invert=t,e.scaleTarget.invert=t,e.manualScale&&(e.manualScale.invert=t);for(let n of this.scene.ownScaleIndicatorsForPane(e.id)){let o=this.scene.indicatorScales.get(n.id);o&&(o.scale.invert=t,o.scaleTarget.invert=t,o.manualScale&&(o.manualScale.invert=t));}}}firstVisibleValue(e,t){for(let n of e){let o=this.scene.offsetOf(n.id);for(let i of n.series)if(i.overlay!==true){if(Ge(i)){let s=i.points[t-o]?.value;if(s!=null&&Number.isFinite(s))return s}else if(i.kind==="candle"||i.kind==="bar"){let s=i.bars[t-o];if(s&&Number.isFinite(s.close))return s.close}}}return 0}maxVisibleVolume(e,t){let n=0;for(let o=e;o<=t;o+=1){let i=this.bars[o]?.volume;i!=null&&i>n&&(n=i);}return n}layoutPanes(){let e=this.scene.orderedPanes(),t=this.coords.height;this.inputsUI?.setCollapsedPanes(this.collapsedMasterMap());let n=this.maximizedPaneId?this.scene.panes.get(this.maximizedPaneId):null;if(n){let d=0;for(let u of e)u===n?u.bounds={top:0,height:t}:u.bounds={top:t,height:0},d+=u.bounds.height;this.inputsUI?.reposition(),this.paneControls?.reposition(),this.axisScaleButtons?.reposition(),this.repositionScrollButton(),this.positionAttribution(),this.publishPricePaneBounds();return}let o=e.filter(d=>d.collapsed),i=e.filter(d=>!d.collapsed),s=o.length*wx,a=Math.max(0,t-s),l=i.reduce((d,u)=>d+(u.heightWeight||1),0)||1,c=0;for(let d of e){let u=d.collapsed?wx:a*(d.heightWeight||1)/l;d.bounds={top:c,height:u},c+=u;}this.inputsUI?.reposition(),this.paneControls?.reposition(),this.axisScaleButtons?.reposition(),this.repositionScrollButton(),this.positionAttribution(),this.publishPricePaneBounds();}repositionScrollButton(){let e=this.coords.height;if(e<=0)return;let t=this.maximizedPaneId?this.scene.panes.get(this.maximizedPaneId):null,n=t?[t]:this.scene.orderedPanes().filter(i=>!i.collapsed),o=n.length?Math.max(...n.map(i=>i.bounds.top+i.bounds.height)):e;this.scrollBtnBottomPx=Rp+Math.max(0,e-o),this.mountContainer?.style.setProperty("--vela-bottom-gutter",`${ti+Math.max(0,e-o)}px`),this.scrollBtnRightPx=this.rightAxisW+kx,this.scrollButton&&(this.scrollButton.style.bottom=`${this.scrollBtnBottomPx}px`,this.scrollButton.style.right=`${this.scrollBtnRightPx}px`);}collapsedMasterMap(){let e=new Map;for(let t of this.scene.panes.values()){if(!t.collapsed)continue;let n=this.scene.orderedIndicatorsForPane(t.id).filter(s=>s.legend!==false),o=new Set(this.scene.ownScaleIndicatorsForPane(t.id).map(s=>s.id)),i=n.find(s=>!o.has(s.id))??n[0];e.set(t.id,i?.id??null);}return e}setToolbarGutter(e){e!==this.toolbarGutter&&(this.toolbarGutter=e,this.publishGutters(),this.positionAttribution(),this.syncSize());}publishGutters(){this.mountContainer?.style.setProperty("--vela-toolbar-gutter",`${this.toolbarGutter}px`),this.mountContainer?.style.setProperty("--vela-scale-gutter",`${this.rightAxisW}px`);}publishPricePaneBounds(){if(!this.mountContainer)return;let e=this.coords.height+ti,t=this.scene.panes.get(Xe),n=t?t.bounds.top:0,o=t?t.bounds.height:this.coords.height,i=Math.max(0,e-(n+o));this.mountContainer.style.setProperty("--vela-price-pane-top",`${n}px`),this.mountContainer.style.setProperty("--vela-price-pane-bottom",`${i}px`);}buildAttributionEl(){return this.attributionHtml!==null?dx(document,this.attributionHtml,this.theme.background):ux(document,this.theme.background)}rebuildAttribution(){this.attributionEl&&(this.attributionEl.remove(),this.attributionEl=this.buildAttributionEl(),this.attributionEnabled||(this.attributionEl.style.display="none"),this.positionAttribution(),this.wrapper.appendChild(this.attributionEl));}positionAttribution(){if(!this.attributionEl)return;let e=this.coords?.height??0,t=this.maximizedPaneId?this.scene.panes.get(this.maximizedPaneId):null,n=t?[t]:this.scene.orderedPanes().filter(i=>!i.collapsed),o=e>0&&n.length?Math.max(...n.map(i=>i.bounds.top+i.bounds.height)):e;Object.assign(this.attributionEl.style,{left:`${(this.toolbarGutter||0)+12}px`,bottom:`${ti+10+Math.max(0,e-o)}px`});}refreshAttributionColor(){this.attributionEl&&(this.attributionHtml!==null?this.attributionEl.style.color=Mp(this.theme.background):Ep(this.attributionEl,this.theme.background));}syncSize(){let e=this.wrapper.clientWidth,t=this.wrapper.clientHeight;if(e<=0||t<=0)return;let n=window.devicePixelRatio||1;this.plot.style.left=`${this.toolbarGutter}px`;let o=this.plot.getBoundingClientRect(),i=Math.max(1,Math.round(o.width*n)),s=Math.max(1,Math.round(o.height*n)),a=this.plotDeviceSize;a&&Math.abs(a.width-o.width*n)<=1&&Math.abs(a.height-o.height*n)<=1&&(i=Math.max(1,a.width),s=Math.max(1,a.height));let l=i/n,c=s/n,d=u=>{u.width=i,u.height=s,u.style.width=`${l}px`,u.style.height=`${c}px`;};d(this.dataCanvas),d(this.backdropCanvas),d(this.volumeCanvas);for(let u of this.extLayers)d(u.canvas);d(this.vpvrCanvas),d(this.chromeCanvas),d(this.drawingsCanvas),d(this.cursorCanvas),this.coords.setSize(Math.max(1,l-this.rightAxisW),Math.max(1,c-ti),n),this.scene.crosshair=null,this.layoutPanes(),this.userDrawings?.onResize(),!this.didInitialFit&&this.coords.barCount>0&&(this.fitContent(),this.didInitialFit=true),this.animator.active?(this.computeScales(),this.paintData(),this.crosshairLayer.render(this.scene,this.coords,this.theme,this.hoverSeparatorY,this.externalCrossPx())):this.scheduler.flushNow(4);}applyBackground(){this.wrapper.style.background=this.theme.background;}};function ZA(r,e){for(let t of r.series){let n=t.kind==="candle"||t.kind==="bar"?t.bars:Ge(t)?t.points:null;if(!n||n.length===0)continue;let o=0,i=n.length;for(;o>1;n[s].timeo.id===t.seriesId);n&&(t.kind==="points"&&Ge(n)?n.points=t.points:t.kind==="bars"&&(n.kind==="candle"||n.kind==="bar")&&(n.bars=t.bars));}e.lines&&(r.lines=e.lines),e.boxes&&(r.boxes=e.boxes),e.labels&&(r.labels=e.labels),e.polylines&&(r.polylines=e.polylines),e.linefills&&(r.linefills=e.linefills),e.tables&&(r.tables=e.tables),e.trades&&(r.trades=e.trades);return}for(let t of e.removed){let n=r.series.findIndex(o=>o.id===t);n>=0&&r.series.splice(n,1);}for(let t of e.added)r.series.push(t);}function Lx(r,e){let t=Jc(r,e),n=o=>o<10?`0${o}`:String(o);return {date:`${t.getUTCFullYear()}-${n(t.getUTCMonth()+1)}-${n(t.getUTCDate())}`,time:`${n(t.getUTCHours())}:${n(t.getUTCMinutes())}`}}function JA(r,e){let{date:t,time:n}=Lx(r,e);return `${t} ${n}`}function eR(r){if(!Array.isArray(r))return [];let e=[];for(let t of r){if(!t||typeof t!="object")continue;let n=t,o=Number(n.from),i=Number(n.to);!Number.isFinite(o)||!Number.isFinite(i)||i<=o||e.push({from:o,to:i,color:typeof n.color=="string"?n.color:"rgba(120,130,160,0.10)"});}return e.sort((t,n)=>t.from-n.from)}function tR(r){if(r==null||typeof r!="object")return null;let e=r,t=n=>{if(!Array.isArray(n))return [];let o=[];for(let i of n){if(!Array.isArray(i))continue;let s=Number(i[0]),a=Number(i[1]);Number.isFinite(s)&&Number.isFinite(a)&&a>s&&o.push([s,a]);}return o.sort((i,s)=>i[0]-s[0])};return {pre:t(e.pre),post:t(e.post),extended:t(e.extended)}}function Op(r){return Math.max(0,Math.min(1,r))}function nR(r){return typeof r=="string"&&$o().includes(r)}function Sx(r){return r==="percent"||r==="indexed"?r:"price"}function Tx(r){let e=Math.abs(r);return e>=1e9?`${(r/1e9).toFixed(2)}B`:e>=1e6?`${(r/1e6).toFixed(2)}M`:e>=1e3?`${(r/1e3).toFixed(2)}K`:r.toFixed(2)}function rR(r){let e=[...r].sort((n,o)=>n.time-o.time),t=[];for(let n of e){let o=t[t.length-1];o&&o.time===n.time?t[t.length-1]=n:t.push(n);}return t}function Np(r,e){let t=(r.open+r.high+r.low+r.close)/4,n=e?(e.open+e.close)/2:(r.open+r.close)/2;return {time:r.time,open:n,high:Math.max(r.high,n,t),low:Math.min(r.low,n,t),close:t,...r.volume!=null?{volume:r.volume}:{}}}function Mx(r){let e=new Array(r.length),t;for(let n=0;n[{key:"upColor",title:"Up color",type:"color",defval:Fp},{key:"downColor",title:"Down color",type:"color",defval:Vp},{key:"heightPct",title:"Height %",type:"int",defval:Bp,min:5,max:50,step:1,tooltip:"Pane height the tallest visible bar occupies"}],defaultInputs:()=>({upColor:Fp,downColor:Vp,heightPct:Bp}),create:()=>new _p};function Hp(){Vn(Ix);}var Wp=24,Gp=30,$p=nt,Up=D,Yp=70;function zp(r,e){return typeof r=="number"&&Number.isFinite(r)?r:e}function Ax(r,e){return typeof r=="string"&&r!==""?r:e}function Dd(r){return {rows:Math.round(Math.min(400,Math.max(2,zp(r.rows,Wp)))),widthFrac:Math.min(.9,Math.max(.05,zp(r.widthPct,Gp)/100)),upColor:Ax(r.upColor,$p),downColor:Ax(r.downColor,Up),showPoc:r.showPoc!==false,valueAreaFrac:Math.min(1,Math.max(0,zp(r.valueAreaPct,Yp)/100))}}var Kp=class{constructor(){this.ctx=null;this.inputs={};}start(e,t){this.ctx=e,this.inputs=t,e.emit({}),e.pushData(Dd(t));}onBars(){}onViewport(){}setInputs(e){this.inputs=e,this.ctx?.pushData(Dd(e));}suspend(){}resume(){this.ctx?.pushData(Dd(this.inputs));}stop(){}},Rx={type:"vpvr",title:"Visible Range Volume Profile",shortTitle:"VRVP",paneHint:"price",overlay:true,inputsSchema:()=>[{key:"rows",title:"Rows",type:"int",defval:Wp,min:2,max:400,step:1},{key:"widthPct",title:"Width %",type:"int",defval:Gp,min:5,max:90,step:1,tooltip:"Pane width the largest row occupies"},{key:"upColor",title:"Up color",type:"color",defval:$p},{key:"downColor",title:"Down color",type:"color",defval:Up},{key:"showPoc",title:"Point of control",type:"bool",defval:true},{key:"valueAreaPct",title:"Value area %",type:"int",defval:Yp,min:0,max:100,step:1}],defaultInputs:()=>({rows:Wp,widthPct:Gp,upColor:$p,downColor:Up,showPoc:true,valueAreaPct:Yp}),create:()=>new Kp};function Xp(){Vn(Rx);}function sr(r){let e=r.title.trim().toLowerCase().replace(/\s+/g,"-");return `${r.instanceId}:${r.kind}:${e}#${r.ordinal}`}function R(r,e,t){let n=r[e];return typeof n=="number"&&Number.isFinite(n)?n:t}function T(r,e,t){let n=r[e];return typeof n=="string"&&n!==""?n:t}function te(r,e,t){let n=r[e];return typeof n=="boolean"?n:t}function sR(r,e,t){let n=new Array(r.length);for(let o=0;o{let u=c.kind??"line",h=sr({instanceId:n,kind:u,title:c.title,ordinal:d});i.set(c.key,h),o.push({id:h,title:c.title,paneId:"",kind:u,points:sR(e,c.values,c.colors),style:{color:c.color,width:c.width??1,lineStyle:c.lineStyle??"solid",...c.base!=null?{base:c.base}:{}},...c.overlay?{overlay:true}:{},...c.display?{display:c.display}:{}});}),t.markers&&t.markers.length>0&&o.push({id:sr({instanceId:n,kind:"markers",title:"markers",ordinal:0}),title:this.spec.shortTitle??this.spec.title,paneId:"",kind:"markers",markers:t.markers});let s=(t.bands??[]).flatMap((c,d)=>{let u=i.get(c.from),h=i.get(c.to);return !u||!h?[]:[{id:sr({instanceId:n,kind:"fill",title:c.key,ordinal:d}),paneId:"",fromSeriesId:u,toSeriesId:h,color:c.color,...c.colors?{colors:[...c.colors]}:{},...c.gradient?{gradient:[...c.gradient]}:{}}]}),a=(t.levels??[]).map((c,d)=>({id:sr({instanceId:n,kind:"hline",title:c.key,ordinal:d}),paneId:"",price:c.price,...c.color!=null?{color:c.color}:{},lineStyle:c.lineStyle??"dashed",width:1,...c.title!=null?{title:c.title}:{}})),l=(t.polylines??[]).map((c,d)=>{let{key:u,...h}=c;return {id:sr({instanceId:n,kind:"polyline",title:u,ordinal:d}),paneId:"",...h}});this.ctx.emit({series:o,fills:s,priceLines:a,polylines:l}),this.ctx.setStatus("idle");}};function Dx(r){return {type:r.type,title:r.title,...r.shortTitle!=null?{shortTitle:r.shortTitle}:{},paneHint:r.overlay?"price":"new",overlay:r.overlay,multiInstance:true,inputsSchema:()=>r.inputs,defaultInputs:()=>Object.fromEntries(r.inputs.map(e=>[e.key,e.defval])),create:()=>new jp(r)}}var Ox=["Close","Open","High","Low","HL2","HLC3","OHLC4","HLCC4"];function oe(r,e){let t=new Array(r.length);for(let n=0;ne.volume!=null&&Number.isFinite(e.volume)?e.volume:Number.NaN)}function et(r){return r.map(e=>e.high)}function tt(r){return r.map(e=>e.low)}function je(r){return r.map(e=>e.close)}function Nx(r){return r.map(e=>e.open)}function X(r,e,t){let n=new Array(r.length);for(let o=0;ot-n)}function Pt(r,e,t){let n=new Array(r.length).fill(Number.NaN);if(e<=0)return n;let o=0;for(let i=0;i=e&&(n[i]=t(r,i-e+1,i));return n}function ge(r,e){return Pt(r,e,(t,n,o)=>{let i=0;for(let s=n;s<=o;s++)i+=t[s];return i})}function Se(r,e){return Pt(r,e,(t,n,o)=>{let i=0;for(let s=n;s<=o;s++)i+=t[s];return i/e})}function $t(r,e){let t=e*(e+1)/2;return Pt(r,e,(n,o,i)=>{let s=0;for(let a=o;a<=i;a++)s+=n[a]*(a-o+1);return s/t})}function Fx(r,e,t){let n=X(r,e,(o,i)=>o*i);return X(ge(n,t),ge(e,t),(o,i)=>i>0?o/i:Number.NaN)}function It(r,e){return Pt(r,e,(t,n,o)=>{let i=0;for(let l=n;l<=o;l++)i+=t[l];let s=i/e,a=0;for(let l=n;l<=o;l++){let c=t[l]-s;a+=c*c;}return Math.sqrt(a/e)})}function Vx(r,e){return Pt(r,e,(t,n,o)=>{let i=0;for(let l=n;l<=o;l++)i+=t[l];let s=i/e,a=0;for(let l=n;l<=o;l++)a+=Math.abs(t[l]-s);return a/e})}function at(r,e){return Pt(r,e,(t,n,o)=>{let i=-1/0;for(let s=n;s<=o;s++)t[s]>i&&(i=t[s]);return i})}function lt(r,e){return Pt(r,e,(t,n,o)=>{let i=1/0;for(let s=n;s<=o;s++)t[s]{let i=-1/0,s=o;for(let a=n;a<=o;a++)t[a]>=i&&(i=t[a],s=a);return o-s})}function _x(r,e){return Pt(r,e,(t,n,o)=>{let i=1/0,s=o;for(let a=n;a<=o;a++)t[a]<=i&&(i=t[a],s=a);return o-s})}function Hx(r,e,t){let n=new Array(r.length).fill(Number.NaN),o=0,i=Number.NaN;for(let s=0;s=e){let l=0;for(let c=s-e+1;c<=s;c++)l+=r[c];i=l/e,n[s]=i;}}return n}function q(r,e){return Hx(r,e,2/(e+1))}function Ne(r,e){return Hx(r,e,1/e)}function st(r,e=1){let t=new Array(r.length).fill(Number.NaN);for(let n=e;n=0&&oMath.max(i,0)),o=re(t,i=>Math.max(-i,0));return X(Ne(n,e),Ne(o,e),(i,s)=>s===0?100:100-100/(1+i/s))}function qp(r,e,t,n){let o=at(e,n),i=lt(t,n),s=new Array(r.length).fill(Number.NaN);for(let a=0;a{let c=0,d=0;for(let p=a;p<=l;p++){let m=p-a;c+=s[p],d+=m*s[p];}let u=i===0?0:(e*d-n*c)/i;return (c-u*n)/e+u*(e-1-t)})}function zx(r,e){let t=Math.max(2,Math.trunc(e)),n=we(re($t(r,Math.max(1,Math.trunc(t/2))),o=>2*o),$t(r,t));return $t(n,Math.max(1,Math.round(Math.sqrt(t))))}function Wx(r,e,t,n){let o=t*(e-1),i=e/Math.max(n,1e-9),s=new Array(e),a=0;for(let l=0;l{let u=0;for(let h=c;h<=d;h++)u+=l[h]*s[h-c];return a===0?Number.NaN:u/a})}function Gx(r,e){let t=q(r,e);return we(re(t,n=>2*n),q(t,e))}function $x(r,e){let t=q(r,e),n=q(t,e),o=q(n,e);return X(X(re(t,i=>3*i),re(n,i=>3*i),(i,s)=>i-s),o,(i,s)=>i+s)}function Ux(r,e,t=2/3,n=2/31){let o=re(st(r,e),Math.abs),i=ge(re(st(r),Math.abs),e),s=new Array(r.length).fill(Number.NaN),a=Number.NaN;for(let l=0;lNumber.isFinite(s)?s:Number.NaN);let o=new Array(e),i=0;for(let s=0;s{let c=0;for(let d=a;d<=l;d++)c+=s[d]*o[l-d];return i===0?Number.NaN:c/i})}function Xx(r,e){let t=st(r),n=ge(re(t,i=>Math.max(i,0)),e),o=ge(re(t,i=>Math.max(-i,0)),e);return X(n,o,(i,s)=>i+s===0?0:100*(i-s)/(i+s))}function Od(r){let e=new Array(r.length).fill(Number.NaN);for(let t=3;t{if(!Number.isFinite(l))return null;let d=r[c].close;return d>l?o.bull:d{let d=n[c];return !Number.isFinite(l)||!Number.isFinite(d)?null:{topValue:l,bottomValue:d,topColor:z(o.bear,90),bottomColor:z(o.bull,90)}});return {plots:[{key:"basis",title:"Basis",values:[...e],color:o.neutral,colors:s},{key:"upper",title:"Upper",values:[...t],color:z(o.bear,30)},{key:"lower",title:"Lower",values:[...n],color:z(o.bull,30)}],bands:[{key:i,from:"upper",to:"lower",color:z(A,90),gradient:a}]}}function ct(r,e,t,n){return {key:r,title:e,values:new Array(t).fill(n),color:z(A,100),display:{pane:false,legend:false,dataWindow:false}}}function Qp(r,e,t,n=92){return {plots:[ct("obAnchor","Overbought Anchor",r,e.overbought),ct("osAnchor","Oversold Anchor",r,e.oversold),ct("topAnchor","Top Anchor",r,e.top),ct("bottomAnchor","Bottom Anchor",r,e.bottom)],bands:[{key:"obZone",from:"obAnchor",to:"topAnchor",color:z(t.overbought,n)},{key:"osZone",from:"osAnchor",to:"bottomAnchor",color:z(t.oversold,n)}]}}function lR(r,e,t){return r.map(n=>Number.isFinite(n)?n<=e.mid?qr(n,e.low,e.mid,t.low,t.mid):qr(n,e.mid,e.high,t.mid,t.high):null)}function Zr(r,e,t,n=50,o=100){return r.map((i,s)=>{if(!Number.isFinite(i))return null;let a=t(i,s),l=i>e;return {topValue:Math.max(i,e),bottomValue:Math.min(i,e),topColor:z(a,l?n:o),bottomColor:z(a,l?o:n)}})}function Zx(r,e){return r.map((t,n)=>{if(!Number.isFinite(t))return null;let o=n>0&&Number.isFinite(r[n-1])?r[n-1]:t,i=t>o;return t>=0?i?e.growAbove:e.fallAbove:i?e.growBelow:e.fallBelow})}function mn(r){let e=(r.overbought+r.oversold)/2,t=lR(r.values,{low:r.oversold,mid:e,high:r.overbought},r.ink),n=Qp(r.values.length,{overbought:r.overbought,oversold:r.oversold,top:r.scale.top,bottom:r.scale.bottom},{overbought:r.ink.high,oversold:r.ink.low},r.zoneTransparency),o=[{key:r.key,title:r.title,values:r.values,color:r.ink.mid,width:r.width??1,colors:t},...n.plots],i=[...n.bands];r.bandFill!=null&&i.push({key:"band",from:"obAnchor",to:"osAnchor",color:r.bandFill}),r.midpointWash&&(o.push(ct("midAnchor","Midpoint Anchor",r.values.length,e)),i.push({key:"wash",from:r.key,to:"midAnchor",color:z(A,100),gradient:Zr(r.values,e,(a,l)=>t[l]??r.ink.mid)}));let s=[{key:"overbought",price:r.overbought,color:r.levelInk,lineStyle:"dashed",title:r.levelTitles?.overbought??"Overbought"},{key:"oversold",price:r.oversold,color:r.levelInk,lineStyle:"dashed",title:r.levelTitles?.oversold??"Oversold"}];return r.midline!=null&&s.splice(1,0,{key:"midline",price:r.midline,color:r.levelInk,lineStyle:"dotted",title:"Midline"}),{plots:o,bands:i,levels:s}}function Ae(r){let e=r.baseline??0,t=i=>i>e?r.ink.bull:iNumber.isFinite(i)?t(i):null)},...r.extraPlots??[]],o=[];return r.fill!==false&&(n.push(ct("baseline","Baseline Anchor",r.values.length,e)),o.push({key:"wash",from:r.key,to:"baseline",color:z(A,100),gradient:Zr(r.values,e,t,r.valueTransparency)})),{plots:n,bands:o,levels:[{key:"zero",price:e,color:r.zeroInk,lineStyle:r.zeroLineStyle??"dashed",title:r.zeroTitle??"Zero Line"},...r.extraLevels??[]]}}function qx(r){let e=/^#([0-9a-f]{6})/i.exec(r.trim());if(!e)return null;let t=parseInt(e[1],16);return [t>>16&255,t>>8&255,t&255]}function qr(r,e,t,n,o){let i=qx(n),s=qx(o);if(!i||!s||!Number.isFinite(r))return n;let a=t-e,l=a===0?0:Math.max(0,Math.min(1,(r-e)/a)),c=d=>Math.round(i[d]+(s[d]-i[d])*l).toString(16).padStart(2,"0");return `#${c(0)}${c(1)}${c(2)}`}var Qx=["SMA","EMA","WMA","RMA (SMMA)","HMA","ALMA","VWMA","DEMA","TEMA","KAMA","LSMA","McGinley","Hamming"],cR=["SMA","EMA","WMA","RMA (SMMA)","HMA","VWMA"];function tm(r,e,t,n,o={}){switch(r){case "EMA":return q(e,n);case "WMA":return $t(e,n);case "RMA":case "RMA (SMMA)":return Ne(e,n);case "HMA":return zx(e,n);case "ALMA":return Wx(e,n,o.almaOffset??.85,o.almaSigma??6);case "VWMA":return Fx(e,Ut(t),n);case "DEMA":return Gx(e,n);case "TEMA":return $x(e,n);case "KAMA":return Ux(e,n);case "LSMA":return ni(e,n,o.lsmaOffset??0);case "McGinley":return Yx(e,n);case "Hamming":return Kx(e,n);default:return Se(e,n)}}function dR(r,e,t,n){return r.map((o,i)=>{if(!Number.isFinite(o))return null;let s=i>0?r[i-1]:Number.NaN;return Number.isFinite(s)?o>s?e:o{let s=R(i,"length",20),a=n(oe(o,T(i,"source","Close")),s),l=Math.trunc(R(i,"offset",0));return l!==0&&(a=Fe(a,l)),{plots:[{key:t.toLowerCase(),title:t,values:a,color:T(i,"color",ce),width:2}]}}}}var uR=iC("sma","Simple Moving Average","SMA",Se),hR=iC("ema","Exponential Moving Average","EMA",q),pR={type:"moving-average",title:"Moving Average",shortTitle:"MA",overlay:true,inputs:[Te("maType","MA 1 Type","SMA",Qx,"Moving average calculation used for MA 1."),F(20,"length","MA 1 Length",5e3,"Number of bars used in the MA 1 calculation."),le("Close","source","MA 1 Source","Price series MA 1 is calculated on."),ne("showMa2","Show MA 2",false,ze,"Displays the optional second moving average."),Te("ma2Type","MA 2 Type","SMA",Qx,"Moving average calculation used for MA 2."),F(50,"ma2Length","MA 2 Length",5e3,"Number of bars used in the MA 2 calculation."),le("Close","ma2Source","MA 2 Source","Price series MA 2 is calculated on."),Q("almaOffset","ALMA Offset",.85,0,1,.05,"ALMA type only. Values near 1 make the average more responsive, values near 0 make it smoother."),Q("almaSigma","ALMA Sigma",6,.1,100,.5,"ALMA type only. Larger values widen the Gaussian window for a smoother average."),pe("lsmaOffset","LSMA Offset",0,0,500,"LSMA type only. Bar offset applied to the linear regression value."),oC,P(ce,"MA 1","color","MA 1 line color."),P(U,"MA 2","ma2Color","MA 2 line color.")],compute:(r,e)=>{let t={almaOffset:R(e,"almaOffset",.85),almaSigma:R(e,"almaSigma",6),lsmaOffset:Math.trunc(R(e,"lsmaOffset",0))},n=Math.trunc(R(e,"offset",0)),o=l=>n===0?l:Fe(l,n),i=T(e,"maType","SMA"),s=o(tm(i,oe(r,T(e,"source","Close")),r,R(e,"length",20),t)),a=[{key:"ma",title:i,values:s,color:T(e,"color",ce),width:2}];if(te(e,"showMa2",false)){let l=T(e,"ma2Type","SMA"),c=o(tm(l,oe(r,T(e,"ma2Source","Close")),r,R(e,"ma2Length",50),t));a.push({key:"ma2",title:`${l} 2`,values:c,color:T(e,"ma2Color",U),width:2});}return {plots:a}}},mR={type:"rma",title:"Smoothed Moving Average",shortTitle:"RMA",overlay:true,inputs:[le("Close","source","Source","Price series the average smooths. Wilder computed his 1978 indicators on the close, but the recursion accepts any source."),F(14,"length","RMA Length",5e3,"Number of bars N in Wilder's smoothing: the line keeps (N \u2212 1)/N of its previous value and blends in 1/N of the new price. That alpha is smaller than an EMA's, so an N-period RMA responds like a (2N \u2212 1)-period EMA."),...nC()],compute:(r,e)=>({plots:[rC("rma","RMA",Ne(oe(r,T(e,"source","Close")),R(e,"length",14)),e)]})},fR={type:"zlema",title:"Zero-Lag Exponential Moving Average",shortTitle:"ZLEMA",overlay:true,inputs:[le("Close","source","Source","Price series the average de-lags and then smooths."),F(21,"length","ZLEMA Length",5e3,"EMA length N. It sets both the smoothing (alpha = 2 / (N + 1)) and the correction: an EMA of length N lags by about (N \u2212 1)/2 bars, and the de-lagging step is sized to cancel exactly that."),...nC()],compute:(r,e)=>{let t=R(e,"length",21),n=oe(r,T(e,"source","Close")),o=Math.round((t-1)/2),i=X(n,Fe(n,o),(s,a)=>2*s-a);return {plots:[rC("zlema","ZLEMA",q(i,t),e)]}}},Jp="Momentum (|CMO|)",Jx="Volatility (StDev Ratio)",eC="Trend Regime",gR={type:"vidya",title:"Variable Index Dynamic Average",shortTitle:"VIDYA",overlay:true,inputs:[le("Close","source","Source","Price series the average smooths. VIDYA is classically computed on the close."),F(12,"length","VIDYA Length",5e3,"EMA-equivalent length N of the base smoothing constant, alpha = 2 / (N + 1). The adaptive scaler rescales this base speed bar by bar."),Te("scaler","Adaptive Scaler",Jp,[Jp,Jx],"Bar-by-bar measure that rescales the smoothing constant. Momentum divides the absolute Chande Momentum Oscillator by 100; Volatility is Chande's original short-term over reference standard deviation."),pe("scalerLength","Scaler Lookback",9,1,5e3,"Lookback of the adaptive scaler \u2014 the CMO period in momentum mode, or the short-term standard deviation window in volatility mode."),pe("refLength","Reference StDev Length",30,2,5e3,"Volatility mode only \u2014 window of the reference standard deviation the short-term reading is divided by."),{...Q("flatThreshold","Flat Threshold",.05,0,10,.01,"One-bar change of VIDYA, as a fraction of ATR, below which the line reads as flat."),group:eC},{...pe("atrLength","ATR Normalization Length",14,1,5e3,"ATR window used to normalize VIDYA's one-bar slope, so the flat threshold behaves consistently across symbols and timeframes."),group:eC},ne("trendColor","Trend Regime Coloring",true,xe,"Colors VIDYA by its regime read \u2014 bullish while sloping up beyond the flat threshold, bearish while sloping down, flat inside congestion."),ne("adaptiveGradient","Adaptive Gradient",true,xe,"Blends the trend color toward the flat color according to the adaptive scaler, so the line pales as momentum dies."),P(O,"Bullish","bullColor"),P(D,"Bearish","bearColor"),P(A,"Flat","flatColor"),P(A,"Neutral","neutralColor"),Zp()],compute:(r,e)=>{let t=R(e,"length",12),n=oe(r,T(e,"source","Close")),o=R(e,"scalerLength",9),i=re(Xx(n,o),M=>Math.abs(M)/100),s=It(n,o),a=It(n,R(e,"refLength",30)),l=X(s,a,(M,S)=>S>0?M/S:0),c=T(e,"scaler",Jp)===Jx?l:i,d=2/(t+1),u=new Array(n.length).fill(Number.NaN),h=Number.NaN;for(let M=0;M{if(!Number.isFinite(M))return null;let L=y[S],v=S>0&&Number.isFinite(u[S-1])?M-u[S-1]:0,k=Number.isFinite(L)&&L!==0?v/L:0,x=k>b?m:k<-b?f:null;return x==null?g:w?qr(Math.min(c[S]??0,1),0,1,g,x):x});return {plots:[{key:"vidya",title:"VIDYA",values:u,color:g,width:R(e,"lineWidth",2),colors:C}]}}},bR={type:"ma-envelope",title:"Moving Average Envelope",shortTitle:"MA Env",overlay:true,inputs:[Te("maType","MA Type","SMA",cR,"Moving average type used as the envelope basis."),{...F(20,"length","Length",5e3,"Number of bars in the basis moving average."),min:2},le("Close","source","Source","Price series the basis moving average is calculated on."),Q("percent","Percent",2.5,0,50,.1,"Envelope offset as a percentage of the basis. Upper = basis \xD7 (1 + percent / 100), lower = basis \xD7 (1 \u2212 percent / 100)."),...Nd()],compute:(r,e)=>{let t=oe(r,T(e,"source","Close")),n=tm(T(e,"maType","SMA"),t,r,R(e,"length",20)),o=R(e,"percent",2.5)/100,i={bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"basisColor",A)};return Fd(r,n,re(n,s=>s*(1+o)),re(n,s=>s*(1-o)),i,"envelope")}},em="Curve",tC="Slope",vR={type:"linear-regression",title:"Linear Regression Curve",shortTitle:"LinReg",overlay:false,inputs:[Te("mode","Mode",em,[em,tC],"Curve plots the regression value on the price chart; Slope plots the per-bar slope of the fit in the pane."),{...F(100,"length","Length",5e3,"Number of bars used to fit the linear regression."),min:2},le("Close","source","Source","Price series the regression is fitted to."),P(O,"Rising","bullColor","Color of the regression curve and slope line while the fit slopes upward."),P(D,"Falling","bearColor","Color of the regression curve and slope line while the fit slopes downward."),P(A,"Regression Line","lineColor","Color of the regression curve and slope line while the fit is flat.")],compute:(r,e)=>{let t=R(e,"length",100),n=oe(r,T(e,"source","Close")),o=ni(n,t,0),i=X(o,ni(n,t,1),(d,u)=>d-u),s=T(e,"bullColor",O),a=T(e,"bearColor",D),l=T(e,"lineColor",A),c=i.map(d=>Number.isFinite(d)?d>0?s:d<0?a:l:null);return T(e,"mode",em)===tC?{plots:[{key:"slope",title:"Slope",values:i,color:l,width:2,colors:c}],levels:[{key:"zero",price:0,color:z(A,50),lineStyle:"dashed"}]}:{plots:[{key:"curve",title:"Curve",values:o,color:l,width:2,colors:c,overlay:true}]}}},sC=[uR,hR,pR,mR,fR,gR,bR,vR];var aC="#ab47bc",lC=U,cC="#ffd700";function om(r,e){let t=R(e,"length",20),n=R(e,"mult",2),o=oe(r,T(e,"source","Close")),i=Se(o,t),s=re(It(o,t),a=>a*n);return {src:o,basis:i,upper:X(i,s,(a,l)=>a+l),lower:X(i,s,(a,l)=>a-l)}}function uC(r,e){return [{...F(20,"length","Length",5e3,"Number of bars used for the Bollinger Bands basis (a simple moving average) and for the standard deviation."),min:2},le("Close","source","Source","Price series the bands are computed from."),Q("mult","Multiplier",2,r,50,e,"Standard deviation multiplier for the upper and lower bands.")]}var yR={type:"bollinger-bands",title:"Bollinger Bands",shortTitle:"BB",overlay:true,inputs:[F(20,"length","Length",5e3,"Number of bars used to calculate the basis SMA and the standard deviation."),le("Close","source","Source","Price series the bands are calculated on."),Q("mult","Multiplier",2,0,50,.1,"Number of standard deviations added above and below the basis to form the bands."),P(U,"Basis","basisColor","Color of the basis (middle band) moving average."),P(ce,"Bands","color","Color of the upper and lower bands."),P(z(ce,92),"Fill","fillColor","Fill color of the area between the upper and lower bands.")],compute:(r,e)=>{let{basis:t,upper:n,lower:o}=om(r,e),i=T(e,"color",ce);return {plots:[{key:"basis",title:"Basis",values:t,color:T(e,"basisColor",U)},{key:"upper",title:"Upper",values:n,color:i},{key:"lower",title:"Lower",values:o,color:i}],bands:[{key:"bb",from:"upper",to:"lower",color:T(e,"fillColor",z(ce,92))}]}}},oi=.5,dC="Thresholds",wR={type:"percent-b",title:"Bollinger Bands %B",shortTitle:"%B",overlay:false,inputs:[...uC(.001,.25),{...Q("overbought","Overbought",1,-10,10,.05,"Level treated as overbought. 1 is the upper band itself, so readings above the default mean price sits outside the bands."),group:dC},{...Q("oversold","Oversold",0,-10,10,.05,"Level treated as oversold. 0 is the lower band itself, so readings below the default mean price sits outside the bands."),group:dC},P(O,"Bullish","bullColor","Color of %B above the 0.5 midline, where price trades in the upper half of the bands."),P(D,"Bearish","bearColor","Color of %B below the 0.5 midline, where price trades in the lower half of the bands."),ne("gradientFill","Gradient Fill",true,xe,"Vertical gradient between %B and the 0.5 midline, fully transparent at the midline and more opaque at the oscillator value."),P(A,"Levels Color","levelsColor","Color of the dashed overbought/oversold levels and of the dotted midline.")],compute:(r,e)=>{let{src:t,upper:n,lower:o}=om(r,e),i=t.map((h,p)=>{let m=n[p],f=o[p];return Number.isFinite(m)&&Number.isFinite(f)&&m!==f?(h-f)/(m-f):Number.NaN}),s=T(e,"bullColor",O),a=T(e,"bearColor",D),l=T(e,"levelsColor",A),c=i.map(h=>Number.isFinite(h)?h>oi?s:a:null),d=[{key:"pb",title:"%B",values:i,color:a,colors:c},{key:"mid",title:"Midline",values:i.map(h=>Number.isFinite(h)?oi:Number.NaN),color:l,display:{pane:false,legend:false,dataWindow:false}}],u=te(e,"gradientFill",true)?[{key:"pbFill",from:"pb",to:"mid",color:z(A,100),gradient:i.map(h=>{if(!Number.isFinite(h))return null;let p=h>oi,m=p?s:a;return {topValue:Math.max(h,oi),bottomValue:Math.min(h,oi),topColor:p?z(m,50):z(m,100),bottomColor:p?z(m,100):z(m,50)}})}]:[];return {plots:d,bands:u,levels:[{key:"overbought",price:R(e,"overbought",1),color:l,lineStyle:"dashed",title:"Overbought"},{key:"oversold",price:R(e,"oversold",0),color:l,lineStyle:"dashed",title:"Oversold"},{key:"midline",price:oi,color:z(l,50),lineStyle:"dotted",title:"Midline"}]}}},nm="Squeeze & Bulge",xR={type:"bandwidth",title:"Bollinger Bands Width",shortTitle:"BandWidth",overlay:false,inputs:[...uC(.001,.25),{...pe("lookback","Reference Lookback",125,2,5e3,"Window used to locate the lowest (Squeeze) and highest (Bulge) BandWidth references."),group:nm},ne("showSqueeze","Show Squeeze Level",true,nm,"Plots the lowest BandWidth of the reference lookback \u2014 unusually compressed volatility, a condition rather than a directional signal."),ne("showBulge","Show Bulge Level",true,nm,"Plots the highest BandWidth of the reference lookback \u2014 extreme width that is unlikely to be sustained."),P(A,"BandWidth","color","Color of the BandWidth line. At its Squeeze reference the line takes the Squeeze color, at its Bulge reference the Bulge color."),ne("gradientFill","Gradient Fill",true,xe,"Fills the area between zero and BandWidth with a vertical gradient, fully transparent at zero."),P(U,"Squeeze Level","squeezeColor","Color of the lowest-BandWidth reference line."),P(D,"Bulge Level","bulgeColor","Color of the highest-BandWidth reference line.")],compute:(r,e)=>{let{basis:t,upper:n,lower:o}=om(r,e),i=t.map((f,g)=>{let b=n[g],y=o[g];return Number.isFinite(f)&&f!==0&&Number.isFinite(b)&&Number.isFinite(y)?(b-y)/f:Number.NaN}),s=R(e,"lookback",125),a=lt(i,s),l=at(i,s),c=T(e,"color",A),d=T(e,"squeezeColor",U),u=T(e,"bulgeColor",D),h=i.map((f,g)=>Number.isFinite(f)?f<=a[g]?d:f>=l[g]?u:c:null),p=[{key:"bbw",title:"BandWidth",values:i,color:c,colors:h},{key:"zero",title:"Zero Line",values:i.map(f=>Number.isFinite(f)?0:Number.NaN),color:z(A,90)}];te(e,"showSqueeze",true)&&p.push({key:"squeeze",title:"Squeeze Level",values:a,color:d}),te(e,"showBulge",true)&&p.push({key:"bulge",title:"Bulge Level",values:l,color:u});let m=te(e,"gradientFill",true)?[{key:"bbwFill",from:"bbw",to:"zero",color:z(A,100),gradient:i.map((f,g)=>{if(!Number.isFinite(f))return null;let b=h[g]??c;return {topValue:f,bottomValue:0,topColor:z(b,50),bottomColor:z(b,100)}})}]:[];return {plots:p,bands:m}}},CR={type:"keltner-channels",title:"Keltner Channels",shortTitle:"KC",overlay:true,inputs:[F(20,"length","EMA Length",5e3,"Number of bars used to compute the exponential moving average basis line."),pe("atrLength","ATR Length",10,1,5e3,"Number of bars used to compute the Average True Range (Wilder smoothing)."),Q("mult","Multiplier",2,0,50,.1,"ATR multiple used to offset the upper and lower bands from the basis line."),le("Close","source","Source","Price series used to compute the basis line."),...Nd("Basis Color")],compute:(r,e)=>{let t=q(oe(r,T(e,"source","Close")),R(e,"length",20)),n=re(Nn(r,R(e,"atrLength",10)),i=>i*R(e,"mult",2)),o={bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"basisColor",A)};return Fd(r,t,X(t,n,(i,s)=>i+s),X(t,n,(i,s)=>i-s),o,"kc")}},SR={type:"donchian-channels",title:"Donchian Channels",shortTitle:"DC",overlay:true,inputs:[F(20,"length","Length",5e3,"Lookback length. The upper and lower channels are the highest high and lowest low over this many bars."),P(D,"Upper","upperColor","Color of the upper channel line."),P(A,"Middle","middleColor","Color of the channel midline."),P(O,"Lower","lowerColor","Color of the lower channel line."),P(z(A,92),"Fill","fillColor","Color of the channel interior fill.")],compute:(r,e)=>{let t=R(e,"length",20),n=at(et(r),t),o=lt(tt(r),t);return {plots:[{key:"upper",title:"Upper",values:n,color:T(e,"upperColor",D)},{key:"middle",title:"Middle",kind:"circles",values:X(n,o,(i,s)=>(i+s)/2),color:T(e,"middleColor",A)},{key:"lower",title:"Lower",values:o,color:T(e,"lowerColor",O)}],bands:[{key:"dc",from:"upper",to:"lower",color:T(e,"fillColor",z(A,92))}]}}},TR={type:"chandelier-exit",title:"Chandelier Exit",shortTitle:"CE",overlay:true,inputs:[F(22,"length","Length",5e3,"Lookback used for both the highest high / lowest low extremes and the ATR."),Q("mult","ATR Multiplier",3,0,50,.1,"Multiple of ATR subtracted from the highest high (long stop) and added to the lowest low (short stop)."),ne("ratchet","Ratchet Stops",false,void 0,"Prevents the long stop from falling and the short stop from rising, resetting once close crosses through the stop."),P(O,"Long Stop","longColor","Color of the long trailing stop line."),P(D,"Short Stop","shortColor","Color of the short trailing stop line.")],compute:(r,e)=>{let t=R(e,"length",22),n=re(Nn(r,t),l=>l*R(e,"mult",3)),o=X(at(et(r),t),n,(l,c)=>l-c),i=X(lt(tt(r),t),n,(l,c)=>l+c),s=o,a=i;if(te(e,"ratchet",false)){s=new Array(r.length).fill(Number.NaN),a=new Array(r.length).fill(Number.NaN);for(let l=0;l0?r[l-1].close:r[l].close,h=l>0&&Number.isFinite(s[l-1])?s[l-1]:c,p=l>0&&Number.isFinite(a[l-1])?a[l-1]:d;s[l]=Number.isFinite(c)?u>h?Math.max(c,h):c:Number.NaN,a[l]=Number.isFinite(d)?u{let t=R(e,"p",10),n=R(e,"q",9),o=re(Nn(r,t),a=>a*R(e,"x",1)),i=X(at(et(r),t),o,(a,l)=>a-l),s=X(lt(tt(r),t),o,(a,l)=>a+l);return {plots:[{key:"stopShort",title:"Stop Short",values:at(i,n),color:T(e,"shortColor",D)},{key:"stopLong",title:"Stop Long",values:lt(s,n),color:T(e,"longColor",O)}]}}},LR={type:"supertrend",title:"SuperTrend",shortTitle:"SuperTrend",overlay:true,inputs:[pe("atrLength","ATR Length",10,1,5e3,"Number of bars used to compute the Wilder ATR."),Q("mult","Factor",3,0,50,.1,"ATR multiplier setting how far the trailing stop sits from the bar midpoint."),P(O,"Uptrend Color","upColor","Line color while the trend is up."),P(D,"Downtrend Color","downColor","Line color while the trend is down.")],compute:(r,e)=>{let t=R(e,"mult",3),n=Nn(r,R(e,"atrLength",10)),o=r.length,i=new Array(o).fill(Number.NaN),s=new Array(o).fill(Number.NaN),a=Number.NaN,l=Number.NaN,c=-1;for(let d=0;d0?r[d-1].close:h.close;a=y<=g?Math.min(m,g):m,l=y>=b?Math.max(f,b):f,c=h.close>a?1:h.close{let t=oe(r,"HL2"),n=Fe(Ne(t,R(e,"jawLength",13)),R(e,"jawOffset",8)),o=Fe(Ne(t,R(e,"teethLength",8)),R(e,"teethOffset",5)),i=Fe(Ne(t,R(e,"lipsLength",5)),R(e,"lipsOffset",3));return {plots:[{key:"jaw",title:"Jaw",values:n,color:T(e,"jawColor",aC)},{key:"teeth",title:"Teeth",values:o,color:T(e,"teethColor",lC)},{key:"lips",title:"Lips",values:i,color:T(e,"lipsColor",cC)}]}}},ar="Alligator Lines",rm="SMMA (Wilder)",ER={type:"gator-oscillator",title:"Gator Oscillator",shortTitle:"Gator Oscillator",overlay:false,inputs:[{...le("HL2","source","Source","Price series fed to the three Alligator averages. Bill Williams' original recipe uses the median price (high + low) / 2."),group:ar},{...Te("maType","Smoothing",rm,[rm,"SMA","EMA"],"Moving average applied to the source for the jaw, teeth and lips. The original uses the smoothed (Wilder-style) moving average."),group:ar},{...pe("jawLength","Jaw Length",13,1,500,"Averaging length of the jaw line."),group:ar},{...pe("jawOffset","Jaw Offset",8,0,100,"Bars the jaw is displaced forward, 8 in the original recipe. The upper histogram measures the absolute spread between the displaced jaw and teeth."),group:ar},{...pe("teethLength","Teeth Length",8,1,500,"Averaging length of the teeth line."),group:ar},{...pe("teethOffset","Teeth Offset",5,0,100,"Bars the teeth are displaced forward, 5 in the original recipe. The teeth line enters both spreads."),group:ar},{...pe("lipsLength","Lips Length",5,1,500,"Averaging length of the lips line."),group:ar},{...pe("lipsOffset","Lips Offset",3,0,100,"Bars the lips are displaced forward, 3 in the original recipe. The lower histogram measures the negative absolute spread between the displaced teeth and lips."),group:ar},P(O,"Expanding","growColor","Column color while a spread grew against its own previous bar \u2014 the averages are spreading apart."),P(D,"Contracting","shrinkColor","Column color while a spread shrank \u2014 the averages are converging. Color encodes expansion, not trade direction."),P(A,"Zero Line","zeroColor","Color of the zero line separating the two histograms.")],compute:(r,e)=>{let t=oe(r,T(e,"source","HL2")),n=T(e,"maType",rm),o=p=>n==="SMA"?Se(t,p):n==="EMA"?q(t,p):Ne(t,p),i=Fe(o(R(e,"jawLength",13)),R(e,"jawOffset",8)),s=Fe(o(R(e,"teethLength",8)),R(e,"teethOffset",5)),a=Fe(o(R(e,"lipsLength",5)),R(e,"lipsOffset",3)),l=re(we(i,s),Math.abs),c=re(we(s,a),Math.abs),d=T(e,"growColor",O),u=T(e,"shrinkColor",D),h=p=>{let m=false;return p.map((f,g)=>{if(!Number.isFinite(f))return null;let b=g>0?p[g-1]:Number.NaN;return Number.isFinite(b)&&(m=f>b?true:f-p),kind:"columns",color:u,colors:h(c),base:0}],levels:[{key:"zero",price:0,color:T(e,"zeroColor",A),lineStyle:"solid",title:"Zero Line"}]}}},hC=[yR,wR,xR,CR,SR,TR,kR,LR,MR,ER];function Qr(r,e,t=0,n=100,o="Overbought Level",i="Oversold Level"){return [Q("overbought",o,r,t,n,1,"Level above which the oscillator is considered overbought."),Q("oversold",i,e,t,n,1,"Level below which the oscillator is considered oversold.")]}var PR={type:"rsi",title:"Relative Strength Index",shortTitle:"RSI",overlay:false,inputs:[F(14,"length","Length",5e3,"Number of bars used in the Wilder smoothing of average gains and losses."),le("Close","source","Source","Price series the RSI is calculated on."),...Qr(70,30,0,100,"Overbought","Oversold"),P(A,"RSI","color","Color of the RSI line at the midline. Toward either threshold it blends into that threshold\u2019s color."),P(O,"Oversold","oversoldColor","Color of the line and zone shading at and below the oversold level."),P(D,"Overbought","overboughtColor","Color of the line and zone shading at and above the overbought level."),P(A,"Levels","levelsColor","Color of the overbought, midline and oversold levels."),P(z(A,90),"Band Fill","fillColor","Color of the fill between the overbought and oversold levels.")],compute:(r,e)=>mn({key:"rsi",title:"RSI",values:Ks(oe(r,T(e,"source","Close")),R(e,"length",14)),scale:{top:100,bottom:0},overbought:R(e,"overbought",70),oversold:R(e,"oversold",30),ink:{low:T(e,"oversoldColor",O),mid:T(e,"color",A),high:T(e,"overboughtColor",D)},levelInk:T(e,"levelsColor",A),width:2,midline:50,bandFill:T(e,"fillColor",z(A,90))})};function bC(r,e,t){let n=R(t,"overbought",80),o=R(t,"oversold",20);return {plots:[{key:"k",title:"%K",values:r,color:T(t,"kColor",ce)},{key:"d",title:"%D",values:e,color:T(t,"dColor",U)},ct("obAnchor","Overbought Anchor",r.length,n),ct("osAnchor","Oversold Anchor",r.length,o)],bands:[{key:"band",from:"obAnchor",to:"osAnchor",color:T(t,"fillColor",z(ce,90))}],levels:[{key:"overbought",price:n,color:A,lineStyle:"dashed",title:"Overbought"},{key:"oversold",price:o,color:A,lineStyle:"dashed",title:"Oversold"}]}}var IR={type:"stochastic",title:"Stochastic",shortTitle:"Stoch",overlay:false,inputs:[F(14,"kLength","%K Length",5e3,"Number of bars used for the highest high / lowest low range of the raw %K."),F(3,"kSmoothing","%K Smoothing",500,"Simple moving average length applied to the raw %K. 1 gives the fast stochastic, 3 the classic slow stochastic."),F(3,"dLength","%D Smoothing",500,"Simple moving average length of the %D signal line, applied to the smoothed %K."),...Qr(80,20),P(ce,"%K","kColor","Color of the %K line."),P(U,"%D","dColor","Color of the %D signal line."),P(z(ce,90),"Band Fill","fillColor","Fill color of the area between the overbought and oversold levels.")],compute:(r,e)=>{let t=Se(qp(je(r),et(r),tt(r),R(e,"kLength",14)),R(e,"kSmoothing",3));return bC(t,Se(t,R(e,"dLength",3)),e)}},AR={type:"stochastic-rsi",title:"Stochastic RSI",shortTitle:"Stoch RSI",overlay:false,inputs:[le("Close","source","RSI Source","Price series the RSI is computed on."),F(14,"rsiLength","RSI Length",5e3,"Lookback length of the Wilder RSI."),F(14,"stochLength","Stochastic Length",5e3,"Lookback over which the highest and lowest RSI values are taken."),F(3,"kSmoothing","%K Smoothing",500,"Simple moving average length applied to the stochastic of RSI to form %K."),F(3,"dLength","%D Smoothing",500,"Simple moving average length applied to %K to form the %D signal line."),...Qr(80,20),P(ce,"%K Color","kColor","Color of the %K line."),P(U,"%D Color","dColor","Color of the %D signal line."),P(z(ce,90),"Zone Fill","fillColor","Fill color of the area between the overbought and oversold levels.")],compute:(r,e)=>{let t=Ks(oe(r,T(e,"source","Close")),R(e,"rsiLength",14)),n=Se(qp(t,t,t,R(e,"stochLength",14)),R(e,"kSmoothing",3));return bC(n,Se(n,R(e,"dLength",3)),e)}},RR={type:"macd",title:"MACD",overlay:false,inputs:[F(12,"fastLength","Fast Length",5e3,"Length of the fast EMA."),F(26,"slowLength","Slow Length",5e3,"Length of the slow EMA."),F(9,"signalLength","Signal Smoothing",500,"Length of the EMA applied to the MACD line to obtain the signal line."),le("Close","source","Source","Price series used to compute the fast and slow EMAs."),P(ce,"MACD Line","color","Color of the MACD line."),P(U,"Signal Line","signalColor","Color of the signal line."),P(O,"Grow Above","growAboveColor","Histogram color when above zero and rising."),P(z(O,50),"Fall Above","fallAboveColor","Histogram color when above zero and falling."),P(z(D,50),"Grow Below","growBelowColor","Histogram color when below zero and rising."),P(D,"Fall Below","fallBelowColor","Histogram color when below zero and falling.")],compute:(r,e)=>{let t=oe(r,T(e,"source","Close")),n=we(q(t,R(e,"fastLength",12)),q(t,R(e,"slowLength",26))),o=q(n,R(e,"signalLength",9)),i=we(n,o),s=Zx(i,{growAbove:T(e,"growAboveColor",O),fallAbove:T(e,"fallAboveColor",z(O,50)),growBelow:T(e,"growBelowColor",z(D,50)),fallBelow:T(e,"fallBelowColor",D)});return {plots:[{key:"hist",title:"Histogram",values:i,kind:"columns",color:O,colors:s,base:0},{key:"macd",title:"MACD",values:n,color:T(e,"color",ce)},{key:"signal",title:"Signal",values:o,color:T(e,"signalColor",U)}],levels:[{key:"zero",price:0,color:A,lineStyle:"dashed",title:"Zero Line"}]}}},DR={type:"ppo",title:"Percentage Price Oscillator",shortTitle:"PPO",overlay:false,inputs:[le("Close","source","Source","Price series fed into the fast and slow averages."),F(12,"fastLength","Fast Length",5e3,"Length of the fast moving average."),F(26,"slowLength","Slow Length",5e3,"Length of the slow moving average. The spread is divided by it and scaled to a percentage of price."),Te("maType","Average Type","EMA",["EMA","SMA"],"Moving average type used for the fast and slow averages."),F(9,"signalLength","Signal Smoothing",500,"Length of the signal line that smooths the PPO line."),Te("signalType","Signal Type","EMA",["EMA","SMA"],"Moving average type used for the signal line."),P(O,"Bullish","bullColor","Color of the PPO line, gradient fill and histogram above the zero line."),P(D,"Bearish","bearColor","Color of the PPO line, gradient fill and histogram below the zero line."),P(U,"Signal Line","signalColor","Color of the signal line."),ne("showHistogram","Show Histogram",true,xe,"Displays the histogram (PPO minus signal line) as columns. Bright columns mark a spread still widening, faded ones a spread narrowing back."),ne("gradientFill","Gradient Fill",true,xe,"Fills the area between the zero line and the PPO line with a vertical gradient.")],compute:(r,e)=>{let t=oe(r,T(e,"source","Close")),n=(p,m,f)=>p==="SMA"?Se(m,f):q(m,f),o=T(e,"maType","EMA"),i=n(o,t,R(e,"fastLength",12)),s=n(o,t,R(e,"slowLength",26)),a=X(i,s,(p,m)=>m===0?Number.NaN:(p-m)/m*100),l=n(T(e,"signalType","EMA"),a,R(e,"signalLength",9)),c=we(a,l),d=T(e,"bullColor",O),u=T(e,"bearColor",D),h=Ae({key:"ppo",title:"PPO Line",values:a,ink:{bull:d,bear:u,neutral:u},zeroInk:z(A,90),fill:te(e,"gradientFill",true),extraPlots:[{key:"signal",title:"Signal Line",values:l,color:T(e,"signalColor",U)}]});if(te(e,"showHistogram",true)){let p=c.map((m,f)=>{if(!Number.isFinite(m))return null;let g=f>0&&Number.isFinite(c[f-1])?c[f-1]:m,b=m>=0?d:u,y=m>=0?m>g:m{let t=oe(r,"HL2"),n=we(Se(t,5),Se(t,34)),o=T(e,"risingColor",O),i=T(e,"fallingColor",D),s=n.map((a,l)=>{if(!Number.isFinite(a))return null;let c=l>0?n[l-1]:Number.NaN;return Number.isFinite(c)&&a>c?o:i});return {plots:[{key:"ao",title:"AO",values:n,kind:"columns",color:o,colors:s,base:0}],levels:[{key:"zero",price:0,color:T(e,"zeroColor",A),lineStyle:"dashed",title:"Zero Line"}]}}},NR=.015,FR={type:"commodity-channel-index",title:"Commodity Channel Index",shortTitle:"CCI",overlay:false,inputs:[F(20,"length","Length",5e3,"Number of bars used for the moving average and the mean absolute deviation of the source."),le("HLC3","source","Source","Price series measured by the CCI; the typical price hlc3 is the classic choice."),Q("upper","Upper Level",100,-1e3,1e3,10,"Overbought reference level, +100 classically."),Q("lower","Lower Level",-100,-1e3,1e3,10,"Oversold reference level, \u2212100 classically."),P(A,"CCI Line","color","Color of the CCI line."),P(O,"Bullish","bullColor","Line and fill color while the CCI reads above zero."),P(D,"Bearish","bearColor","Line and fill color while the CCI reads below zero."),P(A,"Levels","levelsColor","Color of the upper, lower and zero reference lines.")],compute:(r,e)=>{let t=R(e,"length",20),n=oe(r,T(e,"source","HLC3")),o=Se(n,t),i=Vx(n,t),s=n.map((l,c)=>{let d=o[c],u=i[c];return !Number.isFinite(d)||!Number.isFinite(u)?Number.NaN:u===0?0:(l-d)/(NR*u)}),a=T(e,"levelsColor",A);return Ae({key:"cci",title:"CCI",values:s,ink:{bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"color",A)},zeroInk:a,zeroLineStyle:"dotted",extraLevels:[{key:"upper",price:R(e,"upper",100),color:a,lineStyle:"dashed",title:"Upper Level"},{key:"lower",price:R(e,"lower",-100),color:a,lineStyle:"dashed",title:"Lower Level"}]})}},VR={type:"williams-percent-r",title:"Williams %R",shortTitle:"%R",overlay:false,inputs:[F(14,"length","Length",5e3,"Lookback length of the highest high / lowest low range. 14 is the classic setting."),le("Close","source","Source","Series located within the lookback range. Close is the classic choice."),...Qr(-20,-80,-100,0),P(A,"%R Line","color","Color of the %R line between the thresholds. Toward either level it blends into that level\u2019s color."),P(D,"Overbought","overboughtColor","Color of the line and zone shading at and above the overbought level."),P(O,"Oversold","oversoldColor","Color of the line and zone shading at and below the oversold level.")],compute:(r,e)=>{let t=R(e,"length",14),n=oe(r,T(e,"source","Close")),o=at(et(r),t),i=lt(tt(r),t),s=n.map((a,l)=>{let c=o[l],d=i[l];return Number.isFinite(c)&&Number.isFinite(d)&&c>d?-100*(c-a)/(c-d):Number.NaN});return mn({key:"wr",title:"%R",values:s,scale:{top:0,bottom:-100},overbought:R(e,"overbought",-20),oversold:R(e,"oversold",-80),ink:{low:T(e,"oversoldColor",O),mid:T(e,"color",A),high:T(e,"overboughtColor",D)},levelInk:A})}},BR={type:"chande-momentum-oscillator",title:"Chande Momentum Oscillator",shortTitle:"CMO",overlay:false,inputs:[F(9,"length","Length",5e3,"Number of bars over which up moves and down moves are summed."),le("Close","source","Source","Price series used to measure bar-to-bar changes."),Q("overbought","Overbought Level",50,0,100,1,"Level above which the oscillator is considered overbought."),Q("oversold","Oversold Level",-50,-100,0,1,"Level below which the oscillator is considered oversold."),P(A,"CMO Line","color","Color of the CMO line."),P(O,"Bullish","bullColor","Line and fill color while momentum is positive, and shading of the oversold zone."),P(D,"Bearish","bearColor","Line and fill color while momentum is negative, and shading of the overbought zone."),P(A,"Levels","levelsColor","Color of the overbought, oversold, and zero lines.")],compute:(r,e)=>{let t=R(e,"length",9),n=st(oe(r,T(e,"source","Close"))),o=ge(re(n,m=>Math.max(m,0)),t),i=ge(re(n,m=>Math.max(-m,0)),t),s=X(o,i,(m,f)=>m+f===0?0:100*(m-f)/(m+f)),a=T(e,"bullColor",O),l=T(e,"bearColor",D),c=T(e,"levelsColor",A),d=R(e,"overbought",50),u=R(e,"oversold",-50),h=Ae({key:"cmo",title:"CMO",values:s,ink:{bull:a,bear:l,neutral:T(e,"color",A)},zeroInk:c,zeroLineStyle:"dotted",extraLevels:[{key:"overbought",price:d,color:c,lineStyle:"dashed",title:"Overbought"},{key:"oversold",price:u,color:c,lineStyle:"dashed",title:"Oversold"}]}),p=Qp(s.length,{overbought:d,oversold:u,top:100,bottom:-100},{overbought:l,oversold:a});return h.plots.push(...p.plots),h.bands=[...h.bands??[],...p.bands],h}},_R={type:"connors-rsi",title:"Connors RSI",shortTitle:"CRSI",overlay:false,inputs:[F(3,"rsiLength","RSI Length",5e3,"Length of the Wilder RSI applied to the closing price."),F(2,"streakLength","Streak RSI Length",5e3,"Length of the Wilder RSI applied to the up/down close streak."),F(100,"rankLength","Percent Rank Length",5e3,"Lookback of the percent rank applied to the 1-bar rate of change of the closing price."),...Qr(90,10),P(A,"CRSI Line","color","Color of the Connors RSI line."),P(O,"Oversold","oversoldColor","Line, fill and zone color toward and below the oversold level."),P(D,"Overbought","overboughtColor","Line, fill and zone color toward and above the overbought level."),P(A,"Levels","levelsColor","Color of the overbought and oversold levels.")],compute:(r,e)=>{let t=je(r),n=new Array(t.length).fill(0);for(let l=1;l0?Math.max(n[l-1],0)+1:c<0?Math.min(n[l-1],0)-1:0;}let o=Ks(t,R(e,"rsiLength",3)),i=Ks(n,R(e,"streakLength",2)),s=jx(Xr(t,1),R(e,"rankLength",100)),a=t.map((l,c)=>{let d=o[c],u=i[c],h=s[c];return Number.isFinite(d)&&Number.isFinite(u)&&Number.isFinite(h)?(d+u+h)/3:Number.NaN});return mn({key:"crsi",title:"Connors RSI",values:a,scale:{top:100,bottom:0},overbought:R(e,"overbought",90),oversold:R(e,"oversold",10),ink:{low:T(e,"oversoldColor",O),mid:T(e,"color",A),high:T(e,"overboughtColor",D)},levelInk:T(e,"levelsColor",A),midpointWash:true})}},HR={type:"fisher-transform",title:"Fisher Transform",shortTitle:"Fisher",overlay:false,inputs:[F(9,"length","Length",5e3,"Lookback period used to locate the median price hl2 within its highest-lowest range. Ehlers' original length is 10; 9 is the common platform default."),P(A,"Fisher Line","color","Color of the Fisher line when it sits exactly on its trigger."),P(A,"Trigger Line","triggerColor","Color of the trigger line, the Fisher value delayed one bar."),P(O,"Bullish","bullColor","Color of the Fisher line and fill while it is above the trigger."),P(D,"Bearish","bearColor","Color of the Fisher line and fill while it is below the trigger.")],compute:(r,e)=>{let t=R(e,"length",9),n=oe(r,"HL2"),o=at(n,t),i=lt(n,t),s=r.length,a=new Array(s).fill(Number.NaN),l=0,c=0;for(let f=0;fb?(n[f]-b)/(g-b)-.5:0)+.67*l,l=l>.99?.999:l<-0.99?-0.999:l,c=.5*Math.log((1+l)/(1-l))+.5*c,a[f]=c;}let d=Fe(a,1),u=T(e,"color",A),h=T(e,"bullColor",O),p=T(e,"bearColor",D),m=f=>{let g=a[f],b=d[f];return Number.isFinite(b)?g>b?h:gNumber.isFinite(f)?m(g):null)},{key:"trigger",title:"Trigger",values:d,color:T(e,"triggerColor",A)}],bands:[{key:"spread",from:"fisher",to:"trigger",color:z(u,80),colors:a.map((f,g)=>Number.isFinite(f)?z(m(g),80):null)}],levels:[{key:"upper",price:1.5,color:A,lineStyle:"dashed",title:"Upper Level"},{key:"lower",price:-1.5,color:A,lineStyle:"dashed",title:"Lower Level"},{key:"zero",price:0,color:A,lineStyle:"dotted",title:"Zero Line"}]}}},zR={type:"trix",title:"TRIX",overlay:false,inputs:[F(18,"length","Length",5e3,"Length of each of the three EMA smoothing passes applied to the close price."),F(9,"signalLength","Signal Length",500,"Length of the EMA applied to TRIX to form the signal line."),P(A,"TRIX Color","color","Color of the TRIX line."),P(U,"Signal Color","signalColor","Color of the signal line."),P(O,"Bullish","bullColor","Color of the TRIX line and its gradient fill while TRIX holds above zero."),P(D,"Bearish","bearColor","Color of the TRIX line and its gradient fill while TRIX holds below zero.")],compute:(r,e)=>{let t=R(e,"length",18),n=q(q(q(je(r),t),t),t),o=Xr(n,1);return Ae({key:"trix",title:"TRIX",values:o,ink:{bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"color",A)},zeroInk:A,extraPlots:[{key:"signal",title:"Signal",values:q(o,R(e,"signalLength",9)),color:T(e,"signalColor",U)}]})}};function vC(r,e,t){let n=st(r),o=q(q(n,e),t),i=q(q(re(n,Math.abs),e),t);return X(o,i,(s,a)=>a===0?0:s/a)}var WR={type:"true-strength-index",title:"True Strength Index",shortTitle:"TSI",overlay:false,inputs:[F(25,"longLength","Long Length",5e3,"Length of the first (long) EMA applied to the 1-bar price change."),F(13,"shortLength","Short Length",5e3,"Length of the second (short) EMA applied to the long-smoothed price change."),F(13,"signalLength","Signal Length",500,"Length of the EMA of TSI used as the signal line."),P(A,"TSI","color","Color of the TSI line."),P(U,"Signal","signalColor","Color of the signal line."),P(O,"Bullish","bullColor","Color of the TSI line and its gradient fill while TSI holds above zero."),P(D,"Bearish","bearColor","Color of the TSI line and its gradient fill while TSI holds below zero.")],compute:(r,e)=>{let t=re(vC(je(r),R(e,"longLength",25),R(e,"shortLength",13)),n=>100*n);return Ae({key:"tsi",title:"TSI",values:t,ink:{bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"color",A)},zeroInk:A,extraPlots:[{key:"signal",title:"Signal",values:q(t,R(e,"signalLength",13)),color:T(e,"signalColor",U)}]})}},im="Indicator",pC="Oscillator",GR={type:"smi-ergodic",title:"SMI Ergodic Oscillator",shortTitle:"SMIE",overlay:false,inputs:[F(20,"longLength","Long Length",5e3,"Length of the first EMA smoothing applied to the momentum of the closing price."),F(5,"shortLength","Short Length",5e3,"Length of the second EMA smoothing applied to the momentum of the closing price."),F(5,"signalLength","Signal Length",500,"Length of the EMA of the SMI that forms the signal line."),Te("display","Display",im,[im,pC],"Indicator plots the SMI and its signal line. Oscillator plots the difference between them as a histogram."),P(A,"SMI","color","Color of the SMI line while it sits exactly on its signal line."),P(U,"Signal","signalColor","Color of the signal line."),P(O,"Oscillator Grow","growColor","Color of the rising oscillator histogram, and of the SMI line while it leads its signal."),P(D,"Oscillator Fall","fallColor","Color of the falling oscillator histogram, and of the SMI line while it lags its signal.")],compute:(r,e)=>{let t=vC(je(r),R(e,"longLength",20),R(e,"shortLength",5)),n=q(t,R(e,"signalLength",5)),o=T(e,"growColor",O),i=T(e,"fallColor",D),s=[{key:"zero",price:0,color:z(A,50),lineStyle:"dashed",title:"Zero"}];if(T(e,"display",im)===pC){let c=we(t,n),d=c.map((u,h)=>{if(!Number.isFinite(u))return null;let p=h>0&&Number.isFinite(c[h-1])?c[h-1]:u;return u>p?o:i});return {plots:[{key:"osc",title:"Oscillator",values:c,kind:"columns",color:o,colors:d,base:0}],levels:s}}let a=T(e,"color",A),l=c=>{let d=t[c],u=n[c];return Number.isFinite(u)?d>u?o:dNumber.isFinite(c)?l(d):null)},{key:"signal",title:"Signal",values:n,color:T(e,"signalColor",U)}],bands:[{key:"spread",from:"smi",to:"signal",color:z(a,75),colors:t.map((c,d)=>Number.isFinite(c)?z(l(d),75):null)}],levels:s}}},Xs=50,mC="Trigger Levels",$R={type:"schaff-trend-cycle",title:"Schaff Trend Cycle",shortTitle:"Schaff Trend Cycle",overlay:false,inputs:[le("Close","source","Source","Price series used to build the MACD that the trend cycle is measured on."),F(23,"fastLength","Fast Length",5e3,"Fast EMA length of the underlying MACD."),F(50,"slowLength","Slow Length",5e3,"Slow EMA length of the underlying MACD."),{...F(10,"cycleLength","Cycle Length",5e3,"Window of the two stochastic passes. Each pass measures where its input sits inside the range of its own values over this many bars."),min:2},Q("factor","Smoothing Factor",.5,.01,1,.05,"%D style recursive smoothing applied after each stochastic pass. 0.5 is the published default."),{...Q("upper","Upper Trigger",75,0,100,1,"Upper trigger line. A cross down through it flags an emerging downtrend."),group:mC},{...Q("lower","Lower Trigger",25,0,100,1,"Lower trigger line. A cross up through it flags an emerging uptrend."),group:mC},P(O,"Bullish Color","bullColor","Color of the trend cycle line and gradient while the cycle holds the upper half of its 0-100 scale."),P(D,"Bearish Color","bearColor","Color of the trend cycle line and gradient while the cycle holds the lower half of its 0-100 scale."),P(A,"Levels Color","levelsColor","Color of the dashed trigger lines and the dotted midline."),ne("gradientFill","Gradient Fill",true,xe,"Vertical gradient between the midline and the trend cycle, fading out toward the midline.")],compute:(r,e)=>{let t=R(e,"cycleLength",10),n=R(e,"factor",.5),o=oe(r,T(e,"source","Close")),i=we(q(o,R(e,"fastLength",23)),q(o,R(e,"slowLength",50))),s=m=>{let f=lt(m,t),g=at(m,t),b=new Array(m.length).fill(Number.NaN),y=Number.NaN;for(let w=0;wM&&(y=100*(C-M)/(S-M)),b[w]=y);}return b},a=m=>{let f=new Array(m.length).fill(Number.NaN),g=Number.NaN;for(let b=0;bNumber.isFinite(m)?m>Xs?d:u:null)}],p=[];return te(e,"gradientFill",true)&&(h.push(ct("midAnchor","Midline Anchor",l.length,Xs)),p.push({key:"wash",from:"stc",to:"midAnchor",color:z(A,100),gradient:Zr(l,Xs,m=>m>Xs?d:u)})),{plots:h,bands:p,levels:[{key:"upper",price:R(e,"upper",75),color:z(c,25),lineStyle:"dashed",title:"Upper Trigger"},{key:"lower",price:R(e,"lower",25),color:z(c,25),lineStyle:"dashed",title:"Lower Trigger"},{key:"midline",price:Xs,color:z(c,60),lineStyle:"dotted",title:"Midline"}]}}},UR={type:"know-sure-thing",title:"Know Sure Thing",shortTitle:"KST",overlay:false,inputs:[F(10,"rocLength1","ROC Length #1",5e3,"Lookback of the first (shortest) rate of change."),F(15,"rocLength2","ROC Length #2",5e3,"Lookback of the second rate of change."),F(20,"rocLength3","ROC Length #3",5e3,"Lookback of the third rate of change."),F(30,"rocLength4","ROC Length #4",5e3,"Lookback of the fourth (longest) rate of change."),F(10,"smaLength1","SMA Length #1",5e3,"Smoothing length applied to the first rate of change (RCMA #1)."),F(10,"smaLength2","SMA Length #2",5e3,"Smoothing length applied to the second rate of change (RCMA #2)."),F(10,"smaLength3","SMA Length #3",5e3,"Smoothing length applied to the third rate of change (RCMA #3)."),F(15,"smaLength4","SMA Length #4",5e3,"Smoothing length applied to the fourth rate of change (RCMA #4)."),F(9,"signalLength","Signal Length",500,"Simple moving average length of the signal line."),P(O,"Bullish","bullColor","Color of the KST line while above zero."),P(D,"Bearish","bearColor","Color of the KST line while below zero."),P(U,"Signal","signalColor","Color of the signal line.")],compute:(r,e)=>{let t=je(r),n=(s,a,l,c)=>Se(Xr(t,R(e,s,a)),R(e,l,c)),o=[n("rocLength1",10,"smaLength1",10),n("rocLength2",15,"smaLength2",10),n("rocLength3",20,"smaLength3",10),n("rocLength4",30,"smaLength4",15)].reduce((s,a,l)=>X(s,a,(c,d)=>c+d*(l+1)),new Array(t.length).fill(0)),i=T(e,"bullColor",O);return Ae({key:"kst",title:"KST",values:o,ink:{bull:i,bear:T(e,"bearColor",D),neutral:i},zeroInk:A,valueTransparency:60,extraPlots:[{key:"signal",title:"Signal",values:Se(o,R(e,"signalLength",9)),color:T(e,"signalColor",U)}]})}},YR={type:"coppock-curve",title:"Coppock Curve",shortTitle:"Coppock",overlay:false,inputs:[F(10,"wmaLength","WMA Length",5e3,"Length of the weighted moving average applied to the sum of the two rates of change."),F(14,"longRoc","Long RoC Length",5e3,"Lookback of the long rate of change, in bars. The original definition uses 14 monthly closes."),F(11,"shortRoc","Short RoC Length",5e3,"Lookback of the short rate of change, in bars. The original definition uses 11 monthly closes."),le("Close","source","Source","Price series used for the rate of change calculations."),P(A,"Coppock Curve","color","Color of the Coppock Curve line."),P(O,"Bullish","bullColor","Line and fill color while the curve reads above zero."),P(D,"Bearish","bearColor","Line and fill color while the curve reads below zero."),P(A,"Zero Line","zeroColor","Color of the zero reference line.")],compute:(r,e)=>{let t=oe(r,T(e,"source","Close")),n=$t(X(Xr(t,R(e,"longRoc",14)),Xr(t,R(e,"shortRoc",11)),(o,i)=>o+i),R(e,"wmaLength",10));return Ae({key:"coppock",title:"Coppock Curve",values:n,ink:{bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"color",A)},zeroInk:T(e,"zeroColor",A)})}},KR={type:"detrended-price-oscillator",title:"Detrended Price Oscillator",shortTitle:"DPO",overlay:false,inputs:[F(21,"length","Length",5e3,"Lookback of the simple moving average that price is detrended against. The comparison is displaced by Length / 2 + 1 bars."),le("Close","source","Source","Price series used in the detrending calculation."),ne("centered","Centered",false,void 0,"Shifts the oscillator back by Length / 2 + 1 bars so it is centered on the prices it detrends. The most recent bars then show no value."),P(A,"DPO","color","Color of the line when it sits exactly at zero."),P(O,"Above Zero","bullColor","Color of the line and fill while the oscillator is above zero."),P(D,"Below Zero","bearColor","Color of the line and fill while the oscillator is below zero."),P(A,"Zero Line","zeroColor","Color of the zero reference line.")],compute:(r,e)=>{let t=R(e,"length",21),n=Math.trunc(t/2)+1,o=oe(r,T(e,"source","Close")),i=Se(o,t),a=te(e,"centered",false)?Fe(we(Fe(o,n),i),-n):we(o,Fe(i,n));return Ae({key:"dpo",title:"DPO",values:a,ink:{bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"color",A)},zeroInk:T(e,"zeroColor",A)})}},sm="ROC %",fC="Momentum",XR={type:"rate-of-change",title:"Rate of Change",shortTitle:"ROC",overlay:false,inputs:[F(9,"length","Length",5e3,"Lookback period; the source is compared with its value this many bars ago."),le("Close","source","Source","Series used as input for the calculation."),Te("mode","Mode",sm,[sm,fC],"ROC % plots the change as a percentage of the source value from the lookback; Momentum plots the raw difference."),P(A,"Line","color","Color of the line when the reading sits exactly at zero."),P(O,"Bullish","bullColor","Color of the line and fill while the reading is above zero."),P(D,"Bearish","bearColor","Color of the line and fill while the reading is below zero."),ne("gradientFill","Gradient Fill",true,xe,"Fills the area between the line and zero, following the line color.")],compute:(r,e)=>{let t=R(e,"length",9),n=oe(r,T(e,"source","Close")),o=T(e,"mode",sm)===fC?st(n,t):Xr(n,t);return Ae({key:"roc",title:"ROC",values:o,ink:{bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"color",A)},zeroInk:A,fill:te(e,"gradientFill",true)})}},jR={type:"ultimate-oscillator",title:"Ultimate Oscillator",shortTitle:"UO",overlay:false,inputs:[F(7,"fastLength","Fast Length",5e3,"Bars in the fastest averaging window. Weighted 4 in the final blend, so it dominates the oscillator."),F(14,"middleLength","Middle Length",5e3,"Bars in the intermediate averaging window. Weighted 2 in the final blend."),F(28,"slowLength","Slow Length",5e3,"Bars in the slowest averaging window. Weighted 1 in the final blend."),...Qr(70,30,0,100,"Overbought","Oversold"),P(A,"Oscillator","color","Color of the line midway between the levels. Toward either level it blends into that level\u2019s color."),P(A,"Levels","levelsColor","Color of the overbought and oversold levels."),P(O,"Oversold","oversoldColor","Color of the line at the oversold level and of the oversold zone shading."),P(D,"Overbought","overboughtColor","Color of the line at the overbought level and of the overbought zone shading.")],compute:(r,e)=>{let t=r.length,n=new Array(t).fill(Number.NaN),o=new Array(t).fill(Number.NaN);for(let d=0;d0?r[d-1].close:u.close,p=Math.min(u.low,h);n[d]=u.close-p,o[d]=Math.max(u.high,h)-p;}let i=d=>X(ge(n,d),ge(o,d),(u,h)=>h===0?Number.NaN:u/h),s=i(R(e,"fastLength",7)),a=i(R(e,"middleLength",14)),l=i(R(e,"slowLength",28)),c=s.map((d,u)=>{let h=a[u],p=l[u];return Number.isFinite(d)&&Number.isFinite(h)&&Number.isFinite(p)?100*(4*d+2*h+p)/7:Number.NaN});return mn({key:"uo",title:"UO",values:c,scale:{top:100,bottom:0},overbought:R(e,"overbought",70),oversold:R(e,"oversold",30),ink:{low:T(e,"oversoldColor",O),mid:T(e,"color",A),high:T(e,"overboughtColor",D)},levelInk:T(e,"levelsColor",A),zoneTransparency:91})}},qR={type:"relative-vigor-index",title:"Relative Vigor Index",shortTitle:"RVGI",overlay:false,inputs:[F(10,"length","Length",5e3,"Number of bars summed for the smoothed numerator (close \u2212 open) and denominator (high \u2212 low)."),P(O,"RVGI","color","Color of the RVGI line."),P(D,"Signal","signalColor","Color of the signal line.")],compute:(r,e)=>{let t=R(e,"length",10),n=Od(we(je(r),Nx(r))),o=Od(we(et(r),tt(r))),i=X(ge(n,t),ge(o,t),(s,a)=>a===0?0:s/a);return {plots:[{key:"rvgi",title:"RVGI",values:i,color:T(e,"color",O)},{key:"signal",title:"Signal",values:Od(i),color:T(e,"signalColor",D)}],levels:[{key:"zero",price:0,color:z(A,50),lineStyle:"dashed",title:"Zero"}]}}},am="EMA",gC="Wilder (RMA)",ZR={type:"relative-volatility-index",title:"Relative Volatility Index",shortTitle:"RVI",overlay:false,inputs:[F(10,"stdevLength","Stdev Length",5e3,"Number of bars used for the standard deviation of closing prices that serves as each bar's volatility reading."),F(14,"smoothLength","Smoothing Length",5e3,"Number of bars used to smooth the up and down volatility streams."),Te("smoothType","Smoothing Type",am,[am,gC],"Moving average applied to the volatility streams. EMA is Dorsey's classic calculation; Wilder (RMA) matches platforms that use Wilder smoothing."),...Qr(80,20),P(A,"RVI Line","color","Color of the RVI line at the midline. Toward either threshold it blends into that threshold\u2019s color."),P(O,"Up Volatility","overboughtColor","Color of the line and zone shading at and above the overbought level."),P(D,"Down Volatility","oversoldColor","Color of the line and zone shading at and below the oversold level.")],compute:(r,e)=>{let t=je(r),n=It(t,R(e,"stdevLength",10)),o=st(t),i=X(n,o,(d,u)=>u>0?d:0),s=X(n,o,(d,u)=>u<0?d:0),a=R(e,"smoothLength",14),l=T(e,"smoothType",am)===gC?Ne:q,c=X(l(i,a),l(s,a),(d,u)=>d+u===0?0:100*d/(d+u));return mn({key:"rvi",title:"RVI",values:c,scale:{top:100,bottom:0},overbought:R(e,"overbought",80),oversold:R(e,"oversold",20),ink:{low:T(e,"oversoldColor",D),mid:T(e,"color",A),high:T(e,"overboughtColor",O)},levelInk:A,width:2})}},QR={type:"balance-of-power",title:"Balance of Power",shortTitle:"BOP",overlay:false,inputs:[ne("smoothing","Smoothing",false,void 0,"Smooth the raw Balance of Power with a simple moving average instead of plotting the single-bar value."),F(14,"smoothLength","Length",5e3,"Simple moving average length applied when smoothing is enabled."),P(A,"BOP Color","color","Color of the line at exactly zero."),P(O,"Bullish","bullColor","Line and fill color while the Balance of Power is above zero \u2014 buyers in control of the bar."),P(D,"Bearish","bearColor","Line and fill color while the Balance of Power is below zero \u2014 sellers in control of the bar.")],compute:(r,e)=>{let t=r.map(o=>o.high===o.low?0:(o.close-o.open)/(o.high-o.low)),n=te(e,"smoothing",false)?Se(t,R(e,"smoothLength",14)):t;return Ae({key:"bop",title:"BOP",values:n,ink:{bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"color",A)},zeroInk:A,valueTransparency:60})}},JR={type:"elder-ray",title:"Elder Ray",overlay:false,inputs:[F(13,"length","EMA Length",5e3,"Number of bars in the exponential moving average of closing prices used as the reference level for Bull Power and Bear Power. Alexander Elder's classic setting is 13."),P(O,"Bull Power","bullColor","Color of the Bull Power columns."),P(D,"Bear Power","bearColor","Color of the Bear Power columns.")],compute:(r,e)=>{let t=q(je(r),R(e,"length",13));return {plots:[{key:"bull",title:"Bull Power",values:we(et(r),t),kind:"columns",color:T(e,"bullColor",O),base:0},{key:"bear",title:"Bear Power",values:we(tt(r),t),kind:"columns",color:T(e,"bearColor",D),base:0}],levels:[{key:"zero",price:0,color:z(A,30),lineStyle:"dashed",title:"Zero Line"}]}}},eD={type:"ttm-squeeze",title:"TTM Squeeze",overlay:false,inputs:[{...F(20,"length","Length",5e3,"Shared lookback for the Bollinger Bands, the Keltner Channels, and the momentum regression. John Carter's original setting is 20."),min:2},le("Close","source","Source","Price series used for the shared moving average basis, the standard deviation, and the momentum displacement."),Q("bbMult","Bollinger Bands Multiplier",2,.1,50,.1,"Standard deviation multiplier for the Bollinger Bands."),Q("kcMult","Keltner Channels Multiplier",1.5,.1,50,.1,"ATR multiplier for the Keltner Channels. A smaller multiplier demands a tighter compression before the squeeze turns on."),P(O,"Momentum Up","bullColor","Histogram color while momentum is positive. Bars building away from zero print solid, bars fading back print dimmed."),P(D,"Momentum Down","bearColor","Histogram color while momentum is negative. Bars building away from zero print solid, bars fading back print dimmed."),P(U,"Squeeze On","squeezeOnColor","Zero-line dot color while both Bollinger Bands sit fully inside the Keltner Channels."),P(A,"Squeeze Off","squeezeOffColor","Zero-line dot color while the Bollinger Bands trade outside the Keltner Channels."),ne("markFires","Mark Squeeze Fires",true,xe,"Draws a cross on the zero line on the first bar where the bands re-emerge outside the channels, colored by the side of the momentum histogram.")],compute:(r,e)=>{let t=R(e,"length",20),n=oe(r,T(e,"source","Close")),o=Se(n,t),i=re(It(n,t),b=>b*R(e,"bbMult",2)),s=re(Nn(r,t),b=>b*R(e,"kcMult",1.5)),a=X(at(et(r),t),lt(tt(r),t),(b,y)=>(b+y)/2),l=X(a,o,(b,y)=>(b+y)/2),c=ni(we(n,l),t,0),d=o.map((b,y)=>{let w=i[y],C=s[y];return !Number.isFinite(b)||!Number.isFinite(w)||!Number.isFinite(C)?null:w{if(!Number.isFinite(b))return null;let w=y>0&&Number.isFinite(c[y-1])?c[y-1]:b,C=b>w;return b>=0?C?u:z(u,60):C?z(h,60):h}),g=[{key:"mom",title:"Momentum",values:c,kind:"columns",color:u,colors:f,base:0},{key:"state",title:"Squeeze State",values:d.map(b=>b==null?Number.NaN:0),kind:"circles",color:m,width:2,colors:d.map(b=>b==null?null:b?p:m)}];if(te(e,"markFires",true)){let b=d.map((y,w)=>y===false&&d[w-1]===true?0:Number.NaN);g.push({key:"fire",title:"Squeeze Fire",values:b,kind:"cross",color:m,width:3,colors:b.map((y,w)=>Number.isFinite(y)?Number.isFinite(c[w])?c[w]>=0?u:h:m:null)});}return {plots:g}}},yC=[PR,IR,AR,RR,DR,OR,FR,VR,BR,_R,HR,zR,WR,GR,$R,UR,YR,KR,XR,jR,qR,ZR,QR,JR,eD];var tD={type:"aroon",title:"Aroon",overlay:false,inputs:[F(14,"length","Length",5e3,"Lookback length used to locate the highest high and lowest low."),P(O,"Aroon Up","upColor","Color of the Aroon Up line."),P(D,"Aroon Down","downColor","Color of the Aroon Down line.")],compute:(r,e)=>{let t=R(e,"length",14),n=re(Bx(et(r),t),i=>100*(t-i)/t),o=re(_x(tt(r),t),i=>100*(t-i)/t);return {plots:[{key:"up",title:"Aroon Up",values:n,color:T(e,"upColor",O)},{key:"down",title:"Aroon Down",values:o,color:T(e,"downColor",D)}]}}},nD={type:"average-directional-index",title:"Average Directional Index",shortTitle:"ADX",overlay:false,inputs:[F(14,"diLength","DI Length",5e3,"Wilder RMA smoothing length applied to directional movement and true range when computing +DI and \u2212DI."),F(14,"adxLength","ADX Smoothing",5e3,"Wilder RMA smoothing length applied to DX to obtain the ADX line."),Q("keyLevel","Key Level",25,0,100,1,"Trend strength reference level; ADX above it is commonly read as a trending market."),P(O,"+DI Color","plusDiColor","Color of the plus directional indicator, and of the ADX line above the key level while +DI leads."),P(D,"-DI Color","minusDiColor","Color of the minus directional indicator, and of the ADX line above the key level while \u2212DI leads."),P(A,"ADX Color","adxColor","Color of the ADX line while it sits below the key level \u2014 no trend strong enough to trade.")],compute:(r,e)=>{let t=R(e,"diLength",14),n=r.length,o=new Array(n).fill(Number.NaN),i=new Array(n).fill(Number.NaN);for(let g=1;gy&&b>0?b:0,i[g]=y>b&&y>0?y:0;}let s=Ne(jr(r),t),a=X(Ne(o,t),s,(g,b)=>b===0?0:100*g/b),l=X(Ne(i,t),s,(g,b)=>b===0?0:100*g/b),c=X(a,l,(g,b)=>g+b===0?0:100*Math.abs(g-b)/(g+b)),d=Ne(c,R(e,"adxLength",14)),u=T(e,"plusDiColor",O),h=T(e,"minusDiColor",D),p=T(e,"adxColor",A),m=R(e,"keyLevel",25),f=d.map((g,b)=>Number.isFinite(g)?g<=m?p:(a[b]??0)>(l[b]??0)?u:h:null);return {plots:[{key:"plusDi",title:"+DI",values:a,color:z(u,30)},{key:"minusDi",title:"-DI",values:l,color:z(h,30)},{key:"adx",title:"ADX",values:d,color:p,width:2,colors:f}],levels:[{key:"keyLevel",price:m,color:A,lineStyle:"dashed",title:"Key Level"}]}}},rD={type:"vortex-indicator",title:"Vortex Indicator",shortTitle:"VI",overlay:false,inputs:[F(14,"length","Length",5e3,"Number of bars used to sum the vortex movements (VM+ and VM\u2212) and the true range."),P(O,"VI+","plusColor","Color of the positive vortex line (VI+)."),P(D,"VI-","minusColor","Color of the negative vortex line (VI\u2212)."),P(A,"Baseline","baselineColor","Color of the dotted baseline drawn at 1.")],compute:(r,e)=>{let t=R(e,"length",14),n=r.length,o=new Array(n).fill(Number.NaN),i=new Array(n).fill(Number.NaN);for(let a=1;al===0?Number.NaN:a/l),color:T(e,"plusColor",O)},{key:"viMinus",title:"VI-",values:X(ge(i,t),s,(a,l)=>l===0?Number.NaN:a/l),color:T(e,"minusColor",D)}],levels:[{key:"baseline",price:1,color:T(e,"baselineColor",A),lineStyle:"dotted",title:"Baseline"}]}}},wC=[tD,nD,rD];function xC(r,e,t){return r.map((n,o)=>{if(!Number.isFinite(n))return null;let i=o>0&&Number.isFinite(r[o-1])?r[o-1]:n;return n>i?t:e})}function lm(r,e,t,n,o,i,s=1){return {plots:[{key:r,title:e,values:t,color:o,width:s,colors:n},ct("zeroAnchor","Zero Anchor",t.length,0)],bands:[{key:"wash",from:r,to:"zeroAnchor",color:z(A,100),gradient:Zr(t,0,(a,l)=>n[l]??o,i)}]}}var oD={type:"average-true-range",title:"Average True Range",shortTitle:"ATR",overlay:false,inputs:[F(14,"length","Length",5e3,"Number of bars used to average the true range."),Te("smoothing","Smoothing","RMA",["RMA","SMA","EMA","WMA"],"Moving average applied to the true range. RMA is Wilder's original smoothing used by the classic ATR."),P(A,"ATR Line","color","Color of the ATR line while volatility contracts or holds flat."),P(U,"Expanding","expandColor","Color of the ATR line while it rises \u2014 volatility expanding bar to bar.")],compute:(r,e)=>{let t=R(e,"length",14),n=jr(r),o=T(e,"smoothing","RMA"),i=o==="SMA"?Se(n,t):o==="EMA"?q(n,t):o==="WMA"?$t(n,t):Ne(n,t),s=T(e,"color",A);return lm("atr","ATR",i,xC(i,s,T(e,"expandColor",U)),s,75)}},iD={type:"historical-volatility",title:"Historical Volatility",shortTitle:"HV",overlay:false,inputs:[{...F(10,"length","Length",5e3,"Lookback window in bars for the standard deviation of close-to-close log returns."),min:2},ne("annualize","Annualize",true,void 0,"Scale the per-bar volatility to an annual figure by multiplying by the square root of the periods per year."),pe("periodsPerYear","Periods Per Year",252,1,1e5,"Number of periods in a year used for annualization: 252 for daily bars, 52 for weekly, 12 for monthly."),P(U,"Volatility Line","color","Color of the line at its recent highs; it fades toward grey as volatility contracts.")],compute:(r,e)=>{let t=R(e,"length",10),n=we(re(je(r),Math.log),Fe(re(je(r),Math.log),1)),o=re(ge(n,t),h=>h/t),i=ge(re(n,h=>h*h),t),s=te(e,"annualize",true)?Math.sqrt(R(e,"periodsPerYear",252)):1,a=X(i,o,(h,p)=>Math.sqrt(Math.max(h-t*p*p,0)/(t-1))*s*100),l=lt(a,100),c=at(a,100),d=T(e,"color",U),u=a.map((h,p)=>Number.isFinite(h)?qr(h,l[p]??0,c[p]??0,A,d):null);return lm("hv","Historical Volatility",a,u,d,75,2)}},sD={type:"chaikin-volatility",title:"Chaikin Volatility",shortTitle:"CHV",overlay:false,inputs:[F(10,"emaLength","EMA Length",5e3,"Length of the exponential moving average applied to the bar high-low range."),F(10,"rocLength","ROC Length",5e3,"Number of bars used for the rate of change of the smoothed high-low range."),P(A,"CHV Color","color","Color of the Chaikin Volatility line."),P(U,"Expansion","expansionColor","Line and fill color while the reading is above zero \u2014 the smoothed range is wider than it was ROC Length bars ago.")],compute:(r,e)=>{let t=q(we(et(r),tt(r)),R(e,"emaLength",10)),n=Fe(t,R(e,"rocLength",10)),o=X(t,n,(a,l)=>l===0?Number.NaN:100*(a-l)/l),i=T(e,"color",A),s=T(e,"expansionColor",U);return Ae({key:"chv",title:"Chaikin Volatility",values:o,ink:{bull:s,bear:i,neutral:i},zeroInk:A})}},aD={type:"mass-index",title:"Mass Index",shortTitle:"MI",overlay:false,inputs:[F(25,"length","Sum Length",5e3,"Number of bars over which the single/double EMA ratio is summed."),F(9,"emaLength","EMA Length",5e3,"Length of the single EMA of the high-low range and of its double smoothing."),Q("setupLevel","Setup Level",27,0,1e3,.1,"Reversal bulge set-up level; a rise above it arms the pattern."),Q("triggerLevel","Trigger Level",26.5,0,1e3,.1,"Reversal bulge trigger level; a decline below it after a set-up completes the pattern."),P(A,"Mass Index","color","Line color while no reversal bulge is armed."),P(U,"Armed","armedColor","Line color from the rise above the setup level until the decline below the trigger level."),P(A,"Levels","levelsColor","Reversal bulge levels color.")],compute:(r,e)=>{let t=R(e,"emaLength",9),n=q(we(et(r),tt(r)),t),o=X(n,q(n,t),(p,m)=>m===0?1:p/m),i=ge(o,R(e,"length",25)),s=R(e,"setupLevel",27),a=R(e,"triggerLevel",26.5),l=T(e,"color",A),c=T(e,"armedColor",U),d=T(e,"levelsColor",A),u=false,h=i.map(p=>Number.isFinite(p)?(u=p>s?true:p{let t=It(oe(r,T(e,"source","Close")),R(e,"length",20)),n=T(e,"color",A);return lm("stdev","Standard Deviation",t,xC(t,n,T(e,"expandColor",U)),n,80)}},cD={type:"ulcer-index",title:"Ulcer Index",overlay:false,inputs:[{...F(14,"length","Length",500,"Lookback window. At each bar the percentage drawdown from the window's running maximum is squared; the squares are averaged and the root taken."),min:2},le("Close","source","Source","Price series the Ulcer Index is computed on. Close is the standard choice."),Q("threshold","Alert Threshold",5,0,1e3,.25,"Reference level drawn as a dashed line. The index scales with the instrument's volatility and the window length, so set it relative to its own history."),P(A,"Ulcer Index","color","Color of the index near zero; it blends toward the stress color as the reading approaches the threshold."),P(D,"Stress","stressColor","Color of the index at and beyond the alert threshold."),ne("gradientFill","Gradient Fill",true,xe,"Vertical gradient between zero and the Ulcer Index, fully transparent at zero."),ne("showDrawdown","Drawdown %",false,xe,"Plot the current percentage drawdown from the window high as columns below zero \u2014 the raw ingredient the index averages."),P(z(D,50),"Drawdown Color","drawdownColor","Color of the drawdown columns."),P(A,"Threshold","thresholdColor","Color of the alert threshold line.")],compute:(r,e)=>{let t=R(e,"length",14),n=oe(r,T(e,"source","Close")),o=n.length,i=new Array(o).fill(Number.NaN),s=new Array(o).fill(Number.NaN);for(let p=t-1;pNumber.isFinite(p)?c>0?qr(p,0,c,a,l):l:null),u=[{key:"ui",title:"Ulcer Index",values:i,color:a,colors:d}],h=[];return te(e,"gradientFill",true)&&(u.push(ct("zeroAnchor","Zero Base",o,0)),h.push({key:"wash",from:"ui",to:"zeroAnchor",color:z(A,100),gradient:Zr(i,0,(p,m)=>d[m]??a)})),te(e,"showDrawdown",false)&&u.push({key:"dd",title:"Drawdown %",values:s,kind:"columns",color:T(e,"drawdownColor",z(D,50)),base:0}),{plots:u,bands:h,levels:[{key:"zero",price:0,color:z(A,50),lineStyle:"dotted",title:"Zero Level"},{key:"threshold",price:c,color:T(e,"thresholdColor",A),lineStyle:"dashed",title:"Alert Threshold"}]}}},dD={type:"choppiness-index",title:"Choppiness Index",shortTitle:"CHOP",overlay:false,inputs:[{...F(14,"length","Length",5e3,"Number of bars used to sum true ranges and to measure the highest high \u2212 lowest low range."),min:2},Q("upperBand","Upper Band",61.8,0,100,.1,"Readings above this level indicate a choppy, range-bound market."),Q("lowerBand","Lower Band",38.2,0,100,.1,"Readings below this level indicate a strong trend."),P(A,"CHOP Line","color","Color of the Choppiness Index line."),P(O,"Trending","trendingColor","Line, fill and zone color toward and below the lower band \u2014 a trending market."),P(D,"Choppy","choppyColor","Line, fill and zone color toward and above the upper band \u2014 a choppy, range-bound market."),P(z(A,90),"Band Fill","fillColor","Fill color of the zone between the upper and lower bands.")],compute:(r,e)=>{let t=R(e,"length",14),n=ge(jr(r),t),o=X(at(et(r),t),lt(tt(r),t),(s,a)=>s-a),i=X(n,o,(s,a)=>a>0&&s>0?100*Math.log10(s/a)/Math.log10(t):Number.NaN);return mn({key:"chop",title:"CHOP",values:i,scale:{top:100,bottom:0},overbought:R(e,"upperBand",61.8),oversold:R(e,"lowerBand",38.2),ink:{low:T(e,"trendingColor",O),mid:T(e,"color",A),high:T(e,"choppyColor",D)},levelInk:A,bandFill:T(e,"fillColor",z(A,90)),midpointWash:true,levelTitles:{overbought:"Upper Band",oversold:"Lower Band"}})}},CC=[oD,iD,sD,aD,lD,cD,dD];function Vd(r){return r.map(e=>e.volume==null||!Number.isFinite(e.volume)?Number.NaN:e.high===e.low?0:(2*e.close-e.high-e.low)/(e.high-e.low)*e.volume)}function hm(r,e,t,n){return r.map((o,i)=>{if(!Number.isFinite(o))return null;let s=i>0?r[i-1]:Number.NaN;return Number.isFinite(s)?o>s?e:o0?r[s-1].volume:null,c=s>0?e[s-1]:Number.NaN;a!=null&&l!=null&&Number.isFinite(a)&&Number.isFinite(l)&&n(a,l)&&Number.isFinite(c)&&c!==0&&(i*=1+(e[s]-c)/c),o[s]=i;}return o}function LC(r,e,t,n,o,i,s,a=false){let l=u=>{let h=n[u],p=t[u];return a||!Number.isFinite(h)?o.neutral:p>h?o.bull:pNumber.isFinite(u)?l(h):null)}],d=s?[{key:"regime",from:r,to:"signal",color:z(A,100),gradient:t.map((u,h)=>{let p=n[h];if(!Number.isFinite(u)||!Number.isFinite(p))return null;let m=u>p,f=m?o.bull:o.bear;return {topValue:Math.max(u,p),bottomValue:Math.min(u,p),topColor:z(f,m?50:100),bottomColor:z(f,m?100:50)}})}]:[];return {plots:c,bands:d}}var uD={type:"on-balance-volume",title:"On Balance Volume",shortTitle:"OBV",overlay:false,inputs:[ne("smoothing","Smoothing MA",false,ze,"Display a moving average of OBV to act as a smoothing/signal line."),Te("maType","MA Type","SMA",["SMA","EMA","WMA","RMA (SMMA)"],"Moving average type used for the smoothing MA."),F(20,"maLength","MA Length",5e3,"Number of bars used for the smoothing MA."),P(ce,"OBV","color","Color of the OBV line."),P(U,"Smoothing MA","maColor","Color of the smoothing MA line.")],compute:(r,e)=>{let t=Ut(r),n=st(je(r)),o=ri(X(t,n,(s,a)=>a>0?s:a<0?-s:0)),i=[{key:"obv",title:"OBV",values:o,color:T(e,"color",ce)}];if(te(e,"smoothing",false)){let s=R(e,"maLength",20),a=T(e,"maType","SMA"),l=a==="EMA"?q(o,s):a==="WMA"?$t(o,s):a==="RMA (SMMA)"?Ne(o,s):Se(o,s);i.push({key:"ma",title:"Smoothing MA",values:l,color:T(e,"maColor",U)});}return {plots:i}}},hD={type:"accumulation-distribution",title:"Accumulation / Distribution",shortTitle:"A/D",overlay:false,inputs:[ne("slopeColoring","Slope Coloring",true,xe,"Color the line by its slope \u2014 bullish while rising (accumulation), bearish while falling (distribution)."),P(A,"A/D Line","color","Color of the line when slope coloring is disabled or the line is flat."),P(O,"Rising","bullColor","Line color while the A/D Line rises."),P(D,"Falling","bearColor","Line color while the A/D Line falls.")],compute:(r,e)=>{let t=ri(Vd(r)),n=T(e,"color",A);return {plots:[{key:"ad",title:"A/D",values:t,color:n,...te(e,"slopeColoring",true)?{colors:hm(t,T(e,"bullColor",O),T(e,"bearColor",D),n)}:{}}]}}},pD={type:"chaikin-money-flow",title:"Chaikin Money Flow",shortTitle:"CMF",overlay:false,inputs:[F(20,"length","Length",5e3,"Lookback length over which money flow volume and volume are summed."),P(A,"CMF Line","color","Color of the Chaikin Money Flow line."),P(O,"Bullish","bullColor","Line and fill color while the CMF reads above zero (net money flowing in)."),P(D,"Bearish","bearColor","Line and fill color while the CMF reads below zero (net money flowing out)."),P(A,"Zero Line","zeroColor","Color of the zero reference line.")],compute:(r,e)=>{let t=R(e,"length",20),n=X(ge(Vd(r),t),ge(Ut(r),t),(o,i)=>i===0?0:o/i);return Ae({key:"cmf",title:"CMF",values:n,ink:{bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"color",A)},zeroInk:T(e,"zeroColor",A)})}},mD={type:"chaikin-oscillator",title:"Chaikin Oscillator",shortTitle:"Chaikin Osc",overlay:false,inputs:[F(3,"fastLength","Fast Length",5e3,"Length of the fast EMA applied to the accumulation/distribution line."),F(10,"slowLength","Slow Length",5e3,"Length of the slow EMA applied to the accumulation/distribution line."),P(A,"Oscillator","color","Color of the Chaikin Oscillator line."),P(O,"Bullish","bullColor","Line and fill color while the oscillator reads above zero (accumulation)."),P(D,"Bearish","bearColor","Line and fill color while the oscillator reads below zero (distribution).")],compute:(r,e)=>{let t=ri(Vd(r)),n=we(q(t,R(e,"fastLength",3)),q(t,R(e,"slowLength",10)));return Ae({key:"co",title:"Chaikin Oscillator",values:n,ink:{bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"color",A)},zeroInk:A})}},fD={type:"ease-of-movement",title:"Ease of Movement",shortTitle:"EOM",overlay:false,inputs:[F(14,"length","Length",5e3,"Number of bars in the simple moving average smoothing the 1-bar Ease of Movement values."),pe("divisor","Divisor",1e4,1,1e9,"Volume scaling constant of the box ratio; larger values scale the oscillator up. 10000 is the conventional default."),P(A,"EOM Line","color","Color of the line when it sits exactly at zero."),P(O,"Above Zero","bullColor","Color of the line and fill while Ease of Movement is positive."),P(D,"Below Zero","bearColor","Color of the line and fill while Ease of Movement is negative.")],compute:(r,e)=>{let t=R(e,"divisor",1e4),n=st(oe(r,"HL2")),o=r.map((i,s)=>{let a=n[s];return i.volume==null||!Number.isFinite(i.volume)||!Number.isFinite(a)?Number.NaN:i.volume===0?0:t*a*(i.high-i.low)/i.volume});return Ae({key:"eom",title:"EOM",values:Se(o,R(e,"length",14)),ink:{bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"color",A)},zeroInk:A})}},gD={type:"force-index",title:"Force Index",shortTitle:"FI",overlay:false,inputs:[F(13,"length","Length",5e3,"EMA length applied to the raw 1-bar force index, (close \u2212 close[1]) \xD7 volume. Elder used 13 for the intermediate trend and 2 for short-term timing."),P(O,"Force Index","color","Color of the line while above zero (buying pressure)."),P(D,"Bearish","bearColor","Color of the line while below zero (selling pressure).")],compute:(r,e)=>{let t=X(st(je(r)),Ut(r),(o,i)=>o*i),n=T(e,"color",O);return Ae({key:"force",title:"Force Index",values:q(t,R(e,"length",13)),ink:{bull:n,bear:T(e,"bearColor",D),neutral:n},zeroInk:A,width:2,valueTransparency:60})}},bD={type:"klinger-oscillator",title:"Klinger Oscillator",shortTitle:"KVO",overlay:false,inputs:[F(34,"fastLength","Fast Length",5e3,"Length of the fast EMA applied to the volume force."),F(55,"slowLength","Slow Length",5e3,"Length of the slow EMA applied to the volume force."),F(13,"signalLength","Signal Length",500,"Length of the EMA applied to the oscillator to obtain the signal line."),P(O,"Bullish","color","Color of the Klinger oscillator while above zero."),P(D,"Bearish","bearColor","Color of the Klinger oscillator while below zero."),P(U,"Signal","signalColor","Color of the signal line.")],compute:(r,e)=>{let t=r.length,n=new Array(t).fill(Number.NaN),o=1,i=1,s=0,a=0;for(let d=0;d0?r[d-1].high+r[d-1].low+r[d-1].close:h;o=h>p?1:-1;let m=u.high-u.low;s=d>0&&o===i?s+m:a+m;let f=u.volume;n[d]=f==null||!Number.isFinite(f)?Number.NaN:s===0?0:f*Math.abs(2*(m/s)-1)*o*100,i=o,a=m;}let l=we(q(n,R(e,"fastLength",34)),q(n,R(e,"slowLength",55))),c=T(e,"color",O);return Ae({key:"kvo",title:"KVO",values:l,ink:{bull:c,bear:T(e,"bearColor",D),neutral:c},zeroInk:z(A,50),valueTransparency:60,extraPlots:[{key:"signal",title:"Signal",values:q(l,R(e,"signalLength",13)),color:T(e,"signalColor",U)}]})}},vD={type:"money-flow-index",title:"Money Flow Index",shortTitle:"MFI",overlay:false,inputs:[F(14,"length","Length",5e3,"Number of bars used to sum positive and negative money flow."),Q("overbought","Overbought Level",80,0,100,1,"Level above which the MFI is considered overbought."),Q("oversold","Oversold Level",20,0,100,1,"Level below which the MFI is considered oversold."),P(A,"MFI","color","Color of the MFI line between the levels. Toward either level it blends into that level\u2019s color."),P(D,"Overbought","overboughtColor","Color of the line and zone shading at and above the overbought level."),P(O,"Oversold","oversoldColor","Color of the line and zone shading at and below the oversold level."),P(z(A,94),"OB/OS Zone Fill","fillColor","Fill color of the area between the overbought and oversold levels.")],compute:(r,e)=>{let t=R(e,"length",14),n=oe(r,"HLC3"),o=X(n,Ut(r),(c,d)=>c*d),i=st(n),s=ge(X(o,i,(c,d)=>d>0?c:0),t),a=ge(X(o,i,(c,d)=>d<0?c:0),t),l=X(s,a,(c,d)=>c+d>0?100*c/(c+d):Number.NaN);return mn({key:"mfi",title:"MFI",values:l,scale:{top:100,bottom:0},overbought:R(e,"overbought",80),oversold:R(e,"oversold",20),ink:{low:T(e,"oversoldColor",O),mid:T(e,"color",A),high:T(e,"overboughtColor",D)},levelInk:A,zoneTransparency:91,bandFill:T(e,"fillColor",z(A,94))})}};function MC(r){return [P(O,"Bullish","bullColor","Color of the line and gradient fill while it holds above its signal EMA."),P(D,"Bearish","bearColor","Color of the line and gradient fill while it holds below its signal EMA."),P(A,"Neutral","neutralColor","Color used while the signal EMA is still forming, or the line sits exactly on it."),P(A,r,"signalColor","Color of the signal EMA overlay."),ne("gradientFill","Gradient Fill",true,xe,"Fills the gap between the line and its signal EMA with a vertical gradient \u2014 transparent at the average, strongest at the line.")]}var cm="Position vs Average",SC="Single Color",yD={type:"negative-volume-index",title:"Negative Volume Index",shortTitle:"Negative Volume Index",overlay:false,inputs:[Q("base","Base Level",1e3,.01,1e6,1,"Arbitrary seed of the cumulative line, conventionally 1000. The absolute level carries no information \u2014 the line is read by slope and by position against the signal EMA."),ne("showSignal","Signal EMA",true,ze,"Displays the conventional signal overlay. Hiding it only removes the plotted average; the regime coloring and fill still use it."),F(255,"signalLength","Signal Length",5e3,"Length of the signal EMA. The convention is one trading year \u2014 255 sessions on daily charts."),Te("colorMode","Line Coloring",cm,[cm,SC],"'Position vs Average' colors the line by the classic regime read; 'Single Color' draws the whole line in the neutral color."),...MC("Signal EMA")],compute:(r,e)=>{let t=kC(r,je(r),R(e,"base",1e3),(o,i)=>o{let t=oe(r,T(e,"source","Close")),n=kC(r,t,R(e,"base",1e3),(i,s)=>i>s),o=q(n,R(e,"signalLength",255));return LC("pvi","PVI",n,o,{bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"neutralColor",A),signal:T(e,"signalColor",A)},te(e,"showSignal",true),te(e,"gradientFill",true))}},xD={type:"price-volume-trend",title:"Price Volume Trend",shortTitle:"PVT",overlay:false,inputs:[ne("showSignal","Signal Line",false,ze,"Display a moving average of PVT acting as a signal line."),Te("signalType","Signal Type","SMA",["SMA","EMA"],"Moving average type used for the signal line."),F(21,"signalLength","Signal Length",5e3,"Number of bars used to compute the signal line."),P(A,"PVT Color","color","Color of the PVT line while it is flat."),P(O,"Rising","bullColor","Color of the PVT line while it rises bar to bar."),P(D,"Falling","bearColor","Color of the PVT line while it falls bar to bar."),P(U,"Signal Color","signalColor","Color of the signal line.")],compute:(r,e)=>{let t=je(r),n=r.map((a,l)=>{if(l===0||a.volume==null||!Number.isFinite(a.volume))return Number.NaN;let c=t[l-1];return c===0?0:(t[l]-c)/c*a.volume}),o=ri(n),i=T(e,"color",A),s=[{key:"pvt",title:"PVT",values:o,color:i,width:2,colors:hm(o,T(e,"bullColor",O),T(e,"bearColor",D),i)}];if(te(e,"showSignal",false)){let a=R(e,"signalLength",21),l=T(e,"signalType","SMA")==="EMA"?q(o,a):Se(o,a);s.push({key:"signal",title:"Signal",values:l,color:T(e,"signalColor",U)});}return {plots:s}}},CD={type:"volume-oscillator",title:"Volume Oscillator",shortTitle:"Vol Osc",overlay:false,inputs:[F(5,"fastLength","Fast Length",5e3,"Length of the fast EMA of volume."),F(10,"slowLength","Slow Length",5e3,"Length of the slow EMA of volume."),P(O,"Above Zero","color","Color of the line and fill while it holds above zero \u2014 volume expanding."),P(D,"Below Zero","bearColor","Color of the line and fill while it holds below zero \u2014 volume contracting.")],compute:(r,e)=>{let t=Ut(r),n=q(t,R(e,"fastLength",5)),o=q(t,R(e,"slowLength",10)),i=X(n,o,(a,l)=>l===0?0:100*(a-l)/l),s=T(e,"color",O);return Ae({key:"vo",title:"Volume Oscillator",values:i,ink:{bull:s,bear:T(e,"bearColor",D),neutral:s},zeroInk:A,valueTransparency:60})}},dm="Oscillator",SD={type:"pvo",title:"Percentage Volume Oscillator",shortTitle:"PVO",overlay:false,inputs:[{...F(12,"fastLength","Fast Length",5e3,"Period of the fast EMA of volume. The conventional setting is 12."),group:dm},{...F(26,"slowLength","Slow Length",5e3,"Period of the slow EMA of volume. The PVO expresses the fast/slow spread as a percentage of this slow average."),group:dm},{...F(9,"signalLength","Signal Length",500,"Period of the EMA applied to the PVO to form the signal line."),group:dm},P(O,"Expansion Color","color","Color of the oscillator and fill while participation expands."),P(D,"Contraction Color","bearColor","Color of the oscillator and fill while participation contracts."),P(U,"Signal Line","signalColor","Color of the signal line."),P(z(A,50),"Zero Line","zeroColor","Color of the zero reference line."),ne("showSignal","Show Signal Line",true,xe,"Plot the signal line, an EMA of the PVO."),ne("showHistogram","Show Histogram",true,xe,"Plot the difference between the PVO and its signal line as columns behind the oscillator.")],compute:(r,e)=>{let t=Ut(r),n=q(t,R(e,"fastLength",12)),o=q(t,R(e,"slowLength",26)),i=X(n,o,(d,u)=>u>0?100*(d-u)/u:Number.NaN),s=q(i,R(e,"signalLength",9)),a=T(e,"color",O),l=T(e,"bearColor",D),c=[];if(te(e,"showHistogram",true)){let d=we(i,s);c.push({key:"hist",title:"Histogram",values:d,kind:"columns",color:z(a,60),colors:d.map(u=>Number.isFinite(u)?z(u>0?a:l,60):null),base:0});}return te(e,"showSignal",true)&&c.push({key:"signal",title:"Signal",values:s,color:T(e,"signalColor",U)}),Ae({key:"pvo",title:"PVO",values:i,ink:{bull:a,bear:l,neutral:l},zeroInk:T(e,"zeroColor",z(A,50)),extraPlots:c})}},TD={type:"volume-flow-indicator",title:"Volume Flow Indicator",shortTitle:"Volume Flow Indicator",overlay:false,inputs:[{...F(130,"length","Length",5e3,"Rolling summation window, also used for the average volume that scales the result. The published default of 130 bars targets position-horizon work on daily charts."),min:2},Q("coef","Cutoff Coefficient",.2,0,10,.05,"Scales the volatility-based minimum change in typical price. Moves smaller than the cutoff count as noise and contribute no volume."),Q("volCoef","Volume Cap Multiplier",2.5,.1,50,.1,"Caps each bar's volume contribution at this multiple of the average volume, so a single climactic print stays bounded."),{...F(30,"volLength","Volatility Length",5e3,"Window of the standard deviation of the log change in typical price used to build the adaptive cutoff."),min:2},ne("smooth","Smooth VFI",true,ze,"Applies the published light smoothing \u2014 an EMA of the summed line \u2014 before plotting."),F(3,"smoothLength","Smoothing Length",500,"Length of the smoothing EMA. The published version uses 3 bars."),ne("showSignal","Signal Line",true,ze,"Plots an EMA of VFI as a signal line."),F(5,"signalLength","Signal Length",500,"Length of the signal-line EMA."),P(O,"Bullish","color","Color of the VFI line and gradient fill above the zero line \u2014 the net accumulation regime."),P(D,"Bearish","bearColor","Color of the VFI line and gradient fill below the zero line \u2014 the net distribution regime."),P(U,"Signal Line","signalColor","Color of the signal line."),ne("gradientFill","Gradient Fill",true,xe,"Fills the area between the zero line and the VFI line with a vertical gradient.")],compute:(r,e)=>{let t=R(e,"length",130),n=oe(r,"HLC3"),o=we(re(n,Math.log),Fe(re(n,Math.log),1)),i=It(o,R(e,"volLength",30)),s=R(e,"coef",.2),a=R(e,"volCoef",2.5),l=Ut(r),c=Fe(Se(l,t),1),d=st(n),u=r.map((g,b)=>{let y=i[b],w=d[b],C=l[b];if(!Number.isFinite(y)||!Number.isFinite(w)||!Number.isFinite(C))return Number.NaN;let M=s*y*g.close,S=c[b],L=Number.isFinite(S)?Math.min(C,S*a):C;return w>M?L:w<-M?-L:0}),h=X(ge(u,t),c,(g,b)=>b>0?g/b:Number.NaN),p=te(e,"smooth",true)?q(h,R(e,"smoothLength",3)):h,m=T(e,"color",O),f=te(e,"showSignal",true)?[{key:"signal",title:"Signal Line",values:q(p,R(e,"signalLength",5)),color:T(e,"signalColor",U)}]:[];return Ae({key:"vfi",title:"VFI",values:p,ink:{bull:m,bear:T(e,"bearColor",D),neutral:T(e,"bearColor",D)},zeroInk:z(A,90),fill:te(e,"gradientFill",true),extraPlots:f})}},um="Normalized Oscillator (II%)",TC="Cumulative Line",kD={type:"intraday-intensity",title:"Intraday Intensity",shortTitle:"Intraday Intensity",overlay:false,inputs:[Te("mode","Display",um,[um,TC],"The two published forms. The cumulative line is open-ended and read by slope against price; the normalized oscillator divides a rolling sum of intensity by the rolling sum of volume and oscillates around zero."),F(21,"length","Oscillator Length",5e3,"Window of the rolling sums in the normalized form. The common setting is 21 bars. It has no effect on the cumulative line."),P(O,"Bullish","color","Color of positive readings, the rising cumulative line and the fill above zero \u2014 the accumulation side."),P(D,"Bearish","bearColor","Color of negative readings, the falling cumulative line and the fill below zero \u2014 the distribution side."),ne("gradientFill","Gradient Fill",true,xe,"Fills the area between the zero line and the oscillator with a vertical gradient. Applies to the normalized oscillator only.")],compute:(r,e)=>{let t=Vd(r),n=T(e,"color",O),o=T(e,"bearColor",D);if(T(e,"mode",um)===TC){let a=ri(t);return {plots:[{key:"ii",title:"Intraday Intensity",values:a,color:n,colors:hm(a,n,o,n)}]}}let i=R(e,"length",21),s=X(ge(t,i),ge(Ut(r),i),(a,l)=>l>0?100*a/l:Number.NaN);return Ae({key:"ii",title:"Intraday Intensity",values:s,ink:{bull:n,bear:o,neutral:o},zeroInk:z(A,90),fill:te(e,"gradientFill",true)})}},EC=[uD,hD,pD,mD,fD,gD,bD,vD,yD,wD,xD,CD,SD,TD,kD];var ii=864e5;function bm(r,e){if(r==="Week")return Math.floor((Math.floor(e/ii)+3)/7);if(r==="Month"||r==="Quarter"||r==="Year"){let t=new Date(e);return r==="Year"?t.getUTCFullYear():r==="Quarter"?t.getUTCFullYear()*4+Math.floor(t.getUTCMonth()/3):t.getUTCFullYear()*12+t.getUTCMonth()}return Math.floor(e/ii)}function RC(r){if(r.length<2)return 0;let e=[];for(let t=1;tt-n),e[Math.floor(e.length/2)]??0}var LD={type:"parabolic-sar",title:"Parabolic SAR",shortTitle:"SAR",overlay:true,inputs:[Q("start","Start",.02,0,1,.01,"Initial acceleration factor applied when a new trend begins."),Q("increment","Increment",.02,0,1,.01,"Amount added to the acceleration factor each time the trend makes a new extreme point."),Q("maximum","Maximum",.2,.01,1,.01,"Upper cap on the acceleration factor."),P(O,"Bullish","bullColor","Color of the SAR crosses while they trail below price \u2014 uptrend, the stop sits under the market."),P(D,"Bearish","bearColor","Color of the SAR crosses while they sit above price \u2014 downtrend, the stop sits over the market.")],compute:(r,e)=>{let t=R(e,"start",.02),n=R(e,"increment",.02),o=R(e,"maximum",.2),i=r.length,s=new Array(i).fill(Number.NaN);if(i>=2){let d=r[1].close>=r[0].close,u=d?r[0].low:r[0].high,h=d?r[0].high:r[0].low,p=t;for(let m=1;m=2?r[m-2].low:r[m-1].low):u=Math.max(u,r[m-1].high,m>=2?r[m-2].high:r[m-1].high),(d?f.lowu)?(d=!d,u=h,h=d?f.high:f.low,p=t):d&&f.high>h?(h=f.high,p=Math.min(o,p+n)):!d&&f.lowNumber.isFinite(d)?d[ne(r.show,`Band #${e+1}`,r.defOn,ze,`Show the ${["first","second","third"][e]} band pair.`),Q(r.mult,`Band #${e+1} Multiplier`,r.defMult,0,50,.5,"Multiplier for this band pair, in standard deviations or percent depending on the bands mode.")]),ne("hideDwm","Hide VWAP on 1D or Above",true,ze,"Hide the VWAP and its bands on daily and higher timeframes, where an intraday anchored VWAP is not meaningful."),P(O,"Bullish","bullColor","VWAP line color while price closes above it, and the color of the lower (support) bands."),P(D,"Bearish","bearColor","VWAP line color while price closes below it, and the color of the upper (resistance) bands."),P(A,"Bands","bandsColor","Deviation bands fill color."),ne("fill","Bands Fill",true,xe,"Fill the area between each visible band pair.")],compute:(r,e)=>{let t=T(e,"anchor","Session"),n=oe(r,T(e,"source","HLC3")),o=r.length,i=te(e,"hideDwm",true)&&RC(r)>=ii,s=new Array(o).fill(Number.NaN),a=IC.filter(y=>te(e,y.show,y.defOn)).map(y=>({mult:Math.max(0,R(e,y.mult,y.defMult)),up:new Array(o).fill(Number.NaN),down:new Array(o).fill(Number.NaN)})),l=T(e,"bandsMode",pm)===PC,c=Number.NaN,d=0,u=0,h=0;for(let y=0;y0){let v=n[y];d+=v*M,u+=v*v*M,h+=M;}if(h<=0)continue;let S=d/h,L=l?S/100:Math.sqrt(Math.max(0,u/h-S*S));s[y]=S;for(let v of a)v.up[y]=S+v.mult*L,v.down[y]=S-v.mult*L;}let p=T(e,"bullColor",O),m=T(e,"bearColor",D),f=z(T(e,"bandsColor",A),95),g=[{key:"vwap",title:"VWAP",values:s,color:p,colors:s.map((y,w)=>Number.isFinite(y)?r[w].close>=y?p:m:null)}],b=[];return a.forEach((y,w)=>{g.push({key:`up${w}`,title:`Upper Band #${w+1}`,values:y.up,color:z(m,40)},{key:`down${w}`,title:`Lower Band #${w+1}`,values:y.down,color:z(p,40)}),te(e,"fill",true)&&b.push({key:`band${w}`,from:`up${w}`,to:`down${w}`,color:f});}),{plots:g,bands:b}}},mm="Traditional",AC="Fibonacci",fm="Camarilla",Bd="Woodie",gm="Auto",PD={type:"pivot-points",title:"Pivot Points Standard",shortTitle:"Pivots",overlay:true,inputs:[Te("kind","Type",mm,[mm,AC,fm,Bd],"Formula used to calculate the levels. Traditional is the classic floor-trader method; Fibonacci projects 38.2/61.8/100% of the prior range around the pivot; Camarilla scales the prior range around the prior close; Woodie gives extra weight to the period open."),Te("anchor","Pivots Timeframe",gm,[gm,"Daily","Weekly","Monthly","Yearly"],"Period the pivots are anchored to. 'Auto' follows the chart's bar spacing: daily pivots up to 15-minute bars, weekly on other intraday bars, monthly on daily bars, yearly above."),P(U,"Pivot","pivotColor","Color of the central pivot (P) level."),P(D,"Resistances","resistanceColor","Color of the resistance (R) levels."),P(O,"Supports","supportColor","Color of the support (S) levels.")],compute:(r,e)=>{let t=RC(r),n=T(e,"anchor",gm),o=t<=15*6e4?"Session":tnew Array(l).fill(Number.NaN),d={p:c(),r1:c(),s1:c(),r2:c(),s2:c(),r3:c(),s3:c(),r4:c(),s4:c()},u=Number.NaN;for(let g=0;g({key:g,title:b,values:d[g],color:y}),f=[m("p","P",T(e,"pivotColor",U)),m("r1","R1",h),m("s1","S1",p),m("r2","R2",h),m("s2","S2",p)];return s!==Bd&&f.push(m("r3","R3",h),m("s3","S3",p)),s===fm&&f.push(m("r4","R4",h),m("s4","S4",p)),{plots:f}}},ID={type:"52-week-high-low",title:"52 Week High/Low",shortTitle:"52W H/L",overlay:true,inputs:[pe("weeks","Weeks",52,1,520,"Length of the rolling window, in weeks."),ne("showAllTime","Show All-Time High/Low",false,ze,"Additionally display the all-time high and low, tracked over the symbol's full loaded history."),P(O,"52 Week High","highColor","Color of the 52 week high level."),P(D,"52 Week Low","lowColor","Color of the 52 week low level."),P(A,"All-Time High/Low","allTimeColor","Color of the all-time high and all-time low levels.")],compute:(r,e)=>{let t=R(e,"weeks",52)*7*ii,n=r.length,o=new Array(n).fill(Number.NaN),i=new Array(n).fill(Number.NaN),s=new Array(n).fill(Number.NaN),a=new Array(n).fill(Number.NaN),l=[],c=[],d=0,u=-1/0,h=1/0;for(let m=0;m0&&r[l[l.length-1]].high<=f.high;)l.pop();for(l.push(m);c.length>0&&r[c[c.length-1]].low>=f.low;)c.pop();for(c.push(m);r[d].time{let t=R(e,"deviation",5)/100,n=R(e,"depth",10),o=[];if(r.length>1){let c=r[1].close>=r[0].close,d=c?{i:0,price:r[0].high}:{i:0,price:r[0].low};for(let u=1;u=d.price?d={i:u,price:h.high}:h.low<=d.price*(1-t)&&d.i-(o[o.length-1]?.i??-n)>=n&&(o.push(d),c=false,d={i:u,price:h.low}):h.low<=d.price?d={i:u,price:h.low}:h.high>=d.price*(1+t)&&d.i-(o[o.length-1]?.i??-n)>=n&&(o.push(d),c=true,d={i:u,price:h.high});}o.push(d);}let i=T(e,"bullColor",O),s=T(e,"bearColor",D),a=R(e,"lineWidth",2),l=[];for(let c=1;c=d.price?i:s,lineWidth:a,lineStyle:"solid",arrowLeft:false,arrowRight:false});}return {plots:[],polylines:l}}},RD={type:"williams-fractal",title:"Williams Fractal",shortTitle:"Fractals",overlay:true,inputs:[pe("periods","Periods",2,2,50,"Bars required on each side of the candidate bar. 2 is Bill Williams' classic 5-bar fractal; a fractal is confirmed only once this many later bars have closed."),P(D,"Up Fractal","upColor","Color of the up fractal marker (swing high), drawn above the fractal bar."),P(O,"Down Fractal","downColor","Color of the down fractal marker (swing low), drawn below the fractal bar.")],compute:(r,e)=>{let t=R(e,"periods",2),n=[],o=T(e,"upColor",D),i=T(e,"downColor",O),s=(a,l,c)=>{let d=l(r[a]);for(let u=a-t;u<=a+t;u++)if(u!==a&&!c(d,l(r[u])))return false;return true};for(let a=t;al.high,(l,c)=>l>c)&&n.push({time:r[a].time,position:"aboveBar",shape:"triangleup",color:o}),s(a,l=>l.low,(l,c)=>lr instanceof Error?r:new Error(String(r)),vm=class{constructor(e,t={},n={}){Ex(),Hp(),Xp(),OC();let o=OD(e),i=ho(t.theme),s={currentPriceLine:t.currentPriceLine??true,logScale:t.logScale??false,nativeBackend:t.nativeBackend??"auto",...Im(t.animations),glow:t.glow??0,upColor:t.upColor??O,downColor:t.downColor??D,priceStyle:t.priceStyle??"candles"},a=t.renderer??Ys;if(typeof a!="function")throw new Error("[vela] options.renderer must be a renderer class, e.g. import { LwcRenderer } from 'vela/renderers/lwc'. The 'lwc'/'native' string options were removed.");let l=n.renderer??new a(s),c=n.engines??[],d=n.dataFeed??new Lr,u={market:{symbol:t.symbol,timeframe:t.timeframe,bars:t.bars,session:t.session,visibleRange:t.visibleRange,data:t.data},live:t.live??false,theme:i,defaultLanguage:t.defaultLanguage??c[0]?.language??"pine",drawings:t.drawings,volume:t.volume??true};this.rendererControl=new Pi(l),t.settings&&this.rendererControl.setSettingsVisibility(t.settings),this.dataControl=new Ni(d),this.orchestrator=new Cl(o,l,d,c,u,this.dataControl);let h=cu();Object.keys(h).length>0&&this.rendererControl.set(h),this.panesControl=new Sl(this.orchestrator),this.drawingsControl=new Fi(this.orchestrator.drawings),this.marksControl=new Vi(this.orchestrator.marks),this.replayControl=new Bi(this.orchestrator);}registerEngine(e,t){return this.orchestrator.registerEngine(e,t),this}addIndicator(e,t){return this.orchestrator.addIndicator(e,t)}addNativeIndicator(e,t){return this.orchestrator.addNativeIndicator(e,t)}availableNativeIndicators(){return this.orchestrator.availableNativeIndicators()}presentNativeIndicators(){return this.orchestrator.presentNativeIndicators()}indicators(){return this.orchestrator.listIndicators()}runScript(e,t){let n;try{n=this.addIndicator(e,t);}catch(s){return Promise.resolve({ok:false,run:null,error:NC(s),onUpdate:()=>()=>{},remove:()=>{}})}let o=new Set,i=()=>{try{n.remove();}catch{}};return new Promise(s=>{let a=false,l=this.on("script:run",d=>{if(d.id===n.id){if(a){for(let u of o)u(d);return}a=true,c(),s({ok:true,run:d,error:null,onUpdate:u=>(o.add(u),()=>o.delete(u)),remove:()=>{l(),o.clear(),i();}});}}),c=n.on("error",({error:d})=>{a||(a=true,l(),c(),i(),s({ok:false,run:null,error:d,onUpdate:()=>()=>{},remove:()=>{}}));});})}runIndicator(e,t){let n;try{n=this.addIndicator(e,t);}catch(o){return Promise.resolve({ok:false,handle:null,error:NC(o),context:null})}return new Promise(o=>{let i=n.on("ready",()=>{i(),s(),o({ok:true,handle:n,error:null,context:null});}),s=n.on("error",({error:a})=>{i(),s(),n.context().catch(()=>null).then(l=>{try{n.remove();}catch{}o({ok:false,handle:null,error:a,context:l});});});})}setMarket(e){return this.orchestrator.setMarket(e)}get market(){return this.orchestrator.marketSnapshot()}ready(){return this.orchestrator.ready()}historyComplete(){return this.orchestrator.historyComplete()}inspect(){return this.orchestrator.inspect()}get renderer(){return this.rendererControl}get panes(){return this.panesControl}get data(){return this.dataControl}get drawings(){return this.drawingsControl}get marks(){return this.marksControl}get replay(){return this.replayControl}on(e,t){return this.orchestrator.events.on(e,t)}getVisibleRange(){return this.orchestrator.getVisibleRange()}setVisibleRange(e){return this.orchestrator.setVisibleRange(e),this}panBy(e){return this.orchestrator.panBy(e),this}setVisibleRangePreset(e){return this.orchestrator.setVisibleRangePreset(e),this}resize(){this.orchestrator.resize();}setTheme(e){return this.orchestrator.setTheme(ho(e)),this}destroy(){this.orchestrator.destroy();}};function OD(r){if(typeof r!="string")return r;let e=document.querySelector(r);if(!e)throw new Error(`[vela] container not found for selector "${r}"`);return e}function ND(r,e){return async(t,{end:n,signal:o})=>{let{symbol:i,session:s}=r.market,a=i?r.data.resolve(i):null,l=a?r.data.providerInstance(a.provider):void 0;if(!a||!l)return [];let c=await l.getBars(a.ticker,e,{from:t.time,to:n-1,...s?{session:s}:{}});return o.aborted?[]:FC(c.filter(d=>d.time>=t.time&&d.time({price:e.close,open:e.open,high:e.high,low:e.low,...e.volume===void 0?{}:{volume:e.volume}}))}var VC=["symbol","timeframes","style","layout","indicators","actions","undo-redo","alerts","panels","screenshot"];var si=new Map,js=new Map,qs=new Map;function FD(r){return js.set(r.id,r),()=>{js.get(r.id)===r&&js.delete(r.id);}}function VD(r){js.delete(r);}function BD(){return [...js.values()]}var BC=100;function _D(r){return qs.set(r.id,r),()=>{qs.get(r.id)===r&&qs.delete(r.id);}}function HD(r){qs.delete(r);}function zD(){return [...qs.values()].sort((r,e)=>(r.order??BC)-(e.order??BC))}var ym=["indicators","screenshot"],_C=new Set(ym),WD=new Set(VC);function GD(r){if(_C.has(r))return si.get(r)}function $D(r){return WD.has(r.id)&&!_C.has(r.id)?(console.warn(`[vela] widget action "${r.id}": this built-in topbar slot is a stateful control and cannot be overridden \u2014 ignored. Overridable slots: ${ym.join(", ")}.`),()=>{}):(si.set(r.id,r),()=>{si.get(r.id)===r&&si.delete(r.id);})}function UD(r){si.delete(r);}function YD(r,e){let t=[...si.values()].filter(n=>n.target===r);return t.sort((n,o)=>(n.order??0)-(o.order??0)),e?t.filter(n=>!n.when||n.when(e)):t}var Zs=new Map;function KD(r){return Zs.set(r.id,r),()=>{Zs.get(r.id)===r&&Zs.delete(r.id);}}function XD(r){Zs.delete(r);}function jD(){return [...Zs.values()].sort((r,e)=>(r.order??0)-(e.order??0))}var Qs=new Map;function qD(r){return Qs.set(r.id,r),()=>{Qs.get(r.id)===r&&Qs.delete(r.id);}}function ZD(r){Qs.delete(r);}function QD(){return [...Qs.values()].sort((r,e)=>(r.order??0)-(e.order??0))}var Js=new Map;function JD(r){return Js.set(r.key,r),()=>{Js.get(r.key)===r&&Js.delete(r.key);}}function e2(r){Js.delete(r);}function t2(r){return [...Js.values()].filter(e=>e.scope===r)}var _d;function n2(r){return _d=r,()=>{_d===r&&(_d=void 0);}}function r2(){return _d}var ea=new Map;function o2(r,e){return ea.set(r,e),()=>{ea.get(r)===e&&ea.delete(r);}}function i2(r){ea.delete(r);}function s2(r){return {...Object.fromEntries(ea),...r}}var HC=280,wm=200,zC=640;function a2(r,e=wm,t=zC){let n=Number.isFinite(e)&&e>0?e:wm,o=Number.isFinite(t)?Math.max(t,n):Number.POSITIVE_INFINITY;return Number.isFinite(r)?Math.round(Math.min(Math.max(r,n),o)):n}function ai(r){let e=r.description?.split("/")[0]?.trim();return e?e.replace(/\s+Perpetual$/i,""):r.ticker.replace(/[-_/]?(USDT|USDC|USD1|USDS|BUSD|USD|EUR|PERP)$/i,"")||r.ticker}function li(r){let e=r.trim().toUpperCase();return e?`https://crypto-icons.ledger.com/${encodeURIComponent(e)}.png`:void 0}var WC="https://api.binance.com/api/v3",l2="https://api.binance.us/api/v3",xm="https://fapi.binance.com/fapi/v1",c2="wss://stream.binance.com:9443",d2="wss://stream.binance.us:9443",u2="wss://fstream.binance.com",h2=15e3,p2=2e3,GC={1:"1m",3:"3m",5:"5m",15:"15m",30:"30m",60:"1h",120:"2h",240:"4h",360:"6h",480:"8h",720:"12h",D:"1d",W:"1w",M:"1M"},$C={"1m":"1","3m":"3","5m":"5","15m":"15","30m":"30","45m":"45","1h":"60","2h":"120","3h":"180","4h":"240","6h":"360","8h":"480","12h":"720","1d":"D","1w":"W","1mo":"M","1D":"D","1W":"W","4H":"240",D:"D",W:"W",M:"M"},m2=[1,3,5,15,30,60,120,240,360,480,720],f2={1:"1m",3:"3m",5:"5m",15:"15m",30:"30m",60:"1h",120:"2h",240:"4h",360:"6h",480:"8h",720:"12h"},g2=["1","3","5","15","30","45","60","120","180","240","D","W","M"];function UC(r){return $C[r]??$C[r.toLowerCase()]??r}function Cm(r){let e=r.trim().toUpperCase();return e.endsWith(".P")?{apiSymbol:e.slice(0,-2),isFutures:true}:{apiSymbol:e,isFutures:false}}function YC(r){return r.map(e=>({time:Number(e[0]),open:Number(e[1]),high:Number(e[2]),low:Number(e[3]),close:Number(e[4]),volume:Number(e[5])}))}function b2(r){return {time:Number(r.t),open:Number(r.o),high:Number(r.h),low:Number(r.l),close:Number(r.c),volume:Number(r.v)}}function v2(r){let e=new Map;for(let t of r)e.set(t.time,t);return [...e.values()].sort((t,n)=>t.time-n.time)}function y2(r,e){let t=new Map;for(let n of r){let o=Math.floor(n.time/e)*e,i=t.get(o);i?(i.high=Math.max(i.high,n.high),i.low=Math.min(i.low,n.low),i.close=n.close,i.volume=(i.volume??0)+(n.volume??0)):t.set(o,{time:o,open:n.open,high:n.high,low:n.low,close:n.close,volume:n.volume??0});}return [...t.values()].sort((n,o)=>n.time-o.time)}function w2(r){return m2.filter(e=>et-e)[0]??null}var Hd=class{constructor(){this.spotBaseUrl=null;this.spotBaseProbe=null;this.symbolsPromise=null;}info(){return {name:"binance",displayName:"Binance",requiresApiKey:false,supportedTimeframes:g2,capabilities:{enumerate:true,stream:true,symbolInfo:true}}}async getBars(e,t,n){try{let{apiSymbol:o,isFutures:i}=Cm(e),s=i?xm:await this.spotBase(),a=UC(t),l=GC[a];if(l)return v2(YC(await this.fetchKlines(s,o,l,n)));let c=/^\d+$/.test(a)?parseInt(a,10):null,d=c!=null?w2(c):null;if(c==null||d==null)return console.warn(`[vela] Binance: timeframe "${t}" is not supported and cannot be aggregated.`),[];let u=c/d,h={...n,limit:n.limit!=null?n.limit*u+u:void 0},p=YC(await this.fetchKlines(s,o,f2[d],h)),m=y2(p,c*6e4);return n.limit!=null&&m.length>n.limit?m.slice(-n.limit):m}catch(o){return console.warn(`[vela] Binance: failed to fetch ${e} ${t} \u2014 ${o instanceof Error?o.message:String(o)}`),[]}}async getSymbolInfo(e){let{apiSymbol:t,isFutures:n}=Cm(e),o=n?xm:await this.spotBase(),i=n?`${o}/exchangeInfo`:`${o}/exchangeInfo?symbol=${t}`,a=(await this.json(i).catch(()=>null))?.symbols??[],l=n?a.find(u=>u.symbol===t):a[0];if(!l)return;let c=l.filters?.find(u=>u.filterType==="PRICE_FILTER"),d=c?parseFloat(c.tickSize??"0.01"):.01;return {ticker:e,tickerid:`BINANCE:${e}`,prefix:"BINANCE",description:`${l.baseAsset} / ${l.quoteAsset}${n?" Perpetual":""}`,type:n?"futures":"crypto",basecurrency:l.baseAsset,currency:l.quoteAsset,mintick:d,pricescale:Math.round(1/d),timezone:"Etc/UTC",session:"24x7"}}listSymbols(){return this.symbolsPromise||(this.symbolsPromise=Promise.all([this.listSpot().catch(()=>[]),this.listFutures().catch(()=>[])]).then(([e,t])=>[...e,...t])),this.symbolsPromise}resolveSymbolIcon(e){return li(ai(e))}subscribe(e,t,n){let{apiSymbol:o,isFutures:i}=Cm(e),s=GC[UC(t)];return s&&typeof WebSocket<"u"?this.streamKlines(e,t,o,i,s,n):this.pollBars(e,t,n)}streamKlines(e,t,n,o,i,s){let a=false,l=null,c=null,d=null,u=null,h=`${n.toLowerCase()}@kline_${i}`,p=()=>{d&&(clearTimeout(d),d=null);},m=()=>{if(!(a||u)){p(),c&&(clearTimeout(c),c=null);try{l?.close();}catch{}l=null,console.warn(`[vela] Binance: ${e} ${t} stream delivered no data; falling back to polling.`),u=this.pollBars(e,t,s);}},f=async()=>{if(a)return;let g=o?u2:await this.spotWsBase();a||(l=new WebSocket(`${g}/ws/${h}`),d=setTimeout(m,h2),l.onmessage=b=>{if(!(a||u))try{let y=JSON.parse(typeof b.data=="string"?b.data:"");y.k&&(p(),s(b2(y.k)));}catch{}},l.onclose=()=>{!a&&!u&&(c=setTimeout(()=>{f();},p2));},l.onerror=()=>{try{l?.close();}catch{}});};return f(),()=>{a=true,p(),c&&clearTimeout(c),u?.();try{l?.close();}catch{}}}async spotWsBase(){return (await this.spotBase()).includes("binance.us")?d2:c2}pollBars(e,t,n){let o=false,i=null,s=async()=>{if(!o){try{let a=await this.getBars(e,t,{limit:2});for(let l of a)n(l);}catch{}o||(i=setTimeout(()=>{s();},3e3));}};return i=setTimeout(()=>{s();},3e3),()=>{o=true,i&&clearTimeout(i);}}async listSpot(){let e=await this.spotBase();return ((await this.json(`${e}/exchangeInfo`)).symbols??[]).filter(n=>n.status==="TRADING").map(n=>({ticker:n.symbol,description:`${n.baseAsset} / ${n.quoteAsset}`,type:"crypto"}))}async listFutures(){return ((await this.json(`${xm}/exchangeInfo`)).symbols??[]).filter(t=>t.contractType==="PERPETUAL"&&t.status==="TRADING").map(t=>({ticker:`${t.symbol}.P`,description:`${t.baseAsset} / ${t.quoteAsset} Perpetual`,type:"futures"}))}async fetchKlines(e,t,n,o){if(o.from!=null)return this.paginateForward(e,t,n,o.from,o.to??Date.now(),o.limit);let i=o.limit??500;return i>1e3?this.paginateBackward(e,t,n,i,o.to):this.klinesChunk(e,{symbol:t,interval:n,limit:i,endTime:o.to})}async paginateForward(e,t,n,o,i,s){let a=[],l=o;for(;l=s)break}return s?a.slice(0,s):a}async paginateBackward(e,t,n,o,i){let s=[],a=o,l=i,c=Math.ceil(o/1e3)+5;for(;a>0&&c-- >0;){let d=Math.min(a,1e3),u=await this.klinesChunk(e,{symbol:t,interval:n,limit:d,endTime:l});if(u.length===0||(s=u.concat(s),a-=u.length,l=Number(u[0][0])-1,u.length0&&!Array.isArray(o[0])?[]:o:[]}spotBase(){return this.spotBaseUrl?Promise.resolve(this.spotBaseUrl):(this.spotBaseProbe||(this.spotBaseProbe=(async()=>{try{for(let e of [WC,l2])try{if((await fetch(`${e}/ping`,{signal:AbortSignal.timeout(5e3)})).ok)return this.spotBaseUrl=e}catch{}return WC}finally{this.spotBaseProbe=null;}})()),this.spotBaseProbe)}async json(e){let t=await fetch(e);if(!t.ok)throw new Error(`Binance HTTP ${t.status} for ${e}`);return t.json()}};var x2="https://api.hyperliquid.xyz/info",C2="wss://api.hyperliquid.xyz/ws",S2=15e3,T2=2e3,KC={1:"1m",3:"3m",5:"5m",15:"15m",30:"30m",60:"1h",120:"2h",240:"4h",480:"8h",720:"12h",D:"1d",W:"1w",M:"1M"},XC={"1m":"1","3m":"3","5m":"5","15m":"15","30m":"30","45m":"45","1h":"60","2h":"120","3h":"180","4h":"240","6h":"360","8h":"480","12h":"720","1d":"D","1w":"W","1mo":"M","1D":"D","1W":"W","4H":"240",D:"D",W:"W",M:"M"},k2=[1,3,5,15,30,60,120,240,480,720],L2={1:"1m",3:"3m",5:"5m",15:"15m",30:"30m",60:"1h",120:"2h",240:"4h",480:"8h",720:"12h"},M2=["1","3","5","15","30","45","60","120","180","240","360","480","720","D","W","M"],jC={D:864e5,W:6048e5,M:2592e6};function E2(r){if(jC[r])return jC[r];let e=parseInt(r,10);return Number.isFinite(e)&&e>0?e*6e4:36e5}function qC(r){return XC[r]??XC[r.toLowerCase()]??r}function Sm(r){let e=r.trim();return e.includes("/")?e:e.toUpperCase()}function Tm(r){return {time:Number(r.t),open:Number(r.o),high:Number(r.h),low:Number(r.l),close:Number(r.c),volume:Number(r.v)}}function P2(r){let e=new Map;for(let t of r)e.set(t.time,t);return [...e.values()].sort((t,n)=>t.time-n.time)}function I2(r,e){let t=new Map;for(let n of r){let o=Math.floor(n.time/e)*e,i=t.get(o);i?(i.high=Math.max(i.high,n.high),i.low=Math.min(i.low,n.low),i.close=n.close,i.volume=(i.volume??0)+(n.volume??0)):t.set(o,{time:o,open:n.open,high:n.high,low:n.low,close:n.close,volume:n.volume??0});}return [...t.values()].sort((n,o)=>n.time-o.time)}function A2(r){return k2.filter(e=>et-e)[0]??null}var zd=class{constructor(){this.metaPromise=null;this.spotMetaPromise=null;this.symbolsPromise=null;}info(){return {name:"hyperliquid",displayName:"Hyperliquid",requiresApiKey:false,supportedTimeframes:M2,capabilities:{enumerate:true,stream:true,symbolInfo:true}}}async getBars(e,t,n){try{let o=Sm(e),i=qC(t),s=KC[i];if(s)return P2((await this.fetchCandles(o,s,E2(i),n)).map(Tm));let a=/^\d+$/.test(i)?parseInt(i,10):null,l=a!=null?A2(a):null;if(a==null||l==null)return console.warn(`[vela] Hyperliquid: timeframe "${t}" is not supported and cannot be aggregated.`),[];let c=a/l,d={...n,limit:n.limit!=null?n.limit*c+c:void 0},u=(await this.fetchCandles(o,L2[l],l*6e4,d)).map(Tm),h=I2(u,a*6e4);return n.limit!=null&&h.length>n.limit?h.slice(-n.limit):h}catch(o){return console.warn(`[vela] Hyperliquid: failed to fetch ${e} ${t} \u2014 ${o instanceof Error?o.message:String(o)}`),[]}}async getSymbolInfo(e){let t=Sm(e),o=(await this.fetchMeta().catch(()=>null))?.universe?.find(i=>i.name===t);if(o){let i=QC(Math.max(0,6-(o.szDecimals??2)));return ZC(e,t,"USD","futures",`${t} / USD Perpetual`,i)}if(t.includes("/")){let i=await this.fetchSpotMeta().catch(()=>null),s=i?.universe?.find(u=>u.name===t),a=s&&i?.tokens?i.tokens[s.tokens?.[0]??-1]:void 0,[l=t,c="USDC"]=t.split("/"),d=QC(Math.max(0,8-(a?.szDecimals??2)));return ZC(e,l,c,"crypto",`${l} / ${c}`,d)}}listSymbols(){return this.symbolsPromise||(this.symbolsPromise=Promise.all([this.listPerps().catch(()=>[]),this.listSpot().catch(()=>[])]).then(([e,t])=>[...e,...t])),this.symbolsPromise}resolveSymbolIcon(e){return li(ai(e))}subscribe(e,t,n){let o=Sm(e),i=KC[qC(t)];return i&&typeof WebSocket<"u"?this.streamCandles(e,t,o,i,n):this.pollBars(e,t,n)}async listPerps(){return ((await this.fetchMeta()).universe??[]).filter(t=>!t.isDelisted).map(t=>({ticker:t.name,description:`${t.name} / USD Perpetual`,type:"futures"}))}async listSpot(){let e=await this.fetchSpotMeta(),t=e.tokens??[],n=o=>o!=null?t[o]?.name??null:null;return (e.universe??[]).map(o=>{let i=n(o.tokens?.[0]),s=n(o.tokens?.[1]),a=i&&s?`${i} / ${s}`:o.name;return {ticker:o.name,description:a,type:"crypto"}})}async fetchCandles(e,t,n,o){let i=o.to??Date.now(),s=o.from!=null?o.from:i-((o.limit??500)+2)*n,a=await this.candleSnapshot(e,t,s,i);return o.from==null&&o.limit!=null&&a.length>o.limit?a.slice(-o.limit):a}async candleSnapshot(e,t,n,o){let i=await this.post({type:"candleSnapshot",req:{coin:e,interval:t,startTime:Math.floor(n),endTime:Math.floor(o)}});return Array.isArray(i)?i:[]}streamCandles(e,t,n,o,i){let s=false,a=null,l=null,c=null,d=null,u=null,h=()=>{d&&(clearTimeout(d),d=null);},p=()=>{l&&(clearInterval(l),l=null);},m=()=>{if(!(s||u)){h(),p(),c&&(clearTimeout(c),c=null);try{a?.close();}catch{}a=null,console.warn(`[vela] Hyperliquid: ${e} ${t} stream delivered no data; falling back to polling.`),u=this.pollBars(e,t,i);}},f=()=>{s||u||(a=new WebSocket(C2),d=setTimeout(m,S2),a.onopen=()=>{try{a?.send(JSON.stringify({method:"subscribe",subscription:{type:"candle",coin:n,interval:o}}));}catch{}l=setInterval(()=>{try{a?.send(JSON.stringify({method:"ping"}));}catch{}},3e4);},a.onmessage=g=>{if(!(s||u))try{let b=JSON.parse(typeof g.data=="string"?g.data:"");b.channel==="candle"&&b.data&&b.data.s===n&&(h(),i(Tm(b.data)));}catch{}},a.onclose=()=>{p(),!s&&!u&&(c=setTimeout(f,T2));},a.onerror=()=>{try{a?.close();}catch{}});};return f(),()=>{s=true,h(),p(),c&&clearTimeout(c),u?.();try{a?.close();}catch{}}}pollBars(e,t,n){let o=false,i=null,s=async()=>{if(!o){try{let a=await this.getBars(e,t,{limit:2});for(let l of a)n(l);}catch{}o||(i=setTimeout(()=>{s();},3e3));}};return i=setTimeout(()=>{s();},3e3),()=>{o=true,i&&clearTimeout(i);}}fetchMeta(){return this.metaPromise??(this.metaPromise=this.post({type:"meta"}).then(e=>e))}fetchSpotMeta(){return this.spotMetaPromise??(this.spotMetaPromise=this.post({type:"spotMeta"}).then(e=>e))}async post(e){let t=await fetch(x2,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!t.ok)throw new Error(`Hyperliquid HTTP ${t.status}`);return t.json()}};function ZC(r,e,t,n,o,i){return {ticker:r,tickerid:`HYPERLIQUID:${r}`,prefix:"HYPERLIQUID",description:o,type:n,basecurrency:e,currency:t,mintick:i,pricescale:Math.round(1/i),timezone:"Etc/UTC",session:"24x7"}}function QC(r){return Math.pow(10,-r)}var R2={now:()=>Date.now(),delay:r=>new Promise(e=>setTimeout(e,r))},Wd=class{constructor(e,t,n=R2){this.maxConcurrent=e;this.minIntervalMs=t;this.clock=n;this.active=0;this.waiters=[];this.nextStartAt=0;this.pausedUntil=0;}async run(e){await this.acquire();try{return await this.waitForTurn(),await e()}finally{this.release();}}pauseFor(e){e>0&&(this.pausedUntil=Math.max(this.pausedUntil,this.clock.now()+e));}async waitForTurn(){for(;;){let e=this.clock.now(),t=Math.max(this.pausedUntil-e,this.nextStartAt-e);if(t<=0)break;await this.clock.delay(t);}this.nextStartAt=Math.max(this.clock.now(),this.nextStartAt)+this.minIntervalMs;}acquire(){return this.active{this.waiters.push(()=>{this.active+=1,e();});})}release(){this.active-=1;let e=this.waiters.shift();e&&e();}};var km="https://api.exchange.coinbase.com",D2="wss://ws-feed.exchange.coinbase.com",O2={Accept:"application/json"},N2=15e3,F2=2e3,V2=5e3,Gd=300,B2=4,_2=120,H2=4,z2=600,W2=400;function G2(r,e){let t=Number(r.headers.get("retry-after"));return Number.isFinite(t)&&t>0?t*1e3:e}var JC={1:60,5:300,15:900,60:3600,360:21600,D:86400},eS={"1m":"1","3m":"3","5m":"5","15m":"15","30m":"30","45m":"45","1h":"60","2h":"120","3h":"180","4h":"240","6h":"360","8h":"480","12h":"720","1d":"D","1w":"W","1mo":"M","1D":"D","1W":"W","4H":"240",D:"D",W:"W",M:"M"},$2=[1,5,15,60,360,1440],U2={1:60,5:300,15:900,60:3600,360:21600,1440:86400},Y2=["1","3","5","15","30","45","60","120","180","240","360","480","720","D","W","M"],Lm=864e5;function tS(r){return eS[r]??eS[r.toLowerCase()]??r}function Mm(r){return r.trim().toUpperCase()}function K2(r){return {time:Number(r[0])*1e3,open:Number(r[3]),high:Number(r[2]),low:Number(r[1]),close:Number(r[4]),volume:Number(r[5])}}function Em(r){let e=new Map;for(let t of r)e.set(t.time,t);return [...e.values()].sort((t,n)=>t.time-n.time)}function X2(r,e){return nS(r,t=>Math.floor(t/e)*e)}function j2(r,e){return nS(r,e==="W"?q2:Z2)}function nS(r,e){let t=new Map;for(let n of r){let o=e(n.time),i=t.get(o);i?(i.high=Math.max(i.high,n.high),i.low=Math.min(i.low,n.low),i.close=n.close,i.volume=(i.volume??0)+(n.volume??0)):t.set(o,{time:o,open:n.open,high:n.high,low:n.low,close:n.close,volume:n.volume??0});}return [...t.values()].sort((n,o)=>n.time-o.time)}function q2(r){let e=new Date(r),t=(e.getUTCDay()+6)%7;return Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()-t)}function Z2(r){let e=new Date(r);return Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),1)}function Q2(r){return $2.filter(e=>et-e)[0]??null}function Pm(r,e){return e!=null&&r.length>e?r.slice(-e):r}var $d=class{constructor(){this.symbolsPromise=null;this.gate=new Wd(B2,_2);}info(){return {name:"coinbase",displayName:"Coinbase",requiresApiKey:false,supportedTimeframes:Y2,capabilities:{enumerate:true,stream:true,symbolInfo:true}}}async getBars(e,t,n){try{let o=Mm(e),i=tS(t),s=JC[i];if(s)return Em(await this.fetchCandles(o,s,n));if(i==="W"||i==="M"){let h=i==="W"?7*Lm:31*Lm,p=n.from!=null?n:{...n,limit:n.limit!=null?Math.ceil(n.limit*h/Lm)+31:void 0},m=await this.fetchCandles(o,86400,p);return Pm(j2(m,i),n.limit)}let a=/^\d+$/.test(i)?parseInt(i,10):null,l=a!=null?Q2(a):null;if(a==null||l==null)return console.warn(`[vela] Coinbase: timeframe "${t}" is not supported and cannot be aggregated.`),[];let c=a/l,d={...n,limit:n.limit!=null?n.limit*c+c:void 0},u=await this.fetchCandles(o,U2[l],d);return Pm(X2(u,a*6e4),n.limit)}catch(o){return console.warn(`[vela] Coinbase: failed to fetch ${e} ${t} \u2014 ${o instanceof Error?o.message:String(o)}`),[]}}async getSymbolInfo(e){let t=Mm(e),n=await this.json(`${km}/products/${t}`).catch(()=>null);if(!n||!n.id)return;let o=n.quote_increment!=null?parseFloat(n.quote_increment):.01,i=o>0?o:.01;return {ticker:e,tickerid:`COINBASE:${e}`,prefix:"COINBASE",description:`${n.base_currency} / ${n.quote_currency}`,type:"crypto",basecurrency:n.base_currency,currency:n.quote_currency,mintick:i,pricescale:Math.round(1/i),timezone:"Etc/UTC",session:"24x7"}}listSymbols(){return this.symbolsPromise||(this.symbolsPromise=this.fetchProducts().then(e=>e.filter(t=>t.status==="online"&&!t.trading_disabled).map(t=>({ticker:t.id,description:`${t.base_currency} / ${t.quote_currency}`,type:"crypto"}))).catch(()=>[])),this.symbolsPromise}resolveSymbolIcon(e){return li(ai(e))}subscribe(e,t,n){let o=JC[tS(t)];return o&&typeof WebSocket<"u"?this.streamTicker(e,t,o,n):this.pollBars(e,t,n)}async fetchProducts(){let e=await this.json(`${km}/products`);return Array.isArray(e)?e:[]}async fetchCandles(e,t,n){return n.from!=null?this.paginateForward(e,t,n.from,n.to??Date.now(),n.limit):this.paginateBackward(e,t,n.limit??500,n.to??Date.now())}async paginateBackward(e,t,n,o){let i=t*1e3,s=[],a=n,l=o,c=Math.ceil(n/Gd)+4;for(;a>0&&c-- >0;){let d=Math.min(a,Gd),u=l-d*i,h=await this.candlesChunk(e,t,u,l);if(h.length===0||(s=h.concat(s),a-=h.length,l=h[0].time-1,h.length0;){let u=Math.min(l+Gd*s,o),h=await this.candlesChunk(e,t,l,u);if(h.length>0&&a.push(...h),l=u,i!=null&&a.length>=i)break}let d=Em(a);return i!=null?d.slice(0,i):d}async candlesChunk(e,t,n,o){let i=new URL(`${km}/products/${e}/candles`);i.searchParams.set("granularity",String(t)),i.searchParams.set("start",String(Math.floor(n/1e3))),i.searchParams.set("end",String(Math.floor(o/1e3)));let s=await this.json(i.toString());return !Array.isArray(s)||s.length>0&&!Array.isArray(s[0])?[]:s.map(K2).sort((a,l)=>a.time-l.time)}streamTicker(e,t,n,o){let i=Mm(e),s=n*1e3,a=S=>Math.floor(S/s)*s,l=false,c=null,d=null,u=null,h=null,p=null,m=null,f=()=>{u&&(clearTimeout(u),u=null);},g=()=>{h&&(clearInterval(h),h=null);},b=()=>{m&&o({...m});},y=async S=>{try{let L=await this.getBars(e,t,{limit:2});if(l||L.length===0)return;S&&L.length>=2&&o(L[L.length-2]);let v=L[L.length-1];m=m&&m.time===v.time?{...v,high:Math.max(v.high,m.high),low:Math.min(v.low,m.low),close:m.close}:{...v},b();}catch{}},w=(S,L)=>{let v=Number(S);if(!Number.isFinite(v))return;let k=a(L);!m||k>m.time?(m={time:k,open:v,high:v,low:v,close:v,volume:0},b(),y(false)):k===m.time&&(m={...m,close:v,high:Math.max(m.high,v),low:Math.min(m.low,v)},b());},C=()=>{if(!(l||p)){f(),g(),d&&(clearTimeout(d),d=null);try{c?.close();}catch{}c=null,console.warn(`[vela] Coinbase: ${e} ${t} stream delivered no data; falling back to polling.`),p=this.pollBars(e,t,o);}},M=()=>{l||p||(c=new WebSocket(D2),u=setTimeout(C,N2),c.onopen=()=>{try{c?.send(JSON.stringify({type:"subscribe",product_ids:[i],channels:["ticker"]}));}catch{}y(false),h=setInterval(()=>{y(false);},V2);},c.onmessage=S=>{if(!(l||p))try{let L=JSON.parse(typeof S.data=="string"?S.data:"");L.type==="ticker"&&L.product_id===i&&L.price!=null&&(f(),w(L.price,L.time?Date.parse(L.time):Date.now()));}catch{}},c.onclose=()=>{g(),!l&&!p&&(d=setTimeout(M,F2));},c.onerror=()=>{try{c?.close();}catch{}});};return M(),()=>{l=true,f(),g(),d&&clearTimeout(d),p?.();try{c?.close();}catch{}}}pollBars(e,t,n){let o=false,i=null,s=async()=>{if(!o){try{let a=await this.getBars(e,t,{limit:2});for(let l of a)n(l);}catch{}o||(i=setTimeout(()=>{s();},3e3));}};return i=setTimeout(()=>{s();},3e3),()=>{o=true,i&&clearTimeout(i);}}async json(e){return (await this.request(e)).json()}async request(e){for(let t=0;;t+=1){let n=await this.gate.run(()=>fetch(e,{headers:O2}));if(n.status===429&&t.001:true}function y0(r,e,t){let n=r.borderTopLeftRadius,o=parseFloat(n)||0,i=n.endsWith("%")?o/100*Math.min(e,t):o;return Math.max(0,Math.min(i,Math.min(e,t)/2))}function Np(r,e,t,n,o,i){r.beginPath(),i>0&&typeof r.roundRect=="function"?r.roundRect(e,t,n,o,i):r.rect(e,t,n,o);}function KA(r){try{let e=r.ownerDocument.createElement("canvas");e.width=1,e.height=1;let t=e.getContext("2d");return t?(t.drawImage(r,0,0,1,1),e.toDataURL(),!0):!1}catch{return false}}function Rd(r,e,t){let n=e.ownerDocument.defaultView;if(!n)return;r.save(),r.scale(t.dpr,t.dpr);let o=(c,d,u)=>{let h=c.textContent?.replace(/\s+/g," ").trim();if(!h)return;let p=c.ownerDocument.createRange();p.selectNodeContents(c);let m=p.getBoundingClientRect();m.width<=0||m.height<=0||(r.globalAlpha=u,r.fillStyle=d.color,r.font=`${d.fontStyle} ${d.fontWeight} ${d.fontSize} ${d.fontFamily}`,r.textBaseline="middle",r.textAlign="left",r.fillText(h,m.left-t.left,m.top-t.top+m.height/2));},i=(c,d,u)=>{if(!c.complete||c.naturalWidth<=0||!KA(c))return;let h=c.getBoundingClientRect();if(h.width<=0||h.height<=0)return;let p=h.left-t.left,m=h.top-t.top;r.save(),r.globalAlpha=u,Np(r,p,m,h.width,h.height,y0(d,h.width,h.height)),r.clip(),r.drawImage(c,p,m,h.width,h.height),r.restore();},s=(c,d)=>{for(let u of c.children){if(u.hasAttribute("transform"))continue;let h=u.tagName.toLowerCase();if(h==="g"){s(u,d);continue}let p=b=>parseFloat(u.getAttribute(b)??"0")||0,m=null;if(h==="path"){let b=u.getAttribute("d");b&&(m=new Path2D(b));}else if(h==="circle")m=new Path2D,m.arc(p("cx"),p("cy"),p("r"),0,Math.PI*2);else if(h==="ellipse")m=new Path2D,m.ellipse(p("cx"),p("cy"),p("rx"),p("ry"),0,0,Math.PI*2);else if(h==="rect")m=new Path2D,m.rect(p("x"),p("y"),p("width"),p("height"));else if(h==="line")m=new Path2D,m.moveTo(p("x1"),p("y1")),m.lineTo(p("x2"),p("y2"));else if(h==="polyline"||h==="polygon"){let b=(u.getAttribute("points")??"").trim().split(/[\s,]+/).map(Number);if(b.length<4||b.some(Number.isNaN))continue;m=new Path2D,m.moveTo(b[0],b[1]);for(let y=2;y+10&&(r.globalAlpha=d*(parseFloat(f.strokeOpacity)||1),r.strokeStyle=f.stroke,r.lineWidth=g,(f.strokeLinecap==="round"||f.strokeLinecap==="square"||f.strokeLinecap==="butt")&&(r.lineCap=f.strokeLinecap),(f.strokeLinejoin==="round"||f.strokeLinejoin==="bevel"||f.strokeLinejoin==="miter")&&(r.lineJoin=f.strokeLinejoin),r.stroke(m));}},a=(c,d)=>{let u=c.getBoundingClientRect();if(u.width<=0||u.height<=0)return;let h=n.getComputedStyle(c);if(h.display==="none"||h.visibility==="hidden")return;let p=d*(parseFloat(h.opacity)||1);if(p<=.001)return;let m=c.viewBox.baseVal,f=m&&m.width>0?m.width:u.width,g=m&&m.height>0?m.height:u.height;r.save(),r.translate(u.left-t.left,u.top-t.top),r.scale(u.width/f,u.height/g),m&&r.translate(-m.x,-m.y),s(c,p),r.restore();},l=(c,d)=>{let u=n.getComputedStyle(c);if(u.display==="none"||u.visibility==="hidden")return;let h=d*(parseFloat(u.opacity)||1);if(h<=.001)return;let p=c.getBoundingClientRect();if(p.width>0&&p.height>0){let m=p.left-t.left,f=p.top-t.top,g=y0(u,p.width,p.height);Ad(u.backgroundColor)&&(r.globalAlpha=h,r.fillStyle=u.backgroundColor,Np(r,m,f,p.width,p.height,g),r.fill());let b=parseFloat(u.borderTopWidth)||0;b>0&&u.borderTopStyle!=="none"&&Ad(u.borderTopColor)&&(r.globalAlpha=h,r.strokeStyle=u.borderTopColor,r.lineWidth=b,Np(r,m+b/2,f+b/2,p.width-b,p.height-b,Math.max(0,g-b/2)),r.stroke());}for(let m of c.childNodes)m.nodeType===3?o(m,u,h):m instanceof n.HTMLImageElement?i(m,n.getComputedStyle(m),h):m instanceof n.SVGSVGElement?a(m,h):m instanceof n.HTMLElement&&l(m,h);};e instanceof n.HTMLElement&&l(e,1),r.restore();}function w0(r,e,t,n,o){let i=Math.max(0,e),s=Math.min(r.length-1,t);if(i>s)return null;let a=1/0,l=-1/0;for(let w=i;w<=s;w+=1){let S=r[w];S.volume!=null&&S.volume>0&&(S.lowl&&(l=S.high));}if(!Number.isFinite(a))return null;let c=l>a?Math.max(1,Math.round(n)):1,d=l>a?(l-a)/c:1,u=Array.from({length:c},(w,S)=>({price:a+S*d,up:0,down:0}));for(let w=i;w<=s;w+=1){let S=r[w],M=S.volume;if(!(M!=null&&M>0))continue;let C=S.close>=S.open?"up":"down",L=S.high-S.low;if(L<=0){let x=Fp(Math.floor((S.low-a)/d),c);u[x][C]+=M;continue}let v=Fp(Math.floor((S.low-a)/d),c),k=Fp(Math.floor((S.high-a)/d-1e-9),c);for(let x=v;x<=k;x+=1){let E=a+x*d,I=Math.min(S.high,E+d)-Math.max(S.low,E);I>0&&(u[x][C]+=M*I/L);}}let h=0,p=0,m=0;for(let w=0;wp&&(p=S,m=w);}if(p<=0)return null;let f=h*Math.min(1,Math.max(0,o)),g=m,b=m,y=p;for(;y0||b0?u[g-1].up+u[g-1].down:-1,S=bw?(b+=1,y+=S):(g-=1,y+=w);}return {rows:u,rowH:d,min:a,maxTotal:p,poc:m,vaFrom:g,vaTo:b}}function Fp(r,e){return r<0?0:r>=e?e-1:r}function x0(r,e,t,n){let{rows:o,rowH:i,maxTotal:s,poc:a,vaFrom:l,vaTo:c}=e,{rightX:d,maxW:u,yOf:h}=t;if(!(s<=0||u<=0)){for(let p=0;p=l&&p<=c?.62:.28,w>0&&(r.fillStyle=n.upColor,r.fillRect(d-y,g,w,b)),y-w>0&&(r.fillStyle=n.downColor,r.fillRect(d-y+w,g,y-w,b));}if(n.showPoc){let p=o[a],m=h(p.price+i),f=Math.max(1,h(p.price)-m-1);r.globalAlpha=.9,r.strokeStyle=n.pocColor,r.lineWidth=1,r.strokeRect(d-u+.5,m+.5,u-1,f);}r.globalAlpha=1;}}var Dd=class{constructor(){this.canvas=null;this.ctx=null;this.memoKey="";this.memo=null;}mount(e){this.canvas=e,this.ctx=e.getContext("2d");}destroy(){this.canvas=null,this.ctx=null,this.memoKey="",this.memo=null;}render(e){let t=this.ctx,n=this.canvas;if(!t||!n)return;let{bars:o,data:i,visible:s,coords:a,scale:l,bounds:c,theme:d}=e,u=a.dpr;if(t.setTransform(u,0,0,u,0,0),t.clearRect(0,0,n.width/u,n.height/u),!i||!s||o.length===0||c.height<=0)return;let h=a.visibleLogicalRange(),p=Math.max(0,Math.floor(h.from)),m=Math.min(o.length-1,Math.ceil(h.to));if(p>m)return;let f=o[m],g=`${p}:${m}:${o.length}:${f.high}:${f.low}:${f.close}:${f.volume??0}:${i.rows}:${i.valueAreaFrac}`;g!==this.memoKey&&(this.memoKey=g,this.memo=w0(o,p,m,i.rows,i.valueAreaFrac));let b=this.memo;b&&(t.save(),t.beginPath(),t.rect(0,c.top,a.width,c.height),t.clip(),x0(t,b,{rightX:a.width,maxW:a.width*i.widthFrac,yOf:y=>a.priceToY(y,l,c)},{upColor:i.upColor,downColor:i.downColor,showPoc:i.showPoc,pocColor:d.textColor}),t.restore());}};var Xe="price",QA=8,JA="rgba(0,0,0,0)",Od=64,eR=56,M0=26,ii=22,js=26,Vp=24,tR=5,nR="0 2px 8px rgba(0,0,0,0.4)",rR=12,R0=12,E0=Od+R0,Bp=ii+14,oR=120,iR=2,sR=6,P0=350,aR=.02,lR=220;function _p(){return typeof performance<"u"?performance.now():Date.now()}var cR=.004,dR=.2,uR=4,qs=class{constructor(e){this.capabilities=vw;this.surfaceBackground=tn.background;this.surfaceTextColor=tn.textColor;this.toolbarGutter=0;this.mountContainer=null;this.shadeRightEl=null;this.shadeRightSig="";this.userDrawings=null;this.priceAxisTicks=new ir;this.backdropRenderer=new Pd(this.priceAxisTicks);this.volumeRenderer=new Id;this.extLayers=[];this.layerOrderSig="";this.attributionEl=null;this.attributionEnabled=true;this.attributionHtml=null;this.vpvrRenderer=new Dd;this.resizeObserver=null;this.dprMedia=null;this.plotDeviceSize=null;this.coords=new jc;this.scene=new nd;this.backendMode="auto";this.glowAmount=0;this.chrome=new ud(this.priceAxisTicks);this.indicatorSlices=new Ld;this.labelTooltip=null;this.markPopover=null;this.marksExpandedBy="hover";this.markPulseRaf=null;this.markClickCbs=new Set;this.crosshairLayer=new pd;this.hostClock=null;this.ownClock=null;this.countdownUnsub=null;this.symbolPicker=null;this.indicatorTitlesOn=true;this.indicatorValuesOn=true;this.legendActionsProvider=null;this.legendCalloutsProvider=null;this.legendOverviewAction=null;this.keyboard=null;this.keyboardEnabled=true;this.historyChordsEnabled=true;this.liveRegion=null;this.animZoom=new tr(70);this.animPan=new tr(110);this.animScroll=new tr(130);this.animAutoscale=new tr(80);this.animLiveBar=new tr(90,0);this.candleUp=O;this.candleDown=D;this.intro={style:"settle",duration:650};this.introOnStyle="settle";this.introPlayed=false;this.introRaf=null;this.loadingEl=null;this.modelAlpha=1;this.targetBarSpacing=0;this.zoomAnchorLogical=0;this.zoomAnchorX=0;this.zoomAnchorMode="right";this.panVelocity=0;this.bars=[];this.didInitialFit=false;this.paintedData=false;this.skeletonClockMs=0;this.candleBodyAlpha=1;this.candleStructureAlpha=1;this.lastPointer=null;this.volumeActive=false;this.volumeHidden=false;this.vpvrActive=false;this.vpvrHidden=false;this.liveEaseTime=0;this.liveEaseHigh=0;this.liveEaseLow=0;this.liveEaseClose=0;this.axisDragEnabled=true;this.scaleDragHolder=null;this.scaleDragHeight=0;this.scaleDragStart=null;this.paneResizeEnabled=true;this.resizeAbove=null;this.resizeBelow=null;this.resizeSplitStart=null;this.drawingsInteractive=true;this.hoverSeparatorY=null;this.maximizedPaneId=null;this.rightAxisW=Od;this.paneControls=null;this.axisScaleButtons=null;this.paneActionCbs=new Set;this.hoverLogical=null;this.settingsDialog=null;this.hiddenSettings=[];this.dialogHost=null;this.settingsButton=null;this.settingsEnabled=false;this.scrollButton=null;this.pointerNearScrollBtn=false;this.scrollTargetRO=null;this.scrollBtnBottomPx=Bp;this.scrollBtnRightPx=E0;this.layoutMode="desktop";this.viewportCbs=new Set;this.crosshairCbs=new Set;this.chartTypeSettingsCbs=new Set;this.configChangedCbs=new Set;this.themeSelectCbs=new Set;this.factoryConfig=null;this.hostSettingsSections=[];this.clickCbs=new Set;this.axisLongPressCbs=new Set;this.inputChangeCbs=new Set;this.removeIndicatorCbs=new Set;this.toggleVisibleCbs=new Set;this.moveIndicatorCbs=new Set;this.priceStyleCbs=new Set;this.priceStyleWillChangeCbs=new Set;this.name="native";this.features=["logScale","currentPriceLine","priceLabel","countdown","upColor","downColor","glow","animZoom","animPan","animScroll","animAutoscale","animLiveBar","intro","zoomAnchor","axisDrag","paneResize","candleZOrder","candleVisible","seriesOrder","highlights","sessionZones","gridlines","axisLabels","scaleMode","invertScale","paneScales","autoScale","timezone","keyboard","historyChords","priceStyle","priceBaseline","baselinePrice","settings","attribution","dialogHost","tradeMarkers","marks","indicatorTitles","indicatorValues","crosshairOverride","drawingsInteractive","priceAxisTicks"];this.onScrollProximityMove=e=>{if(!this.scrollButton||!this.plot)return;let t=this.plot.getBoundingClientRect(),n=t.width-this.scrollBtnRightPx-js/2,o=t.height-this.scrollBtnBottomPx-js/2,i=Math.hypot(e.clientX-t.left-n,e.clientY-t.top-o)<=oR;i!==this.pointerNearScrollBtn&&(this.pointerNearScrollBtn=i,this.updateScrollToRealtimeButton());};this.onScrollProximityLeave=()=>{this.pointerNearScrollBtn&&(this.pointerNearScrollBtn=false,this.updateScrollToRealtimeButton());};this.onDprChange=()=>{this.watchDpr(),this.resize();};this.externalCross=null;this.snapMode="off";e&&(this.scene.showPriceLine=e.currentPriceLine,this.scene.logScale=e.logScale,this.backendMode=e.nativeBackend,this.animZoom.set(e.animZoom),this.animPan.set(e.animPan),this.animScroll.set(e.animScroll),this.animAutoscale.set(e.animAutoscale),this.animLiveBar.set(e.animLiveBar),this.setIntro(e.animIntro),this.glowAmount=e.glow,this.candleUp=e.upColor,this.candleDown=e.downColor,this.scene.priceStyle=e.priceStyle,this.scene.basePainting=zh(e.priceStyle),this.scene.candleOverride=$c(e.priceStyle,this.scene.style.chartTypes),typeof e.priceAxisTicks=="function"&&this.priceAxisTicks.setHook(e.priceAxisTicks)),this.theme=this.deriveTheme(tn);}applyFeature(e,t){switch(e){case "logScale":if(t&&typeof t=="object"){let n=t;this.setPaneLog(n.pane??Xe,!!n.value);return}this.scene.logScale=!!t;break;case "currentPriceLine":this.scene.showPriceLine=!!t;break;case "priceLabel":this.scene.showPriceLabel=!!t;break;case "countdown":this.scene.showCountdown=!!t,this.syncCountdownTimer();break;case "upColor":this.candleUp=String(t),this.theme&&(this.theme=this.deriveTheme(this.theme));break;case "downColor":this.candleDown=String(t),this.theme&&(this.theme=this.deriveTheme(this.theme));break;case "glow":this.glowAmount=Number(t)||0,this.backend&&"glow"in this.backend&&(this.backend.glow=this.glowAmount);break;case "animZoom":this.animZoom.set(Kt(t,70));return;case "animPan":{let n=Kt(t,110);this.animPan.set(n),this.animScroll.toggle(n>0);return}case "animScroll":this.animScroll.set(Kt(t,130));return;case "animAutoscale":this.animAutoscale.set(Kt(t,80));return;case "animLiveBar":this.animLiveBar.set(Xd(t));return;case "intro":{this.setIntro(jd(t)),this.intro.style&&this.playIntro();return}case "zoomAnchor":this.zoomAnchorMode=t==="right"?"right":"cursor",this.input&&(this.input.rightEdgeZoom=this.zoomAnchorMode==="right");return;case "axisDrag":this.axisDragEnabled=!!t,this.input&&(this.input.axisDrag=this.axisDragEnabled);return;case "paneResize":this.paneResizeEnabled=!!t,this.input&&(this.input.paneResize=this.paneResizeEnabled);return;case "candleZOrder":this.scene.candleZ=Number(t)||0;break;case "candleVisible":this.scene.candlesHidden=t===false;break;case "seriesOrder":this.applySeriesOrder(t);break;case "highlights":this.scene.highlights=fR(t);break;case "sessionZones":this.scene.sessionZones=gR(t);break;case "gridlines":this.scene.showGrid=!!t;break;case "axisLabels":this.scene.showAxisLabels=!!t;break;case "scaleMode":if(t&&typeof t=="object"){let n=t;this.setPaneScaleMode(n.pane??Xe,I0(n.mode));return}this.scene.scaleMode=I0(t);break;case "invertScale":if(t&&typeof t=="object"){let n=t;this.setPaneInvert(n.pane??Xe,!!n.value);return}this.scene.invertScale=!!t;break;case "autoScale":for(let n of this.scene.panes.values())n.manualScale=t?null:{...n.scale};break;case "timezone":this.scene.timezone=typeof t=="string"&&t?t:"UTC";break;case "priceStyle":this.setPriceStyle(bR(t)?t:"candles");break;case "priceBaseline":this.scene.baselineValue=t==null?null:Number(t);break;case "tradeMarkers":this.scene.tradeMarkers=Uw(this.scene.tradeMarkers,t);break;case "marks":this.scene.marks=Qw(this.scene.marks,t),this.markPopover?.close();break;case "crosshairOverride":this.scene.crosshairOverride=Tw(t);break;case "drawingsInteractive":this.drawingsInteractive=t!==false,this.input&&(this.input.drawings=this.drawingsInteractive),this.drawingsInteractive||this.userDrawings?.clearHover();return;case "priceAxisTicks":this.priceAxisTicks.setHook(typeof t=="function"?t:null);break;case "keyboard":this.setKeyboardEnabled(!!t);return;case "historyChords":this.historyChordsEnabled=!!t,this.userDrawings&&(this.userDrawings.historyChords=this.historyChordsEnabled);return;case "settings":this.setSettingsEnabled(!!t);return;case "indicatorTitles":this.indicatorTitlesOn=t!==false,this.inputsUI?.setTitlesVisible(this.indicatorTitlesOn);return;case "indicatorValues":this.indicatorValuesOn=t!==false,this.inputsUI?.setValuesVisible(this.indicatorValuesOn);return;case "attribution":this.attributionHtml=typeof t=="string"&&t.trim()?t:null,this.attributionEnabled=this.attributionHtml!==null||!!t,this.rebuildAttribution();return;case "dialogHost":this.dialogHost=t instanceof HTMLElement?t:null,this.settingsDialog?.close(),this.settingsDialog=null,this.inputsUI?.setDialogHost(this.dialogHost);return;default:return}this.scheduler?.invalidate(4);}readFeature(e){switch(e){case "logScale":return this.scene.logScale;case "currentPriceLine":return this.scene.showPriceLine;case "priceLabel":return this.scene.showPriceLabel;case "countdown":return this.scene.showCountdown;case "upColor":return this.candleUp;case "downColor":return this.candleDown;case "glow":return this.glowAmount;case "animZoom":return this.animZoom.tau;case "animPan":return this.animPan.tau;case "animScroll":return this.animScroll.tau;case "animAutoscale":return this.animAutoscale.tau;case "animLiveBar":return this.animLiveBar.tau;case "intro":return this.intro.style;case "zoomAnchor":return this.zoomAnchorMode;case "axisDrag":return this.input?this.input.axisDrag:this.axisDragEnabled;case "paneResize":return this.input?this.input.paneResize:this.paneResizeEnabled;case "candleZOrder":return this.scene.candleZ;case "candleVisible":return !this.scene.candlesHidden;case "seriesOrder":return this.scene.indicatorZOrder();case "highlights":return this.scene.highlights;case "sessionZones":return this.scene.sessionZones;case "gridlines":return this.scene.showGrid;case "axisLabels":return this.scene.showAxisLabels;case "scaleMode":return this.scene.scaleMode;case "invertScale":return this.scene.invertScale;case "paneScales":return this.paneScaleInfos();case "autoScale":{let t=this.scene.orderedPanes().find(n=>n.kind==="price");return t?t.manualScale==null:true}case "timezone":return this.scene.timezone;case "priceStyle":return this.scene.priceStyle;case "priceBaseline":return this.scene.baselineValue;case "baselinePrice":{let t=this.scene.panes.get(Xe);return t?this.scene.baselinePriceFor(t.scale):this.scene.baselineValue}case "tradeMarkers":return {...this.scene.tradeMarkers,colors:{...this.scene.tradeMarkers.colors}};case "marks":return {visible:this.scene.marks.visible,groups:{...this.scene.marks.groups}};case "crosshairOverride":return this.scene.crosshairOverride?{...this.scene.crosshairOverride}:null;case "drawingsInteractive":return this.drawingsInteractive;case "priceAxisTicks":return this.priceAxisTicks.hook;case "keyboard":return this.keyboardEnabled;case "historyChords":return this.historyChordsEnabled;case "settings":return this.settingsEnabled;case "indicatorTitles":return this.indicatorTitlesOn;case "indicatorValues":return this.indicatorValuesOn;case "attribution":return this.attributionHtml??this.attributionEnabled;case "dialogHost":return this.dialogHost??void 0;default:return}}setNativeData(e,t){e==="volume"?(this.scene.volumeLayer=t??null,this.scheduler?.invalidate(3)):e==="vpvr"?(this.scene.vpvrLayer=t??null,this.scheduler?.invalidate(3)):e.endsWith("-pending")?(this.scene.nativePending.set(e.slice(0,-8),t??[]),this.scheduler?.invalidate(3)):(this.scene.nativeData.set(e,t),this.scheduler?.invalidate(3));}setIndicatorStatus(e,t){this.inputsUI.setStatus(e.id,t);}setLoading(e){if(!e||!this.wrapper){this.loadingEl?.remove(),this.loadingEl=null;return}if(this.loadingEl)return;let t=this.wrapper.ownerDocument,n=t.createElement("div");n.className="vela-loading",Object.assign(n.style,{position:"absolute",inset:"0",display:"flex",alignItems:"center",justifyContent:"center",gap:"7px",pointerEvents:"none"});for(let o=0;o<3;o+=1){let i=t.createElement("span");Object.assign(i.style,{width:"7px",height:"7px",borderRadius:"50%",background:this.chromeTheme().textColor,opacity:"0.15"}),i.animate([{opacity:.12},{opacity:.55}],{duration:800,iterations:1/0,direction:"alternate",easing:"ease-in-out",delay:-o*260}),n.appendChild(i);}this.wrapper.appendChild(n),this.loadingEl=n;}setPricePrecision(e){let t=typeof e=="number"&&e>0?e:void 0;t!==this.scene.priceMintick&&(this.scene.priceMintick=t,this.scheduler?.invalidate(4));}getConfig(){let e=this.scene.style,t=Object.fromEntries(Object.entries(e.chartTypes).map(([o,i])=>[o,{...i}])),n=this.theme;return {version:_h,chartTypes:t,layout:{background:n.background,textColor:n.textColor,fontFamily:n.fontFamily,fontSize:e.fontSize},grid:{vertLines:{visible:e.gridVert.visible,color:e.gridVert.color??n.gridColor},horzLines:{visible:e.gridHorz.visible,color:e.gridHorz.color??n.gridColor}},crosshair:{color:e.crosshair.color??n.textColor,width:e.crosshair.width,style:e.crosshair.style,opacity:e.crosshair.opacity,labelBackground:e.crosshair.labelBackground??n.textColor},priceScale:{mode:this.scene.scaleMode,log:this.scene.logScale,invert:this.scene.invertScale,borderColor:e.borderColor??n.borderColor,labelsVisible:this.scene.showAxisLabels,currentPriceLine:this.scene.showPriceLine,priceLabel:this.scene.showPriceLabel,countdown:this.scene.showCountdown,animateLastPrice:this.animLiveBar.on},animations:{zoom:this.animZoom.on,pan:this.animPan.on,autoscale:this.animAutoscale.on,intro:this.intro.style!==false},panes:{separatorColor:e.separatorColor??n.borderColor},margins:{...e.margins},trades:{visible:this.scene.tradeMarkers.visible,labels:this.scene.tradeMarkers.labels,qty:this.scene.tradeMarkers.qty,longColor:this.scene.tradeMarkers.colors.long,shortColor:this.scene.tradeMarkers.colors.short,exitColor:this.scene.tradeMarkers.colors.exit},timeScale:{timezone:this.scene.timezone},marks:{visible:this.scene.marks.visible,groups:{...this.scene.marks.groups}},candles:{upColor:this.candleUp,downColor:this.candleDown,bodyVisible:e.candle.bodyVisible,borderVisible:e.candle.borderVisible,borderUpColor:e.candle.borderUpColor??this.candleUp,borderDownColor:e.candle.borderDownColor??this.candleDown,wickVisible:e.candle.wickVisible,wickUpColor:e.candle.wickUpColor??this.candleUp,wickDownColor:e.candle.wickDownColor??this.candleDown},bars:{upColor:e.bars.upColor??this.candleUp,downColor:e.bars.downColor??this.candleDown},line:{color:e.line.color??this.candleUp,width:e.line.width},stacking:{candles:this.scene.candleZ,series:Object.fromEntries(this.scene.indicatorZOrder().map(({id:o,z:i})=>[o,i]))},area:(()=>{let o=e.area.lineColor??this.candleUp;return {lineColor:o,width:e.area.width,topColor:e.area.topColor??o,bottomColor:e.area.bottomColor??JA}})(),baseline:(()=>{let o=e.baseline.topLineColor??$o,i=e.baseline.bottomLineColor??Uo;return {topLineColor:o,bottomLineColor:i,topFillColor:e.baseline.topFillColor??J(o,Rn),topFillColor2:e.baseline.topFillColor2??J(o,Dn),bottomFillColor:e.baseline.bottomFillColor??J(i,Rn),bottomFillColor2:e.baseline.bottomFillColor2??J(i,Dn),width:e.baseline.width,baselineLevel:e.baseline.baselineLevel}})(),series:{style:this.scene.priceStyle,baseline:this.scene.baselineValue,spacing:this.coords.spacingScale},sessions:{premarketColor:e.sessions.premarketColor,postmarketColor:e.sessions.postmarketColor,extendedColor:e.sessions.extendedColor}}}applyConfig(e){let t=Mw(this.getConfig(),e),n=this.scene.style;for(let[d,u]of Object.entries(t.chartTypes))if(JSON.stringify(n.chartTypes[d])!==JSON.stringify(u)){this.scene.nativeData.set(`${d}-settings`,{...u});for(let h of this.chartTypeSettingsCbs)h(d,{...u});}n.chartTypes=Object.fromEntries(Object.entries(t.chartTypes).map(([d,u])=>[d,{...u}]));let o=e&&typeof e=="object"?e.layout:void 0,i=o&&typeof o=="object"?o.textColor:void 0,s=typeof i=="string"&&i.trim().length>0,a=this.theme,l={textColor:t.layout.textColor,gridColor:a.gridColor,borderColor:a.borderColor};if(!s&&bt(t.layout.textColor)===bt(t.layout.background)){let d=bt(t.layout.background)?tn:Ri;l={textColor:d.textColor,gridColor:d.gridColor,borderColor:d.borderColor};}this.theme={...this.theme,background:t.layout.background,textColor:l.textColor,gridColor:l.gridColor,borderColor:l.borderColor,fontFamily:t.layout.fontFamily},n.fontSize=t.layout.fontSize;let c=(d,u,h)=>d===null&&u===h?null:u;n.gridVert={visible:t.grid.vertLines.visible,color:c(n.gridVert.color,t.grid.vertLines.color,a.gridColor)},n.gridHorz={visible:t.grid.horzLines.visible,color:c(n.gridHorz.color,t.grid.horzLines.color,a.gridColor)},n.crosshair={color:t.crosshair.color,width:t.crosshair.width,style:t.crosshair.style,opacity:t.crosshair.opacity,labelBackground:t.crosshair.labelBackground},this.scene.scaleMode=t.priceScale.mode,this.scene.logScale=t.priceScale.log,this.scene.invertScale=t.priceScale.invert,n.borderColor=c(n.borderColor,t.priceScale.borderColor,a.borderColor),this.scene.showAxisLabels=t.priceScale.labelsVisible,this.scene.showPriceLine=t.priceScale.currentPriceLine,this.scene.showPriceLabel=t.priceScale.priceLabel,this.scene.showCountdown=t.priceScale.countdown,this.syncCountdownTimer(),this.animLiveBar.toggle(t.priceScale.animateLastPrice),this.animZoom.toggle(t.animations.zoom),this.animPan.toggle(t.animations.pan),this.animScroll.toggle(t.animations.pan),this.animAutoscale.toggle(t.animations.autoscale),this.intro={style:t.animations.intro?this.introOnStyle:false,duration:this.intro.duration||650},n.separatorColor=c(n.separatorColor,t.panes.separatorColor,a.borderColor),t.margins.right!==n.margins.right&&this.coords.barCount>0&&this.applyViewport({barSpacing:this.coords.getViewport().barSpacing,rightOffset:t.margins.right}),n.margins={...t.margins},this.scene.tradeMarkers={visible:t.trades.visible,labels:t.trades.labels,qty:t.trades.qty,colors:{long:t.trades.longColor,short:t.trades.shortColor,exit:t.trades.exitColor}},this.scene.timezone=t.timeScale.timezone,this.scene.marks={visible:t.marks.visible,groups:{...t.marks.groups}},this.candleUp=t.candles.upColor,this.candleDown=t.candles.downColor,n.candle={bodyVisible:t.candles.bodyVisible,borderVisible:t.candles.borderVisible,borderUpColor:t.candles.borderUpColor,borderDownColor:t.candles.borderDownColor,wickVisible:t.candles.wickVisible,wickUpColor:t.candles.wickUpColor,wickDownColor:t.candles.wickDownColor},this.scene.candleZ=t.stacking.candles;for(let[d,u]of Object.entries(t.stacking.series))this.scene.setIndicatorZ(d,u);n.bars={upColor:t.bars.upColor,downColor:t.bars.downColor},n.line={color:t.line.color,width:t.line.width},n.area={lineColor:t.area.lineColor,width:t.area.width,topColor:t.area.topColor,bottomColor:t.area.bottomColor},n.baseline={topLineColor:t.baseline.topLineColor,bottomLineColor:t.baseline.bottomLineColor,topFillColor:t.baseline.topFillColor,topFillColor2:t.baseline.topFillColor2,bottomFillColor:t.baseline.bottomFillColor,bottomFillColor2:t.baseline.bottomFillColor2,width:t.baseline.width,baselineLevel:t.baseline.baselineLevel},n.sessions={premarketColor:t.sessions.premarketColor,postmarketColor:t.sessions.postmarketColor,extendedColor:t.sessions.extendedColor},this.setPriceStyle(t.series.style),this.scene.candleOverride=$c(this.scene.priceStyle,n.chartTypes),this.scene.baselineValue=t.series.baseline,this.coords.setPitchScale(t.series.spacing),this.coords.setViewport(this.clampViewport(this.coords.getViewport().barSpacing,this.coords.getViewport().rightOffset)),this.targetBarSpacing=this.coords.getViewport().barSpacing,this.theme=this.deriveTheme(this.theme),this.wrapper&&(_e(this.wrapper,this.chromeTheme()),this.applyBackground()),this.inputsUI?.setTheme(this.theme),this.paneControls?.setTheme(this.theme),this.axisScaleButtons?.setTheme(this.theme),this.userDrawings?.setTheme(this.chromeTheme()),this.refreshScrollButtonTheme(),this.refreshAttributionColor(),this.scheduler?.invalidate(4);for(let d of this.configChangedCbs)d();}applySeriesOrder(e){if(!e||typeof e!="object")return;let t=e;typeof t.id=="string"&&(typeof t.z=="number"?this.scene.setIndicatorZ(t.id,t.z):t.to==="front"?this.scene.bringIndicatorToFront(t.id):t.to==="back"&&this.scene.sendIndicatorToBack(t.id));}setSettingsEnabled(e){this.settingsEnabled=e,e?(this.plot&&!this.settingsButton&&(this.settingsButton=this.makeSettingsButton(),this.plot.appendChild(this.settingsButton)),this.settingsButton&&(this.settingsButton.style.display="flex"),this.plot&&!this.settingsDialog&&(this.settingsDialog=new Ws(this.dialogHost??this.plot,this.theme))):(this.settingsButton?.style.setProperty("display","none"),this.settingsDialog?.close());}makeSettingsButton(){let e=document.createElement("button");return e.type="button",e.title="Chart settings",e.innerHTML=Re("gear",14),Object.assign(e.style,{position:"absolute",bottom:`${ii+10}px`,right:`${Od+10}px`,zIndex:"6",width:"26px",height:"26px",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",borderRadius:"50%",border:`1px solid ${this.theme.borderColor}`,background:this.theme.background,color:this.theme.textColor,fontSize:"14px",lineHeight:"1",opacity:"0.75",pointerEvents:"auto",padding:"0"}),e.addEventListener("mouseenter",()=>e.style.opacity="1"),e.addEventListener("mouseleave",()=>e.style.opacity="0.75"),e.addEventListener("click",()=>this.toggleSettingsDialog()),e}openSettingsDialog(e){!this.settingsDialog&&this.plot&&(this.settingsDialog=new Ws(this.dialogHost??this.plot,this.theme),this.settingsDialog.setLayoutMode(this.layoutMode)),this.toggleSettingsDialog(e);}syncThemeControl(){this.settingsDialog?.setThemeControl(bt(this.surfaceBackground)?"dark":"light",e=>{for(let t of this.themeSelectCbs)t(e);});}toggleSettingsDialog(e){if(this.settingsDialog){if(e!==void 0&&this.settingsDialog.isOpen()){this.settingsDialog.showSection(e);return}this.settingsDialog.setTheme(this.theme),this.settingsDialog.setHostSections(this.hostSettingsSections),this.settingsDialog.setMarkGroups(this.markGroupsForEventsTab(),t=>td(this.scene.marks,t,this.scene.markGroups),t=>wl(this.scene.marks.groups,t,this.scene.markGroups)),this.settingsDialog.setHiddenSettings(this.hiddenSettings),this.syncThemeControl(),this.settingsDialog.toggle(this.getConfig(),t=>this.applyConfig(t),t=>this.applyConfig(t),()=>{this.factoryConfig&&this.applyConfig(this.factoryResetDocument(this.factoryConfig)),this.settingsDialog?.refresh(this.getConfig());},e);}}factoryResetDocument(e){let t=Lw(e,this.scene.priceStyle),n={...t.marks.groups};for(let o of this.markGroupsInUse())n[o.id]=o.visible!==false;return {...t,marks:{...t.marks,groups:n}}}closeDialogs(){this.inputsUI?.closeOpenDialog(),this.settingsDialog?.close();}makeScrollToRealtimeButton(){let e=document.createElement("button");return e.type="button",e.title="Scroll to most recent bar (Alt+Shift+\u2192)",e.setAttribute("aria-label","Scroll to most recent bar"),e.innerHTML=this.scrollButtonIcon(),Object.assign(e.style,{position:"absolute",bottom:`${Bp}px`,right:`${E0}px`,zIndex:"6",width:`${js}px`,height:`${js}px`,boxSizing:"border-box",display:"none",alignItems:"center",justifyContent:"center",cursor:"pointer",borderRadius:`${tR}px`,border:`1px solid ${this.theme.borderColor}`,boxShadow:nR,background:this.scrollButtonSurface(),color:this.theme.textColor,lineHeight:"0",opacity:"0.85",pointerEvents:"auto",padding:"0"}),e.addEventListener("mouseenter",()=>e.style.opacity="1"),e.addEventListener("mouseleave",()=>e.style.opacity="0.85"),e.addEventListener("click",()=>this.scrollToRealtime()),e}scrollButtonIcon(){return Re("chevrons-right",rR)}scrollButtonSurface(){return J(this.theme.background,.5)}refreshScrollButtonTheme(){this.scrollButton&&(this.scrollButton.style.background=this.scrollButtonSurface(),this.scrollButton.style.color=this.theme.textColor,this.scrollButton.style.borderColor=this.theme.borderColor);}updateScrollToRealtimeButton(){let e=this.scrollButton;if(!e)return;let t=this.coords.barCount>0&&this.coords.getViewport().rightOffset<0;if(this.layoutMode==="mobile"){e.style.display=t?"flex":"none";return}e.style.display=t&&this.pointerNearScrollBtn?"flex":"none";}scrollToRealtime(){this.coords.barCount!==0&&this.glideRightOffset(this.scene.style.margins.right);}glideRightOffset(e){let t=this.coords.getViewport();if(!this.animScroll.on){this.applyViewport({barSpacing:t.barSpacing,rightOffset:e});return}this.panVelocity=0,this.targetBarSpacing=t.barSpacing,this.scrollTargetRO=e,this.animator.start();}screenshotCanvas(){if(!this.dataCanvas)return null;this.computeScales(),this.paintData();let e=document.createElement("canvas");e.width=this.dataCanvas.width,e.height=this.dataCanvas.height;let t=e.getContext("2d");if(!t)return null;t.fillStyle=this.theme.background,t.fillRect(0,0,e.width,e.height);let n=this.plot?.getBoundingClientRect(),o=n&&n.width>0?{left:n.left,top:n.top,dpr:e.width/n.width}:null,i=[...this.mountContainer?.querySelectorAll("[data-vela-screenshot]")??[]];if(o)for(let s of i)s.getAttribute("data-vela-screenshot")==="under"&&Rd(t,s,o);for(let s of [...this.canvasPile(),this.chromeCanvas,this.drawingsCanvas])s&&s.width>0&&s.height>0&&t.drawImage(s,0,0);if(o){for(let s of this.plot?.querySelectorAll("[data-vela-pane]")??[])Rd(t,s,o);for(let s of i)s.getAttribute("data-vela-screenshot")!=="under"&&Rd(t,s,o);}return e}screenshot(){return this.screenshotCanvas()?.toDataURL("image/png")??null}playIntro(){this.introRaf!=null&&cancelAnimationFrame(this.introRaf),this.introRaf=null;let{style:e,duration:t}=this.intro,n=this.bars,o=n.length;if(o===0||!e)return;this.computeScales();for(let a of this.scene.panes.values())a.scale={...a.scaleTarget};this.modelAlpha=0;let i=performance.now(),s=a=>{let l=Math.min(1,(a-i)/t);this.scene.bars=l>=1?n:n.map((c,d)=>this.revealCandle(c,d,l,o,e)),this.paintData(),l<1?this.introRaf=requestAnimationFrame(s):(this.scene.bars=n,this.fadeInModels());};this.introRaf=requestAnimationFrame(s);}fadeInModels(){let e=Math.min(P0,this.intro.duration||P0),t=performance.now(),n=o=>{this.modelAlpha=Math.min(1,(o-t)/e),this.paintData(),this.modelAlpha<1?this.introRaf=requestAnimationFrame(n):(this.modelAlpha=1,this.introRaf=null);};this.introRaf=requestAnimationFrame(n);}revealCandle(e,t,n,o,i){let a=Math.max(0,Math.min(1,(n-t/Math.max(1,o-1)*.55)/.44999999999999996)),l;if(i==="settle"){let u=a-1;l=1+(1.70158+1)*u*u*u+1.70158*u*u;}else {let d=1-a;l=1-d*d*d;}let c=e.open;return {...e,high:c+(e.high-c)*l,low:c+(e.low-c)*l,close:c+(e.close-c)*l}}deriveTheme(e){return {...e,upColor:this.candleUp,downColor:this.candleDown}}chromeTheme(){return {...this.theme,background:this.surfaceBackground,textColor:this.surfaceTextColor,borderColor:bt(this.surfaceBackground)?tn.borderColor:Ri.borderColor}}axisSurface(){return {background:this.theme.background,textColor:this.theme.textColor}}mount(e,t){this.mountContainer=e,this.publishGutters(),this.theme=this.deriveTheme(t),this.surfaceBackground=t.background,this.surfaceTextColor=t.textColor,this.wrapper=document.createElement("div"),Object.assign(this.wrapper.style,{position:"relative",width:"100%",height:"100%",overflow:"hidden",cursor:"crosshair",userSelect:"none",webkitUserSelect:"none"}),_e(this.wrapper,this.chromeTheme()),this.backdropCanvas=document.createElement("canvas"),Object.assign(this.backdropCanvas.style,{position:"absolute",inset:"0",width:"100%",height:"100%",pointerEvents:"none"}),this.volumeCanvas=document.createElement("canvas"),Object.assign(this.volumeCanvas.style,{position:"absolute",inset:"0",width:"100%",height:"100%",pointerEvents:"none"}),this.dataCanvas=this.createGeometryBackend(),this.vpvrCanvas=document.createElement("canvas"),Object.assign(this.vpvrCanvas.style,{position:"absolute",inset:"0",width:"100%",height:"100%",pointerEvents:"none"}),this.chromeCanvas=document.createElement("canvas"),Object.assign(this.chromeCanvas.style,{position:"absolute",inset:"0",width:"100%",height:"100%",pointerEvents:"none"}),this.drawingsCanvas=document.createElement("canvas"),Object.assign(this.drawingsCanvas.style,{position:"absolute",inset:"0",width:"100%",height:"100%",pointerEvents:"none"}),this.cursorCanvas=document.createElement("canvas"),Object.assign(this.cursorCanvas.style,{position:"absolute",inset:"0",width:"100%",height:"100%",pointerEvents:"none"}),this.shadeRightEl=document.createElement("div"),this.shadeRightEl.className="vela-shade-right",this.shadeRightEl.setAttribute("aria-hidden","true"),this.shadeRightEl.hidden=true,Object.assign(this.shadeRightEl.style,{position:"absolute",top:"0",left:"0",width:"0",height:"0",pointerEvents:"none",display:"none"}),this.shadeRightSig="",this.overlayRoot=document.createElement("div"),Object.assign(this.overlayRoot.style,{position:"absolute",inset:"0",pointerEvents:"none"}),this.plot=document.createElement("div"),Object.assign(this.plot.style,{position:"absolute",top:"0",right:"0",bottom:"0",left:"0"}),this.extLayers=Rp().map(i=>({def:i,instance:i.create(),canvas:this.createLayerCanvas(),channel:i.id,owner:null}));let n=this.extLayers.filter(i=>i.def.placement==="below-data").map(i=>i.canvas),o=this.extLayers.filter(i=>i.def.placement!=="below-data").map(i=>i.canvas);this.plot.append(this.backdropCanvas,...n,this.dataCanvas,this.volumeCanvas,this.vpvrCanvas,...o,this.chromeCanvas,this.drawingsCanvas,this.shadeRightEl,this.cursorCanvas,this.overlayRoot),this.layerOrderSig="",this.wrapper.appendChild(this.plot),this.factoryConfig=this.getConfig(),this.attributionEl=this.buildAttributionEl(),this.attributionEnabled||(this.attributionEl.style.display="none"),this.positionAttribution(),this.wrapper.appendChild(this.attributionEl),e.appendChild(this.wrapper),this.applyBackground(),this.backdropRenderer.mount(this.backdropCanvas),this.volumeRenderer.mount(this.volumeCanvas),this.vpvrRenderer.mount(this.vpvrCanvas);for(let i of this.extLayers)i.instance.mount(i.canvas);for(let i of this.scene.indicators.values())this.ensureInstanceLayer(i);this.chrome.mount(this.chromeCanvas),this.crosshairLayer.mount(this.cursorCanvas),this.coords.setViewport(Xc()),this.scene.ensurePane(Xe,"price",0,3),this.scheduler=new qc(i=>this.renderFrame(i)),this.animator=new Zc(i=>this.animTick(i)),this.targetBarSpacing=this.coords.getViewport().barSpacing,this.input=new Qc({getCoords:()=>this.coords,apply:i=>this.applyViewport(i),zoomTo:(i,s,a)=>this.zoomTo(i,s,a),fling:i=>this.fling(i),onPointerMove:(i,s)=>this.handlePointerMove(i,s),onClick:(i,s)=>{this.handleMarkClick(i,s)||(this.userDrawings?.deselect(),this.handleClick(i));},onAxisLongPress:(i,s,a)=>{for(let l of this.axisLongPressCbs)l({axis:i,x:s,y:a});},beginPriceScale:(i,s)=>this.beginPriceScale(i,s),priceScaleBy:i=>this.priceScaleBy(i),beginPricePan:i=>this.beginPricePan(i),pricePanBy:i=>this.pricePanBy(i),resetPriceScale:(i,s)=>this.resetPriceScale(i,s),dataDblClick:(i,s)=>this.dataDblClick(i,s),paneSeparatorAt:i=>this.paneSeparatorAt(i),beginPaneResize:i=>this.beginPaneResize(i),paneResizeBy:i=>this.paneResizeBy(i),resetPaneSize:i=>this.resetPaneSize(i),resetView:()=>this.resetView(),drawingsClaim:(i,s)=>this.userDrawings?.claim(i,s)??false,drawingsMeasureStart:(i,s,a)=>this.userDrawings?.beginMeasureAt(i,s,a)??false,drawingsMarqueeStart:(i,s)=>this.userDrawings?.beginMarqueeAt(i,s)??false,drawingsDeleteAt:(i,s)=>this.userDrawings?.deleteAt(i,s,true)??false,drawingsCancelPlacement:()=>this.userDrawings?.cancelPlacement()??false,drawingsSnapMode:()=>this.snapMode,drawingsPointerDown:(i,s,a,l,c)=>this.userDrawings?.pointerDown(i,s,a,l,c),drawingsPointerMove:(i,s,a,l,c)=>this.userDrawings?.pointerMove(i,s,a,l,c),drawingsPointerUp:(i,s,a)=>this.userDrawings?.pointerUp(i,s,a),drawingsCursor:(i,s)=>(this.drawingsInteractive?this.userDrawings?.cursorAt(i,s):null)??(this.chrome.markGlyphAt(i,s)?"pointer":null),drawingsDblClick:(i,s)=>this.userDrawings?.dblClick(i,s)??false,drawingsClearTransient:()=>this.userDrawings?.clearTransient()}),this.input.rightEdgeZoom=this.zoomAnchorMode==="right",this.input.axisDrag=this.axisDragEnabled,this.input.paneResize=this.paneResizeEnabled,this.input.drawings=this.drawingsInteractive,this.input.attach(this.dataCanvas),this.settingsEnabled&&this.setSettingsEnabled(true),this.syncCountdownTimer(),this.scrollButton=this.makeScrollToRealtimeButton(),this.plot.appendChild(this.scrollButton),this.plot.addEventListener("pointermove",this.onScrollProximityMove),this.plot.addEventListener("pointerleave",this.onScrollProximityLeave),this.labelTooltip=new hd(this.plot,{theme:()=>this.chromeTheme(),lookup:(i,s)=>this.indicatorSlices.labelTooltipAt(i,s)??this.chrome.markTooltipAt(i,s,this.markGroupsInUse())}),this.markPopover=new Ed({plot:this.plot,host:()=>this.dialogHost??this.plot,theme:()=>this.chromeTheme(),onOpenChange:i=>{this.scene.marksActiveKey=i,this.scheduler?.invalidate(2);}}),this.chrome.setMarkIconReady(()=>this.scheduler?.invalidate(2)),this.userDrawings=new Td(this.wrapper,this.plot,this.drawingsCanvas,{projector:()=>this.drawingProjector(),dpr:()=>this.coords.dpr,theme:()=>this.theme,requestScaleUpdate:()=>this.scheduler.invalidate(3),seriesBoundaries:i=>this.scene.seriesBoundaries(i),priceZ:i=>i===Xe?this.scene.candleZ:null,requestDataPaint:()=>this.scheduler.invalidate(3),seriesLook:()=>{let i=this.scene.style,s=Ko(i.candle,this.scene.candleOverride,this.theme.upColor,this.theme.downColor),a=i.bars.upColor??this.theme.upColor,l=i.bars.downColor??this.theme.downColor,c=this.scene.priceStyle;return {style:c,upColor:c==="bars"?a:s.up,downColor:c==="bars"?l:s.down,lineColor:c==="area"?i.area.lineColor??this.theme.upColor:i.line.color??this.theme.upColor}},chartBarMs:()=>this.coords.barInterval,snap:(i,s,a,l)=>this.snapToCandle(i,s,a,l),setSnapMode:i=>this.setSnapMode(i),setToolbarGutter:i=>this.setToolbarGutter(i)}),this.userDrawings.historyChords=this.historyChordsEnabled,this.layoutMode==="mobile"&&(this.mountContainer?.setAttribute("data-vela-layout",this.layoutMode),this.userDrawings.setLayoutMode(this.layoutMode),this.scrollButton&&(this.scrollButton.style.width=`${Vp}px`,this.scrollButton.style.height=`${Vp}px`)),this.keyboard=new Jc({panByBars:i=>this.panByBars(i),zoomByStep:i=>this.zoomByStep(i),stepCrosshair:i=>this.stepCrosshair(i),jumpToEdge:i=>this.focusBar(i==="first"?0:this.coords.barCount-1),resetView:()=>this.resetView(),scrollToRealtime:()=>this.scrollToRealtime(),clearCrosshair:()=>this.handlePointerMove(null,null),preempt:i=>this.userDrawings?.handleKey(i)??false}),this.setKeyboardEnabled(this.keyboardEnabled),this.inputsUI=new _c(this.plot,t,i=>this.paneBoundsFor(i)),this.inputsUI.setLayoutMode(this.layoutMode),this.inputsUI.setTitlesVisible(this.indicatorTitlesOn),this.inputsUI.setValuesVisible(this.indicatorValuesOn),this.inputsUI.setDialogHost(this.dialogHost),this.inputsUI.setSymbolPicker(this.symbolPicker),this.inputsUI.setLegendActions(this.legendActionsProvider),this.inputsUI.setLegendCallouts(this.legendCalloutsProvider),this.inputsUI.setLegendOverviewAction(this.legendOverviewAction),this.inputsUI.setOnChange(i=>{for(let s of this.inputChangeCbs)s({indicatorId:i.indicatorId,key:i.key,value:i.value,...i.kind?{kind:i.kind}:{}});}),this.inputsUI.setOnRemove(i=>{for(let s of this.removeIndicatorCbs)s(i);}),this.inputsUI.setOnToggleVisible((i,s)=>{for(let a of this.toggleVisibleCbs)a(i,s);}),this.inputsUI.setMoveApi({panes:()=>this.scene.orderedPanes().map((i,s)=>({id:i.id,kind:i.kind,label:i.kind==="price"?"Main chart":this.paneMasterTitle(i.id)??`Pane ${s}`,top:i.bounds.top,height:i.bounds.height})),move:(i,s)=>{for(let a of this.moveIndicatorCbs)a(i,s);}}),this.paneControls=new Hc(this.plot,t,{panes:()=>this.paneControlViews(),rightAxis:()=>this.rightAxisW,onMove:(i,s)=>this.movePaneLocal(i,s),onToggleCollapse:i=>{let s=this.scene.panes.get(i);if(!s)return;let a=!s.collapsed;s.collapsed=a,this.afterPaneLayoutChange(),this.emitPaneAction({type:"collapse",paneId:i,collapsed:a});},onToggleMaximize:i=>{let s=this.maximizedPaneId!==i;this.maximizedPaneId=s?i:null,this.afterPaneLayoutChange(),this.emitPaneAction({type:"maximize",paneId:i,maximized:s});}}),this.paneControls.setSuspended(this.layoutMode==="mobile"),this.axisScaleButtons=new zc(this.plot,t,{panes:()=>this.axisScaleViews(),rightAxis:()=>this.rightAxisW,onToggleAuto:i=>this.togglePaneAuto(i),onToggleLog:i=>{let s=this.scene.panes.get(i);s&&this.setPaneLog(i,!Zo(this.scene,s));}}),this.resizeObserver=new ResizeObserver(i=>{for(let s of i){if(s.target!==this.plot)continue;let a=s.devicePixelContentBoxSize?.[0];a&&(this.plotDeviceSize={width:a.inlineSize,height:a.blockSize});}this.resize();}),this.resizeObserver.observe(this.wrapper);try{this.resizeObserver.observe(this.plot,{box:"device-pixel-content-box"});}catch{}this.watchDpr(),this.syncSize();}makeDataCanvas(){let e=document.createElement("canvas");return Object.assign(e.style,{position:"absolute",inset:"0",width:"100%",height:"100%"}),e}createGeometryBackend(){if((this.backendMode==="auto"||this.backendMode==="webgl2")&&yw()){let n=this.makeDataCanvas(),o=new Kc;if(o.glow=this.glowAmount,o.onNeedsRedraw=()=>this.scheduler?.invalidate(4),o.onContextFailed=()=>this.swapToCanvas2dFallback(),o.mount(n),o.ok)return this.backend=o,n;o.destroy();}let e=this.makeDataCanvas(),t=new Ds;return t.mount(e),this.backend=t,e}swapToCanvas2dFallback(){if(this.backend.kind==="canvas2d")return;let e=this.dataCanvas;this.input?.detach(),this.backend.destroy();let t=this.makeDataCanvas(),n=new Ds;n.mount(t),this.backend=n,e.replaceWith(t),this.dataCanvas=t,this.input?.attach(t),this.syncSize();}watchDpr(){typeof window.matchMedia=="function"&&(this.dprMedia?.removeEventListener("change",this.onDprChange),this.dprMedia=window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`),this.dprMedia.addEventListener("change",this.onDprChange,{once:true}));}setTheme(e){this.theme=this.deriveTheme(e),this.surfaceBackground=e.background,this.surfaceTextColor=e.textColor,this.wrapper&&_e(this.wrapper,this.chromeTheme()),this.applyBackground(),this.inputsUI.setTheme(e),this.paneControls?.setTheme(this.theme),this.axisScaleButtons?.setTheme(this.theme),this.settingsDialog?.refreshConfig(this.getConfig()),this.syncThemeControl(),this.settingsDialog?.setTheme(this.theme),this.settingsButton&&(this.settingsButton.style.background=this.theme.background,this.settingsButton.style.color=this.theme.textColor,this.settingsButton.style.borderColor=this.theme.borderColor),this.refreshScrollButtonTheme(),this.userDrawings?.setTheme(this.chromeTheme()),this.refreshAttributionColor(),this.scheduler.invalidate(4);}resize(){this.syncSize();}setWallClock(e){e!==this.hostClock&&(this.hostClock=e,this.countdownUnsub!=null&&(this.countdownUnsub(),this.countdownUnsub=null),this.syncCountdownTimer());}syncCountdownTimer(){if(this.scene.showCountdown){if(this.countdownUnsub==null){let e=this.hostClock??this.ownClock??(this.ownClock=new Gi);this.countdownUnsub=e.onTick(()=>{this.scene.showCountdown&&this.scene.bars.length>0&&this.scheduler?.invalidate(2);});}}else this.countdownUnsub!=null&&(this.countdownUnsub(),this.countdownUnsub=null);}destroy(){this.introRaf!=null&&cancelAnimationFrame(this.introRaf),this.loadingEl?.remove(),this.loadingEl=null,this.countdownUnsub!=null&&(this.countdownUnsub(),this.countdownUnsub=null),this.scheduler?.destroy(),this.animator?.stop(),this.input?.detach(),this.keyboard?.detach(),this.keyboard=null,this.liveRegion=null,this.inputsUI?.destroy(),this.paneControls?.destroy(),this.axisScaleButtons?.destroy(),this.resizeObserver?.disconnect(),this.resizeObserver=null,this.dprMedia?.removeEventListener("change",this.onDprChange),this.dprMedia=null,this.userDrawings?.destroy(),this.userDrawings=null,this.settingsDialog?.destroy(),this.settingsDialog=null,this.settingsButton?.remove(),this.settingsButton=null,this.plot?.removeEventListener("pointermove",this.onScrollProximityMove),this.plot?.removeEventListener("pointerleave",this.onScrollProximityLeave),this.labelTooltip?.destroy(),this.labelTooltip=null,this.markPopover?.destroy(),this.markPopover=null,this.chrome.setMarkIconReady(null),this.markPulseRaf!==null&&cancelAnimationFrame(this.markPulseRaf),this.markPulseRaf=null,this.scrollButton?.remove(),this.scrollButton=null;for(let e of this.extLayers)e.instance.destroy?.();this.extLayers=[],this.backdropRenderer.destroy(),this.volumeRenderer.destroy(),this.vpvrRenderer.destroy(),this.backend.destroy(),this.chrome.destroy(),this.crosshairLayer.destroy(),this.shadeRightEl?.remove(),this.shadeRightEl=null,this.attributionEl?.remove(),this.attributionEl=null,this.mountContainer?.style.removeProperty("--vela-toolbar-gutter"),this.mountContainer?.style.removeProperty("--vela-scale-gutter"),this.mountContainer?.style.removeProperty("--vela-bottom-gutter"),this.mountContainer?.style.removeProperty("--vela-price-pane-top"),this.mountContainer?.style.removeProperty("--vela-price-pane-bottom"),this.mountContainer=null,this.wrapper?.remove();}setBars(e,t){this.introRaf!=null&&(cancelAnimationFrame(this.introRaf),this.introRaf=null,this.modelAlpha=1),this.liveEaseTime=0;let n=this.bars,o=n[0]?.time;this.bars=vR(e),this.scene.bars=this.bars,this.coords.setBars(this.bars.map(s=>s.time));for(let s of this.scene.indicators.values())this.refreshAnchorOffset(s);if(t?.preserveView===true&&o!=null&&this.bars.length>0){let s=this.bars[0].time,a=0;if(s!==o){let l=this.bars.findIndex(c=>c.time===o);if(l>0)a=l;else {let c=n.findIndex(d=>d.time===s);c>0&&(a=-c);}}a!==0&&(this.zoomAnchorLogical+=a,this.hoverLogical!=null&&(this.hoverLogical+=a));}let i=t?.preserveView===true&&this.didInitialFit;if(this.coords.width>0&&!i&&(this.didInitialFit?this.reframeKeepZoom():this.fitContent(),this.didInitialFit=true),!this.introPlayed&&this.bars.length>0&&(this.introPlayed=true,this.intro.style)){this.playIntro();return}this.scheduler.invalidate(4);}updateBar(e){let t=this.bars.length,n=this.bars[t-1];if(n&&e.time===n.time)this.bars[t-1]=e,!this.animLiveBar.on||this.liveEaseTime!==e.time?this.syncLiveEase(e):this.animator.start();else if(!n||e.time>n.time){let o=this.coords.getViewport(),i=t>0&&o.rightOffset<0&&this.scrollTargetRO===null;this.bars.push(e),this.syncLiveEase(e),this.coords.barInterval>0?this.coords.appendBar(e.time):this.coords.setBars(this.bars.map(s=>s.time)),i&&this.coords.setViewport({...o,rightOffset:o.rightOffset-1});}else return;this.scene.bars=this.bars,this.scheduler.invalidate(4);}setIntro(e){this.intro=e,e.style&&(this.introOnStyle=e.style);}syncLiveEase(e){this.liveEaseTime=e.time,this.liveEaseHigh=e.high,this.liveEaseLow=e.low,this.liveEaseClose=e.close;}easeLiveBar(e){let t=this.bars[this.bars.length-1];if(!t||this.liveEaseTime!==t.time)return false;let n=Math.max(1e-9,Math.abs(t.close)*1e-6),o=this.animLiveBar.tau,i=Lt(this.liveEaseHigh,t.high,e,o),s=Lt(this.liveEaseLow,t.low,e,o),a=Lt(this.liveEaseClose,t.close,e,o),l=Math.abs(i-t.high)>n||Math.abs(s-t.low)>n||Math.abs(a-t.close)>n;return this.liveEaseHigh=l?i:t.high,this.liveEaseLow=l?s:t.low,this.liveEaseClose=l?a:t.close,l}ensurePane(e){this.scene.ensurePane(e.id,e.kind,e.order,e.heightWeight??(e.kind==="price"?3:1)),this.layoutPanes(),this.paneControls?.refresh(),this.scheduler.invalidate(4);}removePane(e){e!==Xe&&(this.scene.removePane(e),this.maximizedPaneId===e&&(this.maximizedPaneId=null),this.refreshAxisWidth(),this.layoutPanes(),this.paneControls?.refresh(),this.scheduler.invalidate(4));}setIndicatorPane(e,t,n){let o=this.scene.indicators.get(e.id);o&&(o.paneId=t,o.ownScale=n?.ownScale===true,o.ownScale||this.scene.dropIndicatorScale(e.id),this.inputsUI.setPane(e.id,t),this.refreshAnchorOffset(o),this.refreshAxisWidth(),this.layoutPanes(),this.paneControls?.refresh(),this.scheduler.invalidate(4));}orderPanes(e){this.scene.orderPanes(e),this.layoutPanes(),this.paneControls?.refresh(),this.scheduler.invalidate(4);}setPaneCollapsed(e,t){let n=this.scene.panes.get(e);!n||n.collapsed===t||(n.collapsed=t,this.layoutPanes(),this.paneControls?.refresh(),this.scheduler.invalidate(4));}setPaneMaximized(e){e!==null&&!this.scene.panes.has(e)&&(e=null),this.maximizedPaneId=e,this.layoutPanes(),this.paneControls?.refresh(),this.scheduler.invalidate(4);}onPaneAction(e){return this.paneActionCbs.add(e),()=>this.paneActionCbs.delete(e)}emitPaneAction(e){for(let t of this.paneActionCbs)t(e);}onMoveIndicator(e){return this.moveIndicatorCbs.add(e),()=>this.moveIndicatorCbs.delete(e)}maxOwnScaleColumns(){let e=0;for(let t of this.scene.panes.values()){let n=this.scene.ownScaleIndicatorsForPane(t.id).length;n>e&&(e=n);}return e}refreshAxisWidth(){let e=Od+eR*this.maxOwnScaleColumns();return e===this.rightAxisW?false:(this.rightAxisW=e,this.publishGutters(),this.coords.width>0&&this.syncSize(),true)}refreshAnchorOffset(e){let t=e.anchorTime;if(t==null||this.bars.length===0){this.scene.setAnchorOffset(e.id,0);return}let n=this.bars[0].time;if(t===n){this.scene.setAnchorOffset(e.id,0);return}if(t>1;this.bars[a].time>=t?(s=a,i=a-1):o=a+1;}if(s>=this.bars.length||this.bars[s].time!==t){console.warn(`[vela] indicator "${e.id}" anchorTime matches no chart bar \u2014 rendering unanchored`),this.scene.setAnchorOffset(e.id,0);return}this.scene.setAnchorOffset(e.id,s);}mountIndicator(e){return this.scene.indicators.set(e.id,e),this.refreshAnchorOffset(e),e.native&&this.extLayers.some(t=>t.def.id===e.native.type)?this.scene.assignIndicatorZTop(e.id):this.scene.assignIndicatorZ(e.id),this.ensureInstanceLayer(e),e.legend!==false&&this.inputsUI.upsert(e.id,e.shorttitle??e.title,e.inputs,e.inputValues,e.paneId,{native:!!e.native,...e.props?{props:e.props,propValues:e.propValues??{}}:{}}),e.native?.type==="volume"?(this.volumeActive=true,this.volumeHidden=false):e.native?.type==="vpvr"&&(this.vpvrActive=true,this.vpvrHidden=false),e.ownScale&&this.refreshAxisWidth(),this.paneControls?.refresh(),this.scheduler.invalidate(4),{id:e.id}}updateIndicator(e,t){let n=this.scene.indicators.get(e.id);if(n){if(t.kind==="value"&&t.anchorTime!==void 0){let o=t.anchorTime??void 0;o!==n.anchorTime&&(n.anchorTime=o,this.refreshAnchorOffset(n));}pR(n,t),this.scheduler.invalidate(3);}}removeIndicator(e){let t=this.scene.indicators.get(e.id)?.native?.type;t==="volume"?(this.volumeActive=false,this.volumeHidden=false,this.scene.volumeLayer=null):t==="vpvr"&&(this.vpvrActive=false,this.vpvrHidden=false,this.scene.vpvrLayer=null),this.scene.indicators.delete(e.id),this.dropInstanceLayer(e.id),this.scene.forgetIndicatorZ(e.id),this.scene.forgetAnchorOffset(e.id),this.scene.dropIndicatorScale(e.id),this.inputsUI.remove(e.id),this.refreshAxisWidth(),this.paneControls?.refresh(),this.scheduler.invalidate(4);}setIndicatorInputs(e,t,n){this.inputsUI.setValues(e.id,t,n);}setSymbolPicker(e){this.symbolPicker=e,this.inputsUI?.setSymbolPicker(e);}setLegendActions(e){this.legendActionsProvider=e,this.inputsUI?.setLegendActions(e);}setLegendCallouts(e){this.legendCalloutsProvider=e,this.inputsUI?.setLegendCallouts(e);}setLegendOverviewAction(e){this.legendOverviewAction=e,this.inputsUI?.setLegendOverviewAction(e);}openIndicatorSettings(e){this.inputsUI?.openSettingsFor(e);}setIndicatorVisible(e,t){let n=this.scene.indicators.get(e.id)?.native?.type;if(n==="volume"||n==="vpvr"){n==="volume"?this.volumeHidden=!t:this.vpvrHidden=!t,this.inputsUI.setVisible(e.id,t),this.scheduler.invalidate(4);return}t||this.scene.indicators.delete(e.id),this.inputsUI.setVisible(e.id,t),this.scheduler.invalidate(4);}onInputChange(e){return this.inputChangeCbs.add(e),()=>this.inputChangeCbs.delete(e)}onToggleIndicatorVisible(e){return this.toggleVisibleCbs.add(e),()=>this.toggleVisibleCbs.delete(e)}onPriceStyleChange(e){return this.priceStyleCbs.add(e),()=>this.priceStyleCbs.delete(e)}onPriceStyleWillChange(e){return this.priceStyleWillChangeCbs.add(e),()=>this.priceStyleWillChangeCbs.delete(e)}setPriceStyle(e){if(e===this.scene.priceStyle)return;let t=this.scene.priceStyle;for(let n of this.priceStyleWillChangeCbs)n(t,e);this.scene.priceStyle=e,this.scene.basePainting=zh(e),this.scene.candleOverride=$c(e,this.scene.style.chartTypes);for(let n of this.priceStyleCbs)n(e);}onRemoveIndicator(e){return this.removeIndicatorCbs.add(e),()=>this.removeIndicatorCbs.delete(e)}setLayoutMode(e){if(e!==this.layoutMode){if(this.layoutMode=e,this.mountContainer?.setAttribute("data-vela-layout",e),this.userDrawings?.setLayoutMode(e),this.settingsDialog?.setLayoutMode(e),this.inputsUI?.setLayoutMode(e),this.paneControls?.setSuspended(e==="mobile"),this.scrollButton){let t=e==="mobile"?Vp:js;this.scrollButton.style.width=`${t}px`,this.scrollButton.style.height=`${t}px`;}this.updateScrollToRealtimeButton();}}setSettingsSections(e){this.hostSettingsSections=e,this.settingsDialog?.setHostSections(e);}setSettingsVisibility(e){this.hiddenSettings=[...e.hidden??[]],this.settingsDialog?.setHiddenSettings(this.hiddenSettings);}listSettingsIds(){return Cx(this.hostSettingsSections,this.markGroupsInUse())}onChartTypeSettingsChange(e){return this.chartTypeSettingsCbs.add(e),()=>this.chartTypeSettingsCbs.delete(e)}onConfigChanged(e){return this.configChangedCbs.add(e),()=>this.configChangedCbs.delete(e)}onThemeSelect(e){return this.themeSelectCbs.add(e),()=>this.themeSelectCbs.delete(e)}onCrosshairMove(e){return this.crosshairCbs.add(e),()=>this.crosshairCbs.delete(e)}onClick(e){return this.clickCbs.add(e),()=>this.clickCbs.delete(e)}onAxisLongPress(e){return this.axisLongPressCbs.add(e),()=>this.axisLongPressCbs.delete(e)}setTimelineMarks(e,t){this.scene.timelineMarks=e,this.scene.markGroups=t,this.scene.marksExpandedStack=null,this.markPopover?.close(),this.scheduler?.invalidate(2);}onMarkClick(e){return this.markClickCbs.add(e),()=>this.markClickCbs.delete(e)}markGroupsInUse(){return mx(this.scene.timelineMarks,this.scene.markGroups)}markGroupsForEventsTab(){let e=new Set(this.scene.markGroups.map(t=>t.id));return this.markGroupsInUse().map(t=>t.parent!==void 0&&!e.has(t.parent)?{...t,parent:void 0}:t)}onViewportChange(e){return this.viewportCbs.add(e),()=>this.viewportCbs.delete(e)}getVisibleRange(){let e=this.coords.barCount;if(e===0||this.coords.width===0)return null;let t=this.coords.visibleLogicalRange(),n=Math.max(0,Math.ceil(t.from)),o=Math.min(e-1,Math.floor(t.to));return os*.001?(n=pn(Lt(n,s,e,this.animZoom.tau)),o=this.anchoredRightOffset(n),i=true):n!==s&&(n=s,o=this.anchoredRightOffset(n));let a=aR/Math.max(1e-6,n*this.coords.spacingScale);if(Math.abs(this.panVelocity)>a){o+=this.panVelocity*e;let c=this.animPan.tau;this.panVelocity=c>0?this.panVelocity*Math.exp(-e/c):0,Math.abs(this.panVelocity)<=a?this.panVelocity=0:i=true;}if(this.scrollTargetRO!=null){let c=this.scrollTargetRO,d=Lt(o,c,e,this.animScroll.tau);Math.abs(d-c)<.001?(o=c,this.scrollTargetRO=null):(o=d,i=true);}let l=this.clampViewport(n,o);return l.barSpacing!==n&&(this.targetBarSpacing=l.barSpacing),this.scrollTargetRO!=null&&l.rightOffset!==o&&(this.scrollTargetRO=l.rightOffset),this.coords.setViewport(l),this.computeScales(),this.easeScales(e)&&(i=true),this.easeLiveBar(e)&&(i=true),this.skeletonClockMs+=e,this.paintData(),this.renderCrosshairLayer(),this.updateLegendValues(),this.emitViewportChange(),i}easeScales(e){let t=false,n=this.animAutoscale.tau;for(let o of this.scene.panes.values()){let i=o.scaleTarget,s=o.scale;if(i.log&&s.min>0&&i.min>0){let d=Math.log(i.min),u=Math.log(i.max),h=Math.max(1e-9,Math.abs(u-d)),p=Lt(Math.log(s.min),d,e,n),m=Lt(Math.log(s.max),u,e,n);Math.abs(p-d)<=h*.001&&Math.abs(m-u)<=h*.001?o.scale={min:i.min,max:i.max,log:true}:(t=true,o.scale={min:Math.exp(p),max:Math.exp(m),log:true});continue}let a=Math.max(1e-9,Math.abs(i.max-i.min)),l=Lt(s.min,i.min,e,n),c=Lt(s.max,i.max,e,n);Math.abs(l-i.min)<=a*.001&&Math.abs(c-i.max)<=a*.001?(l=i.min,c=i.max):t=true,o.scale={min:l,max:c,log:i.log};}for(let o of this.scene.indicatorScales.values()){let i=o.scaleTarget,s=o.scale,a=Math.max(1e-9,Math.abs(i.max-i.min)),l=Lt(s.min,i.min,e,n),c=Lt(s.max,i.max,e,n);Math.abs(l-i.min)<=a*.001&&Math.abs(c-i.max)<=a*.001?(l=i.min,c=i.max):t=true,o.scale={min:l,max:c};}return t}emitViewportChange(){this.updateScrollToRealtimeButton();let e=this.getVisibleRange();if(e)for(let t of this.viewportCbs)t(e);}handlePointerMove(e,t){if(e===null||t===null||this.coords.barCount===0){this.scene.crosshair=null,this.hoverSeparatorY=null,this.lastPointer=null,this.marksExpandedBy==="hover"&&this.setMarksExpanded(null),this.setMarkHover(null),this.scheduler.invalidate(1),this.hoverLogical=null;let p={time:null,price:null,paneKind:null,values:new Map,ohlc:null};for(let m of this.crosshairCbs)m(p);return}let n=e>=0&&t>=0&&e<=this.coords.width&&t<=this.coords.height;this.scene.crosshair=n?{x:e,y:t}:null,this.lastPointer=n?{x:e,y:t}:null,this.hoverSeparatorY=e>=0&&t>=0&&t<=this.coords.height?this.separatorHoverY(t):null,this.scheduler.invalidate(1),this.setMarksExpanded(n?this.chrome.markStackAt(e,t):null),this.setMarkHover(n?this.chrome.markGlyphAt(e,t)?.cluster.key??null:null);let o=Math.round(this.coords.xToLogical(e)),i=o>=0&&o=0&&ta.id),time:i.time,...n.cluster.group!==void 0?{group:n.cluster.group}:{}};for(let a of this.markClickCbs)a(s);return o.some(a=>a.content!==void 0)?this.markPopover?.open(n.cluster,{x:n.x,y:n.y,size:n.size}):(this.scene.marksFlash={key:n.cluster.key,until:_p()+lR},this.syncMarkPulse()),true}trackMarkPopover(){let e=this.markPopover?.key;if(!e)return;let t=this.chrome.markGlyphByKey(e);this.markPopover.track(t&&!(t.decked&&t.depth!==0)?{x:t.x,y:t.y,size:t.size}:null);}setMarkHover(e){this.scene.marksHoverKey!==e&&(this.scene.marksHoverKey=e,this.scene.marksHoverSince=_p(),this.scheduler?.invalidate(2),this.syncMarkPulse());}syncMarkPulse(){if(this.markPulseRaf!==null||typeof requestAnimationFrame!="function")return;let e=()=>{this.markPulseRaf=null;let t=_p();this.scene.marksFlash&&this.scene.marksFlash.until<=t&&(this.scene.marksFlash=null),this.scheduler?.invalidate(2),(this.scene.marksHoverKey!==null&&t-this.scene.marksHoverSince=t.bounds.top&&e<=t.bounds.top+t.bounds.height)return t;return null}nearestPaneToY(e){let t=null,n=1/0;for(let o of this.scene.panes.values()){let i=e=o+64&&i.length>0){let s=Math.floor((e-o-64)/56),a=i[s];if(a)return {holder:this.scene.ensureIndicatorScale(a.id,n.scaleTarget),height:n.bounds.height}}return {holder:n,height:n.bounds.height}}beginPriceScale(e,t){let n=this.resolveScaleHolder(e,t);n&&(this.scaleDragHolder=n.holder,this.scaleDragHeight=n.height,this.scaleDragStart={...n.holder.scale},n.holder.manualScale={...n.holder.scale},this.axisScaleButtons?.reposition(),this.scheduler.invalidate(4));}priceScaleBy(e){let t=this.scaleDragHolder,n=this.scaleDragStart;!t||!n||this.setManualScale(t,l0(n,Math.exp(e*cR)));}beginPricePan(e){let t=this.paneNodeAtY(e);return !t||!t.manualScale?false:(this.scaleDragHolder=t,this.scaleDragHeight=t.bounds.height,this.scaleDragStart={...t.scale},true)}pricePanBy(e){let t=this.scaleDragHolder,n=this.scaleDragStart;!t||!n||this.setManualScale(t,c0(n,e,this.scaleDragHeight));}resetPriceScale(e,t){let n=this.resolveScaleHolder(e,t);n&&(n.holder.manualScale=null,this.axisScaleButtons?.reposition(),this.scheduler.invalidate(4));}dataDblClick(e,t){let n=this.paneNodeAtY(t)??this.nearestPaneToY(t);if(!n)return;let o=this.maximizedPaneId!==n.id;this.maximizedPaneId=o?n.id:null,this.afterPaneLayoutChange(),this.emitPaneAction({type:"maximize",paneId:n.id,maximized:o});}resetView(){this.fitContent(),this.scheduler.invalidate(4),this.emitViewportChange();}setManualScale(e,t){e.manualScale=t,e.scale={...t},e.scaleTarget={...t},e.initialized=true,this.scheduler.invalidate(4);}afterPaneLayoutChange(){this.layoutPanes(),this.paneControls?.refresh(),this.scheduler.invalidate(4);}paneControlViews(){let e=this.scene.orderedPanes();return e.map((t,n)=>({id:t.id,kind:t.kind,collapsed:t.collapsed,maximized:this.maximizedPaneId===t.id,top:t.bounds.top,height:t.bounds.height,index:n,count:e.length}))}movePaneLocal(e,t){let n=this.scene.orderedPanes(),o=n.findIndex(l=>l.id===e);if(o<0)return;let i=t==="up"?o-1:o+1;if(i<1||i>=n.length)return;let s=n.map(l=>l.id),a=s[o];s[o]=s[i],s[i]=a,this.scene.orderPanes(s),this.afterPaneLayoutChange(),this.emitPaneAction({type:"move",paneId:e,dir:t});}paneSeparatorAt(e){return this.separatorPaneIndexAt(e)!==null}separatorHoverY(e){if(!this.paneResizeEnabled)return null;let t=this.separatorPaneIndexAt(e);return t===null?null:this.scene.orderedPanes()[t].bounds.top}separatorPaneIndexAt(e){let t=this.scene.orderedPanes();for(let n=1;na-i&&(l+=n-(a-i)),l!==o.rightOffset&&this.applyViewport({barSpacing:o.barSpacing,rightOffset:l});let c=this.scene.orderedPanes().find(u=>u.kind==="price")??this.scene.orderedPanes()[0]??null,d=this.scene.crosshair?.y??(c?c.bounds.top+c.bounds.height/2:this.coords.height/2);this.handlePointerMove(this.coords.logicalToX(n),d),this.announceBar(n);}announceBar(e){if(!this.liveRegion)return;let t=this.bars[e],n=this.dataWindowPricePane(),o=this.dataWindowOHLC(t,n),i=[];t&&i.push(mR(t.time,this.scene.timezone)),o&&i.push(`Open ${o.o}, High ${o.h}, Low ${o.l}, Close ${o.c}`);for(let s of this.dataWindowGroups(e,n))for(let a of s.rows)i.push(`${a.label} ${a.value}`);this.liveRegion.textContent=i.join(". ");}getDataWindowReadout(){let e=this.bars.length;if(e===0)return {date:"",time:"",ohlc:null,groups:[]};let t=this.hoverLogical!=null?this.hoverLogical:e-1,n=this.bars[t],o=this.dataWindowPricePane(),i=n?D0(n.time,this.scene.timezone):{date:"",time:""};return {date:i.date,time:i.time,ohlc:this.dataWindowOHLC(n,o),groups:this.dataWindowGroups(t,o)}}dataWindowPricePane(){return this.scene.orderedPanes().find(e=>e.kind==="price")??null}dataWindowFmt(e,t){return t?ad(t.scale,t.bounds.height,e,this.scene.priceMintick):String(e)}dataWindowOHLC(e,t){return e?{o:this.dataWindowFmt(e.open,t),h:this.dataWindowFmt(e.high,t),l:this.dataWindowFmt(e.low,t),c:this.dataWindowFmt(e.close,t),vol:e.volume!=null?A0(e.volume):void 0,up:e.close>=e.open}:null}dataWindowGroups(e,t){let n=[];for(let o of this.scene.indicators.values()){let i=this.readoutRowsFor(o,e,t,"dataWindow");i.length&&n.push({name:o.title,rows:i});}return n}readoutRowsFor(e,t,n,o){if(e.native?.type==="volume")return this.volumeReadoutRows(e,t);let i=(e.paneId?this.scene.panes.get(e.paneId):null)??n,s=this.scene.offsetOf(e.id),a=[];for(let l of e.series){if(!Rt(l,o))continue;let c,d;if(l.kind==="candle"||l.kind==="bar")c=l.bars[t-s]?.close,d=l.style?.up??this.theme.upColor;else if($e(l))c=l.points[t-s]?.value,d=l.points[t-s]?.color??l.style.color;else continue;c==null||!Number.isFinite(c)||a.push({label:l.title||e.title,value:this.dataWindowFmt(c,i),color:d});}return a}volumeReadoutRows(e,t){if(this.volumeHidden)return [];let n=this.bars[t],o=n?.volume;if(n==null||o==null||!Number.isFinite(o))return [];let i=this.scene.volumeLayer,s=n.close>=n.open?i?.upColor??this.theme.upColor:i?.downColor??this.theme.downColor;return [{label:e.title,value:A0(o),color:s}]}updateLegendValues(){if(!this.inputsUI)return;let e=this.bars.length,t=new Map;if(e>0){let n=this.hoverLogical!=null?this.hoverLogical:e-1,o=this.dataWindowPricePane();for(let i of this.scene.indicators.values())t.set(i.id,this.readoutRowsFor(i,n,o,"legend").map(s=>({value:s.value,color:s.color})));}this.inputsUI.setPlotValues(t);}renderFrame(e){this.animator.active||(Yh(e)?(this.computeScales(),this.paintData()):Fw(e)&&this.paintedData&&(this.chrome.prepare(this.scene,this.coords,this.theme),this.chrome.render(this.scene,this.coords,this.theme,this.axisSurface()),this.trackMarkPopover()),this.renderCrosshairLayer(),!Yh(e)&&this.paintedData&&this.repaintCursorLayers(),this.updateLegendValues());}renderCrosshairLayer(){this.crosshairLayer.render(this.scene,this.coords,this.theme,this.hoverSeparatorY,this.externalCrossPx()),this.syncShadeRight();}syncShadeRight(){let e=this.shadeRightEl;if(!e)return;let t=this.crosshairLayer.shadeRightArea,n=t?`${t.x},${t.width},${t.height}`:"";if(n!==this.shadeRightSig){if(this.shadeRightSig=n,!t){e.hidden=true,e.style.display="none";return}Object.assign(e.style,{left:`${t.x}px`,width:`${t.width}px`,height:`${t.height}px`,display:""}),e.hidden=false;}}repaintCursorLayers(){let e=this.scene.panes.get(Xe);if(!e)return;let t=typeof performance<"u"?performance.now():Date.now();for(let n of this.extLayers){if(!n.def.repaintOnCursor)continue;let o=this.layerPane(n)??e;o.collapsed||this.layerHiddenWithCandles(n)||(n.instance.render(this.extLayerArgs(n,o.scale,o.bounds,t)),this.animZoom.on&&n.instance.animating?.()&&this.animator.start());}}clearLayerCanvas(e){e.width===0||e.height===0||e.getContext("2d")?.clearRect(0,0,e.width,e.height);}extLayerArgs(e,t,n,o){return {bars:this.scene.bars,data:this.scene.nativeData.get(e.channel),settings:this.scene.nativeData.get(`${e.def.id}-settings`)??{},pending:this.scene.nativePending.get(e.channel)??[],coords:this.coords,scale:t,bounds:n,theme:this.theme,priceStyle:this.scene.priceStyle,nowMs:o,cursor:this.lastPointer}}paintData(){this.syncLayerCanvasOrder(),this.stampScaleInvert(),this.backend.modelAlpha=this.modelAlpha,this.backend.candleBodyAlpha=this.candleBodyAlpha,this.backend.candleStructureAlpha=this.candleStructureAlpha;let e=1,t=1;this.backend.candleBodyScale=t;let n=this.scene.panes.get(Xe);if(n){let a=this.nativeLayerPane("volume")??n;this.volumeRenderer.render({bars:this.scene.bars,data:this.scene.volumeLayer,visible:this.volumeActive&&!this.volumeHidden&&!a.collapsed,coords:this.coords,bounds:a.bounds,fillPane:a.kind!=="price"}),this.vpvrRenderer.render({bars:this.scene.bars,data:this.scene.vpvrLayer,visible:this.vpvrActive&&!this.vpvrHidden,coords:this.coords,scale:n.scale,bounds:n.bounds,theme:this.theme});let l=typeof performance<"u"?performance.now():Date.now(),c=null;for(let d of this.extLayers){let u=this.layerPane(d)??n;if(u.collapsed||this.layerHiddenWithCandles(d)){this.clearLayerCanvas(d.canvas);continue}let h=this.extLayerArgs(d,u.scale,u.bounds,l);d.instance.render(h),u===n&&(c=h0(c,d.instance.modulateBase?.(h)??null)),this.animZoom.on&&d.instance.animating?.()&&this.animator.start();}c&&(c.candleBodyScale!=null&&(this.backend.candleBodyScale=Hp(c.candleBodyScale)||.01),c.candleBodyAlpha!=null&&(this.backend.candleBodyAlpha=Hp(c.candleBodyAlpha)*this.candleBodyAlpha),c.gridAlpha!=null&&(e=Hp(c.gridAlpha)));}let o=this.bars.length-1,i=o>=0?this.bars[o]:void 0,s=!!i&&this.liveEaseTime===i.time&&(i.high!==this.liveEaseHigh||i.low!==this.liveEaseLow||i.close!==this.liveEaseClose);s&&i&&(this.bars[o]={...i,high:this.liveEaseHigh,low:this.liveEaseLow,close:this.liveEaseClose}),this.scene.drawingSlices=n0(this.indicatorSlices.prepare(this.scene,this.coords,this.theme,this.dataCanvas),this.userDrawings?.prepareSlices(this.scene.orderedPanes().map(a=>a.id))??new Map),this.backdropRenderer.render(this.scene,this.coords,this.theme,e),this.backend.render(this.scene,this.coords,this.theme),this.chrome.render(this.scene,this.coords,this.theme,this.axisSurface()),this.trackMarkPopover(),this.userDrawings?.render(),s&&i&&(this.bars[o]=i),this.paintedData=true;}drawingProjector(){return r0(this.coords,e=>{let t=this.scene.panes.get(e);return t?{scale:t.scale,bounds:t.bounds,collapsed:t.collapsed}:null},e=>this.paneNodeAtY(e)?.id??null,(e,t)=>this.barsInTimeRange(e,t),this.userDrawings?.seriesGateway?(e,t,n)=>this.userDrawings.seriesGateway.seriesInRange(e,t,n):void 0)}barsInTimeRange(e,t){let n=Math.min(e,t),o=Math.max(e,t),i=[];for(let s of this.bars)if(!(s.timeo)break;i.push(s);}return i}get userDrawingsPort(){return this.userDrawings??void 0}focus(){this.dataCanvas?.focus({preventScroll:true});}setExternalCrosshair(e,t=null){let n=e==null?null:{time:e,price:t},o=this.externalCross;!n&&!o||n&&o&&o.time===n.time&&o.price===n.price||(this.externalCross=n,this.scheduler.invalidate(1));}externalCrossPx(){let e=this.externalCross;if(!e||this.coords.barCount===0)return null;let t=Math.floor(this.coords.timeToLogical(e.time));if(!(t=0&&n>=0&&n<=this.coords.width,i=null;if(e.price!=null){let s=this.scene.orderedPanes().find(a=>a.kind==="price");s&&(i=this.coords.priceToY(e.price,s.scale,s.bounds),(!Number.isFinite(i)||is.bounds.top+s.bounds.height)&&(i=null));}return {x:n,y:i,time:this.coords.logicalToTime(Math.max(t,0)),price:i!=null?e.price:null,line:o}}setSnapMode(e){this.snapMode=e;}snapToCandle(e,t,n="strong",o){if(n==="off")return e;let i=this.bars.length;if(i===0)return e;let s=Math.max(0,Math.min(i-1,Math.round(this.coords.timeToLogical(e.time)))),a=this.bars[s];if(!a)return e;let l;if(t!==Xe)l={time:a.time,price:e.price};else {let c=a.open;for(let d of [a.high,a.low,a.close])Math.abs(d-e.price)QA)return e}return l}computeScales(){let e=this.coords.barCount;if(e===0)return;let t=this.coords.visibleLogicalRange(),n=Math.max(0,Math.floor(t.from)),o=Math.min(e-1,Math.ceil(t.to));if(oc.kind==="price")??null;this.chrome.prepare(this.scene,this.coords,this.theme);let a=this.animator.active,l=this.scene.style.margins;for(let c of i){if(c.manualScale){c.scaleTarget=c.manualScale,c.scale={...c.manualScale},c.initialized=true;continue}let u=this.scene.indicatorsForPane(c.id).filter(m=>m.ownScale!==true),h=this.chrome.paneDrawingsRange(u,this.scene,c===s,t);if(c===s){let m=i0(this.scene.indicators.values(),n,o,f=>this.scene.offsetOf(f));m&&(h=h?{min:Math.min(h.min,m.min),max:Math.max(h.max,m.max)}:m);}let p=c.kind==="price"&&(!this.scene.candlesHidden||this.priceLayersAnchoredToBars(u)||!this.paneHasMeasurableContent(u,h));if(c.scaleTarget=Md(u,this.bars,p,n,o,h,Zo(this.scene,c),m=>this.scene.offsetOf(m),l),c.percentBaseline=c.kind==="price"?this.bars[n]?.close??0:this.firstVisibleValue(u,n),c.axisFormat=void 0,c.axisBands=void 0,this.volumeOwnsPane(c,u)){let m=this.maxVisibleVolume(n,o);m>0&&(c.scaleTarget={min:0,max:m/Pp},c.axisFormat="volume");}else if(this.layerNativesOwnPane(c,u)&&(c.scaleTarget=Md([],this.bars,true,n,o,h,Zo(this.scene,c),m=>this.scene.offsetOf(m),l),c.percentBaseline=this.bars[n]?.close??0,u.every(m=>m.paneAxis!=null))){c.axisFormat="none";let m=u.find(f=>typeof f.paneAxis=="object");c.axisBands=m?m.paneAxis.bands:void 0;}if(c===s&&this.scene.tradeMarkers.visible&&c.bounds.height>0){let m=this.tradesScaleHints(t);if(m){let f=c.scaleTarget,g={...f,min:Math.min(f.min,m.min),max:Math.max(f.max,m.max)};c.scaleTarget=s0(g,c.bounds.height,m.abovePx,m.belowPx);}}(!a||!c.initialized)&&(c.scale={...c.scaleTarget},c.initialized=true);for(let m of this.scene.ownScaleIndicatorsForPane(c.id)){let f=this.scene.ensureIndicatorScale(m.id,c.scaleTarget);if(f.manualScale){f.scaleTarget=f.manualScale,f.scale={...f.manualScale},f.initialized=true;continue}let g=this.chrome.paneDrawingsRange([m],this.scene,false,t);f.scaleTarget=Md([m],this.bars,false,n,o,g,false,b=>this.scene.offsetOf(b),l),(!a||!f.initialized)&&(f.scale={...f.scaleTarget},f.initialized=true);}}}tradesScaleHints(e){let t=null,n={timeToLogical:o=>this.coords.timeToLogical(o),barAt:o=>{let i=this.bars[Math.round(o)];return i?{high:i.high,low:i.low}:null}};for(let o of this.scene.indicators.values()){if(!o.trades?.length)continue;let i=jw(o.trades,this.scene.tradeMarkers,n,e.from,e.to,this.scene.style.fontSize);i&&(t=t?{min:Math.min(t.min,i.min),max:Math.max(t.max,i.max),abovePx:Math.max(t.abovePx,i.abovePx),belowPx:Math.max(t.belowPx,i.belowPx)}:i);}return t}fitContent(){let e=this.coords.barCount,t=this.coords.width;if(e<=0||t<=0)return;this.animator?.stop(),this.panVelocity=0;for(let s of this.scene.panes.values())s.manualScale=null;for(let s of this.scene.indicatorScales.values())s.manualScale=null;let n=Math.min(e,200),o=this.scene.style.margins.right,i=this.clampViewport(t/((n+o)*this.coords.spacingScale),o);this.coords.setViewport(i),this.targetBarSpacing=i.barSpacing;}reframeKeepZoom(){this.animator?.stop(),this.panVelocity=0;for(let t of this.scene.panes.values())t.manualScale=null;for(let t of this.scene.indicatorScales.values())t.manualScale=null;let e={barSpacing:pn(this.coords.getViewport().barSpacing),rightOffset:this.scene.style.margins.right};this.coords.setViewport(e),this.targetBarSpacing=e.barSpacing;}paneBoundsFor(e){let t=this.scene.panes.get(e);return {top:t?.bounds.top??0,height:t?.bounds.height??0,rightAxis:this.rightAxisW}}paneMasterTitle(e){let t=this.scene.orderedIndicatorsForPane(e);return (t.find(o=>o.ownScale!==true)??t[0])?.title||null}nativeLayerPane(e){for(let t of this.scene.indicators.values())if(t.native?.type===e)return this.scene.panes.get(t.paneId??Xe)??null;return null}createLayerCanvas(){let e=document.createElement("canvas");return Object.assign(e.style,{position:"absolute",inset:"0",width:"100%",height:"100%",pointerEvents:"none"}),e}ensureInstanceLayer(e){let t=e.native?.channel;if(!t||!this.plot||this.extLayers.some(s=>s.owner===e.id))return;let n=this.extLayers.find(s=>s.owner===null&&s.def.id===e.native.type);if(!n)return;let o=this.createLayerCanvas();o.width=this.dataCanvas.width,o.height=this.dataCanvas.height,o.style.width=this.dataCanvas.style.width||"100%",o.style.height=this.dataCanvas.style.height||"100%";let i={def:n.def,instance:n.def.create(),canvas:o,channel:t,owner:e.id};this.extLayers.push(i),this.plot.insertBefore(o,this.chromeCanvas),i.instance.mount(o);}dropInstanceLayer(e){let t=this.extLayers.findIndex(o=>o.owner===e);if(t<0)return;let[n]=this.extLayers.splice(t,1);n.instance.destroy?.(),n.canvas.remove();}layerOwner(e){if(e.owner!==null)return this.scene.indicators.get(e.owner)??null;for(let t of this.scene.indicators.values())if(t.native?.type===e.def.id&&!t.native.channel)return t;return null}layerPane(e){let t=this.layerOwner(e),n=t?t.paneId??Xe:Xe;return this.scene.panes.get(n)??null}orderedLayerCanvases(){let e=new Map(this.extLayers.map(o=>[o.channel,o.canvas])),{below:t,above:n}=p0(this.extLayers.map(o=>{let i=this.layerOwner(o);return {id:o.channel,placement:o.def.placement==="below-data"?"below-data":"above-data",ownerZ:i?this.scene.zOf(i.id):null}}),this.scene.candleZ);return {below:t.map(o=>e.get(o)),above:n.map(o=>e.get(o))}}canvasPile(){let{below:e,above:t}=this.orderedLayerCanvases();return [this.backdropCanvas,...e,this.dataCanvas,this.volumeCanvas,this.vpvrCanvas,...t]}syncLayerCanvasOrder(){if(this.extLayers.length===0||!this.plot)return;let{below:e,above:t}=this.orderedLayerCanvases(),n=[...e.map(o=>this.extLayers.find(i=>i.canvas===o).channel),"|",...t.map(o=>this.extLayers.find(i=>i.canvas===o).channel)].join(",");if(n!==this.layerOrderSig){this.layerOrderSig=n;for(let o of e)this.plot.insertBefore(o,this.dataCanvas);for(let o of t)this.plot.insertBefore(o,this.chromeCanvas);}}volumeOwnsPane(e,t){return e.kind==="price"||!this.volumeActive||this.volumeHidden||!this.scene.volumeLayer||this.nativeLayerPane("volume")!==e?false:t.every(n=>n.native?.type==="volume")}layerNativesOwnPane(e,t){return e.kind==="price"||t.length===0?false:t.every(n=>n.series.length===0&&!!n.native&&this.extLayers.some(o=>o.def.id===n.native.type))}layerHiddenWithCandles(e){return this.scene.candlesHidden&&e.owner===null&&e.def.id===this.scene.priceStyle}priceLayersAnchoredToBars(e){return e.some(t=>t.series.length===0&&!!t.native&&this.extLayers.some(n=>n.def.id===t.native.type))}paneHasMeasurableContent(e,t){return t?true:e.some(n=>n.priceLines.length>0||n.series.some(o=>o.overlay!==true))}paneScaleInfos(){return this.scene.orderedPanes().map(e=>({id:e.id,kind:e.kind,top:e.bounds.top,height:e.bounds.height,mode:Zh(this.scene,e),log:Zo(this.scene,e),invert:Qh(this.scene,e)}))}axisScaleViews(){return this.scene.orderedPanes().map(e=>({id:e.id,top:e.bounds.top,height:e.bounds.height,collapsed:e.collapsed,auto:e.manualScale==null,log:Zo(this.scene,e)}))}togglePaneAuto(e){let t=this.scene.panes.get(e);t&&(t.manualScale=t.manualScale==null?{...t.scale}:null,this.scheduler?.invalidate(4));}setPaneScaleMode(e,t){if(e===Xe)this.scene.scaleMode=t;else {let n=this.scene.panes.get(e);if(!n)return;n.scaleMode=t;}this.scheduler?.invalidate(4);}setPaneLog(e,t){let n=e===Xe?this.scene.orderedPanes().find(o=>o.kind==="price"):this.scene.panes.get(e);if(e===Xe)this.scene.logScale=t;else {if(!n)return;n.logScale=t;}n?.manualScale&&(n.manualScale.log=t),this.scheduler?.invalidate(4);}setPaneInvert(e,t){if(e===Xe)this.scene.invertScale=t;else {let n=this.scene.panes.get(e);if(!n)return;n.invert=t;}this.scheduler?.invalidate(4);}stampScaleInvert(){for(let e of this.scene.panes.values()){let t=Qh(this.scene,e);e.scale.invert=t,e.scaleTarget.invert=t,e.manualScale&&(e.manualScale.invert=t);for(let n of this.scene.ownScaleIndicatorsForPane(e.id)){let o=this.scene.indicatorScales.get(n.id);o&&(o.scale.invert=t,o.scaleTarget.invert=t,o.manualScale&&(o.manualScale.invert=t));}}}firstVisibleValue(e,t){for(let n of e){let o=this.scene.offsetOf(n.id);for(let i of n.series)if(i.overlay!==true){if($e(i)){let s=i.points[t-o]?.value;if(s!=null&&Number.isFinite(s))return s}else if(i.kind==="candle"||i.kind==="bar"){let s=i.bars[t-o];if(s&&Number.isFinite(s.close))return s.close}}}return 0}maxVisibleVolume(e,t){let n=0;for(let o=e;o<=t;o+=1){let i=this.bars[o]?.volume;i!=null&&i>n&&(n=i);}return n}layoutPanes(){let e=this.scene.orderedPanes(),t=this.coords.height;this.inputsUI?.setCollapsedPanes(this.collapsedMasterMap());let n=this.maximizedPaneId?this.scene.panes.get(this.maximizedPaneId):null;if(n){let d=0;for(let u of e)u===n?u.bounds={top:0,height:t}:u.bounds={top:t,height:0},d+=u.bounds.height;this.inputsUI?.reposition(),this.paneControls?.reposition(),this.axisScaleButtons?.reposition(),this.repositionScrollButton(),this.positionAttribution(),this.publishPricePaneBounds();return}let o=e.filter(d=>d.collapsed),i=e.filter(d=>!d.collapsed),s=o.length*M0,a=Math.max(0,t-s),l=i.reduce((d,u)=>d+(u.heightWeight||1),0)||1,c=0;for(let d of e){let u=d.collapsed?M0:a*(d.heightWeight||1)/l;d.bounds={top:c,height:u},c+=u;}this.inputsUI?.reposition(),this.paneControls?.reposition(),this.axisScaleButtons?.reposition(),this.repositionScrollButton(),this.positionAttribution(),this.publishPricePaneBounds();}repositionScrollButton(){let e=this.coords.height;if(e<=0)return;let t=this.maximizedPaneId?this.scene.panes.get(this.maximizedPaneId):null,n=t?[t]:this.scene.orderedPanes().filter(i=>!i.collapsed),o=n.length?Math.max(...n.map(i=>i.bounds.top+i.bounds.height)):e;this.scrollBtnBottomPx=Bp+Math.max(0,e-o),this.mountContainer?.style.setProperty("--vela-bottom-gutter",`${ii+Math.max(0,e-o)}px`),this.scrollBtnRightPx=this.rightAxisW+R0,this.scrollButton&&(this.scrollButton.style.bottom=`${this.scrollBtnBottomPx}px`,this.scrollButton.style.right=`${this.scrollBtnRightPx}px`);}collapsedMasterMap(){let e=new Map;for(let t of this.scene.panes.values()){if(!t.collapsed)continue;let n=this.scene.orderedIndicatorsForPane(t.id).filter(s=>s.legend!==false),o=new Set(this.scene.ownScaleIndicatorsForPane(t.id).map(s=>s.id)),i=n.find(s=>!o.has(s.id))??n[0];e.set(t.id,i?.id??null);}return e}setToolbarGutter(e){e!==this.toolbarGutter&&(this.toolbarGutter=e,this.publishGutters(),this.positionAttribution(),this.syncSize());}publishGutters(){this.mountContainer?.style.setProperty("--vela-toolbar-gutter",`${this.toolbarGutter}px`),this.mountContainer?.style.setProperty("--vela-scale-gutter",`${this.rightAxisW}px`);}publishPricePaneBounds(){if(!this.mountContainer)return;let e=this.coords.height+ii,t=this.scene.panes.get(Xe),n=t?t.bounds.top:0,o=t?t.bounds.height:this.coords.height,i=Math.max(0,e-(n+o));this.mountContainer.style.setProperty("--vela-price-pane-top",`${n}px`),this.mountContainer.style.setProperty("--vela-price-pane-bottom",`${i}px`);}buildAttributionEl(){return this.attributionHtml!==null?b0(document,this.attributionHtml,this.theme.background):v0(document,this.theme.background)}rebuildAttribution(){this.attributionEl&&(this.attributionEl.remove(),this.attributionEl=this.buildAttributionEl(),this.attributionEnabled||(this.attributionEl.style.display="none"),this.positionAttribution(),this.wrapper.appendChild(this.attributionEl));}positionAttribution(){if(!this.attributionEl)return;let e=this.coords?.height??0,t=this.maximizedPaneId?this.scene.panes.get(this.maximizedPaneId):null,n=t?[t]:this.scene.orderedPanes().filter(i=>!i.collapsed),o=e>0&&n.length?Math.max(...n.map(i=>i.bounds.top+i.bounds.height)):e;Object.assign(this.attributionEl.style,{left:`${(this.toolbarGutter||0)+12}px`,bottom:`${ii+10+Math.max(0,e-o)}px`});}refreshAttributionColor(){this.attributionEl&&(this.attributionHtml!==null?this.attributionEl.style.color=Dp(this.theme.background):Op(this.attributionEl,this.theme.background));}syncSize(){let e=this.wrapper.clientWidth,t=this.wrapper.clientHeight;if(e<=0||t<=0)return;let n=window.devicePixelRatio||1;this.plot.style.left=`${this.toolbarGutter}px`;let o=this.plot.getBoundingClientRect(),i=Math.max(1,Math.round(o.width*n)),s=Math.max(1,Math.round(o.height*n)),a=this.plotDeviceSize;a&&Math.abs(a.width-o.width*n)<=1&&Math.abs(a.height-o.height*n)<=1&&(i=Math.max(1,a.width),s=Math.max(1,a.height));let l=i/n,c=s/n,d=u=>{u.width=i,u.height=s,u.style.width=`${l}px`,u.style.height=`${c}px`;};d(this.dataCanvas),d(this.backdropCanvas),d(this.volumeCanvas);for(let u of this.extLayers)d(u.canvas);d(this.vpvrCanvas),d(this.chromeCanvas),d(this.drawingsCanvas),d(this.cursorCanvas),this.coords.setSize(Math.max(1,l-this.rightAxisW),Math.max(1,c-ii),n),this.scene.crosshair=null,this.layoutPanes(),this.userDrawings?.onResize(),!this.didInitialFit&&this.coords.barCount>0&&(this.fitContent(),this.didInitialFit=true),this.animator.active?(this.computeScales(),this.paintData(),this.renderCrosshairLayer()):this.scheduler.flushNow(4);}applyBackground(){this.wrapper.style.background=this.theme.background;}};function hR(r,e){for(let t of r.series){let n=t.kind==="candle"||t.kind==="bar"?t.bars:$e(t)?t.points:null;if(!n||n.length===0)continue;let o=0,i=n.length;for(;o>1;n[s].timeo.id===t.seriesId);n&&(t.kind==="points"&&$e(n)?n.points=t.points:t.kind==="bars"&&(n.kind==="candle"||n.kind==="bar")&&(n.bars=t.bars));}e.lines&&(r.lines=e.lines),e.boxes&&(r.boxes=e.boxes),e.labels&&(r.labels=e.labels),e.polylines&&(r.polylines=e.polylines),e.linefills&&(r.linefills=e.linefills),e.tables&&(r.tables=e.tables),e.trades&&(r.trades=e.trades);return}for(let t of e.removed){let n=r.series.findIndex(o=>o.id===t);n>=0&&r.series.splice(n,1);}for(let t of e.added)r.series.push(t);}function D0(r,e){let t=rd(r,e),n=o=>o<10?`0${o}`:String(o);return {date:`${t.getUTCFullYear()}-${n(t.getUTCMonth()+1)}-${n(t.getUTCDate())}`,time:`${n(t.getUTCHours())}:${n(t.getUTCMinutes())}`}}function mR(r,e){let{date:t,time:n}=D0(r,e);return `${t} ${n}`}function fR(r){if(!Array.isArray(r))return [];let e=[];for(let t of r){if(!t||typeof t!="object")continue;let n=t,o=Number(n.from),i=Number(n.to);!Number.isFinite(o)||!Number.isFinite(i)||i<=o||e.push({from:o,to:i,color:typeof n.color=="string"?n.color:"rgba(120,130,160,0.10)"});}return e.sort((t,n)=>t.from-n.from)}function gR(r){if(r==null||typeof r!="object")return null;let e=r,t=n=>{if(!Array.isArray(n))return [];let o=[];for(let i of n){if(!Array.isArray(i))continue;let s=Number(i[0]),a=Number(i[1]);Number.isFinite(s)&&Number.isFinite(a)&&a>s&&o.push([s,a]);}return o.sort((i,s)=>i[0]-s[0])};return {pre:t(e.pre),post:t(e.post),extended:t(e.extended)}}function Hp(r){return Math.max(0,Math.min(1,r))}function bR(r){return typeof r=="string"&&Xo().includes(r)}function I0(r){return r==="percent"||r==="indexed"?r:"price"}function A0(r){let e=Math.abs(r);return e>=1e9?`${(r/1e9).toFixed(2)}B`:e>=1e6?`${(r/1e6).toFixed(2)}M`:e>=1e3?`${(r/1e3).toFixed(2)}K`:r.toFixed(2)}function vR(r){let e=[...r].sort((n,o)=>n.time-o.time),t=[];for(let n of e){let o=t[t.length-1];o&&o.time===n.time?t[t.length-1]=n:t.push(n);}return t}function zp(r,e){let t=(r.open+r.high+r.low+r.close)/4,n=e?(e.open+e.close)/2:(r.open+r.close)/2;return {time:r.time,open:n,high:Math.max(r.high,n,t),low:Math.min(r.low,n,t),close:t,...r.volume!=null?{volume:r.volume}:{}}}function O0(r){let e=new Array(r.length),t;for(let n=0;n[{key:"upColor",title:"Up color",type:"color",defval:Wp},{key:"downColor",title:"Down color",type:"color",defval:Gp},{key:"heightPct",title:"Height %",type:"int",defval:$p,min:5,max:50,step:1,tooltip:"Pane height the tallest visible bar occupies"}],defaultInputs:()=>({upColor:Wp,downColor:Gp,heightPct:$p}),create:()=>new Up};function Yp(){Vn(V0);}var Xp=24,jp=30,qp=nt,Zp=D,Qp=70;function Kp(r,e){return typeof r=="number"&&Number.isFinite(r)?r:e}function B0(r,e){return typeof r=="string"&&r!==""?r:e}function Fd(r){return {rows:Math.round(Math.min(400,Math.max(2,Kp(r.rows,Xp)))),widthFrac:Math.min(.9,Math.max(.05,Kp(r.widthPct,jp)/100)),upColor:B0(r.upColor,qp),downColor:B0(r.downColor,Zp),showPoc:r.showPoc!==false,valueAreaFrac:Math.min(1,Math.max(0,Kp(r.valueAreaPct,Qp)/100))}}var Jp=class{constructor(){this.ctx=null;this.inputs={};}start(e,t){this.ctx=e,this.inputs=t,e.emit({}),e.pushData(Fd(t));}onBars(){}onViewport(){}setInputs(e){this.inputs=e,this.ctx?.pushData(Fd(e));}suspend(){}resume(){this.ctx?.pushData(Fd(this.inputs));}stop(){}},_0={type:"vpvr",title:"Visible Range Volume Profile",shortTitle:"VRVP",paneHint:"price",overlay:true,inputsSchema:()=>[{key:"rows",title:"Rows",type:"int",defval:Xp,min:2,max:400,step:1},{key:"widthPct",title:"Width %",type:"int",defval:jp,min:5,max:90,step:1,tooltip:"Pane width the largest row occupies"},{key:"upColor",title:"Up color",type:"color",defval:qp},{key:"downColor",title:"Down color",type:"color",defval:Zp},{key:"showPoc",title:"Point of control",type:"bool",defval:true},{key:"valueAreaPct",title:"Value area %",type:"int",defval:Qp,min:0,max:100,step:1}],defaultInputs:()=>({rows:Xp,widthPct:jp,upColor:qp,downColor:Zp,showPoc:true,valueAreaPct:Qp}),create:()=>new Jp};function em(){Vn(_0);}function cr(r){let e=r.title.trim().toLowerCase().replace(/\s+/g,"-");return `${r.instanceId}:${r.kind}:${e}#${r.ordinal}`}function R(r,e,t){let n=r[e];return typeof n=="number"&&Number.isFinite(n)?n:t}function T(r,e,t){let n=r[e];return typeof n=="string"&&n!==""?n:t}function te(r,e,t){let n=r[e];return typeof n=="boolean"?n:t}function xR(r,e,t){let n=new Array(r.length);for(let o=0;o{let u=c.kind??"line",h=cr({instanceId:n,kind:u,title:c.title,ordinal:d});i.set(c.key,h),o.push({id:h,title:c.title,paneId:"",kind:u,points:xR(e,c.values,c.colors),style:{color:c.color,width:c.width??1,lineStyle:c.lineStyle??"solid",...c.base!=null?{base:c.base}:{}},...c.overlay?{overlay:true}:{},...c.display?{display:c.display}:{}});}),t.markers&&t.markers.length>0&&o.push({id:cr({instanceId:n,kind:"markers",title:"markers",ordinal:0}),title:this.spec.shortTitle??this.spec.title,paneId:"",kind:"markers",markers:t.markers});let s=(t.bands??[]).flatMap((c,d)=>{let u=i.get(c.from),h=i.get(c.to);return !u||!h?[]:[{id:cr({instanceId:n,kind:"fill",title:c.key,ordinal:d}),paneId:"",fromSeriesId:u,toSeriesId:h,color:c.color,...c.colors?{colors:[...c.colors]}:{},...c.gradient?{gradient:[...c.gradient]}:{}}]}),a=(t.levels??[]).map((c,d)=>({id:cr({instanceId:n,kind:"hline",title:c.key,ordinal:d}),paneId:"",price:c.price,...c.color!=null?{color:c.color}:{},lineStyle:c.lineStyle??"dashed",width:1,...c.title!=null?{title:c.title}:{}})),l=(t.polylines??[]).map((c,d)=>{let{key:u,...h}=c;return {id:cr({instanceId:n,kind:"polyline",title:u,ordinal:d}),paneId:"",...h}});this.ctx.emit({series:o,fills:s,priceLines:a,polylines:l}),this.ctx.setStatus("idle");}};function H0(r){return {type:r.type,title:r.title,...r.shortTitle!=null?{shortTitle:r.shortTitle}:{},paneHint:r.overlay?"price":"new",overlay:r.overlay,multiInstance:true,inputsSchema:()=>r.inputs,defaultInputs:()=>Object.fromEntries(r.inputs.map(e=>[e.key,e.defval])),create:()=>new tm(r)}}var z0=["Close","Open","High","Low","HL2","HLC3","OHLC4","HLCC4"];function oe(r,e){let t=new Array(r.length);for(let n=0;ne.volume!=null&&Number.isFinite(e.volume)?e.volume:Number.NaN)}function et(r){return r.map(e=>e.high)}function tt(r){return r.map(e=>e.low)}function je(r){return r.map(e=>e.close)}function W0(r){return r.map(e=>e.open)}function X(r,e,t){let n=new Array(r.length);for(let o=0;ot-n)}function Pt(r,e,t){let n=new Array(r.length).fill(Number.NaN);if(e<=0)return n;let o=0;for(let i=0;i=e&&(n[i]=t(r,i-e+1,i));return n}function ge(r,e){return Pt(r,e,(t,n,o)=>{let i=0;for(let s=n;s<=o;s++)i+=t[s];return i})}function Ce(r,e){return Pt(r,e,(t,n,o)=>{let i=0;for(let s=n;s<=o;s++)i+=t[s];return i/e})}function Ut(r,e){let t=e*(e+1)/2;return Pt(r,e,(n,o,i)=>{let s=0;for(let a=o;a<=i;a++)s+=n[a]*(a-o+1);return s/t})}function G0(r,e,t){let n=X(r,e,(o,i)=>o*i);return X(ge(n,t),ge(e,t),(o,i)=>i>0?o/i:Number.NaN)}function It(r,e){return Pt(r,e,(t,n,o)=>{let i=0;for(let l=n;l<=o;l++)i+=t[l];let s=i/e,a=0;for(let l=n;l<=o;l++){let c=t[l]-s;a+=c*c;}return Math.sqrt(a/e)})}function $0(r,e){return Pt(r,e,(t,n,o)=>{let i=0;for(let l=n;l<=o;l++)i+=t[l];let s=i/e,a=0;for(let l=n;l<=o;l++)a+=Math.abs(t[l]-s);return a/e})}function at(r,e){return Pt(r,e,(t,n,o)=>{let i=-1/0;for(let s=n;s<=o;s++)t[s]>i&&(i=t[s]);return i})}function lt(r,e){return Pt(r,e,(t,n,o)=>{let i=1/0;for(let s=n;s<=o;s++)t[s]{let i=-1/0,s=o;for(let a=n;a<=o;a++)t[a]>=i&&(i=t[a],s=a);return o-s})}function Y0(r,e){return Pt(r,e,(t,n,o)=>{let i=1/0,s=o;for(let a=n;a<=o;a++)t[a]<=i&&(i=t[a],s=a);return o-s})}function K0(r,e,t){let n=new Array(r.length).fill(Number.NaN),o=0,i=Number.NaN;for(let s=0;s=e){let l=0;for(let c=s-e+1;c<=s;c++)l+=r[c];i=l/e,n[s]=i;}}return n}function q(r,e){return K0(r,e,2/(e+1))}function Ne(r,e){return K0(r,e,1/e)}function st(r,e=1){let t=new Array(r.length).fill(Number.NaN);for(let n=e;n=0&&oMath.max(i,0)),o=re(t,i=>Math.max(-i,0));return X(Ne(n,e),Ne(o,e),(i,s)=>s===0?100:100-100/(1+i/s))}function nm(r,e,t,n){let o=at(e,n),i=lt(t,n),s=new Array(r.length).fill(Number.NaN);for(let a=0;a{let c=0,d=0;for(let p=a;p<=l;p++){let m=p-a;c+=s[p],d+=m*s[p];}let u=i===0?0:(e*d-n*c)/i;return (c-u*n)/e+u*(e-1-t)})}function X0(r,e){let t=Math.max(2,Math.trunc(e)),n=we(re(Ut(r,Math.max(1,Math.trunc(t/2))),o=>2*o),Ut(r,t));return Ut(n,Math.max(1,Math.round(Math.sqrt(t))))}function j0(r,e,t,n){let o=t*(e-1),i=e/Math.max(n,1e-9),s=new Array(e),a=0;for(let l=0;l{let u=0;for(let h=c;h<=d;h++)u+=l[h]*s[h-c];return a===0?Number.NaN:u/a})}function q0(r,e){let t=q(r,e);return we(re(t,n=>2*n),q(t,e))}function Z0(r,e){let t=q(r,e),n=q(t,e),o=q(n,e);return X(X(re(t,i=>3*i),re(n,i=>3*i),(i,s)=>i-s),o,(i,s)=>i+s)}function Q0(r,e,t=2/3,n=2/31){let o=re(st(r,e),Math.abs),i=ge(re(st(r),Math.abs),e),s=new Array(r.length).fill(Number.NaN),a=Number.NaN;for(let l=0;lNumber.isFinite(s)?s:Number.NaN);let o=new Array(e),i=0;for(let s=0;s{let c=0;for(let d=a;d<=l;d++)c+=s[d]*o[l-d];return i===0?Number.NaN:c/i})}function tS(r,e){let t=st(r),n=ge(re(t,i=>Math.max(i,0)),e),o=ge(re(t,i=>Math.max(-i,0)),e);return X(n,o,(i,s)=>i+s===0?0:100*(i-s)/(i+s))}function Vd(r){let e=new Array(r.length).fill(Number.NaN);for(let t=3;t{if(!Number.isFinite(l))return null;let d=r[c].close;return d>l?o.bull:d{let d=n[c];return !Number.isFinite(l)||!Number.isFinite(d)?null:{topValue:l,bottomValue:d,topColor:z(o.bear,90),bottomColor:z(o.bull,90)}});return {plots:[{key:"basis",title:"Basis",values:[...e],color:o.neutral,colors:s},{key:"upper",title:"Upper",values:[...t],color:z(o.bear,30)},{key:"lower",title:"Lower",values:[...n],color:z(o.bull,30)}],bands:[{key:i,from:"upper",to:"lower",color:z(A,90),gradient:a}]}}function ct(r,e,t,n){return {key:r,title:e,values:new Array(t).fill(n),color:z(A,100),display:{pane:false,legend:false,dataWindow:false}}}function om(r,e,t,n=92){return {plots:[ct("obAnchor","Overbought Anchor",r,e.overbought),ct("osAnchor","Oversold Anchor",r,e.oversold),ct("topAnchor","Top Anchor",r,e.top),ct("bottomAnchor","Bottom Anchor",r,e.bottom)],bands:[{key:"obZone",from:"obAnchor",to:"topAnchor",color:z(t.overbought,n)},{key:"osZone",from:"osAnchor",to:"bottomAnchor",color:z(t.oversold,n)}]}}function CR(r,e,t){return r.map(n=>Number.isFinite(n)?n<=e.mid?eo(n,e.low,e.mid,t.low,t.mid):eo(n,e.mid,e.high,t.mid,t.high):null)}function to(r,e,t,n=50,o=100){return r.map((i,s)=>{if(!Number.isFinite(i))return null;let a=t(i,s),l=i>e;return {topValue:Math.max(i,e),bottomValue:Math.min(i,e),topColor:z(a,l?n:o),bottomColor:z(a,l?o:n)}})}function oS(r,e){return r.map((t,n)=>{if(!Number.isFinite(t))return null;let o=n>0&&Number.isFinite(r[n-1])?r[n-1]:t,i=t>o;return t>=0?i?e.growAbove:e.fallAbove:i?e.growBelow:e.fallBelow})}function fn(r){let e=(r.overbought+r.oversold)/2,t=CR(r.values,{low:r.oversold,mid:e,high:r.overbought},r.ink),n=om(r.values.length,{overbought:r.overbought,oversold:r.oversold,top:r.scale.top,bottom:r.scale.bottom},{overbought:r.ink.high,oversold:r.ink.low},r.zoneTransparency),o=[{key:r.key,title:r.title,values:r.values,color:r.ink.mid,width:r.width??1,colors:t},...n.plots],i=[...n.bands];r.bandFill!=null&&i.push({key:"band",from:"obAnchor",to:"osAnchor",color:r.bandFill}),r.midpointWash&&(o.push(ct("midAnchor","Midpoint Anchor",r.values.length,e)),i.push({key:"wash",from:r.key,to:"midAnchor",color:z(A,100),gradient:to(r.values,e,(a,l)=>t[l]??r.ink.mid)}));let s=[{key:"overbought",price:r.overbought,color:r.levelInk,lineStyle:"dashed",title:r.levelTitles?.overbought??"Overbought"},{key:"oversold",price:r.oversold,color:r.levelInk,lineStyle:"dashed",title:r.levelTitles?.oversold??"Oversold"}];return r.midline!=null&&s.splice(1,0,{key:"midline",price:r.midline,color:r.levelInk,lineStyle:"dotted",title:"Midline"}),{plots:o,bands:i,levels:s}}function Ae(r){let e=r.baseline??0,t=i=>i>e?r.ink.bull:iNumber.isFinite(i)?t(i):null)},...r.extraPlots??[]],o=[];return r.fill!==false&&(n.push(ct("baseline","Baseline Anchor",r.values.length,e)),o.push({key:"wash",from:r.key,to:"baseline",color:z(A,100),gradient:to(r.values,e,t,r.valueTransparency)})),{plots:n,bands:o,levels:[{key:"zero",price:e,color:r.zeroInk,lineStyle:r.zeroLineStyle??"dashed",title:r.zeroTitle??"Zero Line"},...r.extraLevels??[]]}}function rS(r){let e=/^#([0-9a-f]{6})/i.exec(r.trim());if(!e)return null;let t=parseInt(e[1],16);return [t>>16&255,t>>8&255,t&255]}function eo(r,e,t,n,o){let i=rS(n),s=rS(o);if(!i||!s||!Number.isFinite(r))return n;let a=t-e,l=a===0?0:Math.max(0,Math.min(1,(r-e)/a)),c=d=>Math.round(i[d]+(s[d]-i[d])*l).toString(16).padStart(2,"0");return `#${c(0)}${c(1)}${c(2)}`}var iS=["SMA","EMA","WMA","RMA (SMMA)","HMA","ALMA","VWMA","DEMA","TEMA","KAMA","LSMA","McGinley","Hamming"],TR=["SMA","EMA","WMA","RMA (SMMA)","HMA","VWMA"];function am(r,e,t,n,o={}){switch(r){case "EMA":return q(e,n);case "WMA":return Ut(e,n);case "RMA":case "RMA (SMMA)":return Ne(e,n);case "HMA":return X0(e,n);case "ALMA":return j0(e,n,o.almaOffset??.85,o.almaSigma??6);case "VWMA":return G0(e,Yt(t),n);case "DEMA":return q0(e,n);case "TEMA":return Z0(e,n);case "KAMA":return Q0(e,n);case "LSMA":return si(e,n,o.lsmaOffset??0);case "McGinley":return J0(e,n);case "Hamming":return eS(e,n);default:return Ce(e,n)}}function kR(r,e,t,n){return r.map((o,i)=>{if(!Number.isFinite(o))return null;let s=i>0?r[i-1]:Number.NaN;return Number.isFinite(s)?o>s?e:o{let s=R(i,"length",20),a=n(oe(o,T(i,"source","Close")),s),l=Math.trunc(R(i,"offset",0));return l!==0&&(a=Fe(a,l)),{plots:[{key:t.toLowerCase(),title:t,values:a,color:T(i,"color",ce),width:2}]}}}}var LR=hS("sma","Simple Moving Average","SMA",Ce),MR=hS("ema","Exponential Moving Average","EMA",q),ER={type:"moving-average",title:"Moving Average",shortTitle:"MA",overlay:true,inputs:[Te("maType","MA 1 Type","SMA",iS,"Moving average calculation used for MA 1."),F(20,"length","MA 1 Length",5e3,"Number of bars used in the MA 1 calculation."),le("Close","source","MA 1 Source","Price series MA 1 is calculated on."),ne("showMa2","Show MA 2",false,We,"Displays the optional second moving average."),Te("ma2Type","MA 2 Type","SMA",iS,"Moving average calculation used for MA 2."),F(50,"ma2Length","MA 2 Length",5e3,"Number of bars used in the MA 2 calculation."),le("Close","ma2Source","MA 2 Source","Price series MA 2 is calculated on."),Q("almaOffset","ALMA Offset",.85,0,1,.05,"ALMA type only. Values near 1 make the average more responsive, values near 0 make it smoother."),Q("almaSigma","ALMA Sigma",6,.1,100,.5,"ALMA type only. Larger values widen the Gaussian window for a smoother average."),pe("lsmaOffset","LSMA Offset",0,0,500,"LSMA type only. Bar offset applied to the linear regression value."),uS,P(ce,"MA 1","color","MA 1 line color."),P(Y,"MA 2","ma2Color","MA 2 line color.")],compute:(r,e)=>{let t={almaOffset:R(e,"almaOffset",.85),almaSigma:R(e,"almaSigma",6),lsmaOffset:Math.trunc(R(e,"lsmaOffset",0))},n=Math.trunc(R(e,"offset",0)),o=l=>n===0?l:Fe(l,n),i=T(e,"maType","SMA"),s=o(am(i,oe(r,T(e,"source","Close")),r,R(e,"length",20),t)),a=[{key:"ma",title:i,values:s,color:T(e,"color",ce),width:2}];if(te(e,"showMa2",false)){let l=T(e,"ma2Type","SMA"),c=o(am(l,oe(r,T(e,"ma2Source","Close")),r,R(e,"ma2Length",50),t));a.push({key:"ma2",title:`${l} 2`,values:c,color:T(e,"ma2Color",Y),width:2});}return {plots:a}}},PR={type:"rma",title:"Smoothed Moving Average",shortTitle:"RMA",overlay:true,inputs:[le("Close","source","Source","Price series the average smooths. Wilder computed his 1978 indicators on the close, but the recursion accepts any source."),F(14,"length","RMA Length",5e3,"Number of bars N in Wilder's smoothing: the line keeps (N \u2212 1)/N of its previous value and blends in 1/N of the new price. That alpha is smaller than an EMA's, so an N-period RMA responds like a (2N \u2212 1)-period EMA."),...cS()],compute:(r,e)=>({plots:[dS("rma","RMA",Ne(oe(r,T(e,"source","Close")),R(e,"length",14)),e)]})},IR={type:"zlema",title:"Zero-Lag Exponential Moving Average",shortTitle:"ZLEMA",overlay:true,inputs:[le("Close","source","Source","Price series the average de-lags and then smooths."),F(21,"length","ZLEMA Length",5e3,"EMA length N. It sets both the smoothing (alpha = 2 / (N + 1)) and the correction: an EMA of length N lags by about (N \u2212 1)/2 bars, and the de-lagging step is sized to cancel exactly that."),...cS()],compute:(r,e)=>{let t=R(e,"length",21),n=oe(r,T(e,"source","Close")),o=Math.round((t-1)/2),i=X(n,Fe(n,o),(s,a)=>2*s-a);return {plots:[dS("zlema","ZLEMA",q(i,t),e)]}}},im="Momentum (|CMO|)",sS="Volatility (StDev Ratio)",aS="Trend Regime",AR={type:"vidya",title:"Variable Index Dynamic Average",shortTitle:"VIDYA",overlay:true,inputs:[le("Close","source","Source","Price series the average smooths. VIDYA is classically computed on the close."),F(12,"length","VIDYA Length",5e3,"EMA-equivalent length N of the base smoothing constant, alpha = 2 / (N + 1). The adaptive scaler rescales this base speed bar by bar."),Te("scaler","Adaptive Scaler",im,[im,sS],"Bar-by-bar measure that rescales the smoothing constant. Momentum divides the absolute Chande Momentum Oscillator by 100; Volatility is Chande's original short-term over reference standard deviation."),pe("scalerLength","Scaler Lookback",9,1,5e3,"Lookback of the adaptive scaler \u2014 the CMO period in momentum mode, or the short-term standard deviation window in volatility mode."),pe("refLength","Reference StDev Length",30,2,5e3,"Volatility mode only \u2014 window of the reference standard deviation the short-term reading is divided by."),{...Q("flatThreshold","Flat Threshold",.05,0,10,.01,"One-bar change of VIDYA, as a fraction of ATR, below which the line reads as flat."),group:aS},{...pe("atrLength","ATR Normalization Length",14,1,5e3,"ATR window used to normalize VIDYA's one-bar slope, so the flat threshold behaves consistently across symbols and timeframes."),group:aS},ne("trendColor","Trend Regime Coloring",true,xe,"Colors VIDYA by its regime read \u2014 bullish while sloping up beyond the flat threshold, bearish while sloping down, flat inside congestion."),ne("adaptiveGradient","Adaptive Gradient",true,xe,"Blends the trend color toward the flat color according to the adaptive scaler, so the line pales as momentum dies."),P(O,"Bullish","bullColor"),P(D,"Bearish","bearColor"),P(A,"Flat","flatColor"),P(A,"Neutral","neutralColor"),rm()],compute:(r,e)=>{let t=R(e,"length",12),n=oe(r,T(e,"source","Close")),o=R(e,"scalerLength",9),i=re(tS(n,o),M=>Math.abs(M)/100),s=It(n,o),a=It(n,R(e,"refLength",30)),l=X(s,a,(M,C)=>C>0?M/C:0),c=T(e,"scaler",im)===sS?l:i,d=2/(t+1),u=new Array(n.length).fill(Number.NaN),h=Number.NaN;for(let M=0;M{if(!Number.isFinite(M))return null;let L=y[C],v=C>0&&Number.isFinite(u[C-1])?M-u[C-1]:0,k=Number.isFinite(L)&&L!==0?v/L:0,x=k>b?m:k<-b?f:null;return x==null?g:w?eo(Math.min(c[C]??0,1),0,1,g,x):x});return {plots:[{key:"vidya",title:"VIDYA",values:u,color:g,width:R(e,"lineWidth",2),colors:S}]}}},RR={type:"ma-envelope",title:"Moving Average Envelope",shortTitle:"MA Env",overlay:true,inputs:[Te("maType","MA Type","SMA",TR,"Moving average type used as the envelope basis."),{...F(20,"length","Length",5e3,"Number of bars in the basis moving average."),min:2},le("Close","source","Source","Price series the basis moving average is calculated on."),Q("percent","Percent",2.5,0,50,.1,"Envelope offset as a percentage of the basis. Upper = basis \xD7 (1 + percent / 100), lower = basis \xD7 (1 \u2212 percent / 100)."),...Bd()],compute:(r,e)=>{let t=oe(r,T(e,"source","Close")),n=am(T(e,"maType","SMA"),t,r,R(e,"length",20)),o=R(e,"percent",2.5)/100,i={bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"basisColor",A)};return _d(r,n,re(n,s=>s*(1+o)),re(n,s=>s*(1-o)),i,"envelope")}},sm="Curve",lS="Slope",DR={type:"linear-regression",title:"Linear Regression Curve",shortTitle:"LinReg",overlay:false,inputs:[Te("mode","Mode",sm,[sm,lS],"Curve plots the regression value on the price chart; Slope plots the per-bar slope of the fit in the pane."),{...F(100,"length","Length",5e3,"Number of bars used to fit the linear regression."),min:2},le("Close","source","Source","Price series the regression is fitted to."),P(O,"Rising","bullColor","Color of the regression curve and slope line while the fit slopes upward."),P(D,"Falling","bearColor","Color of the regression curve and slope line while the fit slopes downward."),P(A,"Regression Line","lineColor","Color of the regression curve and slope line while the fit is flat.")],compute:(r,e)=>{let t=R(e,"length",100),n=oe(r,T(e,"source","Close")),o=si(n,t,0),i=X(o,si(n,t,1),(d,u)=>d-u),s=T(e,"bullColor",O),a=T(e,"bearColor",D),l=T(e,"lineColor",A),c=i.map(d=>Number.isFinite(d)?d>0?s:d<0?a:l:null);return T(e,"mode",sm)===lS?{plots:[{key:"slope",title:"Slope",values:i,color:l,width:2,colors:c}],levels:[{key:"zero",price:0,color:z(A,50),lineStyle:"dashed"}]}:{plots:[{key:"curve",title:"Curve",values:o,color:l,width:2,colors:c,overlay:true}]}}},pS=[LR,MR,ER,PR,IR,AR,RR,DR];var mS="#ab47bc",fS=Y,gS="#ffd700";function dm(r,e){let t=R(e,"length",20),n=R(e,"mult",2),o=oe(r,T(e,"source","Close")),i=Ce(o,t),s=re(It(o,t),a=>a*n);return {src:o,basis:i,upper:X(i,s,(a,l)=>a+l),lower:X(i,s,(a,l)=>a-l)}}function vS(r,e){return [{...F(20,"length","Length",5e3,"Number of bars used for the Bollinger Bands basis (a simple moving average) and for the standard deviation."),min:2},le("Close","source","Source","Price series the bands are computed from."),Q("mult","Multiplier",2,r,50,e,"Standard deviation multiplier for the upper and lower bands.")]}var OR={type:"bollinger-bands",title:"Bollinger Bands",shortTitle:"BB",overlay:true,inputs:[F(20,"length","Length",5e3,"Number of bars used to calculate the basis SMA and the standard deviation."),le("Close","source","Source","Price series the bands are calculated on."),Q("mult","Multiplier",2,0,50,.1,"Number of standard deviations added above and below the basis to form the bands."),P(Y,"Basis","basisColor","Color of the basis (middle band) moving average."),P(ce,"Bands","color","Color of the upper and lower bands."),P(z(ce,92),"Fill","fillColor","Fill color of the area between the upper and lower bands.")],compute:(r,e)=>{let{basis:t,upper:n,lower:o}=dm(r,e),i=T(e,"color",ce);return {plots:[{key:"basis",title:"Basis",values:t,color:T(e,"basisColor",Y)},{key:"upper",title:"Upper",values:n,color:i},{key:"lower",title:"Lower",values:o,color:i}],bands:[{key:"bb",from:"upper",to:"lower",color:T(e,"fillColor",z(ce,92))}]}}},li=.5,bS="Thresholds",NR={type:"percent-b",title:"Bollinger Bands %B",shortTitle:"%B",overlay:false,inputs:[...vS(.001,.25),{...Q("overbought","Overbought",1,-10,10,.05,"Level treated as overbought. 1 is the upper band itself, so readings above the default mean price sits outside the bands."),group:bS},{...Q("oversold","Oversold",0,-10,10,.05,"Level treated as oversold. 0 is the lower band itself, so readings below the default mean price sits outside the bands."),group:bS},P(O,"Bullish","bullColor","Color of %B above the 0.5 midline, where price trades in the upper half of the bands."),P(D,"Bearish","bearColor","Color of %B below the 0.5 midline, where price trades in the lower half of the bands."),ne("gradientFill","Gradient Fill",true,xe,"Vertical gradient between %B and the 0.5 midline, fully transparent at the midline and more opaque at the oscillator value."),P(A,"Levels Color","levelsColor","Color of the dashed overbought/oversold levels and of the dotted midline.")],compute:(r,e)=>{let{src:t,upper:n,lower:o}=dm(r,e),i=t.map((h,p)=>{let m=n[p],f=o[p];return Number.isFinite(m)&&Number.isFinite(f)&&m!==f?(h-f)/(m-f):Number.NaN}),s=T(e,"bullColor",O),a=T(e,"bearColor",D),l=T(e,"levelsColor",A),c=i.map(h=>Number.isFinite(h)?h>li?s:a:null),d=[{key:"pb",title:"%B",values:i,color:a,colors:c},{key:"mid",title:"Midline",values:i.map(h=>Number.isFinite(h)?li:Number.NaN),color:l,display:{pane:false,legend:false,dataWindow:false}}],u=te(e,"gradientFill",true)?[{key:"pbFill",from:"pb",to:"mid",color:z(A,100),gradient:i.map(h=>{if(!Number.isFinite(h))return null;let p=h>li,m=p?s:a;return {topValue:Math.max(h,li),bottomValue:Math.min(h,li),topColor:p?z(m,50):z(m,100),bottomColor:p?z(m,100):z(m,50)}})}]:[];return {plots:d,bands:u,levels:[{key:"overbought",price:R(e,"overbought",1),color:l,lineStyle:"dashed",title:"Overbought"},{key:"oversold",price:R(e,"oversold",0),color:l,lineStyle:"dashed",title:"Oversold"},{key:"midline",price:li,color:z(l,50),lineStyle:"dotted",title:"Midline"}]}}},lm="Squeeze & Bulge",FR={type:"bandwidth",title:"Bollinger Bands Width",shortTitle:"BandWidth",overlay:false,inputs:[...vS(.001,.25),{...pe("lookback","Reference Lookback",125,2,5e3,"Window used to locate the lowest (Squeeze) and highest (Bulge) BandWidth references."),group:lm},ne("showSqueeze","Show Squeeze Level",true,lm,"Plots the lowest BandWidth of the reference lookback \u2014 unusually compressed volatility, a condition rather than a directional signal."),ne("showBulge","Show Bulge Level",true,lm,"Plots the highest BandWidth of the reference lookback \u2014 extreme width that is unlikely to be sustained."),P(A,"BandWidth","color","Color of the BandWidth line. At its Squeeze reference the line takes the Squeeze color, at its Bulge reference the Bulge color."),ne("gradientFill","Gradient Fill",true,xe,"Fills the area between zero and BandWidth with a vertical gradient, fully transparent at zero."),P(Y,"Squeeze Level","squeezeColor","Color of the lowest-BandWidth reference line."),P(D,"Bulge Level","bulgeColor","Color of the highest-BandWidth reference line.")],compute:(r,e)=>{let{basis:t,upper:n,lower:o}=dm(r,e),i=t.map((f,g)=>{let b=n[g],y=o[g];return Number.isFinite(f)&&f!==0&&Number.isFinite(b)&&Number.isFinite(y)?(b-y)/f:Number.NaN}),s=R(e,"lookback",125),a=lt(i,s),l=at(i,s),c=T(e,"color",A),d=T(e,"squeezeColor",Y),u=T(e,"bulgeColor",D),h=i.map((f,g)=>Number.isFinite(f)?f<=a[g]?d:f>=l[g]?u:c:null),p=[{key:"bbw",title:"BandWidth",values:i,color:c,colors:h},{key:"zero",title:"Zero Line",values:i.map(f=>Number.isFinite(f)?0:Number.NaN),color:z(A,90)}];te(e,"showSqueeze",true)&&p.push({key:"squeeze",title:"Squeeze Level",values:a,color:d}),te(e,"showBulge",true)&&p.push({key:"bulge",title:"Bulge Level",values:l,color:u});let m=te(e,"gradientFill",true)?[{key:"bbwFill",from:"bbw",to:"zero",color:z(A,100),gradient:i.map((f,g)=>{if(!Number.isFinite(f))return null;let b=h[g]??c;return {topValue:f,bottomValue:0,topColor:z(b,50),bottomColor:z(b,100)}})}]:[];return {plots:p,bands:m}}},VR={type:"keltner-channels",title:"Keltner Channels",shortTitle:"KC",overlay:true,inputs:[F(20,"length","EMA Length",5e3,"Number of bars used to compute the exponential moving average basis line."),pe("atrLength","ATR Length",10,1,5e3,"Number of bars used to compute the Average True Range (Wilder smoothing)."),Q("mult","Multiplier",2,0,50,.1,"ATR multiple used to offset the upper and lower bands from the basis line."),le("Close","source","Source","Price series used to compute the basis line."),...Bd("Basis Color")],compute:(r,e)=>{let t=q(oe(r,T(e,"source","Close")),R(e,"length",20)),n=re(Nn(r,R(e,"atrLength",10)),i=>i*R(e,"mult",2)),o={bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"basisColor",A)};return _d(r,t,X(t,n,(i,s)=>i+s),X(t,n,(i,s)=>i-s),o,"kc")}},BR={type:"donchian-channels",title:"Donchian Channels",shortTitle:"DC",overlay:true,inputs:[F(20,"length","Length",5e3,"Lookback length. The upper and lower channels are the highest high and lowest low over this many bars."),P(D,"Upper","upperColor","Color of the upper channel line."),P(A,"Middle","middleColor","Color of the channel midline."),P(O,"Lower","lowerColor","Color of the lower channel line."),P(z(A,92),"Fill","fillColor","Color of the channel interior fill.")],compute:(r,e)=>{let t=R(e,"length",20),n=at(et(r),t),o=lt(tt(r),t);return {plots:[{key:"upper",title:"Upper",values:n,color:T(e,"upperColor",D)},{key:"middle",title:"Middle",kind:"circles",values:X(n,o,(i,s)=>(i+s)/2),color:T(e,"middleColor",A)},{key:"lower",title:"Lower",values:o,color:T(e,"lowerColor",O)}],bands:[{key:"dc",from:"upper",to:"lower",color:T(e,"fillColor",z(A,92))}]}}},_R={type:"chandelier-exit",title:"Chandelier Exit",shortTitle:"CE",overlay:true,inputs:[F(22,"length","Length",5e3,"Lookback used for both the highest high / lowest low extremes and the ATR."),Q("mult","ATR Multiplier",3,0,50,.1,"Multiple of ATR subtracted from the highest high (long stop) and added to the lowest low (short stop)."),ne("ratchet","Ratchet Stops",false,void 0,"Prevents the long stop from falling and the short stop from rising, resetting once close crosses through the stop."),P(O,"Long Stop","longColor","Color of the long trailing stop line."),P(D,"Short Stop","shortColor","Color of the short trailing stop line.")],compute:(r,e)=>{let t=R(e,"length",22),n=re(Nn(r,t),l=>l*R(e,"mult",3)),o=X(at(et(r),t),n,(l,c)=>l-c),i=X(lt(tt(r),t),n,(l,c)=>l+c),s=o,a=i;if(te(e,"ratchet",false)){s=new Array(r.length).fill(Number.NaN),a=new Array(r.length).fill(Number.NaN);for(let l=0;l0?r[l-1].close:r[l].close,h=l>0&&Number.isFinite(s[l-1])?s[l-1]:c,p=l>0&&Number.isFinite(a[l-1])?a[l-1]:d;s[l]=Number.isFinite(c)?u>h?Math.max(c,h):c:Number.NaN,a[l]=Number.isFinite(d)?u{let t=R(e,"p",10),n=R(e,"q",9),o=re(Nn(r,t),a=>a*R(e,"x",1)),i=X(at(et(r),t),o,(a,l)=>a-l),s=X(lt(tt(r),t),o,(a,l)=>a+l);return {plots:[{key:"stopShort",title:"Stop Short",values:at(i,n),color:T(e,"shortColor",D)},{key:"stopLong",title:"Stop Long",values:lt(s,n),color:T(e,"longColor",O)}]}}},zR={type:"supertrend",title:"SuperTrend",shortTitle:"SuperTrend",overlay:true,inputs:[pe("atrLength","ATR Length",10,1,5e3,"Number of bars used to compute the Wilder ATR."),Q("mult","Factor",3,0,50,.1,"ATR multiplier setting how far the trailing stop sits from the bar midpoint."),P(O,"Uptrend Color","upColor","Line color while the trend is up."),P(D,"Downtrend Color","downColor","Line color while the trend is down.")],compute:(r,e)=>{let t=R(e,"mult",3),n=Nn(r,R(e,"atrLength",10)),o=r.length,i=new Array(o).fill(Number.NaN),s=new Array(o).fill(Number.NaN),a=Number.NaN,l=Number.NaN,c=-1;for(let d=0;d0?r[d-1].close:h.close;a=y<=g?Math.min(m,g):m,l=y>=b?Math.max(f,b):f,c=h.close>a?1:h.close{let t=oe(r,"HL2"),n=Fe(Ne(t,R(e,"jawLength",13)),R(e,"jawOffset",8)),o=Fe(Ne(t,R(e,"teethLength",8)),R(e,"teethOffset",5)),i=Fe(Ne(t,R(e,"lipsLength",5)),R(e,"lipsOffset",3));return {plots:[{key:"jaw",title:"Jaw",values:n,color:T(e,"jawColor",mS)},{key:"teeth",title:"Teeth",values:o,color:T(e,"teethColor",fS)},{key:"lips",title:"Lips",values:i,color:T(e,"lipsColor",gS)}]}}},dr="Alligator Lines",cm="SMMA (Wilder)",GR={type:"gator-oscillator",title:"Gator Oscillator",shortTitle:"Gator Oscillator",overlay:false,inputs:[{...le("HL2","source","Source","Price series fed to the three Alligator averages. Bill Williams' original recipe uses the median price (high + low) / 2."),group:dr},{...Te("maType","Smoothing",cm,[cm,"SMA","EMA"],"Moving average applied to the source for the jaw, teeth and lips. The original uses the smoothed (Wilder-style) moving average."),group:dr},{...pe("jawLength","Jaw Length",13,1,500,"Averaging length of the jaw line."),group:dr},{...pe("jawOffset","Jaw Offset",8,0,100,"Bars the jaw is displaced forward, 8 in the original recipe. The upper histogram measures the absolute spread between the displaced jaw and teeth."),group:dr},{...pe("teethLength","Teeth Length",8,1,500,"Averaging length of the teeth line."),group:dr},{...pe("teethOffset","Teeth Offset",5,0,100,"Bars the teeth are displaced forward, 5 in the original recipe. The teeth line enters both spreads."),group:dr},{...pe("lipsLength","Lips Length",5,1,500,"Averaging length of the lips line."),group:dr},{...pe("lipsOffset","Lips Offset",3,0,100,"Bars the lips are displaced forward, 3 in the original recipe. The lower histogram measures the negative absolute spread between the displaced teeth and lips."),group:dr},P(O,"Expanding","growColor","Column color while a spread grew against its own previous bar \u2014 the averages are spreading apart."),P(D,"Contracting","shrinkColor","Column color while a spread shrank \u2014 the averages are converging. Color encodes expansion, not trade direction."),P(A,"Zero Line","zeroColor","Color of the zero line separating the two histograms.")],compute:(r,e)=>{let t=oe(r,T(e,"source","HL2")),n=T(e,"maType",cm),o=p=>n==="SMA"?Ce(t,p):n==="EMA"?q(t,p):Ne(t,p),i=Fe(o(R(e,"jawLength",13)),R(e,"jawOffset",8)),s=Fe(o(R(e,"teethLength",8)),R(e,"teethOffset",5)),a=Fe(o(R(e,"lipsLength",5)),R(e,"lipsOffset",3)),l=re(we(i,s),Math.abs),c=re(we(s,a),Math.abs),d=T(e,"growColor",O),u=T(e,"shrinkColor",D),h=p=>{let m=false;return p.map((f,g)=>{if(!Number.isFinite(f))return null;let b=g>0?p[g-1]:Number.NaN;return Number.isFinite(b)&&(m=f>b?true:f-p),kind:"columns",color:u,colors:h(c),base:0}],levels:[{key:"zero",price:0,color:T(e,"zeroColor",A),lineStyle:"solid",title:"Zero Line"}]}}},yS=[OR,NR,FR,VR,BR,_R,HR,zR,WR,GR];function no(r,e,t=0,n=100,o="Overbought Level",i="Oversold Level"){return [Q("overbought",o,r,t,n,1,"Level above which the oscillator is considered overbought."),Q("oversold",i,e,t,n,1,"Level below which the oscillator is considered oversold.")]}var $R={type:"rsi",title:"Relative Strength Index",shortTitle:"RSI",overlay:false,inputs:[F(14,"length","Length",5e3,"Number of bars used in the Wilder smoothing of average gains and losses."),le("Close","source","Source","Price series the RSI is calculated on."),...no(70,30,0,100,"Overbought","Oversold"),P(A,"RSI","color","Color of the RSI line at the midline. Toward either threshold it blends into that threshold\u2019s color."),P(O,"Oversold","oversoldColor","Color of the line and zone shading at and below the oversold level."),P(D,"Overbought","overboughtColor","Color of the line and zone shading at and above the overbought level."),P(A,"Levels","levelsColor","Color of the overbought, midline and oversold levels."),P(z(A,90),"Band Fill","fillColor","Color of the fill between the overbought and oversold levels.")],compute:(r,e)=>fn({key:"rsi",title:"RSI",values:Zs(oe(r,T(e,"source","Close")),R(e,"length",14)),scale:{top:100,bottom:0},overbought:R(e,"overbought",70),oversold:R(e,"oversold",30),ink:{low:T(e,"oversoldColor",O),mid:T(e,"color",A),high:T(e,"overboughtColor",D)},levelInk:T(e,"levelsColor",A),width:2,midline:50,bandFill:T(e,"fillColor",z(A,90))})};function TS(r,e,t){let n=R(t,"overbought",80),o=R(t,"oversold",20);return {plots:[{key:"k",title:"%K",values:r,color:T(t,"kColor",ce)},{key:"d",title:"%D",values:e,color:T(t,"dColor",Y)},ct("obAnchor","Overbought Anchor",r.length,n),ct("osAnchor","Oversold Anchor",r.length,o)],bands:[{key:"band",from:"obAnchor",to:"osAnchor",color:T(t,"fillColor",z(ce,90))}],levels:[{key:"overbought",price:n,color:A,lineStyle:"dashed",title:"Overbought"},{key:"oversold",price:o,color:A,lineStyle:"dashed",title:"Oversold"}]}}var UR={type:"stochastic",title:"Stochastic",shortTitle:"Stoch",overlay:false,inputs:[F(14,"kLength","%K Length",5e3,"Number of bars used for the highest high / lowest low range of the raw %K."),F(3,"kSmoothing","%K Smoothing",500,"Simple moving average length applied to the raw %K. 1 gives the fast stochastic, 3 the classic slow stochastic."),F(3,"dLength","%D Smoothing",500,"Simple moving average length of the %D signal line, applied to the smoothed %K."),...no(80,20),P(ce,"%K","kColor","Color of the %K line."),P(Y,"%D","dColor","Color of the %D signal line."),P(z(ce,90),"Band Fill","fillColor","Fill color of the area between the overbought and oversold levels.")],compute:(r,e)=>{let t=Ce(nm(je(r),et(r),tt(r),R(e,"kLength",14)),R(e,"kSmoothing",3));return TS(t,Ce(t,R(e,"dLength",3)),e)}},YR={type:"stochastic-rsi",title:"Stochastic RSI",shortTitle:"Stoch RSI",overlay:false,inputs:[le("Close","source","RSI Source","Price series the RSI is computed on."),F(14,"rsiLength","RSI Length",5e3,"Lookback length of the Wilder RSI."),F(14,"stochLength","Stochastic Length",5e3,"Lookback over which the highest and lowest RSI values are taken."),F(3,"kSmoothing","%K Smoothing",500,"Simple moving average length applied to the stochastic of RSI to form %K."),F(3,"dLength","%D Smoothing",500,"Simple moving average length applied to %K to form the %D signal line."),...no(80,20),P(ce,"%K Color","kColor","Color of the %K line."),P(Y,"%D Color","dColor","Color of the %D signal line."),P(z(ce,90),"Zone Fill","fillColor","Fill color of the area between the overbought and oversold levels.")],compute:(r,e)=>{let t=Zs(oe(r,T(e,"source","Close")),R(e,"rsiLength",14)),n=Ce(nm(t,t,t,R(e,"stochLength",14)),R(e,"kSmoothing",3));return TS(n,Ce(n,R(e,"dLength",3)),e)}},KR={type:"macd",title:"MACD",overlay:false,inputs:[F(12,"fastLength","Fast Length",5e3,"Length of the fast EMA."),F(26,"slowLength","Slow Length",5e3,"Length of the slow EMA."),F(9,"signalLength","Signal Smoothing",500,"Length of the EMA applied to the MACD line to obtain the signal line."),le("Close","source","Source","Price series used to compute the fast and slow EMAs."),P(ce,"MACD Line","color","Color of the MACD line."),P(Y,"Signal Line","signalColor","Color of the signal line."),P(O,"Grow Above","growAboveColor","Histogram color when above zero and rising."),P(z(O,50),"Fall Above","fallAboveColor","Histogram color when above zero and falling."),P(z(D,50),"Grow Below","growBelowColor","Histogram color when below zero and rising."),P(D,"Fall Below","fallBelowColor","Histogram color when below zero and falling.")],compute:(r,e)=>{let t=oe(r,T(e,"source","Close")),n=we(q(t,R(e,"fastLength",12)),q(t,R(e,"slowLength",26))),o=q(n,R(e,"signalLength",9)),i=we(n,o),s=oS(i,{growAbove:T(e,"growAboveColor",O),fallAbove:T(e,"fallAboveColor",z(O,50)),growBelow:T(e,"growBelowColor",z(D,50)),fallBelow:T(e,"fallBelowColor",D)});return {plots:[{key:"hist",title:"Histogram",values:i,kind:"columns",color:O,colors:s,base:0},{key:"macd",title:"MACD",values:n,color:T(e,"color",ce)},{key:"signal",title:"Signal",values:o,color:T(e,"signalColor",Y)}],levels:[{key:"zero",price:0,color:A,lineStyle:"dashed",title:"Zero Line"}]}}},XR={type:"ppo",title:"Percentage Price Oscillator",shortTitle:"PPO",overlay:false,inputs:[le("Close","source","Source","Price series fed into the fast and slow averages."),F(12,"fastLength","Fast Length",5e3,"Length of the fast moving average."),F(26,"slowLength","Slow Length",5e3,"Length of the slow moving average. The spread is divided by it and scaled to a percentage of price."),Te("maType","Average Type","EMA",["EMA","SMA"],"Moving average type used for the fast and slow averages."),F(9,"signalLength","Signal Smoothing",500,"Length of the signal line that smooths the PPO line."),Te("signalType","Signal Type","EMA",["EMA","SMA"],"Moving average type used for the signal line."),P(O,"Bullish","bullColor","Color of the PPO line, gradient fill and histogram above the zero line."),P(D,"Bearish","bearColor","Color of the PPO line, gradient fill and histogram below the zero line."),P(Y,"Signal Line","signalColor","Color of the signal line."),ne("showHistogram","Show Histogram",true,xe,"Displays the histogram (PPO minus signal line) as columns. Bright columns mark a spread still widening, faded ones a spread narrowing back."),ne("gradientFill","Gradient Fill",true,xe,"Fills the area between the zero line and the PPO line with a vertical gradient.")],compute:(r,e)=>{let t=oe(r,T(e,"source","Close")),n=(p,m,f)=>p==="SMA"?Ce(m,f):q(m,f),o=T(e,"maType","EMA"),i=n(o,t,R(e,"fastLength",12)),s=n(o,t,R(e,"slowLength",26)),a=X(i,s,(p,m)=>m===0?Number.NaN:(p-m)/m*100),l=n(T(e,"signalType","EMA"),a,R(e,"signalLength",9)),c=we(a,l),d=T(e,"bullColor",O),u=T(e,"bearColor",D),h=Ae({key:"ppo",title:"PPO Line",values:a,ink:{bull:d,bear:u,neutral:u},zeroInk:z(A,90),fill:te(e,"gradientFill",true),extraPlots:[{key:"signal",title:"Signal Line",values:l,color:T(e,"signalColor",Y)}]});if(te(e,"showHistogram",true)){let p=c.map((m,f)=>{if(!Number.isFinite(m))return null;let g=f>0&&Number.isFinite(c[f-1])?c[f-1]:m,b=m>=0?d:u,y=m>=0?m>g:m{let t=oe(r,"HL2"),n=we(Ce(t,5),Ce(t,34)),o=T(e,"risingColor",O),i=T(e,"fallingColor",D),s=n.map((a,l)=>{if(!Number.isFinite(a))return null;let c=l>0?n[l-1]:Number.NaN;return Number.isFinite(c)&&a>c?o:i});return {plots:[{key:"ao",title:"AO",values:n,kind:"columns",color:o,colors:s,base:0}],levels:[{key:"zero",price:0,color:T(e,"zeroColor",A),lineStyle:"dashed",title:"Zero Line"}]}}},qR=.015,ZR={type:"commodity-channel-index",title:"Commodity Channel Index",shortTitle:"CCI",overlay:false,inputs:[F(20,"length","Length",5e3,"Number of bars used for the moving average and the mean absolute deviation of the source."),le("HLC3","source","Source","Price series measured by the CCI; the typical price hlc3 is the classic choice."),Q("upper","Upper Level",100,-1e3,1e3,10,"Overbought reference level, +100 classically."),Q("lower","Lower Level",-100,-1e3,1e3,10,"Oversold reference level, \u2212100 classically."),P(A,"CCI Line","color","Color of the CCI line."),P(O,"Bullish","bullColor","Line and fill color while the CCI reads above zero."),P(D,"Bearish","bearColor","Line and fill color while the CCI reads below zero."),P(A,"Levels","levelsColor","Color of the upper, lower and zero reference lines.")],compute:(r,e)=>{let t=R(e,"length",20),n=oe(r,T(e,"source","HLC3")),o=Ce(n,t),i=$0(n,t),s=n.map((l,c)=>{let d=o[c],u=i[c];return !Number.isFinite(d)||!Number.isFinite(u)?Number.NaN:u===0?0:(l-d)/(qR*u)}),a=T(e,"levelsColor",A);return Ae({key:"cci",title:"CCI",values:s,ink:{bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"color",A)},zeroInk:a,zeroLineStyle:"dotted",extraLevels:[{key:"upper",price:R(e,"upper",100),color:a,lineStyle:"dashed",title:"Upper Level"},{key:"lower",price:R(e,"lower",-100),color:a,lineStyle:"dashed",title:"Lower Level"}]})}},QR={type:"williams-percent-r",title:"Williams %R",shortTitle:"%R",overlay:false,inputs:[F(14,"length","Length",5e3,"Lookback length of the highest high / lowest low range. 14 is the classic setting."),le("Close","source","Source","Series located within the lookback range. Close is the classic choice."),...no(-20,-80,-100,0),P(A,"%R Line","color","Color of the %R line between the thresholds. Toward either level it blends into that level\u2019s color."),P(D,"Overbought","overboughtColor","Color of the line and zone shading at and above the overbought level."),P(O,"Oversold","oversoldColor","Color of the line and zone shading at and below the oversold level.")],compute:(r,e)=>{let t=R(e,"length",14),n=oe(r,T(e,"source","Close")),o=at(et(r),t),i=lt(tt(r),t),s=n.map((a,l)=>{let c=o[l],d=i[l];return Number.isFinite(c)&&Number.isFinite(d)&&c>d?-100*(c-a)/(c-d):Number.NaN});return fn({key:"wr",title:"%R",values:s,scale:{top:0,bottom:-100},overbought:R(e,"overbought",-20),oversold:R(e,"oversold",-80),ink:{low:T(e,"oversoldColor",O),mid:T(e,"color",A),high:T(e,"overboughtColor",D)},levelInk:A})}},JR={type:"chande-momentum-oscillator",title:"Chande Momentum Oscillator",shortTitle:"CMO",overlay:false,inputs:[F(9,"length","Length",5e3,"Number of bars over which up moves and down moves are summed."),le("Close","source","Source","Price series used to measure bar-to-bar changes."),Q("overbought","Overbought Level",50,0,100,1,"Level above which the oscillator is considered overbought."),Q("oversold","Oversold Level",-50,-100,0,1,"Level below which the oscillator is considered oversold."),P(A,"CMO Line","color","Color of the CMO line."),P(O,"Bullish","bullColor","Line and fill color while momentum is positive, and shading of the oversold zone."),P(D,"Bearish","bearColor","Line and fill color while momentum is negative, and shading of the overbought zone."),P(A,"Levels","levelsColor","Color of the overbought, oversold, and zero lines.")],compute:(r,e)=>{let t=R(e,"length",9),n=st(oe(r,T(e,"source","Close"))),o=ge(re(n,m=>Math.max(m,0)),t),i=ge(re(n,m=>Math.max(-m,0)),t),s=X(o,i,(m,f)=>m+f===0?0:100*(m-f)/(m+f)),a=T(e,"bullColor",O),l=T(e,"bearColor",D),c=T(e,"levelsColor",A),d=R(e,"overbought",50),u=R(e,"oversold",-50),h=Ae({key:"cmo",title:"CMO",values:s,ink:{bull:a,bear:l,neutral:T(e,"color",A)},zeroInk:c,zeroLineStyle:"dotted",extraLevels:[{key:"overbought",price:d,color:c,lineStyle:"dashed",title:"Overbought"},{key:"oversold",price:u,color:c,lineStyle:"dashed",title:"Oversold"}]}),p=om(s.length,{overbought:d,oversold:u,top:100,bottom:-100},{overbought:l,oversold:a});return h.plots.push(...p.plots),h.bands=[...h.bands??[],...p.bands],h}},eD={type:"connors-rsi",title:"Connors RSI",shortTitle:"CRSI",overlay:false,inputs:[F(3,"rsiLength","RSI Length",5e3,"Length of the Wilder RSI applied to the closing price."),F(2,"streakLength","Streak RSI Length",5e3,"Length of the Wilder RSI applied to the up/down close streak."),F(100,"rankLength","Percent Rank Length",5e3,"Lookback of the percent rank applied to the 1-bar rate of change of the closing price."),...no(90,10),P(A,"CRSI Line","color","Color of the Connors RSI line."),P(O,"Oversold","oversoldColor","Line, fill and zone color toward and below the oversold level."),P(D,"Overbought","overboughtColor","Line, fill and zone color toward and above the overbought level."),P(A,"Levels","levelsColor","Color of the overbought and oversold levels.")],compute:(r,e)=>{let t=je(r),n=new Array(t.length).fill(0);for(let l=1;l0?Math.max(n[l-1],0)+1:c<0?Math.min(n[l-1],0)-1:0;}let o=Zs(t,R(e,"rsiLength",3)),i=Zs(n,R(e,"streakLength",2)),s=nS(Qr(t,1),R(e,"rankLength",100)),a=t.map((l,c)=>{let d=o[c],u=i[c],h=s[c];return Number.isFinite(d)&&Number.isFinite(u)&&Number.isFinite(h)?(d+u+h)/3:Number.NaN});return fn({key:"crsi",title:"Connors RSI",values:a,scale:{top:100,bottom:0},overbought:R(e,"overbought",90),oversold:R(e,"oversold",10),ink:{low:T(e,"oversoldColor",O),mid:T(e,"color",A),high:T(e,"overboughtColor",D)},levelInk:T(e,"levelsColor",A),midpointWash:true})}},tD={type:"fisher-transform",title:"Fisher Transform",shortTitle:"Fisher",overlay:false,inputs:[F(9,"length","Length",5e3,"Lookback period used to locate the median price hl2 within its highest-lowest range. Ehlers' original length is 10; 9 is the common platform default."),P(A,"Fisher Line","color","Color of the Fisher line when it sits exactly on its trigger."),P(A,"Trigger Line","triggerColor","Color of the trigger line, the Fisher value delayed one bar."),P(O,"Bullish","bullColor","Color of the Fisher line and fill while it is above the trigger."),P(D,"Bearish","bearColor","Color of the Fisher line and fill while it is below the trigger.")],compute:(r,e)=>{let t=R(e,"length",9),n=oe(r,"HL2"),o=at(n,t),i=lt(n,t),s=r.length,a=new Array(s).fill(Number.NaN),l=0,c=0;for(let f=0;fb?(n[f]-b)/(g-b)-.5:0)+.67*l,l=l>.99?.999:l<-0.99?-0.999:l,c=.5*Math.log((1+l)/(1-l))+.5*c,a[f]=c;}let d=Fe(a,1),u=T(e,"color",A),h=T(e,"bullColor",O),p=T(e,"bearColor",D),m=f=>{let g=a[f],b=d[f];return Number.isFinite(b)?g>b?h:gNumber.isFinite(f)?m(g):null)},{key:"trigger",title:"Trigger",values:d,color:T(e,"triggerColor",A)}],bands:[{key:"spread",from:"fisher",to:"trigger",color:z(u,80),colors:a.map((f,g)=>Number.isFinite(f)?z(m(g),80):null)}],levels:[{key:"upper",price:1.5,color:A,lineStyle:"dashed",title:"Upper Level"},{key:"lower",price:-1.5,color:A,lineStyle:"dashed",title:"Lower Level"},{key:"zero",price:0,color:A,lineStyle:"dotted",title:"Zero Line"}]}}},nD={type:"trix",title:"TRIX",overlay:false,inputs:[F(18,"length","Length",5e3,"Length of each of the three EMA smoothing passes applied to the close price."),F(9,"signalLength","Signal Length",500,"Length of the EMA applied to TRIX to form the signal line."),P(A,"TRIX Color","color","Color of the TRIX line."),P(Y,"Signal Color","signalColor","Color of the signal line."),P(O,"Bullish","bullColor","Color of the TRIX line and its gradient fill while TRIX holds above zero."),P(D,"Bearish","bearColor","Color of the TRIX line and its gradient fill while TRIX holds below zero.")],compute:(r,e)=>{let t=R(e,"length",18),n=q(q(q(je(r),t),t),t),o=Qr(n,1);return Ae({key:"trix",title:"TRIX",values:o,ink:{bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"color",A)},zeroInk:A,extraPlots:[{key:"signal",title:"Signal",values:q(o,R(e,"signalLength",9)),color:T(e,"signalColor",Y)}]})}};function kS(r,e,t){let n=st(r),o=q(q(n,e),t),i=q(q(re(n,Math.abs),e),t);return X(o,i,(s,a)=>a===0?0:s/a)}var rD={type:"true-strength-index",title:"True Strength Index",shortTitle:"TSI",overlay:false,inputs:[F(25,"longLength","Long Length",5e3,"Length of the first (long) EMA applied to the 1-bar price change."),F(13,"shortLength","Short Length",5e3,"Length of the second (short) EMA applied to the long-smoothed price change."),F(13,"signalLength","Signal Length",500,"Length of the EMA of TSI used as the signal line."),P(A,"TSI","color","Color of the TSI line."),P(Y,"Signal","signalColor","Color of the signal line."),P(O,"Bullish","bullColor","Color of the TSI line and its gradient fill while TSI holds above zero."),P(D,"Bearish","bearColor","Color of the TSI line and its gradient fill while TSI holds below zero.")],compute:(r,e)=>{let t=re(kS(je(r),R(e,"longLength",25),R(e,"shortLength",13)),n=>100*n);return Ae({key:"tsi",title:"TSI",values:t,ink:{bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"color",A)},zeroInk:A,extraPlots:[{key:"signal",title:"Signal",values:q(t,R(e,"signalLength",13)),color:T(e,"signalColor",Y)}]})}},um="Indicator",wS="Oscillator",oD={type:"smi-ergodic",title:"SMI Ergodic Oscillator",shortTitle:"SMIE",overlay:false,inputs:[F(20,"longLength","Long Length",5e3,"Length of the first EMA smoothing applied to the momentum of the closing price."),F(5,"shortLength","Short Length",5e3,"Length of the second EMA smoothing applied to the momentum of the closing price."),F(5,"signalLength","Signal Length",500,"Length of the EMA of the SMI that forms the signal line."),Te("display","Display",um,[um,wS],"Indicator plots the SMI and its signal line. Oscillator plots the difference between them as a histogram."),P(A,"SMI","color","Color of the SMI line while it sits exactly on its signal line."),P(Y,"Signal","signalColor","Color of the signal line."),P(O,"Oscillator Grow","growColor","Color of the rising oscillator histogram, and of the SMI line while it leads its signal."),P(D,"Oscillator Fall","fallColor","Color of the falling oscillator histogram, and of the SMI line while it lags its signal.")],compute:(r,e)=>{let t=kS(je(r),R(e,"longLength",20),R(e,"shortLength",5)),n=q(t,R(e,"signalLength",5)),o=T(e,"growColor",O),i=T(e,"fallColor",D),s=[{key:"zero",price:0,color:z(A,50),lineStyle:"dashed",title:"Zero"}];if(T(e,"display",um)===wS){let c=we(t,n),d=c.map((u,h)=>{if(!Number.isFinite(u))return null;let p=h>0&&Number.isFinite(c[h-1])?c[h-1]:u;return u>p?o:i});return {plots:[{key:"osc",title:"Oscillator",values:c,kind:"columns",color:o,colors:d,base:0}],levels:s}}let a=T(e,"color",A),l=c=>{let d=t[c],u=n[c];return Number.isFinite(u)?d>u?o:dNumber.isFinite(c)?l(d):null)},{key:"signal",title:"Signal",values:n,color:T(e,"signalColor",Y)}],bands:[{key:"spread",from:"smi",to:"signal",color:z(a,75),colors:t.map((c,d)=>Number.isFinite(c)?z(l(d),75):null)}],levels:s}}},Qs=50,xS="Trigger Levels",iD={type:"schaff-trend-cycle",title:"Schaff Trend Cycle",shortTitle:"Schaff Trend Cycle",overlay:false,inputs:[le("Close","source","Source","Price series used to build the MACD that the trend cycle is measured on."),F(23,"fastLength","Fast Length",5e3,"Fast EMA length of the underlying MACD."),F(50,"slowLength","Slow Length",5e3,"Slow EMA length of the underlying MACD."),{...F(10,"cycleLength","Cycle Length",5e3,"Window of the two stochastic passes. Each pass measures where its input sits inside the range of its own values over this many bars."),min:2},Q("factor","Smoothing Factor",.5,.01,1,.05,"%D style recursive smoothing applied after each stochastic pass. 0.5 is the published default."),{...Q("upper","Upper Trigger",75,0,100,1,"Upper trigger line. A cross down through it flags an emerging downtrend."),group:xS},{...Q("lower","Lower Trigger",25,0,100,1,"Lower trigger line. A cross up through it flags an emerging uptrend."),group:xS},P(O,"Bullish Color","bullColor","Color of the trend cycle line and gradient while the cycle holds the upper half of its 0-100 scale."),P(D,"Bearish Color","bearColor","Color of the trend cycle line and gradient while the cycle holds the lower half of its 0-100 scale."),P(A,"Levels Color","levelsColor","Color of the dashed trigger lines and the dotted midline."),ne("gradientFill","Gradient Fill",true,xe,"Vertical gradient between the midline and the trend cycle, fading out toward the midline.")],compute:(r,e)=>{let t=R(e,"cycleLength",10),n=R(e,"factor",.5),o=oe(r,T(e,"source","Close")),i=we(q(o,R(e,"fastLength",23)),q(o,R(e,"slowLength",50))),s=m=>{let f=lt(m,t),g=at(m,t),b=new Array(m.length).fill(Number.NaN),y=Number.NaN;for(let w=0;wM&&(y=100*(S-M)/(C-M)),b[w]=y);}return b},a=m=>{let f=new Array(m.length).fill(Number.NaN),g=Number.NaN;for(let b=0;bNumber.isFinite(m)?m>Qs?d:u:null)}],p=[];return te(e,"gradientFill",true)&&(h.push(ct("midAnchor","Midline Anchor",l.length,Qs)),p.push({key:"wash",from:"stc",to:"midAnchor",color:z(A,100),gradient:to(l,Qs,m=>m>Qs?d:u)})),{plots:h,bands:p,levels:[{key:"upper",price:R(e,"upper",75),color:z(c,25),lineStyle:"dashed",title:"Upper Trigger"},{key:"lower",price:R(e,"lower",25),color:z(c,25),lineStyle:"dashed",title:"Lower Trigger"},{key:"midline",price:Qs,color:z(c,60),lineStyle:"dotted",title:"Midline"}]}}},sD={type:"know-sure-thing",title:"Know Sure Thing",shortTitle:"KST",overlay:false,inputs:[F(10,"rocLength1","ROC Length #1",5e3,"Lookback of the first (shortest) rate of change."),F(15,"rocLength2","ROC Length #2",5e3,"Lookback of the second rate of change."),F(20,"rocLength3","ROC Length #3",5e3,"Lookback of the third rate of change."),F(30,"rocLength4","ROC Length #4",5e3,"Lookback of the fourth (longest) rate of change."),F(10,"smaLength1","SMA Length #1",5e3,"Smoothing length applied to the first rate of change (RCMA #1)."),F(10,"smaLength2","SMA Length #2",5e3,"Smoothing length applied to the second rate of change (RCMA #2)."),F(10,"smaLength3","SMA Length #3",5e3,"Smoothing length applied to the third rate of change (RCMA #3)."),F(15,"smaLength4","SMA Length #4",5e3,"Smoothing length applied to the fourth rate of change (RCMA #4)."),F(9,"signalLength","Signal Length",500,"Simple moving average length of the signal line."),P(O,"Bullish","bullColor","Color of the KST line while above zero."),P(D,"Bearish","bearColor","Color of the KST line while below zero."),P(Y,"Signal","signalColor","Color of the signal line.")],compute:(r,e)=>{let t=je(r),n=(s,a,l,c)=>Ce(Qr(t,R(e,s,a)),R(e,l,c)),o=[n("rocLength1",10,"smaLength1",10),n("rocLength2",15,"smaLength2",10),n("rocLength3",20,"smaLength3",10),n("rocLength4",30,"smaLength4",15)].reduce((s,a,l)=>X(s,a,(c,d)=>c+d*(l+1)),new Array(t.length).fill(0)),i=T(e,"bullColor",O);return Ae({key:"kst",title:"KST",values:o,ink:{bull:i,bear:T(e,"bearColor",D),neutral:i},zeroInk:A,valueTransparency:60,extraPlots:[{key:"signal",title:"Signal",values:Ce(o,R(e,"signalLength",9)),color:T(e,"signalColor",Y)}]})}},aD={type:"coppock-curve",title:"Coppock Curve",shortTitle:"Coppock",overlay:false,inputs:[F(10,"wmaLength","WMA Length",5e3,"Length of the weighted moving average applied to the sum of the two rates of change."),F(14,"longRoc","Long RoC Length",5e3,"Lookback of the long rate of change, in bars. The original definition uses 14 monthly closes."),F(11,"shortRoc","Short RoC Length",5e3,"Lookback of the short rate of change, in bars. The original definition uses 11 monthly closes."),le("Close","source","Source","Price series used for the rate of change calculations."),P(A,"Coppock Curve","color","Color of the Coppock Curve line."),P(O,"Bullish","bullColor","Line and fill color while the curve reads above zero."),P(D,"Bearish","bearColor","Line and fill color while the curve reads below zero."),P(A,"Zero Line","zeroColor","Color of the zero reference line.")],compute:(r,e)=>{let t=oe(r,T(e,"source","Close")),n=Ut(X(Qr(t,R(e,"longRoc",14)),Qr(t,R(e,"shortRoc",11)),(o,i)=>o+i),R(e,"wmaLength",10));return Ae({key:"coppock",title:"Coppock Curve",values:n,ink:{bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"color",A)},zeroInk:T(e,"zeroColor",A)})}},lD={type:"detrended-price-oscillator",title:"Detrended Price Oscillator",shortTitle:"DPO",overlay:false,inputs:[F(21,"length","Length",5e3,"Lookback of the simple moving average that price is detrended against. The comparison is displaced by Length / 2 + 1 bars."),le("Close","source","Source","Price series used in the detrending calculation."),ne("centered","Centered",false,void 0,"Shifts the oscillator back by Length / 2 + 1 bars so it is centered on the prices it detrends. The most recent bars then show no value."),P(A,"DPO","color","Color of the line when it sits exactly at zero."),P(O,"Above Zero","bullColor","Color of the line and fill while the oscillator is above zero."),P(D,"Below Zero","bearColor","Color of the line and fill while the oscillator is below zero."),P(A,"Zero Line","zeroColor","Color of the zero reference line.")],compute:(r,e)=>{let t=R(e,"length",21),n=Math.trunc(t/2)+1,o=oe(r,T(e,"source","Close")),i=Ce(o,t),a=te(e,"centered",false)?Fe(we(Fe(o,n),i),-n):we(o,Fe(i,n));return Ae({key:"dpo",title:"DPO",values:a,ink:{bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"color",A)},zeroInk:T(e,"zeroColor",A)})}},hm="ROC %",SS="Momentum",cD={type:"rate-of-change",title:"Rate of Change",shortTitle:"ROC",overlay:false,inputs:[F(9,"length","Length",5e3,"Lookback period; the source is compared with its value this many bars ago."),le("Close","source","Source","Series used as input for the calculation."),Te("mode","Mode",hm,[hm,SS],"ROC % plots the change as a percentage of the source value from the lookback; Momentum plots the raw difference."),P(A,"Line","color","Color of the line when the reading sits exactly at zero."),P(O,"Bullish","bullColor","Color of the line and fill while the reading is above zero."),P(D,"Bearish","bearColor","Color of the line and fill while the reading is below zero."),ne("gradientFill","Gradient Fill",true,xe,"Fills the area between the line and zero, following the line color.")],compute:(r,e)=>{let t=R(e,"length",9),n=oe(r,T(e,"source","Close")),o=T(e,"mode",hm)===SS?st(n,t):Qr(n,t);return Ae({key:"roc",title:"ROC",values:o,ink:{bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"color",A)},zeroInk:A,fill:te(e,"gradientFill",true)})}},dD={type:"ultimate-oscillator",title:"Ultimate Oscillator",shortTitle:"UO",overlay:false,inputs:[F(7,"fastLength","Fast Length",5e3,"Bars in the fastest averaging window. Weighted 4 in the final blend, so it dominates the oscillator."),F(14,"middleLength","Middle Length",5e3,"Bars in the intermediate averaging window. Weighted 2 in the final blend."),F(28,"slowLength","Slow Length",5e3,"Bars in the slowest averaging window. Weighted 1 in the final blend."),...no(70,30,0,100,"Overbought","Oversold"),P(A,"Oscillator","color","Color of the line midway between the levels. Toward either level it blends into that level\u2019s color."),P(A,"Levels","levelsColor","Color of the overbought and oversold levels."),P(O,"Oversold","oversoldColor","Color of the line at the oversold level and of the oversold zone shading."),P(D,"Overbought","overboughtColor","Color of the line at the overbought level and of the overbought zone shading.")],compute:(r,e)=>{let t=r.length,n=new Array(t).fill(Number.NaN),o=new Array(t).fill(Number.NaN);for(let d=0;d0?r[d-1].close:u.close,p=Math.min(u.low,h);n[d]=u.close-p,o[d]=Math.max(u.high,h)-p;}let i=d=>X(ge(n,d),ge(o,d),(u,h)=>h===0?Number.NaN:u/h),s=i(R(e,"fastLength",7)),a=i(R(e,"middleLength",14)),l=i(R(e,"slowLength",28)),c=s.map((d,u)=>{let h=a[u],p=l[u];return Number.isFinite(d)&&Number.isFinite(h)&&Number.isFinite(p)?100*(4*d+2*h+p)/7:Number.NaN});return fn({key:"uo",title:"UO",values:c,scale:{top:100,bottom:0},overbought:R(e,"overbought",70),oversold:R(e,"oversold",30),ink:{low:T(e,"oversoldColor",O),mid:T(e,"color",A),high:T(e,"overboughtColor",D)},levelInk:T(e,"levelsColor",A),zoneTransparency:91})}},uD={type:"relative-vigor-index",title:"Relative Vigor Index",shortTitle:"RVGI",overlay:false,inputs:[F(10,"length","Length",5e3,"Number of bars summed for the smoothed numerator (close \u2212 open) and denominator (high \u2212 low)."),P(O,"RVGI","color","Color of the RVGI line."),P(D,"Signal","signalColor","Color of the signal line.")],compute:(r,e)=>{let t=R(e,"length",10),n=Vd(we(je(r),W0(r))),o=Vd(we(et(r),tt(r))),i=X(ge(n,t),ge(o,t),(s,a)=>a===0?0:s/a);return {plots:[{key:"rvgi",title:"RVGI",values:i,color:T(e,"color",O)},{key:"signal",title:"Signal",values:Vd(i),color:T(e,"signalColor",D)}],levels:[{key:"zero",price:0,color:z(A,50),lineStyle:"dashed",title:"Zero"}]}}},pm="EMA",CS="Wilder (RMA)",hD={type:"relative-volatility-index",title:"Relative Volatility Index",shortTitle:"RVI",overlay:false,inputs:[F(10,"stdevLength","Stdev Length",5e3,"Number of bars used for the standard deviation of closing prices that serves as each bar's volatility reading."),F(14,"smoothLength","Smoothing Length",5e3,"Number of bars used to smooth the up and down volatility streams."),Te("smoothType","Smoothing Type",pm,[pm,CS],"Moving average applied to the volatility streams. EMA is Dorsey's classic calculation; Wilder (RMA) matches platforms that use Wilder smoothing."),...no(80,20),P(A,"RVI Line","color","Color of the RVI line at the midline. Toward either threshold it blends into that threshold\u2019s color."),P(O,"Up Volatility","overboughtColor","Color of the line and zone shading at and above the overbought level."),P(D,"Down Volatility","oversoldColor","Color of the line and zone shading at and below the oversold level.")],compute:(r,e)=>{let t=je(r),n=It(t,R(e,"stdevLength",10)),o=st(t),i=X(n,o,(d,u)=>u>0?d:0),s=X(n,o,(d,u)=>u<0?d:0),a=R(e,"smoothLength",14),l=T(e,"smoothType",pm)===CS?Ne:q,c=X(l(i,a),l(s,a),(d,u)=>d+u===0?0:100*d/(d+u));return fn({key:"rvi",title:"RVI",values:c,scale:{top:100,bottom:0},overbought:R(e,"overbought",80),oversold:R(e,"oversold",20),ink:{low:T(e,"oversoldColor",D),mid:T(e,"color",A),high:T(e,"overboughtColor",O)},levelInk:A,width:2})}},pD={type:"balance-of-power",title:"Balance of Power",shortTitle:"BOP",overlay:false,inputs:[ne("smoothing","Smoothing",false,void 0,"Smooth the raw Balance of Power with a simple moving average instead of plotting the single-bar value."),F(14,"smoothLength","Length",5e3,"Simple moving average length applied when smoothing is enabled."),P(A,"BOP Color","color","Color of the line at exactly zero."),P(O,"Bullish","bullColor","Line and fill color while the Balance of Power is above zero \u2014 buyers in control of the bar."),P(D,"Bearish","bearColor","Line and fill color while the Balance of Power is below zero \u2014 sellers in control of the bar.")],compute:(r,e)=>{let t=r.map(o=>o.high===o.low?0:(o.close-o.open)/(o.high-o.low)),n=te(e,"smoothing",false)?Ce(t,R(e,"smoothLength",14)):t;return Ae({key:"bop",title:"BOP",values:n,ink:{bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"color",A)},zeroInk:A,valueTransparency:60})}},mD={type:"elder-ray",title:"Elder Ray",overlay:false,inputs:[F(13,"length","EMA Length",5e3,"Number of bars in the exponential moving average of closing prices used as the reference level for Bull Power and Bear Power. Alexander Elder's classic setting is 13."),P(O,"Bull Power","bullColor","Color of the Bull Power columns."),P(D,"Bear Power","bearColor","Color of the Bear Power columns.")],compute:(r,e)=>{let t=q(je(r),R(e,"length",13));return {plots:[{key:"bull",title:"Bull Power",values:we(et(r),t),kind:"columns",color:T(e,"bullColor",O),base:0},{key:"bear",title:"Bear Power",values:we(tt(r),t),kind:"columns",color:T(e,"bearColor",D),base:0}],levels:[{key:"zero",price:0,color:z(A,30),lineStyle:"dashed",title:"Zero Line"}]}}},fD={type:"ttm-squeeze",title:"TTM Squeeze",overlay:false,inputs:[{...F(20,"length","Length",5e3,"Shared lookback for the Bollinger Bands, the Keltner Channels, and the momentum regression. John Carter's original setting is 20."),min:2},le("Close","source","Source","Price series used for the shared moving average basis, the standard deviation, and the momentum displacement."),Q("bbMult","Bollinger Bands Multiplier",2,.1,50,.1,"Standard deviation multiplier for the Bollinger Bands."),Q("kcMult","Keltner Channels Multiplier",1.5,.1,50,.1,"ATR multiplier for the Keltner Channels. A smaller multiplier demands a tighter compression before the squeeze turns on."),P(O,"Momentum Up","bullColor","Histogram color while momentum is positive. Bars building away from zero print solid, bars fading back print dimmed."),P(D,"Momentum Down","bearColor","Histogram color while momentum is negative. Bars building away from zero print solid, bars fading back print dimmed."),P(Y,"Squeeze On","squeezeOnColor","Zero-line dot color while both Bollinger Bands sit fully inside the Keltner Channels."),P(A,"Squeeze Off","squeezeOffColor","Zero-line dot color while the Bollinger Bands trade outside the Keltner Channels."),ne("markFires","Mark Squeeze Fires",true,xe,"Draws a cross on the zero line on the first bar where the bands re-emerge outside the channels, colored by the side of the momentum histogram.")],compute:(r,e)=>{let t=R(e,"length",20),n=oe(r,T(e,"source","Close")),o=Ce(n,t),i=re(It(n,t),b=>b*R(e,"bbMult",2)),s=re(Nn(r,t),b=>b*R(e,"kcMult",1.5)),a=X(at(et(r),t),lt(tt(r),t),(b,y)=>(b+y)/2),l=X(a,o,(b,y)=>(b+y)/2),c=si(we(n,l),t,0),d=o.map((b,y)=>{let w=i[y],S=s[y];return !Number.isFinite(b)||!Number.isFinite(w)||!Number.isFinite(S)?null:w{if(!Number.isFinite(b))return null;let w=y>0&&Number.isFinite(c[y-1])?c[y-1]:b,S=b>w;return b>=0?S?u:z(u,60):S?z(h,60):h}),g=[{key:"mom",title:"Momentum",values:c,kind:"columns",color:u,colors:f,base:0},{key:"state",title:"Squeeze State",values:d.map(b=>b==null?Number.NaN:0),kind:"circles",color:m,width:2,colors:d.map(b=>b==null?null:b?p:m)}];if(te(e,"markFires",true)){let b=d.map((y,w)=>y===false&&d[w-1]===true?0:Number.NaN);g.push({key:"fire",title:"Squeeze Fire",values:b,kind:"cross",color:m,width:3,colors:b.map((y,w)=>Number.isFinite(y)?Number.isFinite(c[w])?c[w]>=0?u:h:m:null)});}return {plots:g}}},LS=[$R,UR,YR,KR,XR,jR,ZR,QR,JR,eD,tD,nD,rD,oD,iD,sD,aD,lD,cD,dD,uD,hD,pD,mD,fD];var gD={type:"aroon",title:"Aroon",overlay:false,inputs:[F(14,"length","Length",5e3,"Lookback length used to locate the highest high and lowest low."),P(O,"Aroon Up","upColor","Color of the Aroon Up line."),P(D,"Aroon Down","downColor","Color of the Aroon Down line.")],compute:(r,e)=>{let t=R(e,"length",14),n=re(U0(et(r),t),i=>100*(t-i)/t),o=re(Y0(tt(r),t),i=>100*(t-i)/t);return {plots:[{key:"up",title:"Aroon Up",values:n,color:T(e,"upColor",O)},{key:"down",title:"Aroon Down",values:o,color:T(e,"downColor",D)}]}}},bD={type:"average-directional-index",title:"Average Directional Index",shortTitle:"ADX",overlay:false,inputs:[F(14,"diLength","DI Length",5e3,"Wilder RMA smoothing length applied to directional movement and true range when computing +DI and \u2212DI."),F(14,"adxLength","ADX Smoothing",5e3,"Wilder RMA smoothing length applied to DX to obtain the ADX line."),Q("keyLevel","Key Level",25,0,100,1,"Trend strength reference level; ADX above it is commonly read as a trending market."),P(O,"+DI Color","plusDiColor","Color of the plus directional indicator, and of the ADX line above the key level while +DI leads."),P(D,"-DI Color","minusDiColor","Color of the minus directional indicator, and of the ADX line above the key level while \u2212DI leads."),P(A,"ADX Color","adxColor","Color of the ADX line while it sits below the key level \u2014 no trend strong enough to trade.")],compute:(r,e)=>{let t=R(e,"diLength",14),n=r.length,o=new Array(n).fill(Number.NaN),i=new Array(n).fill(Number.NaN);for(let g=1;gy&&b>0?b:0,i[g]=y>b&&y>0?y:0;}let s=Ne(Jr(r),t),a=X(Ne(o,t),s,(g,b)=>b===0?0:100*g/b),l=X(Ne(i,t),s,(g,b)=>b===0?0:100*g/b),c=X(a,l,(g,b)=>g+b===0?0:100*Math.abs(g-b)/(g+b)),d=Ne(c,R(e,"adxLength",14)),u=T(e,"plusDiColor",O),h=T(e,"minusDiColor",D),p=T(e,"adxColor",A),m=R(e,"keyLevel",25),f=d.map((g,b)=>Number.isFinite(g)?g<=m?p:(a[b]??0)>(l[b]??0)?u:h:null);return {plots:[{key:"plusDi",title:"+DI",values:a,color:z(u,30)},{key:"minusDi",title:"-DI",values:l,color:z(h,30)},{key:"adx",title:"ADX",values:d,color:p,width:2,colors:f}],levels:[{key:"keyLevel",price:m,color:A,lineStyle:"dashed",title:"Key Level"}]}}},vD={type:"vortex-indicator",title:"Vortex Indicator",shortTitle:"VI",overlay:false,inputs:[F(14,"length","Length",5e3,"Number of bars used to sum the vortex movements (VM+ and VM\u2212) and the true range."),P(O,"VI+","plusColor","Color of the positive vortex line (VI+)."),P(D,"VI-","minusColor","Color of the negative vortex line (VI\u2212)."),P(A,"Baseline","baselineColor","Color of the dotted baseline drawn at 1.")],compute:(r,e)=>{let t=R(e,"length",14),n=r.length,o=new Array(n).fill(Number.NaN),i=new Array(n).fill(Number.NaN);for(let a=1;al===0?Number.NaN:a/l),color:T(e,"plusColor",O)},{key:"viMinus",title:"VI-",values:X(ge(i,t),s,(a,l)=>l===0?Number.NaN:a/l),color:T(e,"minusColor",D)}],levels:[{key:"baseline",price:1,color:T(e,"baselineColor",A),lineStyle:"dotted",title:"Baseline"}]}}},MS=[gD,bD,vD];function ES(r,e,t){return r.map((n,o)=>{if(!Number.isFinite(n))return null;let i=o>0&&Number.isFinite(r[o-1])?r[o-1]:n;return n>i?t:e})}function mm(r,e,t,n,o,i,s=1){return {plots:[{key:r,title:e,values:t,color:o,width:s,colors:n},ct("zeroAnchor","Zero Anchor",t.length,0)],bands:[{key:"wash",from:r,to:"zeroAnchor",color:z(A,100),gradient:to(t,0,(a,l)=>n[l]??o,i)}]}}var yD={type:"average-true-range",title:"Average True Range",shortTitle:"ATR",overlay:false,inputs:[F(14,"length","Length",5e3,"Number of bars used to average the true range."),Te("smoothing","Smoothing","RMA",["RMA","SMA","EMA","WMA"],"Moving average applied to the true range. RMA is Wilder's original smoothing used by the classic ATR."),P(A,"ATR Line","color","Color of the ATR line while volatility contracts or holds flat."),P(Y,"Expanding","expandColor","Color of the ATR line while it rises \u2014 volatility expanding bar to bar.")],compute:(r,e)=>{let t=R(e,"length",14),n=Jr(r),o=T(e,"smoothing","RMA"),i=o==="SMA"?Ce(n,t):o==="EMA"?q(n,t):o==="WMA"?Ut(n,t):Ne(n,t),s=T(e,"color",A);return mm("atr","ATR",i,ES(i,s,T(e,"expandColor",Y)),s,75)}},wD={type:"historical-volatility",title:"Historical Volatility",shortTitle:"HV",overlay:false,inputs:[{...F(10,"length","Length",5e3,"Lookback window in bars for the standard deviation of close-to-close log returns."),min:2},ne("annualize","Annualize",true,void 0,"Scale the per-bar volatility to an annual figure by multiplying by the square root of the periods per year."),pe("periodsPerYear","Periods Per Year",252,1,1e5,"Number of periods in a year used for annualization: 252 for daily bars, 52 for weekly, 12 for monthly."),P(Y,"Volatility Line","color","Color of the line at its recent highs; it fades toward grey as volatility contracts.")],compute:(r,e)=>{let t=R(e,"length",10),n=we(re(je(r),Math.log),Fe(re(je(r),Math.log),1)),o=re(ge(n,t),h=>h/t),i=ge(re(n,h=>h*h),t),s=te(e,"annualize",true)?Math.sqrt(R(e,"periodsPerYear",252)):1,a=X(i,o,(h,p)=>Math.sqrt(Math.max(h-t*p*p,0)/(t-1))*s*100),l=lt(a,100),c=at(a,100),d=T(e,"color",Y),u=a.map((h,p)=>Number.isFinite(h)?eo(h,l[p]??0,c[p]??0,A,d):null);return mm("hv","Historical Volatility",a,u,d,75,2)}},xD={type:"chaikin-volatility",title:"Chaikin Volatility",shortTitle:"CHV",overlay:false,inputs:[F(10,"emaLength","EMA Length",5e3,"Length of the exponential moving average applied to the bar high-low range."),F(10,"rocLength","ROC Length",5e3,"Number of bars used for the rate of change of the smoothed high-low range."),P(A,"CHV Color","color","Color of the Chaikin Volatility line."),P(Y,"Expansion","expansionColor","Line and fill color while the reading is above zero \u2014 the smoothed range is wider than it was ROC Length bars ago.")],compute:(r,e)=>{let t=q(we(et(r),tt(r)),R(e,"emaLength",10)),n=Fe(t,R(e,"rocLength",10)),o=X(t,n,(a,l)=>l===0?Number.NaN:100*(a-l)/l),i=T(e,"color",A),s=T(e,"expansionColor",Y);return Ae({key:"chv",title:"Chaikin Volatility",values:o,ink:{bull:s,bear:i,neutral:i},zeroInk:A})}},SD={type:"mass-index",title:"Mass Index",shortTitle:"MI",overlay:false,inputs:[F(25,"length","Sum Length",5e3,"Number of bars over which the single/double EMA ratio is summed."),F(9,"emaLength","EMA Length",5e3,"Length of the single EMA of the high-low range and of its double smoothing."),Q("setupLevel","Setup Level",27,0,1e3,.1,"Reversal bulge set-up level; a rise above it arms the pattern."),Q("triggerLevel","Trigger Level",26.5,0,1e3,.1,"Reversal bulge trigger level; a decline below it after a set-up completes the pattern."),P(A,"Mass Index","color","Line color while no reversal bulge is armed."),P(Y,"Armed","armedColor","Line color from the rise above the setup level until the decline below the trigger level."),P(A,"Levels","levelsColor","Reversal bulge levels color.")],compute:(r,e)=>{let t=R(e,"emaLength",9),n=q(we(et(r),tt(r)),t),o=X(n,q(n,t),(p,m)=>m===0?1:p/m),i=ge(o,R(e,"length",25)),s=R(e,"setupLevel",27),a=R(e,"triggerLevel",26.5),l=T(e,"color",A),c=T(e,"armedColor",Y),d=T(e,"levelsColor",A),u=false,h=i.map(p=>Number.isFinite(p)?(u=p>s?true:p{let t=It(oe(r,T(e,"source","Close")),R(e,"length",20)),n=T(e,"color",A);return mm("stdev","Standard Deviation",t,ES(t,n,T(e,"expandColor",Y)),n,80)}},TD={type:"ulcer-index",title:"Ulcer Index",overlay:false,inputs:[{...F(14,"length","Length",500,"Lookback window. At each bar the percentage drawdown from the window's running maximum is squared; the squares are averaged and the root taken."),min:2},le("Close","source","Source","Price series the Ulcer Index is computed on. Close is the standard choice."),Q("threshold","Alert Threshold",5,0,1e3,.25,"Reference level drawn as a dashed line. The index scales with the instrument's volatility and the window length, so set it relative to its own history."),P(A,"Ulcer Index","color","Color of the index near zero; it blends toward the stress color as the reading approaches the threshold."),P(D,"Stress","stressColor","Color of the index at and beyond the alert threshold."),ne("gradientFill","Gradient Fill",true,xe,"Vertical gradient between zero and the Ulcer Index, fully transparent at zero."),ne("showDrawdown","Drawdown %",false,xe,"Plot the current percentage drawdown from the window high as columns below zero \u2014 the raw ingredient the index averages."),P(z(D,50),"Drawdown Color","drawdownColor","Color of the drawdown columns."),P(A,"Threshold","thresholdColor","Color of the alert threshold line.")],compute:(r,e)=>{let t=R(e,"length",14),n=oe(r,T(e,"source","Close")),o=n.length,i=new Array(o).fill(Number.NaN),s=new Array(o).fill(Number.NaN);for(let p=t-1;pNumber.isFinite(p)?c>0?eo(p,0,c,a,l):l:null),u=[{key:"ui",title:"Ulcer Index",values:i,color:a,colors:d}],h=[];return te(e,"gradientFill",true)&&(u.push(ct("zeroAnchor","Zero Base",o,0)),h.push({key:"wash",from:"ui",to:"zeroAnchor",color:z(A,100),gradient:to(i,0,(p,m)=>d[m]??a)})),te(e,"showDrawdown",false)&&u.push({key:"dd",title:"Drawdown %",values:s,kind:"columns",color:T(e,"drawdownColor",z(D,50)),base:0}),{plots:u,bands:h,levels:[{key:"zero",price:0,color:z(A,50),lineStyle:"dotted",title:"Zero Level"},{key:"threshold",price:c,color:T(e,"thresholdColor",A),lineStyle:"dashed",title:"Alert Threshold"}]}}},kD={type:"choppiness-index",title:"Choppiness Index",shortTitle:"CHOP",overlay:false,inputs:[{...F(14,"length","Length",5e3,"Number of bars used to sum true ranges and to measure the highest high \u2212 lowest low range."),min:2},Q("upperBand","Upper Band",61.8,0,100,.1,"Readings above this level indicate a choppy, range-bound market."),Q("lowerBand","Lower Band",38.2,0,100,.1,"Readings below this level indicate a strong trend."),P(A,"CHOP Line","color","Color of the Choppiness Index line."),P(O,"Trending","trendingColor","Line, fill and zone color toward and below the lower band \u2014 a trending market."),P(D,"Choppy","choppyColor","Line, fill and zone color toward and above the upper band \u2014 a choppy, range-bound market."),P(z(A,90),"Band Fill","fillColor","Fill color of the zone between the upper and lower bands.")],compute:(r,e)=>{let t=R(e,"length",14),n=ge(Jr(r),t),o=X(at(et(r),t),lt(tt(r),t),(s,a)=>s-a),i=X(n,o,(s,a)=>a>0&&s>0?100*Math.log10(s/a)/Math.log10(t):Number.NaN);return fn({key:"chop",title:"CHOP",values:i,scale:{top:100,bottom:0},overbought:R(e,"upperBand",61.8),oversold:R(e,"lowerBand",38.2),ink:{low:T(e,"trendingColor",O),mid:T(e,"color",A),high:T(e,"choppyColor",D)},levelInk:A,bandFill:T(e,"fillColor",z(A,90)),midpointWash:true,levelTitles:{overbought:"Upper Band",oversold:"Lower Band"}})}},PS=[yD,wD,xD,SD,CD,TD,kD];function Hd(r){return r.map(e=>e.volume==null||!Number.isFinite(e.volume)?Number.NaN:e.high===e.low?0:(2*e.close-e.high-e.low)/(e.high-e.low)*e.volume)}function vm(r,e,t,n){return r.map((o,i)=>{if(!Number.isFinite(o))return null;let s=i>0?r[i-1]:Number.NaN;return Number.isFinite(s)?o>s?e:o0?r[s-1].volume:null,c=s>0?e[s-1]:Number.NaN;a!=null&&l!=null&&Number.isFinite(a)&&Number.isFinite(l)&&n(a,l)&&Number.isFinite(c)&&c!==0&&(i*=1+(e[s]-c)/c),o[s]=i;}return o}function DS(r,e,t,n,o,i,s,a=false){let l=u=>{let h=n[u],p=t[u];return a||!Number.isFinite(h)?o.neutral:p>h?o.bull:pNumber.isFinite(u)?l(h):null)}],d=s?[{key:"regime",from:r,to:"signal",color:z(A,100),gradient:t.map((u,h)=>{let p=n[h];if(!Number.isFinite(u)||!Number.isFinite(p))return null;let m=u>p,f=m?o.bull:o.bear;return {topValue:Math.max(u,p),bottomValue:Math.min(u,p),topColor:z(f,m?50:100),bottomColor:z(f,m?100:50)}})}]:[];return {plots:c,bands:d}}var LD={type:"on-balance-volume",title:"On Balance Volume",shortTitle:"OBV",overlay:false,inputs:[ne("smoothing","Smoothing MA",false,We,"Display a moving average of OBV to act as a smoothing/signal line."),Te("maType","MA Type","SMA",["SMA","EMA","WMA","RMA (SMMA)"],"Moving average type used for the smoothing MA."),F(20,"maLength","MA Length",5e3,"Number of bars used for the smoothing MA."),P(ce,"OBV","color","Color of the OBV line."),P(Y,"Smoothing MA","maColor","Color of the smoothing MA line.")],compute:(r,e)=>{let t=Yt(r),n=st(je(r)),o=ai(X(t,n,(s,a)=>a>0?s:a<0?-s:0)),i=[{key:"obv",title:"OBV",values:o,color:T(e,"color",ce)}];if(te(e,"smoothing",false)){let s=R(e,"maLength",20),a=T(e,"maType","SMA"),l=a==="EMA"?q(o,s):a==="WMA"?Ut(o,s):a==="RMA (SMMA)"?Ne(o,s):Ce(o,s);i.push({key:"ma",title:"Smoothing MA",values:l,color:T(e,"maColor",Y)});}return {plots:i}}},MD={type:"accumulation-distribution",title:"Accumulation / Distribution",shortTitle:"A/D",overlay:false,inputs:[ne("slopeColoring","Slope Coloring",true,xe,"Color the line by its slope \u2014 bullish while rising (accumulation), bearish while falling (distribution)."),P(A,"A/D Line","color","Color of the line when slope coloring is disabled or the line is flat."),P(O,"Rising","bullColor","Line color while the A/D Line rises."),P(D,"Falling","bearColor","Line color while the A/D Line falls.")],compute:(r,e)=>{let t=ai(Hd(r)),n=T(e,"color",A);return {plots:[{key:"ad",title:"A/D",values:t,color:n,...te(e,"slopeColoring",true)?{colors:vm(t,T(e,"bullColor",O),T(e,"bearColor",D),n)}:{}}]}}},ED={type:"chaikin-money-flow",title:"Chaikin Money Flow",shortTitle:"CMF",overlay:false,inputs:[F(20,"length","Length",5e3,"Lookback length over which money flow volume and volume are summed."),P(A,"CMF Line","color","Color of the Chaikin Money Flow line."),P(O,"Bullish","bullColor","Line and fill color while the CMF reads above zero (net money flowing in)."),P(D,"Bearish","bearColor","Line and fill color while the CMF reads below zero (net money flowing out)."),P(A,"Zero Line","zeroColor","Color of the zero reference line.")],compute:(r,e)=>{let t=R(e,"length",20),n=X(ge(Hd(r),t),ge(Yt(r),t),(o,i)=>i===0?0:o/i);return Ae({key:"cmf",title:"CMF",values:n,ink:{bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"color",A)},zeroInk:T(e,"zeroColor",A)})}},PD={type:"chaikin-oscillator",title:"Chaikin Oscillator",shortTitle:"Chaikin Osc",overlay:false,inputs:[F(3,"fastLength","Fast Length",5e3,"Length of the fast EMA applied to the accumulation/distribution line."),F(10,"slowLength","Slow Length",5e3,"Length of the slow EMA applied to the accumulation/distribution line."),P(A,"Oscillator","color","Color of the Chaikin Oscillator line."),P(O,"Bullish","bullColor","Line and fill color while the oscillator reads above zero (accumulation)."),P(D,"Bearish","bearColor","Line and fill color while the oscillator reads below zero (distribution).")],compute:(r,e)=>{let t=ai(Hd(r)),n=we(q(t,R(e,"fastLength",3)),q(t,R(e,"slowLength",10)));return Ae({key:"co",title:"Chaikin Oscillator",values:n,ink:{bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"color",A)},zeroInk:A})}},ID={type:"ease-of-movement",title:"Ease of Movement",shortTitle:"EOM",overlay:false,inputs:[F(14,"length","Length",5e3,"Number of bars in the simple moving average smoothing the 1-bar Ease of Movement values."),pe("divisor","Divisor",1e4,1,1e9,"Volume scaling constant of the box ratio; larger values scale the oscillator up. 10000 is the conventional default."),P(A,"EOM Line","color","Color of the line when it sits exactly at zero."),P(O,"Above Zero","bullColor","Color of the line and fill while Ease of Movement is positive."),P(D,"Below Zero","bearColor","Color of the line and fill while Ease of Movement is negative.")],compute:(r,e)=>{let t=R(e,"divisor",1e4),n=st(oe(r,"HL2")),o=r.map((i,s)=>{let a=n[s];return i.volume==null||!Number.isFinite(i.volume)||!Number.isFinite(a)?Number.NaN:i.volume===0?0:t*a*(i.high-i.low)/i.volume});return Ae({key:"eom",title:"EOM",values:Ce(o,R(e,"length",14)),ink:{bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"color",A)},zeroInk:A})}},AD={type:"force-index",title:"Force Index",shortTitle:"FI",overlay:false,inputs:[F(13,"length","Length",5e3,"EMA length applied to the raw 1-bar force index, (close \u2212 close[1]) \xD7 volume. Elder used 13 for the intermediate trend and 2 for short-term timing."),P(O,"Force Index","color","Color of the line while above zero (buying pressure)."),P(D,"Bearish","bearColor","Color of the line while below zero (selling pressure).")],compute:(r,e)=>{let t=X(st(je(r)),Yt(r),(o,i)=>o*i),n=T(e,"color",O);return Ae({key:"force",title:"Force Index",values:q(t,R(e,"length",13)),ink:{bull:n,bear:T(e,"bearColor",D),neutral:n},zeroInk:A,width:2,valueTransparency:60})}},RD={type:"klinger-oscillator",title:"Klinger Oscillator",shortTitle:"KVO",overlay:false,inputs:[F(34,"fastLength","Fast Length",5e3,"Length of the fast EMA applied to the volume force."),F(55,"slowLength","Slow Length",5e3,"Length of the slow EMA applied to the volume force."),F(13,"signalLength","Signal Length",500,"Length of the EMA applied to the oscillator to obtain the signal line."),P(O,"Bullish","color","Color of the Klinger oscillator while above zero."),P(D,"Bearish","bearColor","Color of the Klinger oscillator while below zero."),P(Y,"Signal","signalColor","Color of the signal line.")],compute:(r,e)=>{let t=r.length,n=new Array(t).fill(Number.NaN),o=1,i=1,s=0,a=0;for(let d=0;d0?r[d-1].high+r[d-1].low+r[d-1].close:h;o=h>p?1:-1;let m=u.high-u.low;s=d>0&&o===i?s+m:a+m;let f=u.volume;n[d]=f==null||!Number.isFinite(f)?Number.NaN:s===0?0:f*Math.abs(2*(m/s)-1)*o*100,i=o,a=m;}let l=we(q(n,R(e,"fastLength",34)),q(n,R(e,"slowLength",55))),c=T(e,"color",O);return Ae({key:"kvo",title:"KVO",values:l,ink:{bull:c,bear:T(e,"bearColor",D),neutral:c},zeroInk:z(A,50),valueTransparency:60,extraPlots:[{key:"signal",title:"Signal",values:q(l,R(e,"signalLength",13)),color:T(e,"signalColor",Y)}]})}},DD={type:"money-flow-index",title:"Money Flow Index",shortTitle:"MFI",overlay:false,inputs:[F(14,"length","Length",5e3,"Number of bars used to sum positive and negative money flow."),Q("overbought","Overbought Level",80,0,100,1,"Level above which the MFI is considered overbought."),Q("oversold","Oversold Level",20,0,100,1,"Level below which the MFI is considered oversold."),P(A,"MFI","color","Color of the MFI line between the levels. Toward either level it blends into that level\u2019s color."),P(D,"Overbought","overboughtColor","Color of the line and zone shading at and above the overbought level."),P(O,"Oversold","oversoldColor","Color of the line and zone shading at and below the oversold level."),P(z(A,94),"OB/OS Zone Fill","fillColor","Fill color of the area between the overbought and oversold levels.")],compute:(r,e)=>{let t=R(e,"length",14),n=oe(r,"HLC3"),o=X(n,Yt(r),(c,d)=>c*d),i=st(n),s=ge(X(o,i,(c,d)=>d>0?c:0),t),a=ge(X(o,i,(c,d)=>d<0?c:0),t),l=X(s,a,(c,d)=>c+d>0?100*c/(c+d):Number.NaN);return fn({key:"mfi",title:"MFI",values:l,scale:{top:100,bottom:0},overbought:R(e,"overbought",80),oversold:R(e,"oversold",20),ink:{low:T(e,"oversoldColor",O),mid:T(e,"color",A),high:T(e,"overboughtColor",D)},levelInk:A,zoneTransparency:91,bandFill:T(e,"fillColor",z(A,94))})}};function OS(r){return [P(O,"Bullish","bullColor","Color of the line and gradient fill while it holds above its signal EMA."),P(D,"Bearish","bearColor","Color of the line and gradient fill while it holds below its signal EMA."),P(A,"Neutral","neutralColor","Color used while the signal EMA is still forming, or the line sits exactly on it."),P(A,r,"signalColor","Color of the signal EMA overlay."),ne("gradientFill","Gradient Fill",true,xe,"Fills the gap between the line and its signal EMA with a vertical gradient \u2014 transparent at the average, strongest at the line.")]}var fm="Position vs Average",IS="Single Color",OD={type:"negative-volume-index",title:"Negative Volume Index",shortTitle:"Negative Volume Index",overlay:false,inputs:[Q("base","Base Level",1e3,.01,1e6,1,"Arbitrary seed of the cumulative line, conventionally 1000. The absolute level carries no information \u2014 the line is read by slope and by position against the signal EMA."),ne("showSignal","Signal EMA",true,We,"Displays the conventional signal overlay. Hiding it only removes the plotted average; the regime coloring and fill still use it."),F(255,"signalLength","Signal Length",5e3,"Length of the signal EMA. The convention is one trading year \u2014 255 sessions on daily charts."),Te("colorMode","Line Coloring",fm,[fm,IS],"'Position vs Average' colors the line by the classic regime read; 'Single Color' draws the whole line in the neutral color."),...OS("Signal EMA")],compute:(r,e)=>{let t=RS(r,je(r),R(e,"base",1e3),(o,i)=>o{let t=oe(r,T(e,"source","Close")),n=RS(r,t,R(e,"base",1e3),(i,s)=>i>s),o=q(n,R(e,"signalLength",255));return DS("pvi","PVI",n,o,{bull:T(e,"bullColor",O),bear:T(e,"bearColor",D),neutral:T(e,"neutralColor",A),signal:T(e,"signalColor",A)},te(e,"showSignal",true),te(e,"gradientFill",true))}},FD={type:"price-volume-trend",title:"Price Volume Trend",shortTitle:"PVT",overlay:false,inputs:[ne("showSignal","Signal Line",false,We,"Display a moving average of PVT acting as a signal line."),Te("signalType","Signal Type","SMA",["SMA","EMA"],"Moving average type used for the signal line."),F(21,"signalLength","Signal Length",5e3,"Number of bars used to compute the signal line."),P(A,"PVT Color","color","Color of the PVT line while it is flat."),P(O,"Rising","bullColor","Color of the PVT line while it rises bar to bar."),P(D,"Falling","bearColor","Color of the PVT line while it falls bar to bar."),P(Y,"Signal Color","signalColor","Color of the signal line.")],compute:(r,e)=>{let t=je(r),n=r.map((a,l)=>{if(l===0||a.volume==null||!Number.isFinite(a.volume))return Number.NaN;let c=t[l-1];return c===0?0:(t[l]-c)/c*a.volume}),o=ai(n),i=T(e,"color",A),s=[{key:"pvt",title:"PVT",values:o,color:i,width:2,colors:vm(o,T(e,"bullColor",O),T(e,"bearColor",D),i)}];if(te(e,"showSignal",false)){let a=R(e,"signalLength",21),l=T(e,"signalType","SMA")==="EMA"?q(o,a):Ce(o,a);s.push({key:"signal",title:"Signal",values:l,color:T(e,"signalColor",Y)});}return {plots:s}}},VD={type:"volume-oscillator",title:"Volume Oscillator",shortTitle:"Vol Osc",overlay:false,inputs:[F(5,"fastLength","Fast Length",5e3,"Length of the fast EMA of volume."),F(10,"slowLength","Slow Length",5e3,"Length of the slow EMA of volume."),P(O,"Above Zero","color","Color of the line and fill while it holds above zero \u2014 volume expanding."),P(D,"Below Zero","bearColor","Color of the line and fill while it holds below zero \u2014 volume contracting.")],compute:(r,e)=>{let t=Yt(r),n=q(t,R(e,"fastLength",5)),o=q(t,R(e,"slowLength",10)),i=X(n,o,(a,l)=>l===0?0:100*(a-l)/l),s=T(e,"color",O);return Ae({key:"vo",title:"Volume Oscillator",values:i,ink:{bull:s,bear:T(e,"bearColor",D),neutral:s},zeroInk:A,valueTransparency:60})}},gm="Oscillator",BD={type:"pvo",title:"Percentage Volume Oscillator",shortTitle:"PVO",overlay:false,inputs:[{...F(12,"fastLength","Fast Length",5e3,"Period of the fast EMA of volume. The conventional setting is 12."),group:gm},{...F(26,"slowLength","Slow Length",5e3,"Period of the slow EMA of volume. The PVO expresses the fast/slow spread as a percentage of this slow average."),group:gm},{...F(9,"signalLength","Signal Length",500,"Period of the EMA applied to the PVO to form the signal line."),group:gm},P(O,"Expansion Color","color","Color of the oscillator and fill while participation expands."),P(D,"Contraction Color","bearColor","Color of the oscillator and fill while participation contracts."),P(Y,"Signal Line","signalColor","Color of the signal line."),P(z(A,50),"Zero Line","zeroColor","Color of the zero reference line."),ne("showSignal","Show Signal Line",true,xe,"Plot the signal line, an EMA of the PVO."),ne("showHistogram","Show Histogram",true,xe,"Plot the difference between the PVO and its signal line as columns behind the oscillator.")],compute:(r,e)=>{let t=Yt(r),n=q(t,R(e,"fastLength",12)),o=q(t,R(e,"slowLength",26)),i=X(n,o,(d,u)=>u>0?100*(d-u)/u:Number.NaN),s=q(i,R(e,"signalLength",9)),a=T(e,"color",O),l=T(e,"bearColor",D),c=[];if(te(e,"showHistogram",true)){let d=we(i,s);c.push({key:"hist",title:"Histogram",values:d,kind:"columns",color:z(a,60),colors:d.map(u=>Number.isFinite(u)?z(u>0?a:l,60):null),base:0});}return te(e,"showSignal",true)&&c.push({key:"signal",title:"Signal",values:s,color:T(e,"signalColor",Y)}),Ae({key:"pvo",title:"PVO",values:i,ink:{bull:a,bear:l,neutral:l},zeroInk:T(e,"zeroColor",z(A,50)),extraPlots:c})}},_D={type:"volume-flow-indicator",title:"Volume Flow Indicator",shortTitle:"Volume Flow Indicator",overlay:false,inputs:[{...F(130,"length","Length",5e3,"Rolling summation window, also used for the average volume that scales the result. The published default of 130 bars targets position-horizon work on daily charts."),min:2},Q("coef","Cutoff Coefficient",.2,0,10,.05,"Scales the volatility-based minimum change in typical price. Moves smaller than the cutoff count as noise and contribute no volume."),Q("volCoef","Volume Cap Multiplier",2.5,.1,50,.1,"Caps each bar's volume contribution at this multiple of the average volume, so a single climactic print stays bounded."),{...F(30,"volLength","Volatility Length",5e3,"Window of the standard deviation of the log change in typical price used to build the adaptive cutoff."),min:2},ne("smooth","Smooth VFI",true,We,"Applies the published light smoothing \u2014 an EMA of the summed line \u2014 before plotting."),F(3,"smoothLength","Smoothing Length",500,"Length of the smoothing EMA. The published version uses 3 bars."),ne("showSignal","Signal Line",true,We,"Plots an EMA of VFI as a signal line."),F(5,"signalLength","Signal Length",500,"Length of the signal-line EMA."),P(O,"Bullish","color","Color of the VFI line and gradient fill above the zero line \u2014 the net accumulation regime."),P(D,"Bearish","bearColor","Color of the VFI line and gradient fill below the zero line \u2014 the net distribution regime."),P(Y,"Signal Line","signalColor","Color of the signal line."),ne("gradientFill","Gradient Fill",true,xe,"Fills the area between the zero line and the VFI line with a vertical gradient.")],compute:(r,e)=>{let t=R(e,"length",130),n=oe(r,"HLC3"),o=we(re(n,Math.log),Fe(re(n,Math.log),1)),i=It(o,R(e,"volLength",30)),s=R(e,"coef",.2),a=R(e,"volCoef",2.5),l=Yt(r),c=Fe(Ce(l,t),1),d=st(n),u=r.map((g,b)=>{let y=i[b],w=d[b],S=l[b];if(!Number.isFinite(y)||!Number.isFinite(w)||!Number.isFinite(S))return Number.NaN;let M=s*y*g.close,C=c[b],L=Number.isFinite(C)?Math.min(S,C*a):S;return w>M?L:w<-M?-L:0}),h=X(ge(u,t),c,(g,b)=>b>0?g/b:Number.NaN),p=te(e,"smooth",true)?q(h,R(e,"smoothLength",3)):h,m=T(e,"color",O),f=te(e,"showSignal",true)?[{key:"signal",title:"Signal Line",values:q(p,R(e,"signalLength",5)),color:T(e,"signalColor",Y)}]:[];return Ae({key:"vfi",title:"VFI",values:p,ink:{bull:m,bear:T(e,"bearColor",D),neutral:T(e,"bearColor",D)},zeroInk:z(A,90),fill:te(e,"gradientFill",true),extraPlots:f})}},bm="Normalized Oscillator (II%)",AS="Cumulative Line",HD={type:"intraday-intensity",title:"Intraday Intensity",shortTitle:"Intraday Intensity",overlay:false,inputs:[Te("mode","Display",bm,[bm,AS],"The two published forms. The cumulative line is open-ended and read by slope against price; the normalized oscillator divides a rolling sum of intensity by the rolling sum of volume and oscillates around zero."),F(21,"length","Oscillator Length",5e3,"Window of the rolling sums in the normalized form. The common setting is 21 bars. It has no effect on the cumulative line."),P(O,"Bullish","color","Color of positive readings, the rising cumulative line and the fill above zero \u2014 the accumulation side."),P(D,"Bearish","bearColor","Color of negative readings, the falling cumulative line and the fill below zero \u2014 the distribution side."),ne("gradientFill","Gradient Fill",true,xe,"Fills the area between the zero line and the oscillator with a vertical gradient. Applies to the normalized oscillator only.")],compute:(r,e)=>{let t=Hd(r),n=T(e,"color",O),o=T(e,"bearColor",D);if(T(e,"mode",bm)===AS){let a=ai(t);return {plots:[{key:"ii",title:"Intraday Intensity",values:a,color:n,colors:vm(a,n,o,n)}]}}let i=R(e,"length",21),s=X(ge(t,i),ge(Yt(r),i),(a,l)=>l>0?100*a/l:Number.NaN);return Ae({key:"ii",title:"Intraday Intensity",values:s,ink:{bull:n,bear:o,neutral:o},zeroInk:z(A,90),fill:te(e,"gradientFill",true)})}},NS=[LD,MD,ED,PD,ID,AD,RD,DD,OD,ND,FD,VD,BD,_D,HD];var ci=864e5;function Cm(r,e){if(r==="Week")return Math.floor((Math.floor(e/ci)+3)/7);if(r==="Month"||r==="Quarter"||r==="Year"){let t=new Date(e);return r==="Year"?t.getUTCFullYear():r==="Quarter"?t.getUTCFullYear()*4+Math.floor(t.getUTCMonth()/3):t.getUTCFullYear()*12+t.getUTCMonth()}return Math.floor(e/ci)}function _S(r){if(r.length<2)return 0;let e=[];for(let t=1;tt-n),e[Math.floor(e.length/2)]??0}var zD={type:"parabolic-sar",title:"Parabolic SAR",shortTitle:"SAR",overlay:true,inputs:[Q("start","Start",.02,0,1,.01,"Initial acceleration factor applied when a new trend begins."),Q("increment","Increment",.02,0,1,.01,"Amount added to the acceleration factor each time the trend makes a new extreme point."),Q("maximum","Maximum",.2,.01,1,.01,"Upper cap on the acceleration factor."),P(O,"Bullish","bullColor","Color of the SAR crosses while they trail below price \u2014 uptrend, the stop sits under the market."),P(D,"Bearish","bearColor","Color of the SAR crosses while they sit above price \u2014 downtrend, the stop sits over the market.")],compute:(r,e)=>{let t=R(e,"start",.02),n=R(e,"increment",.02),o=R(e,"maximum",.2),i=r.length,s=new Array(i).fill(Number.NaN);if(i>=2){let d=r[1].close>=r[0].close,u=d?r[0].low:r[0].high,h=d?r[0].high:r[0].low,p=t;for(let m=1;m=2?r[m-2].low:r[m-1].low):u=Math.max(u,r[m-1].high,m>=2?r[m-2].high:r[m-1].high),(d?f.lowu)?(d=!d,u=h,h=d?f.high:f.low,p=t):d&&f.high>h?(h=f.high,p=Math.min(o,p+n)):!d&&f.lowNumber.isFinite(d)?d[ne(r.show,`Band #${e+1}`,r.defOn,We,`Show the ${["first","second","third"][e]} band pair.`),Q(r.mult,`Band #${e+1} Multiplier`,r.defMult,0,50,.5,"Multiplier for this band pair, in standard deviations or percent depending on the bands mode.")]),ne("hideDwm","Hide VWAP on 1D or Above",true,We,"Hide the VWAP and its bands on daily and higher timeframes, where an intraday anchored VWAP is not meaningful."),P(O,"Bullish","bullColor","VWAP line color while price closes above it, and the color of the lower (support) bands."),P(D,"Bearish","bearColor","VWAP line color while price closes below it, and the color of the upper (resistance) bands."),P(A,"Bands","bandsColor","Deviation bands fill color."),ne("fill","Bands Fill",true,xe,"Fill the area between each visible band pair.")],compute:(r,e)=>{let t=T(e,"anchor","Session"),n=oe(r,T(e,"source","HLC3")),o=r.length,i=te(e,"hideDwm",true)&&_S(r)>=ci,s=new Array(o).fill(Number.NaN),a=VS.filter(y=>te(e,y.show,y.defOn)).map(y=>({mult:Math.max(0,R(e,y.mult,y.defMult)),up:new Array(o).fill(Number.NaN),down:new Array(o).fill(Number.NaN)})),l=T(e,"bandsMode",ym)===FS,c=Number.NaN,d=0,u=0,h=0;for(let y=0;y0){let v=n[y];d+=v*M,u+=v*v*M,h+=M;}if(h<=0)continue;let C=d/h,L=l?C/100:Math.sqrt(Math.max(0,u/h-C*C));s[y]=C;for(let v of a)v.up[y]=C+v.mult*L,v.down[y]=C-v.mult*L;}let p=T(e,"bullColor",O),m=T(e,"bearColor",D),f=z(T(e,"bandsColor",A),95),g=[{key:"vwap",title:"VWAP",values:s,color:p,colors:s.map((y,w)=>Number.isFinite(y)?r[w].close>=y?p:m:null)}],b=[];return a.forEach((y,w)=>{g.push({key:`up${w}`,title:`Upper Band #${w+1}`,values:y.up,color:z(m,40)},{key:`down${w}`,title:`Lower Band #${w+1}`,values:y.down,color:z(p,40)}),te(e,"fill",true)&&b.push({key:`band${w}`,from:`up${w}`,to:`down${w}`,color:f});}),{plots:g,bands:b}}},wm="Traditional",BS="Fibonacci",xm="Camarilla",zd="Woodie",Sm="Auto",$D={type:"pivot-points",title:"Pivot Points Standard",shortTitle:"Pivots",overlay:true,inputs:[Te("kind","Type",wm,[wm,BS,xm,zd],"Formula used to calculate the levels. Traditional is the classic floor-trader method; Fibonacci projects 38.2/61.8/100% of the prior range around the pivot; Camarilla scales the prior range around the prior close; Woodie gives extra weight to the period open."),Te("anchor","Pivots Timeframe",Sm,[Sm,"Daily","Weekly","Monthly","Yearly"],"Period the pivots are anchored to. 'Auto' follows the chart's bar spacing: daily pivots up to 15-minute bars, weekly on other intraday bars, monthly on daily bars, yearly above."),P(Y,"Pivot","pivotColor","Color of the central pivot (P) level."),P(D,"Resistances","resistanceColor","Color of the resistance (R) levels."),P(O,"Supports","supportColor","Color of the support (S) levels.")],compute:(r,e)=>{let t=_S(r),n=T(e,"anchor",Sm),o=t<=15*6e4?"Session":tnew Array(l).fill(Number.NaN),d={p:c(),r1:c(),s1:c(),r2:c(),s2:c(),r3:c(),s3:c(),r4:c(),s4:c()},u=Number.NaN;for(let g=0;g({key:g,title:b,values:d[g],color:y}),f=[m("p","P",T(e,"pivotColor",Y)),m("r1","R1",h),m("s1","S1",p),m("r2","R2",h),m("s2","S2",p)];return s!==zd&&f.push(m("r3","R3",h),m("s3","S3",p)),s===xm&&f.push(m("r4","R4",h),m("s4","S4",p)),{plots:f}}},UD={type:"52-week-high-low",title:"52 Week High/Low",shortTitle:"52W H/L",overlay:true,inputs:[pe("weeks","Weeks",52,1,520,"Length of the rolling window, in weeks."),ne("showAllTime","Show All-Time High/Low",false,We,"Additionally display the all-time high and low, tracked over the symbol's full loaded history."),P(O,"52 Week High","highColor","Color of the 52 week high level."),P(D,"52 Week Low","lowColor","Color of the 52 week low level."),P(A,"All-Time High/Low","allTimeColor","Color of the all-time high and all-time low levels.")],compute:(r,e)=>{let t=R(e,"weeks",52)*7*ci,n=r.length,o=new Array(n).fill(Number.NaN),i=new Array(n).fill(Number.NaN),s=new Array(n).fill(Number.NaN),a=new Array(n).fill(Number.NaN),l=[],c=[],d=0,u=-1/0,h=1/0;for(let m=0;m0&&r[l[l.length-1]].high<=f.high;)l.pop();for(l.push(m);c.length>0&&r[c[c.length-1]].low>=f.low;)c.pop();for(c.push(m);r[d].time{let t=R(e,"deviation",5)/100,n=R(e,"depth",10),o=[];if(r.length>1){let c=r[1].close>=r[0].close,d=c?{i:0,price:r[0].high}:{i:0,price:r[0].low};for(let u=1;u=d.price?d={i:u,price:h.high}:h.low<=d.price*(1-t)&&d.i-(o[o.length-1]?.i??-n)>=n&&(o.push(d),c=false,d={i:u,price:h.low}):h.low<=d.price?d={i:u,price:h.low}:h.high>=d.price*(1+t)&&d.i-(o[o.length-1]?.i??-n)>=n&&(o.push(d),c=true,d={i:u,price:h.high});}o.push(d);}let i=T(e,"bullColor",O),s=T(e,"bearColor",D),a=R(e,"lineWidth",2),l=[];for(let c=1;c=d.price?i:s,lineWidth:a,lineStyle:"solid",arrowLeft:false,arrowRight:false});}return {plots:[],polylines:l}}},KD={type:"williams-fractal",title:"Williams Fractal",shortTitle:"Fractals",overlay:true,inputs:[pe("periods","Periods",2,2,50,"Bars required on each side of the candidate bar. 2 is Bill Williams' classic 5-bar fractal; a fractal is confirmed only once this many later bars have closed."),P(D,"Up Fractal","upColor","Color of the up fractal marker (swing high), drawn above the fractal bar."),P(O,"Down Fractal","downColor","Color of the down fractal marker (swing low), drawn below the fractal bar.")],compute:(r,e)=>{let t=R(e,"periods",2),n=[],o=T(e,"upColor",D),i=T(e,"downColor",O),s=(a,l,c)=>{let d=l(r[a]);for(let u=a-t;u<=a+t;u++)if(u!==a&&!c(d,l(r[u])))return false;return true};for(let a=t;al.high,(l,c)=>l>c)&&n.push({time:r[a].time,position:"aboveBar",shape:"triangleup",color:o}),s(a,l=>l.low,(l,c)=>lr instanceof Error?r:new Error(String(r)),Tm=class{constructor(e,t={},n={}){N0(),Yp(),em(),zS();let o=jD(e),i=go(t.theme),s={currentPriceLine:t.currentPriceLine??true,logScale:t.logScale??false,nativeBackend:t.nativeBackend??"auto",...Fm(t.animations),glow:t.glow??0,upColor:t.upColor??O,downColor:t.downColor??D,priceStyle:t.priceStyle??"candles",priceAxisTicks:t.priceAxis?.ticks??null},a=t.renderer??qs;if(typeof a!="function")throw new Error("[vela] options.renderer must be a renderer class, e.g. import { LwcRenderer } from 'vela/renderers/lwc'. The 'lwc'/'native' string options were removed.");let l=n.renderer??new a(s),c=n.engines??[],d=n.dataFeed??new Ir,u={market:{symbol:t.symbol,timeframe:t.timeframe,bars:t.bars,session:t.session,visibleRange:t.visibleRange,data:t.data},live:t.live??false,theme:i,defaultLanguage:t.defaultLanguage??c[0]?.language??"pine",drawings:t.drawings,volume:t.volume??true};this.rendererControl=new Di(l),t.settings&&this.rendererControl.setSettingsVisibility(t.settings),this.dataControl=new _i(d),this.orchestrator=new kl(o,l,d,c,u,this.dataControl);let h=hu();Object.keys(h).length>0&&this.rendererControl.set(h),this.panesControl=new Ll(this.orchestrator),this.drawingsControl=new Hi(this.orchestrator.drawings),this.marksControl=new zi(this.orchestrator.marks),this.replayControl=new Wi(this.orchestrator);}registerEngine(e,t){return this.orchestrator.registerEngine(e,t),this}addIndicator(e,t){return this.orchestrator.addIndicator(e,t)}addNativeIndicator(e,t){return this.orchestrator.addNativeIndicator(e,t)}availableNativeIndicators(){return this.orchestrator.availableNativeIndicators()}presentNativeIndicators(){return this.orchestrator.presentNativeIndicators()}indicators(){return this.orchestrator.listIndicators()}runScript(e,t){let n;try{n=this.addIndicator(e,t);}catch(s){return Promise.resolve({ok:false,run:null,error:WS(s),onUpdate:()=>()=>{},remove:()=>{}})}let o=new Set,i=()=>{try{n.remove();}catch{}};return new Promise(s=>{let a=false,l=this.on("script:run",d=>{if(d.id===n.id){if(a){for(let u of o)u(d);return}a=true,c(),s({ok:true,run:d,error:null,onUpdate:u=>(o.add(u),()=>o.delete(u)),remove:()=>{l(),o.clear(),i();}});}}),c=n.on("error",({error:d})=>{a||(a=true,l(),c(),i(),s({ok:false,run:null,error:d,onUpdate:()=>()=>{},remove:()=>{}}));});})}runIndicator(e,t){let n;try{n=this.addIndicator(e,t);}catch(o){return Promise.resolve({ok:false,handle:null,error:WS(o),context:null})}return new Promise(o=>{let i=n.on("ready",()=>{i(),s(),o({ok:true,handle:n,error:null,context:null});}),s=n.on("error",({error:a})=>{i(),s(),n.context().catch(()=>null).then(l=>{try{n.remove();}catch{}o({ok:false,handle:null,error:a,context:l});});});})}setMarket(e){return this.orchestrator.setMarket(e)}get market(){return this.orchestrator.marketSnapshot()}ready(){return this.orchestrator.ready()}historyComplete(){return this.orchestrator.historyComplete()}inspect(){return this.orchestrator.inspect()}get renderer(){return this.rendererControl}get panes(){return this.panesControl}get data(){return this.dataControl}get drawings(){return this.drawingsControl}get marks(){return this.marksControl}get replay(){return this.replayControl}on(e,t){return this.orchestrator.events.on(e,t)}getVisibleRange(){return this.orchestrator.getVisibleRange()}setVisibleRange(e){return this.orchestrator.setVisibleRange(e),this}panBy(e){return this.orchestrator.panBy(e),this}setVisibleRangePreset(e){return this.orchestrator.setVisibleRangePreset(e),this}resize(){this.orchestrator.resize();}setTheme(e){return this.orchestrator.setTheme(go(e)),this}destroy(){this.orchestrator.destroy();}};function jD(r){if(typeof r!="string")return r;let e=document.querySelector(r);if(!e)throw new Error(`[vela] container not found for selector "${r}"`);return e}function qD(r,e){return async(t,{end:n,signal:o})=>{let{symbol:i,session:s}=r.market,a=i?r.data.resolve(i):null,l=a?r.data.providerInstance(a.provider):void 0;if(!a||!l)return [];let c=await l.getBars(a.ticker,e,{from:t.time,to:n-1,...s?{session:s}:{}});return o.aborted?[]:GS(c.filter(d=>d.time>=t.time&&d.time({price:e.close,open:e.open,high:e.high,low:e.low,...e.volume===void 0?{}:{volume:e.volume}}))}var $S=["symbol","timeframes","style","layout","indicators","actions","undo-redo","alerts","panels","screenshot"];var di=new Map,Js=new Map,ea=new Map;function ZD(r){return Js.set(r.id,r),()=>{Js.get(r.id)===r&&Js.delete(r.id);}}function QD(r){Js.delete(r);}function JD(){return [...Js.values()]}var US=100;function e2(r){return ea.set(r.id,r),()=>{ea.get(r.id)===r&&ea.delete(r.id);}}function t2(r){ea.delete(r);}function n2(){return [...ea.values()].sort((r,e)=>(r.order??US)-(e.order??US))}var km=["indicators","screenshot"],YS=new Set(km),r2=new Set($S);function o2(r){if(YS.has(r))return di.get(r)}function i2(r){return r2.has(r.id)&&!YS.has(r.id)?(console.warn(`[vela] widget action "${r.id}": this built-in topbar slot is a stateful control and cannot be overridden \u2014 ignored. Overridable slots: ${km.join(", ")}.`),()=>{}):(di.set(r.id,r),()=>{di.get(r.id)===r&&di.delete(r.id);})}function s2(r){di.delete(r);}function a2(r,e){let t=[...di.values()].filter(n=>n.target===r);return t.sort((n,o)=>(n.order??0)-(o.order??0)),e?t.filter(n=>!n.when||n.when(e)):t}var ta=new Map;function l2(r){return ta.set(r.id,r),()=>{ta.get(r.id)===r&&ta.delete(r.id);}}function c2(r){ta.delete(r);}function d2(){return [...ta.values()].sort((r,e)=>(r.order??0)-(e.order??0))}var na=new Map;function u2(r){return na.set(r.id,r),()=>{na.get(r.id)===r&&na.delete(r.id);}}function h2(r){na.delete(r);}function p2(){return [...na.values()].sort((r,e)=>(r.order??0)-(e.order??0))}var ra=new Map;function m2(r){return ra.set(r.key,r),()=>{ra.get(r.key)===r&&ra.delete(r.key);}}function f2(r){ra.delete(r);}function g2(r){return [...ra.values()].filter(e=>e.scope===r)}var Wd;function b2(r){return Wd=r,()=>{Wd===r&&(Wd=void 0);}}function v2(){return Wd}var oa=new Map;function y2(r,e){return oa.set(r,e),()=>{oa.get(r)===e&&oa.delete(r);}}function w2(r){oa.delete(r);}function x2(r){return {...Object.fromEntries(oa),...r}}var S2={body:{"reset-view":-30,"remove-drawings":-20,"remove-indicators":-10,settings:1e3},"price-axis":{auto:-80,invert:-70,"scale:regular":-60,"scale:percent":-50,"scale:indexed":-40,"scale:log":-30,labels:-20,levels:-10,settings:1e3},"time-axis":{timezone:-10,settings:1e3}};var KS=280,Lm=200,XS=640;function C2(r,e=Lm,t=XS){let n=Number.isFinite(e)&&e>0?e:Lm,o=Number.isFinite(t)?Math.max(t,n):Number.POSITIVE_INFINITY;return Number.isFinite(r)?Math.round(Math.min(Math.max(r,n),o)):n}function ui(r){let e=r.description?.split("/")[0]?.trim();return e?e.replace(/\s+Perpetual$/i,""):r.ticker.replace(/[-_/]?(USDT|USDC|USD1|USDS|BUSD|USD|EUR|PERP)$/i,"")||r.ticker}function hi(r){let e=r.trim().toUpperCase();return e?`https://crypto-icons.ledger.com/${encodeURIComponent(e)}.png`:void 0}var jS="https://api.binance.com/api/v3",T2="https://api.binance.us/api/v3",Mm="https://fapi.binance.com/fapi/v1",k2="wss://stream.binance.com:9443",L2="wss://stream.binance.us:9443",M2="wss://fstream.binance.com",E2=15e3,P2=2e3,qS={1:"1m",3:"3m",5:"5m",15:"15m",30:"30m",60:"1h",120:"2h",240:"4h",360:"6h",480:"8h",720:"12h",D:"1d",W:"1w",M:"1M"},ZS={"1m":"1","3m":"3","5m":"5","15m":"15","30m":"30","45m":"45","1h":"60","2h":"120","3h":"180","4h":"240","6h":"360","8h":"480","12h":"720","1d":"D","1w":"W","1mo":"M","1D":"D","1W":"W","4H":"240",D:"D",W:"W",M:"M"},I2=[1,3,5,15,30,60,120,240,360,480,720],A2={1:"1m",3:"3m",5:"5m",15:"15m",30:"30m",60:"1h",120:"2h",240:"4h",360:"6h",480:"8h",720:"12h"},R2=["1","3","5","15","30","45","60","120","180","240","D","W","M"];function QS(r){return ZS[r]??ZS[r.toLowerCase()]??r}function Em(r){let e=r.trim().toUpperCase();return e.endsWith(".P")?{apiSymbol:e.slice(0,-2),isFutures:true}:{apiSymbol:e,isFutures:false}}function JS(r){return r.map(e=>({time:Number(e[0]),open:Number(e[1]),high:Number(e[2]),low:Number(e[3]),close:Number(e[4]),volume:Number(e[5])}))}function D2(r){return {time:Number(r.t),open:Number(r.o),high:Number(r.h),low:Number(r.l),close:Number(r.c),volume:Number(r.v)}}function O2(r){let e=new Map;for(let t of r)e.set(t.time,t);return [...e.values()].sort((t,n)=>t.time-n.time)}function N2(r,e){let t=new Map;for(let n of r){let o=Math.floor(n.time/e)*e,i=t.get(o);i?(i.high=Math.max(i.high,n.high),i.low=Math.min(i.low,n.low),i.close=n.close,i.volume=(i.volume??0)+(n.volume??0)):t.set(o,{time:o,open:n.open,high:n.high,low:n.low,close:n.close,volume:n.volume??0});}return [...t.values()].sort((n,o)=>n.time-o.time)}function F2(r){return I2.filter(e=>et-e)[0]??null}var Gd=class{constructor(){this.spotBaseUrl=null;this.spotBaseProbe=null;this.symbolsPromise=null;}info(){return {name:"binance",displayName:"Binance",requiresApiKey:false,supportedTimeframes:R2,capabilities:{enumerate:true,stream:true,symbolInfo:true}}}async getBars(e,t,n){try{let{apiSymbol:o,isFutures:i}=Em(e),s=i?Mm:await this.spotBase(),a=QS(t),l=qS[a];if(l)return O2(JS(await this.fetchKlines(s,o,l,n)));let c=/^\d+$/.test(a)?parseInt(a,10):null,d=c!=null?F2(c):null;if(c==null||d==null)return console.warn(`[vela] Binance: timeframe "${t}" is not supported and cannot be aggregated.`),[];let u=c/d,h={...n,limit:n.limit!=null?n.limit*u+u:void 0},p=JS(await this.fetchKlines(s,o,A2[d],h)),m=N2(p,c*6e4);return n.limit!=null&&m.length>n.limit?m.slice(-n.limit):m}catch(o){return console.warn(`[vela] Binance: failed to fetch ${e} ${t} \u2014 ${o instanceof Error?o.message:String(o)}`),[]}}async getSymbolInfo(e){let{apiSymbol:t,isFutures:n}=Em(e),o=n?Mm:await this.spotBase(),i=n?`${o}/exchangeInfo`:`${o}/exchangeInfo?symbol=${t}`,a=(await this.json(i).catch(()=>null))?.symbols??[],l=n?a.find(u=>u.symbol===t):a[0];if(!l)return;let c=l.filters?.find(u=>u.filterType==="PRICE_FILTER"),d=c?parseFloat(c.tickSize??"0.01"):.01;return {ticker:e,tickerid:`BINANCE:${e}`,prefix:"BINANCE",description:`${l.baseAsset} / ${l.quoteAsset}${n?" Perpetual":""}`,type:n?"futures":"crypto",basecurrency:l.baseAsset,currency:l.quoteAsset,mintick:d,pricescale:Math.round(1/d),timezone:"Etc/UTC",session:"24x7"}}listSymbols(){return this.symbolsPromise||(this.symbolsPromise=Promise.all([this.listSpot().catch(()=>[]),this.listFutures().catch(()=>[])]).then(([e,t])=>[...e,...t])),this.symbolsPromise}resolveSymbolIcon(e){return hi(ui(e))}subscribe(e,t,n){let{apiSymbol:o,isFutures:i}=Em(e),s=qS[QS(t)];return s&&typeof WebSocket<"u"?this.streamKlines(e,t,o,i,s,n):this.pollBars(e,t,n)}streamKlines(e,t,n,o,i,s){let a=false,l=null,c=null,d=null,u=null,h=`${n.toLowerCase()}@kline_${i}`,p=()=>{d&&(clearTimeout(d),d=null);},m=()=>{if(!(a||u)){p(),c&&(clearTimeout(c),c=null);try{l?.close();}catch{}l=null,console.warn(`[vela] Binance: ${e} ${t} stream delivered no data; falling back to polling.`),u=this.pollBars(e,t,s);}},f=async()=>{if(a)return;let g=o?M2:await this.spotWsBase();a||(l=new WebSocket(`${g}/ws/${h}`),d=setTimeout(m,E2),l.onmessage=b=>{if(!(a||u))try{let y=JSON.parse(typeof b.data=="string"?b.data:"");y.k&&(p(),s(D2(y.k)));}catch{}},l.onclose=()=>{!a&&!u&&(c=setTimeout(()=>{f();},P2));},l.onerror=()=>{try{l?.close();}catch{}});};return f(),()=>{a=true,p(),c&&clearTimeout(c),u?.();try{l?.close();}catch{}}}async spotWsBase(){return (await this.spotBase()).includes("binance.us")?L2:k2}pollBars(e,t,n){let o=false,i=null,s=async()=>{if(!o){try{let a=await this.getBars(e,t,{limit:2});for(let l of a)n(l);}catch{}o||(i=setTimeout(()=>{s();},3e3));}};return i=setTimeout(()=>{s();},3e3),()=>{o=true,i&&clearTimeout(i);}}async listSpot(){let e=await this.spotBase();return ((await this.json(`${e}/exchangeInfo`)).symbols??[]).filter(n=>n.status==="TRADING").map(n=>({ticker:n.symbol,description:`${n.baseAsset} / ${n.quoteAsset}`,type:"crypto"}))}async listFutures(){return ((await this.json(`${Mm}/exchangeInfo`)).symbols??[]).filter(t=>t.contractType==="PERPETUAL"&&t.status==="TRADING").map(t=>({ticker:`${t.symbol}.P`,description:`${t.baseAsset} / ${t.quoteAsset} Perpetual`,type:"futures"}))}async fetchKlines(e,t,n,o){if(o.from!=null)return this.paginateForward(e,t,n,o.from,o.to??Date.now(),o.limit);let i=o.limit??500;return i>1e3?this.paginateBackward(e,t,n,i,o.to):this.klinesChunk(e,{symbol:t,interval:n,limit:i,endTime:o.to})}async paginateForward(e,t,n,o,i,s){let a=[],l=o;for(;l=s)break}return s?a.slice(0,s):a}async paginateBackward(e,t,n,o,i){let s=[],a=o,l=i,c=Math.ceil(o/1e3)+5;for(;a>0&&c-- >0;){let d=Math.min(a,1e3),u=await this.klinesChunk(e,{symbol:t,interval:n,limit:d,endTime:l});if(u.length===0||(s=u.concat(s),a-=u.length,l=Number(u[0][0])-1,u.length0&&!Array.isArray(o[0])?[]:o:[]}spotBase(){return this.spotBaseUrl?Promise.resolve(this.spotBaseUrl):(this.spotBaseProbe||(this.spotBaseProbe=(async()=>{try{for(let e of [jS,T2])try{if((await fetch(`${e}/ping`,{signal:AbortSignal.timeout(5e3)})).ok)return this.spotBaseUrl=e}catch{}return jS}finally{this.spotBaseProbe=null;}})()),this.spotBaseProbe)}async json(e){let t=await fetch(e);if(!t.ok)throw new Error(`Binance HTTP ${t.status} for ${e}`);return t.json()}};var V2="https://api.hyperliquid.xyz/info",B2="wss://api.hyperliquid.xyz/ws",_2=15e3,H2=2e3,eC={1:"1m",3:"3m",5:"5m",15:"15m",30:"30m",60:"1h",120:"2h",240:"4h",480:"8h",720:"12h",D:"1d",W:"1w",M:"1M"},tC={"1m":"1","3m":"3","5m":"5","15m":"15","30m":"30","45m":"45","1h":"60","2h":"120","3h":"180","4h":"240","6h":"360","8h":"480","12h":"720","1d":"D","1w":"W","1mo":"M","1D":"D","1W":"W","4H":"240",D:"D",W:"W",M:"M"},z2=[1,3,5,15,30,60,120,240,480,720],W2={1:"1m",3:"3m",5:"5m",15:"15m",30:"30m",60:"1h",120:"2h",240:"4h",480:"8h",720:"12h"},G2=["1","3","5","15","30","45","60","120","180","240","360","480","720","D","W","M"],nC={D:864e5,W:6048e5,M:2592e6};function $2(r){if(nC[r])return nC[r];let e=parseInt(r,10);return Number.isFinite(e)&&e>0?e*6e4:36e5}function rC(r){return tC[r]??tC[r.toLowerCase()]??r}function Pm(r){let e=r.trim();return e.includes("/")?e:e.toUpperCase()}function Im(r){return {time:Number(r.t),open:Number(r.o),high:Number(r.h),low:Number(r.l),close:Number(r.c),volume:Number(r.v)}}function U2(r){let e=new Map;for(let t of r)e.set(t.time,t);return [...e.values()].sort((t,n)=>t.time-n.time)}function Y2(r,e){let t=new Map;for(let n of r){let o=Math.floor(n.time/e)*e,i=t.get(o);i?(i.high=Math.max(i.high,n.high),i.low=Math.min(i.low,n.low),i.close=n.close,i.volume=(i.volume??0)+(n.volume??0)):t.set(o,{time:o,open:n.open,high:n.high,low:n.low,close:n.close,volume:n.volume??0});}return [...t.values()].sort((n,o)=>n.time-o.time)}function K2(r){return z2.filter(e=>et-e)[0]??null}var $d=class{constructor(){this.metaPromise=null;this.spotMetaPromise=null;this.symbolsPromise=null;}info(){return {name:"hyperliquid",displayName:"Hyperliquid",requiresApiKey:false,supportedTimeframes:G2,capabilities:{enumerate:true,stream:true,symbolInfo:true}}}async getBars(e,t,n){try{let o=Pm(e),i=rC(t),s=eC[i];if(s)return U2((await this.fetchCandles(o,s,$2(i),n)).map(Im));let a=/^\d+$/.test(i)?parseInt(i,10):null,l=a!=null?K2(a):null;if(a==null||l==null)return console.warn(`[vela] Hyperliquid: timeframe "${t}" is not supported and cannot be aggregated.`),[];let c=a/l,d={...n,limit:n.limit!=null?n.limit*c+c:void 0},u=(await this.fetchCandles(o,W2[l],l*6e4,d)).map(Im),h=Y2(u,a*6e4);return n.limit!=null&&h.length>n.limit?h.slice(-n.limit):h}catch(o){return console.warn(`[vela] Hyperliquid: failed to fetch ${e} ${t} \u2014 ${o instanceof Error?o.message:String(o)}`),[]}}async getSymbolInfo(e){let t=Pm(e),o=(await this.fetchMeta().catch(()=>null))?.universe?.find(i=>i.name===t);if(o){let i=iC(Math.max(0,6-(o.szDecimals??2)));return oC(e,t,"USD","futures",`${t} / USD Perpetual`,i)}if(t.includes("/")){let i=await this.fetchSpotMeta().catch(()=>null),s=i?.universe?.find(u=>u.name===t),a=s&&i?.tokens?i.tokens[s.tokens?.[0]??-1]:void 0,[l=t,c="USDC"]=t.split("/"),d=iC(Math.max(0,8-(a?.szDecimals??2)));return oC(e,l,c,"crypto",`${l} / ${c}`,d)}}listSymbols(){return this.symbolsPromise||(this.symbolsPromise=Promise.all([this.listPerps().catch(()=>[]),this.listSpot().catch(()=>[])]).then(([e,t])=>[...e,...t])),this.symbolsPromise}resolveSymbolIcon(e){return hi(ui(e))}subscribe(e,t,n){let o=Pm(e),i=eC[rC(t)];return i&&typeof WebSocket<"u"?this.streamCandles(e,t,o,i,n):this.pollBars(e,t,n)}async listPerps(){return ((await this.fetchMeta()).universe??[]).filter(t=>!t.isDelisted).map(t=>({ticker:t.name,description:`${t.name} / USD Perpetual`,type:"futures"}))}async listSpot(){let e=await this.fetchSpotMeta(),t=e.tokens??[],n=o=>o!=null?t[o]?.name??null:null;return (e.universe??[]).map(o=>{let i=n(o.tokens?.[0]),s=n(o.tokens?.[1]),a=i&&s?`${i} / ${s}`:o.name;return {ticker:o.name,description:a,type:"crypto"}})}async fetchCandles(e,t,n,o){let i=o.to??Date.now(),s=o.from!=null?o.from:i-((o.limit??500)+2)*n,a=await this.candleSnapshot(e,t,s,i);return o.from==null&&o.limit!=null&&a.length>o.limit?a.slice(-o.limit):a}async candleSnapshot(e,t,n,o){let i=await this.post({type:"candleSnapshot",req:{coin:e,interval:t,startTime:Math.floor(n),endTime:Math.floor(o)}});return Array.isArray(i)?i:[]}streamCandles(e,t,n,o,i){let s=false,a=null,l=null,c=null,d=null,u=null,h=()=>{d&&(clearTimeout(d),d=null);},p=()=>{l&&(clearInterval(l),l=null);},m=()=>{if(!(s||u)){h(),p(),c&&(clearTimeout(c),c=null);try{a?.close();}catch{}a=null,console.warn(`[vela] Hyperliquid: ${e} ${t} stream delivered no data; falling back to polling.`),u=this.pollBars(e,t,i);}},f=()=>{s||u||(a=new WebSocket(B2),d=setTimeout(m,_2),a.onopen=()=>{try{a?.send(JSON.stringify({method:"subscribe",subscription:{type:"candle",coin:n,interval:o}}));}catch{}l=setInterval(()=>{try{a?.send(JSON.stringify({method:"ping"}));}catch{}},3e4);},a.onmessage=g=>{if(!(s||u))try{let b=JSON.parse(typeof g.data=="string"?g.data:"");b.channel==="candle"&&b.data&&b.data.s===n&&(h(),i(Im(b.data)));}catch{}},a.onclose=()=>{p(),!s&&!u&&(c=setTimeout(f,H2));},a.onerror=()=>{try{a?.close();}catch{}});};return f(),()=>{s=true,h(),p(),c&&clearTimeout(c),u?.();try{a?.close();}catch{}}}pollBars(e,t,n){let o=false,i=null,s=async()=>{if(!o){try{let a=await this.getBars(e,t,{limit:2});for(let l of a)n(l);}catch{}o||(i=setTimeout(()=>{s();},3e3));}};return i=setTimeout(()=>{s();},3e3),()=>{o=true,i&&clearTimeout(i);}}fetchMeta(){return this.metaPromise??(this.metaPromise=this.post({type:"meta"}).then(e=>e))}fetchSpotMeta(){return this.spotMetaPromise??(this.spotMetaPromise=this.post({type:"spotMeta"}).then(e=>e))}async post(e){let t=await fetch(V2,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!t.ok)throw new Error(`Hyperliquid HTTP ${t.status}`);return t.json()}};function oC(r,e,t,n,o,i){return {ticker:r,tickerid:`HYPERLIQUID:${r}`,prefix:"HYPERLIQUID",description:o,type:n,basecurrency:e,currency:t,mintick:i,pricescale:Math.round(1/i),timezone:"Etc/UTC",session:"24x7"}}function iC(r){return Math.pow(10,-r)}var X2={now:()=>Date.now(),delay:r=>new Promise(e=>setTimeout(e,r))},Ud=class{constructor(e,t,n=X2){this.maxConcurrent=e;this.minIntervalMs=t;this.clock=n;this.active=0;this.waiters=[];this.nextStartAt=0;this.pausedUntil=0;}async run(e){await this.acquire();try{return await this.waitForTurn(),await e()}finally{this.release();}}pauseFor(e){e>0&&(this.pausedUntil=Math.max(this.pausedUntil,this.clock.now()+e));}async waitForTurn(){for(;;){let e=this.clock.now(),t=Math.max(this.pausedUntil-e,this.nextStartAt-e);if(t<=0)break;await this.clock.delay(t);}this.nextStartAt=Math.max(this.clock.now(),this.nextStartAt)+this.minIntervalMs;}acquire(){return this.active{this.waiters.push(()=>{this.active+=1,e();});})}release(){this.active-=1;let e=this.waiters.shift();e&&e();}};var Am="https://api.exchange.coinbase.com",j2="wss://ws-feed.exchange.coinbase.com",q2={Accept:"application/json"},Z2=15e3,Q2=2e3,J2=5e3,Yd=300,eO=4,tO=120,nO=4,rO=600,oO=400;function iO(r,e){let t=Number(r.headers.get("retry-after"));return Number.isFinite(t)&&t>0?t*1e3:e}var sC={1:60,5:300,15:900,60:3600,360:21600,D:86400},aC={"1m":"1","3m":"3","5m":"5","15m":"15","30m":"30","45m":"45","1h":"60","2h":"120","3h":"180","4h":"240","6h":"360","8h":"480","12h":"720","1d":"D","1w":"W","1mo":"M","1D":"D","1W":"W","4H":"240",D:"D",W:"W",M:"M"},sO=[1,5,15,60,360,1440],aO={1:60,5:300,15:900,60:3600,360:21600,1440:86400},lO=["1","3","5","15","30","45","60","120","180","240","360","480","720","D","W","M"],Rm=864e5;function lC(r){return aC[r]??aC[r.toLowerCase()]??r}function Dm(r){return r.trim().toUpperCase()}function cO(r){return {time:Number(r[0])*1e3,open:Number(r[3]),high:Number(r[2]),low:Number(r[1]),close:Number(r[4]),volume:Number(r[5])}}function Om(r){let e=new Map;for(let t of r)e.set(t.time,t);return [...e.values()].sort((t,n)=>t.time-n.time)}function dO(r,e){return cC(r,t=>Math.floor(t/e)*e)}function uO(r,e){return cC(r,e==="W"?hO:pO)}function cC(r,e){let t=new Map;for(let n of r){let o=e(n.time),i=t.get(o);i?(i.high=Math.max(i.high,n.high),i.low=Math.min(i.low,n.low),i.close=n.close,i.volume=(i.volume??0)+(n.volume??0)):t.set(o,{time:o,open:n.open,high:n.high,low:n.low,close:n.close,volume:n.volume??0});}return [...t.values()].sort((n,o)=>n.time-o.time)}function hO(r){let e=new Date(r),t=(e.getUTCDay()+6)%7;return Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()-t)}function pO(r){let e=new Date(r);return Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),1)}function mO(r){return sO.filter(e=>et-e)[0]??null}function Nm(r,e){return e!=null&&r.length>e?r.slice(-e):r}var Kd=class{constructor(){this.symbolsPromise=null;this.gate=new Ud(eO,tO);}info(){return {name:"coinbase",displayName:"Coinbase",requiresApiKey:false,supportedTimeframes:lO,capabilities:{enumerate:true,stream:true,symbolInfo:true}}}async getBars(e,t,n){try{let o=Dm(e),i=lC(t),s=sC[i];if(s)return Om(await this.fetchCandles(o,s,n));if(i==="W"||i==="M"){let h=i==="W"?7*Rm:31*Rm,p=n.from!=null?n:{...n,limit:n.limit!=null?Math.ceil(n.limit*h/Rm)+31:void 0},m=await this.fetchCandles(o,86400,p);return Nm(uO(m,i),n.limit)}let a=/^\d+$/.test(i)?parseInt(i,10):null,l=a!=null?mO(a):null;if(a==null||l==null)return console.warn(`[vela] Coinbase: timeframe "${t}" is not supported and cannot be aggregated.`),[];let c=a/l,d={...n,limit:n.limit!=null?n.limit*c+c:void 0},u=await this.fetchCandles(o,aO[l],d);return Nm(dO(u,a*6e4),n.limit)}catch(o){return console.warn(`[vela] Coinbase: failed to fetch ${e} ${t} \u2014 ${o instanceof Error?o.message:String(o)}`),[]}}async getSymbolInfo(e){let t=Dm(e),n=await this.json(`${Am}/products/${t}`).catch(()=>null);if(!n||!n.id)return;let o=n.quote_increment!=null?parseFloat(n.quote_increment):.01,i=o>0?o:.01;return {ticker:e,tickerid:`COINBASE:${e}`,prefix:"COINBASE",description:`${n.base_currency} / ${n.quote_currency}`,type:"crypto",basecurrency:n.base_currency,currency:n.quote_currency,mintick:i,pricescale:Math.round(1/i),timezone:"Etc/UTC",session:"24x7"}}listSymbols(){return this.symbolsPromise||(this.symbolsPromise=this.fetchProducts().then(e=>e.filter(t=>t.status==="online"&&!t.trading_disabled).map(t=>({ticker:t.id,description:`${t.base_currency} / ${t.quote_currency}`,type:"crypto"}))).catch(()=>[])),this.symbolsPromise}resolveSymbolIcon(e){return hi(ui(e))}subscribe(e,t,n){let o=sC[lC(t)];return o&&typeof WebSocket<"u"?this.streamTicker(e,t,o,n):this.pollBars(e,t,n)}async fetchProducts(){let e=await this.json(`${Am}/products`);return Array.isArray(e)?e:[]}async fetchCandles(e,t,n){return n.from!=null?this.paginateForward(e,t,n.from,n.to??Date.now(),n.limit):this.paginateBackward(e,t,n.limit??500,n.to??Date.now())}async paginateBackward(e,t,n,o){let i=t*1e3,s=[],a=n,l=o,c=Math.ceil(n/Yd)+4;for(;a>0&&c-- >0;){let d=Math.min(a,Yd),u=l-d*i,h=await this.candlesChunk(e,t,u,l);if(h.length===0||(s=h.concat(s),a-=h.length,l=h[0].time-1,h.length0;){let u=Math.min(l+Yd*s,o),h=await this.candlesChunk(e,t,l,u);if(h.length>0&&a.push(...h),l=u,i!=null&&a.length>=i)break}let d=Om(a);return i!=null?d.slice(0,i):d}async candlesChunk(e,t,n,o){let i=new URL(`${Am}/products/${e}/candles`);i.searchParams.set("granularity",String(t)),i.searchParams.set("start",String(Math.floor(n/1e3))),i.searchParams.set("end",String(Math.floor(o/1e3)));let s=await this.json(i.toString());return !Array.isArray(s)||s.length>0&&!Array.isArray(s[0])?[]:s.map(cO).sort((a,l)=>a.time-l.time)}streamTicker(e,t,n,o){let i=Dm(e),s=n*1e3,a=C=>Math.floor(C/s)*s,l=false,c=null,d=null,u=null,h=null,p=null,m=null,f=()=>{u&&(clearTimeout(u),u=null);},g=()=>{h&&(clearInterval(h),h=null);},b=()=>{m&&o({...m});},y=async C=>{try{let L=await this.getBars(e,t,{limit:2});if(l||L.length===0)return;C&&L.length>=2&&o(L[L.length-2]);let v=L[L.length-1];m=m&&m.time===v.time?{...v,high:Math.max(v.high,m.high),low:Math.min(v.low,m.low),close:m.close}:{...v},b();}catch{}},w=(C,L)=>{let v=Number(C);if(!Number.isFinite(v))return;let k=a(L);!m||k>m.time?(m={time:k,open:v,high:v,low:v,close:v,volume:0},b(),y(false)):k===m.time&&(m={...m,close:v,high:Math.max(m.high,v),low:Math.min(m.low,v)},b());},S=()=>{if(!(l||p)){f(),g(),d&&(clearTimeout(d),d=null);try{c?.close();}catch{}c=null,console.warn(`[vela] Coinbase: ${e} ${t} stream delivered no data; falling back to polling.`),p=this.pollBars(e,t,o);}},M=()=>{l||p||(c=new WebSocket(j2),u=setTimeout(S,Z2),c.onopen=()=>{try{c?.send(JSON.stringify({type:"subscribe",product_ids:[i],channels:["ticker"]}));}catch{}y(false),h=setInterval(()=>{y(false);},J2);},c.onmessage=C=>{if(!(l||p))try{let L=JSON.parse(typeof C.data=="string"?C.data:"");L.type==="ticker"&&L.product_id===i&&L.price!=null&&(f(),w(L.price,L.time?Date.parse(L.time):Date.now()));}catch{}},c.onclose=()=>{g(),!l&&!p&&(d=setTimeout(M,Q2));},c.onerror=()=>{try{c?.close();}catch{}});};return M(),()=>{l=true,f(),g(),d&&clearTimeout(d),p?.();try{c?.close();}catch{}}}pollBars(e,t,n){let o=false,i=null,s=async()=>{if(!o){try{let a=await this.getBars(e,t,{limit:2});for(let l of a)n(l);}catch{}o||(i=setTimeout(()=>{s();},3e3));}};return i=setTimeout(()=>{s();},3e3),()=>{o=true,i&&clearTimeout(i);}}async json(e){return (await this.request(e)).json()}async request(e){for(let t=0;;t+=1){let n=await this.gate.run(()=>fetch(e,{headers:q2}));if(n.status===429&&t { const menu = document.createElement('div'); menu.className = 'ta-more'; menu.setAttribute('role', 'menu'); - const close = () => { + const opener = document.activeElement; + const close = (restore) => { + const inside = menu.contains(document.activeElement); menu.remove(); document.removeEventListener('pointerdown', away, true); document.removeEventListener('keydown', key, true); + /* Esc used to drop focus on : a keyboard user lost their place in the toolbar (audit 8 Oct, G6). */ + if (restore && inside) { + const back = (opener && opener !== document.body && document.contains(opener)) ? opener : anchor; + try { if (back && back.focus) back.focus({ preventScroll: true }); } catch (err) { /* nothing to focus */ } + } }; const away = (ev) => { if (!menu.contains(ev.target) && !(anchor && anchor.contains(ev.target))) close(); }; - const key = (ev) => { if (ev.key === 'Escape') { ev.stopPropagation(); close(); } }; + const key = (ev) => { if (ev.key === 'Escape') { ev.stopPropagation(); close(true); } }; for (const [label, go] of items) { const b = document.createElement('button'); b.type = 'button'; diff --git a/console/mcp/server.py b/console/mcp/server.py index 444d070..c862147 100644 --- a/console/mcp/server.py +++ b/console/mcp/server.py @@ -78,7 +78,7 @@ import sys as _sys _sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) - from freshness import DEAD_AFTER_S, STALE_AFTER_S, _command_gate, _freshness + from freshness import DEAD_AFTER_S, STALE_AFTER_S, _command_gate, _freshness # noqa: F401 (re-exported for callers) try: import edge_text @@ -123,6 +123,11 @@ def _console_token() -> str: return "" +# Calls to the console are loopback: an `http_proxy` in the environment must not get them (it would be sent the console +# token and every Pine script), so this opener has no proxy handler (audit SEC-13). +_LOCAL = urllib.request.build_opener(urllib.request.ProxyHandler({})) + + def _call(path: str, payload: dict | None = None, timeout: float = 20.0) -> dict: """One console request. Returns the unwrapped `data`, or raises RuntimeError with the console's own message — the tools below turn that into a sentence rather than a traceback.""" @@ -137,7 +142,7 @@ def _call(path: str, payload: dict | None = None, timeout: float = 20.0) -> dict method="POST" if payload is not None else "GET", ) try: - with urllib.request.urlopen(req, timeout=timeout) as res: + with _LOCAL.open(req, timeout=timeout) as res: body = json.loads(res.read().decode("utf-8")) except urllib.error.HTTPError as exc: # The console answers refusals with a JSON body (401 no token, 400 a bad query, 409 busy…). @@ -247,6 +252,30 @@ def _command(action: str, timeout: float = INLINE_WAIT + 8.0, **fields) -> str: return line +MAX_PINE_CHARS = 60000 # one answer; a longer script is read in slices with `offset` + + +def _pine_slice(pine: str, offset: int = 0) -> str: + """A fenced Pine block that never cuts silently. The tools used to stop at 6000 / 8000 characters with no word, while + saying "full source": an agent ran or ported a fragment as if it were the script (audit 8 Oct, AS-1).""" + text = pine.strip() + total = len(text) + start = max(0, min(int(offset or 0), total)) + end = min(total, start + MAX_PINE_CHARS) + block = "```pine\n" + text[start:end] + "\n```" + if end < total: + block += (f"\n… truncated: showing characters {start}-{end} of {total} — call again with offset={end} " + "for the rest. Do NOT run or port this fragment as the whole script.") + elif start: + block += f"\n(characters {start}-{total} of {total})" + return block + + +def _more(shown: int, total: int, what: str) -> str: + """One line saying a list was cut, or nothing when it was not.""" + return f"… {shown} of {total} {what} shown — narrow the query to see the rest" if total > shown else "" + + # ── chart tools ───────────────────────────────────────────────────────────────────────────────── # ── vectorbt backtesting (the tier in console/backend/backtest_service.py, own venv, :8788) ── # These are thin HTTP clients like every other tool here: the console proxies, the service computes. @@ -254,10 +283,16 @@ def _command(action: str, timeout: float = INLINE_WAIT + 8.0, **fields) -> str: # _chart/backtest/ (their own namespace) and never touch the live chart's state. def _bt(path: str, payload: dict | None = None, timeout: float = 240.0) -> dict: - return _call(path, payload, timeout=timeout) + """The backtest tier, or an answer that says why not. Every other tool turns a refusal into a sentence; these four + raised, and the agent saw a traceback (audit AS-5).""" + try: + return _call(path, payload, timeout=timeout) + except RuntimeError as exc: + return {"ok": False, "error": f"{exc} — the vectorbt tier is optional: install it with ./install.sh --with-backtest and " + "start console/backend/backtest_service.py in its own venv"} -@mcp.tool(annotations=_ann("Backtest a strategy with vectorbt", read_only=False)) +@mcp.tool(annotations=_ann("Backtest a strategy with vectorbt", read_only=False, open_world=True, destructive=False)) def bt_run(source: str = "binance:BTCUSDT:30m", fast: int = 20, slow: int = 50, fee: float = 0.001, bars: int = 1000) -> str: """Run one MA-cross backtest and return its metrics (return, Sharpe, drawdown, trades). @@ -278,7 +313,7 @@ def bt_run(source: str = "binance:BTCUSDT:30m", fast: int = 20, slow: int = 50, f"expectancy {m['expectancy']:.2f}\nrun_id {r['run_id']} (trades saved; use bt_status)") -@mcp.tool(annotations=_ann("Sweep MA parameters with vectorbt", read_only=False)) +@mcp.tool(annotations=_ann("Sweep MA parameters with vectorbt", read_only=False, open_world=True, destructive=False)) def bt_optimize(source: str = "binance:BTCUSDT:30m", lo: int = 5, hi: int = 60, fee: float = 0.001, bars: int = 1000, top: int = 10) -> str: """Sweep every MA pair in [lo, hi] at once (vectorbt's real strength) and rank by return. @@ -431,17 +466,29 @@ def _label(s: dict) -> str: warning = _freshness(state.get("age_s")) if warning: lines.append(warning.lstrip("\n")) + if not state.get("bars"): + lines.append(_NO_BARS) return "\n".join(lines) +_NO_BARS = ("⚠ the chart holds no bars (the market feed may be unreachable): an empty chart is what any picture or " + "indicator result will show.") + + @mcp.tool(annotations=_ann("Capture the chart", read_only=True)) def chart_shot(name: str = ""): """Capture the chart as a PNG. Returns the image (when the client takes images) and its path.""" + blocked = _command_gate(_page_age()) # the same preflight every other chart tool runs + if blocked: + return f"✗ {blocked}" try: queued = _call("/api/chart/command", {"action": "shot", "wait": INLINE_WAIT + 10.0}, timeout=INLINE_WAIT + 14.0) except RuntimeError as exc: return f"✗ {exc}" + if not queued.get("pushed"): + return ("✗ no chart view is attached — open the Trader's Agent row in Hermes Desktop (or " + f"{BASE} in a browser) and call this tool again.") result = queued.get("result") or {} shot = result.get("shot") or "" if not result: @@ -466,6 +513,11 @@ def chart_shot(name: str = ""): return f"✗ captured the chart but could not write {path}: {exc}" size_kb = round(os.path.getsize(path) / 1024, 1) text = f"✓ chart captured ({size_kb} KB) → {path}" + try: + if not (_call("/api/chart/state", timeout=5.0).get("bars")): + text += "\n" + _NO_BARS + except RuntimeError: + pass if MCPImage is None: return text return [text, MCPImage(path=path)] @@ -506,9 +558,11 @@ def chart_apply_pine(pine: str, inputs: dict[str, Any] | None = None) -> str: One landasan for every door (chat, script pane, Library): geometry (boxes/lines/labels/tables) lands on the console's overlay and is read back after drawing; plot series lands as a matching - Vela native — only when the script actually plots. PineTS implements a subset: `import`, `while` - and `for…in` are not available — the answer says so rather than pretending. Sizes it can do: - studies with plot/hline/fill/bgcolor and simple ta.* calls. + Vela native — only when the script actually plots. PineTS implements most of Pine v6: `while`, + `for…in`, tuples, `request.security` (higher timeframes are fetched), box/line/label/table and + strategy() all run. The one thing refused outright is `import` (answer `NOT_RUNNABLE[import]`; the + answer says so rather than pretending). `request.security` reached only under a last-bar condition + (`barstate.islast` and the like) is an open engine bug and comes back empty. `inputs` sets the script's own settings (its `input.*()` values) by label, e.g. {"Length": 50, "Show upper band": false}; anything you leave out keeps the script's default, and @@ -565,7 +619,7 @@ def chart_clear() -> str: return _command("clear") -@mcp.tool(annotations=_ann("Add a Vela indicator", destructive=True)) +@mcp.tool(annotations=_ann("Add a Vela indicator", destructive=False)) def chart_add_indicator(native: str) -> str: """Add a Vela native indicator to the chart, by name (ema, supertrend, donchian-channels, …).""" if not native.strip(): @@ -646,7 +700,7 @@ def chart_natives() -> str: return _command("natives") -@mcp.tool(annotations=_ann("Open the Indicators surface", read_only=False)) +@mcp.tool(annotations=_ann("Open the Indicators surface", read_only=False, destructive=False)) def chart_indicators(section: str = "", q: str = "", family: str = "", star: str = "", unstar: str = "", mount: str = "", show: bool = True) -> str: @@ -680,7 +734,7 @@ def chart_indicators(section: str = "", q: str = "", family: str = "", return _command("indicators", **fields) -@mcp.tool(annotations=_ann("Full screen for the chart", read_only=False)) +@mcp.tool(annotations=_ann("Full screen for the chart", read_only=False, destructive=False)) def chart_fullscreen(on: bool = True) -> str: """Give the chart the whole pane — and the whole screen, where the host allows it. @@ -695,7 +749,7 @@ def chart_fullscreen(on: bool = True) -> str: return _command("fullscreen", on=bool(on)) -@mcp.tool(annotations=_ann("Replay the chart", read_only=False)) +@mcp.tool(annotations=_ann("Replay the chart", read_only=False, destructive=False)) def chart_replay(op: str = "state", bars: int = 100, from_ms: int = 0, interval_ms: int = 0) -> str: """Drive Vela's own replay engine — the operator's replay button, from the agent's side. @@ -715,7 +769,7 @@ def chart_replay(op: str = "state", bars: int = 100, from_ms: int = 0, interval_ return _command("replay", **fields) -@mcp.tool(annotations=_ann("Draw on the chart with Vela's drawing tools", read_only=False)) +@mcp.tool(annotations=_ann("Draw on the chart with Vela's drawing tools", read_only=False, destructive=True)) def chart_drawing(op: str = "list", type: str = "", anchors: list[dict] | None = None, id: str = "", ids: list[str] | None = None, style: dict | None = None, text: str = "", props: dict | None = None, locked: bool | None = None, visible: bool | None = None, @@ -758,7 +812,7 @@ def chart_drawing(op: str = "list", type: str = "", anchors: list[dict] | None = return _command("drawing", **fields) -@mcp.tool(annotations=_ann("Chart view settings (type, scale, time zone, status line …)", read_only=False)) +@mcp.tool(annotations=_ann("Chart view settings (type, scale, time zone, status line …)", read_only=False, destructive=False)) def chart_view(setting: str = "state", value: str = "") -> str: """Read or set one chart view setting — the things the operator would click in Vela's menus. @@ -780,7 +834,7 @@ def chart_view(setting: str = "state", value: str = "") -> str: return _command("view", **fields) -@mcp.tool(annotations=_ann("Event marks on the chart's time axis", read_only=False)) +@mcp.tool(annotations=_ann("Event marks on the chart's time axis", read_only=False, destructive=True)) def chart_marks(op: str = "list", time: str = "", bars_ago: int = -1, title: str = "", content: str = "", color: str = "", shape: str = "", letter: str = "", id: str = "") -> str: """Place small event marks on the chart's time axis (news, a trade idea, "I entered here"). @@ -804,7 +858,7 @@ def chart_marks(op: str = "list", time: str = "", bars_ago: int = -1, title: str return _command("marks", **fields) -@mcp.tool(annotations=_ann("Console theme (light / dark)", read_only=False)) +@mcp.tool(annotations=_ann("Console theme (light / dark)", read_only=False, destructive=False)) def chart_theme(theme: str = "") -> str: """Read or set the console's theme: 'light', 'dark', or '' to report what is worn now. @@ -829,7 +883,7 @@ def chart_reload() -> str: return _command("reload", once_per_view=True) -@mcp.tool(annotations=_ann("Chart palette")) +@mcp.tool(annotations=_ann("Chart palette", destructive=False)) def chart_palette(try_apply: bool = False) -> str: """What colours the chart is actually wearing (background, candle up/down, console theme). @@ -843,7 +897,7 @@ def chart_palette(try_apply: bool = False) -> str: return _command("palette", **fields) -@mcp.tool(annotations=_ann("Open the script catalogue in the drawer")) +@mcp.tool(annotations=_ann("Open the script catalogue in the drawer", destructive=False)) def chart_browse(family: str = "", show: bool = True) -> str: """Open the catalogue in the drawer — the one surface (the Library panel is deleted, 3 Oct). @@ -888,20 +942,35 @@ def library_search(query: str, kind: str = "", limit: int = 8) -> str: @mcp.tool(annotations=_ann("Read one Library indicator", read_only=True, open_world=True)) -def library_indicator(query: str) -> str: - """One Library indicator by name or slug: what it is, its licence, and its full Pine source.""" +def library_indicator(query: str, offset: int = 0) -> str: + """One Library indicator by name or slug: what it is, its licence, and its Pine source. + + The source comes whole up to 60,000 characters. A longer one is cut AND SAID so (`… truncated: …`), with the `offset` + to ask for next; never run or port a script that was reported truncated. + """ if not query.strip(): return "✗ empty query" slug = query.strip() try: - if " " in slug or slug.lower() != slug: # a name, not a slug: resolve it first - found = _call("/api/search?" + urllib.parse.urlencode({"q": slug, "type": "indicators", "limit": 1}), + def search_first(): + found = _call("/api/search?" + urllib.parse.urlencode({"q": query.strip(), "type": "indicators", "limit": 1}), timeout=25.0) rows = found.get("results") or [] - if not rows: + return rows[0].get("slug") if rows else None + + if " " in slug or slug.lower() != slug: # a name, not a slug: resolve it first + slug = search_first() + if not slug: return f"✗ nothing in the Library matches {query!r}" - slug = rows[0].get("slug") or slug - meta = _call("/api/indicator?" + urllib.parse.urlencode({"slug": slug}), timeout=25.0) + try: + meta = _call("/api/indicator?" + urllib.parse.urlencode({"slug": slug}), timeout=25.0) + except RuntimeError: + # A one-word lower-case name ("killzone") looks like a slug but may not be one: search before giving up. + found_slug = search_first() + if not found_slug or found_slug == slug: + raise + slug = found_slug + meta = _call("/api/indicator?" + urllib.parse.urlencode({"slug": slug}), timeout=25.0) except RuntimeError as exc: return f"✗ {exc}" item = meta.get("indicator") or meta @@ -915,7 +984,7 @@ def library_indicator(query: str) -> str: pine = src.get("source") or src.get("pine") or "" if pine: head.append("Pine source (LuxAlgo Library — CC BY-NC-SA 4.0, not redistributable):") - head.append("```pine\n" + pine.strip()[:6000] + "\n```") + head.append(_pine_slice(pine, offset)) else: head.append("(no Pine source on this entry)") except RuntimeError as exc: @@ -1007,15 +1076,17 @@ def library_concept(slug: str) -> str: lines.append("indicators:") lines += [f"- {r.get('title') or r.get('slug')} ({r.get('slug')})" if isinstance(r, dict) else f"- {r}" for r in related[:20]] + if _more(20, len(related), "related indicator(s)"): + lines.append(_more(20, len(related), "related indicator(s)")) return "\n".join(lines) @mcp.tool(annotations=_ann("Library source by slug", read_only=True, open_world=True)) -def library_source(slug: str) -> str: +def library_source(slug: str, offset: int = 0) -> str: """The Pine source of one Library entry, by EXACT slug — no name resolution, no guessing. Same rule as library_indicator: LuxAlgo Library source is CC BY-NC-SA 4.0, fine to run locally, - never to redistribute. + never to redistribute. A source over 60,000 characters is cut AND SAID so; pass `offset` for the rest. """ if not slug.strip(): return "✗ empty slug" @@ -1026,9 +1097,8 @@ def library_source(slug: str) -> str: pine = data.get("source") or data.get("pine") or "" if not pine: return f"✗ no source stored for {slug!r} — check the slug with library_search" - return (f"# {slug.strip()} — {len(pine.splitlines())} line(s)\n" - "Pine source (LuxAlgo Library — CC BY-NC-SA 4.0, not redistributable):\n" - "```pine\n" + pine.strip()[:8000] + "\n```") + return (f"# {slug.strip()} — {len(pine.splitlines())} line(s), {len(pine.strip())} characters\n" + "Pine source (LuxAlgo Library — CC BY-NC-SA 4.0, not redistributable):\n" + _pine_slice(pine, offset)) @mcp.tool(annotations=_ann("LuxAlgo edge presets", read_only=True, open_world=True)) @@ -1048,6 +1118,8 @@ def edge_presets(category: str = "") -> str: for row in rows[:30]: label = row.get("name") or row.get("id") or row out.append(f"- {label}") + if _more(30, len(rows), "preset(s)"): + out.append(_more(30, len(rows), "preset(s)")) if data.get("categories"): out.append("categories: " + ", ".join(map(str, data["categories"]))) return "\n".join(out) @@ -1065,12 +1137,14 @@ def edge_report(preset: str, symbol: str) -> str: return f"✗ {exc}" report = data.get("report") or {} lines = [f"{preset} on {symbol.upper()}:"] - for key, value in list(report.items())[:20]: + for key, value in list(report.items())[:40]: if isinstance(value, (str, int, float, bool)) or value is None: lines.append(f"- {key}: {value}") elif isinstance(value, list): lines.append(f"- {key}: {len(value)} row(s)") # nested structures are summarised: the raw report can be large + if _more(40, len(report), "field(s)"): + lines.append(_more(40, len(report), "field(s)")) return "\n".join(lines) if len(lines) > 1 else f"no report fields came back for {preset} / {symbol}" @@ -1085,7 +1159,8 @@ def edge_symbols() -> str: head = f"{data.get('count', len(rows))} symbol(s)" if data.get("note"): head += f" · {data['note']}" - return head + "\n" + ", ".join(map(str, rows[:60])) + more = _more(60, len(rows), "symbol(s)") + return head + "\n" + ", ".join(map(str, rows[:60])) + (("\n" + more) if more else "") # ── Edge Stats: LuxAlgo's open-source engine, run locally (console/backend/edgestats.py) ────────────── @@ -1273,6 +1348,8 @@ def propfirms(query: str = "") -> str: out.append(f"- {name}" + (f" — {', '.join(extra)}" if extra else "")) else: out.append(f"- {row}") + if _more(30, len(firms), "firm(s)"): + out.append(_more(30, len(firms), "firm(s)")) return "\n".join(out) @@ -1294,6 +1371,8 @@ def propfirm_offers(query: str = "") -> str: row.get("discount") or row.get("price"), row.get("ends") or row.get("expires")) if v)) else: out.append(f"- {row}") + if _more(30, len(rows), "offer(s)"): + out.append(_more(30, len(rows), "offer(s)")) return "\n".join(out) @@ -1355,7 +1434,7 @@ def _natives(live: bool = False) -> list: @mcp.tool(annotations=_ann("Run several chart commands", destructive=True)) -def chart_batch(commands: str, stop_on_error: bool = True) -> str: +def chart_batch(commands: str | list[dict[str, Any]], stop_on_error: bool = True) -> str: """Run several chart actions in ONE call, in order. `commands` is JSON: a list of objects, each `{"action": "market", "symbol": "BTCUSDT", @@ -1392,7 +1471,7 @@ def chart_batch(commands: str, stop_on_error: bool = True) -> str: return "\n".join(lines) -@mcp.tool(annotations=_ann("Remember the chart's state")) +@mcp.tool(annotations=_ann("Remember the chart's state", destructive=False)) def chart_snapshot() -> str: """Remember the chart's indicators plus its symbol/timeframe as a restore point for chart_undo. diff --git a/console/requirements-test.txt b/console/requirements-test.txt new file mode 100644 index 0000000..fc89b6d --- /dev/null +++ b/console/requirements-test.txt @@ -0,0 +1,3 @@ +# What CI installs on top of the stdlib for the MCP tool layer. Pinned to the versions the suite was last green on. +-r requirements.txt +fastmcp==4.0.10 diff --git a/console/requirements.txt b/console/requirements.txt new file mode 100644 index 0000000..0f46775 --- /dev/null +++ b/console/requirements.txt @@ -0,0 +1,3 @@ +# The console itself is stdlib-only. This is its one optional library: the MCP client used for the LuxAlgo Library proxy. +# Tested against 1.x and 2.x (CI runs both). +mcp>=1,<3 diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index 48b9d2a..1bd96d6 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -1,7 +1,7 @@ # HANDOFF — Trader's Agent (Hermes Desktop plugin + local Vela console) **Written for:** an outside agent/model picking this up cold (no access to the chat that built it). -**Written by:** the previous agent session, 20 Sep 2026; **updated 4 Oct 2026**, repo `godzillacode0000/tradersagent-plugin` @ `568ea9f` (this file lives at `docs/HANDOFF.md`; bump the SHA when you ship). +**Written by:** the previous agent session, 20 Sep 2026; **updated 4 Oct 2026**, repo `godzillacode0000/tradersagent-plugin` (this file lives at `docs/HANDOFF.md`; the exact commit is `git log -1`: a SHA typed here is stale the moment it is committed. Last full audit: 8 Oct 2026 over `3c2ad34`, see `CHANGELOG.md`). **Operator:** one user, Malay/English speaker, runs a single laptop (Omarchy/Arch, 8 GB RAM), drives it mostly from his phone over Telegram, wants short answers with commands explained plainly. @@ -19,8 +19,9 @@ the agent (and the user) read and drive that chart with low latency. It is delib `console/frontend/vendor/pinets/PROVENANCE.md`); Library Pine source is CC BY-NC-SA 4.0 and must **never** be committed (it may be fetched at runtime and drawn, with attribution). - **MIT** for this plugin's own code. -- **private repo**, personal use. Grok cannot clone it; the operator will paste this file (and file - contents) instead. +- **public repo** (checked 8 Oct 2026; earlier versions of this file said private). That is why nothing from the Library may be + committed and why the licence notices matter: anything committed is already redistributed. Grok-style agents that cannot + clone get this file pasted by the operator. Goal in the operator's words: *"chart ni yang connect, communicate, see and understand the chart with the lowest latency possible"* — chat on the left, chart docked on the right, agent drives the chart through @@ -46,7 +47,7 @@ native tools. Versions: Hermes Desktop 0.21.5, console `SERVER_VERSION = 1.0.0`. CI was red from 28 Sep (`1f9d340`) to 2 Oct (`8df6e2e` — a stale MCP test only CI could see); green since `ab3708b`, and -green on every ship below. **1034 backend tests** (+77 skipped without `fastmcp` / a real Edge Stats engine), 8 plugin contributions across 5 areas. +green on every ship below. **about 1,090 backend tests** (77+ skipped without `fastmcp` / a real Edge Stats engine; run the suite for the exact count), 8 plugin contributions across 5 areas. Shipped since this file was written: the paper broker (Phase 5), replay (6/6b), the top-bar one-door consolidation, the drawer as the single Library surface, and Phase 7 — three agent doors into Vela (`chart_drawing` 76 types / `chart_view` settings / `chart_marks`), 54 MCP tools (8 of them `edgestats_*`). 4 Oct: Edge Stats — the optional local engine, the sheet behind the `⋯` menu, the eight tools (see CHANGELOG; real Binance / Dukascopy downloads were never run from the build machine). Also 4 Oct: the top row @@ -268,7 +269,7 @@ Working, with evidence: - Latency: symbol switch **686–698 ms** end to end, screenshot **35 ms**, `clear` **7 ms**, SSE push single-digit ms (transport is not the bottleneck; the chart engine fetch+render is). - Console health: `/api/health` ok, LuxAlgo MCP connected, 29 endpoints. -- 1034 backend tests (77 skipped bare; 1 with fastmcp + a real engine), plugin harness OK (8 contributions / 5 areas), CI green since `ab3708b` +- ~1,090 backend tests (see the suite's own count; skips depend on `fastmcp`, node and a real engine), plugin harness OK (8 contributions / 5 areas), CI green since `ab3708b` (see the correction above — earlier runs were red for a week and nobody looked). Current live state (transient): chart on **BTCUSDT 1m** (dark), the Breakout Detector overlay restored @@ -276,10 +277,29 @@ from the last session, replay off; the docked pane may be hidden — check the h --- +## 6b. Audit of 8 Oct 2026: what is still open + +Seven read-only lanes (security, backend, frontend, agent surface and docs, tests and CI, the Pine engine, UI and accessibility) +audited `3c2ad34`; the fixes are in `CHANGELOG.md` under *Fixed*. What the fixes did **not** do, so it is not mistaken for done: + +- **Pine runs as JavaScript in the console's page** (PineTS compiles Pine to JS). A Content-Security-Policy now stops the page + sending anything to an unlisted host, but it cannot stop script injection by itself. The real fix is running PineTS in a + sandboxed frame; until then, treat Pine from an untrusted source (a prompt-injected agent, a pasted script) as code. +- **The paper broker's approval gate is "a request that looks like our page"**, not a credential: a caller that holds the + console token can imitate it. It is paper money and it is documented so; a real-order tier needs a real approval factor first. +- **Two consoles on one machine share one paper account file** with no cross-process lock. +- `/api/bars` still answers a venue failure as `ok: true` with an `error` field, and has no negative cache. +- Installer downloads (`pip install vectorbt`, `npx pnpm`, `uvx fastmcp`) are not version-pinned or hash-checked. +- No browser test runs in CI (the focus ring, the ⋯ button at 1024 px and the 200 % zoom layout were verified in Chromium by hand); + there is no performance budget test; about half the UI tests are still source-string pins. +- `request.security` reached only under a last-bar guard is wrong in the vendored engine (upstream); a minimal repro exists. +- The two bundled "extra" Pine scripts (`console/frontend/extra/`) are read by nothing: the picker was never built. +- The editor font is 6.25 px by the operator's choice (6 Oct); a setting that honours browser text size would be kinder. + ## 7. Open problems — what to settle next (ranked) 1. **Real LuxAlgo indicators cannot run.** The catalogue's indicators (what the operator actually wants: - "the LuxAlgo indicators I see on their site") are full Pine v6 scripts; PineTS rejects `for … in` and + "the LuxAlgo indicators I see on their site") are full Pine v6 scripts; PineTS runs `for … in` (only `import` is refused) and friends. Options to investigate, in order of user value: (a) a PineTS-compatible **port** of the specific indicators he names (subset-safe, no MTF calls); (b) compute-from-data drawings (the PDH/PDL pattern) for level-type indicators; diff --git a/docs/MCP-TOOLS.md b/docs/MCP-TOOLS.md index 4d84d20..1bc2546 100644 --- a/docs/MCP-TOOLS.md +++ b/docs/MCP-TOOLS.md @@ -21,12 +21,10 @@ Verify: `hermes mcp test traders-chart` · **new tools need a new session** (or | `chart_studies` | — | Everything **on** the chart right now, each row labelled with the reader that saw it: `study` (what the console's own chip counts), `cell` (the workspace cell's on-chart rows), `overlay` (a script run through the console's landasan), `paint` (the PineTS paint layer), `native` (Vela's own names). Ask it before calling a chart clean: `chart_state`'s `natives` list is Vela's names only, and a script mounted from the Library is not one of them. | | `chart_state` | — | Symbol, timeframe, last price, bars, indicators on the chart, plus `build`/`viewer` when the page publishes them (stale-frame check). | | `chart_shot` | `name: str = ""` | One PNG of the chart. Returned as an image when the client takes images, plus the path on disk. | -| `chart_palette` | `try_apply: bool = false` | What colours the chart is actually wearing (background, candles, console theme). `try_apply=true` asserts the console's palette and reports what landed 300 ms later. | -| `chart_browse` | `family: str = ""`, `show: bool = true` | Open the Library's concept-family list in the pane, optionally narrowed to one family slug. Family bubbles expose Library **concepts** (not indicator scripts); the empty family opens all concepts. Answers with the rows actually painted. The catalogue itself is `library_list`; this one is the *surface*. | | `broker_state` | — | The **paper** (simulated Binance spot) account: cash, equity, positions with live P&L, and the orders waiting for the operator. Read-only. | -| `broker_propose` | `symbol: str`, `side: str` (`buy`/`sell`), `qty: float`, `note: str = ""` | Propose a paper order. It does **not** trade: it puts an Approve/Reject card on the chart and waits. There is deliberately **no approve tool** — only the operator, on the card. Fills at the live price at approval — or the replay cursor price while replay is on (see `chart_replay`). | -| `library_search` | `query: str`, `kind: str = ""` (`concept`/`indicator`), `limit: int = 8` | Search the LuxAlgo Library (concepts + indicators). See the Library section below for the other nine. | -| `library_indicator` | `query: str` | One indicator by name or slug: summary, licence, and its full Pine source. | +| `chart_pine_inputs` | `pine: str` | List the settings a script declares — label, type, default, range or options, group — without running it, opening the pane or touching the chart. Call it before `chart_apply_pine` / `chart_draw` with `inputs` when you do not know the labels. | +| `chart_watch` | `seconds: int = 15`, `timeout_s` | Watch for a spell (blocks up to 120 s) and answer with a **diff** (what changed) rather than a second snapshot. | +| `chart_alert` | `seconds: int = 30`, `move_pct: float = 0.0`, `timeout_s` | Wait (up to 300 s) for the **market** to move. Reuses the heartbeat's own `last`, reports the move (from → to, percent and absolute) as soon as price travels `move_pct` percent from the first reading — `0` means any change. Where `chart_watch` answers "did the chart change", this answers "did price do something", and reports the largest excursion it saw when the threshold is never met. | ## Mutating tools @@ -45,27 +43,27 @@ Verify: `hermes mcp test traders-chart` · **new tools need a new session** (or | `chart_remove_indicator` | `native: str = ""`, `all: bool = false` | Take studies **off** the chart — one by name, or every study with `all=true`. Reports `removed X · chart now carries: Y`. | | `chart_apply_pine` | `pine: str`, `inputs: dict = {}` | Run Pine over the chart's live bars and paint what it makes: geometry (boxes/lines/labels/tables) on the console's overlay, plot series as a **matching Vela native** — the same landasan as `chart_draw`, the script pane and the Library. PineTS is a measured subset: `import` is refused outright, while `while`, `for … in`, `request.security`, tuple returns, `box/line/label/table` and `strategy()` all run. `inputs` sets the script's own settings (its `input.*()` values) **by label** — `{"Length": 50, "Show upper band": false}`; the label is matched ignoring case and spacing, and the variable name or `in_0` id work too. What you leave out keeps its default, `null` resets one, a number outside the input's range is limited to it, and the answer says what was used, what was refused and why (with a *did you mean* for a near miss), and which inputs the script does have. When the script pane holds this very script, its Settings show the values. | | `chart_draw` | `pine: str`, `inputs: dict = {}` | Run Pine and paint the geometry it **builds** (boxes/lines/labels/tables) on the console's overlay; any plot series lands as a native — one landasan with `chart_apply_pine`. The explicit route for level-type scripts (SMC/liquidity models, PDH/PDL). | -| `chart_pine_inputs` | `pine: str` | **Read-only.** List the settings a script declares — label, type, default, range or options, group — without running it, opening the pane or touching the chart. Call it before `chart_apply_pine` / `chart_draw` with `inputs` when you do not know the labels. | | `chart_clear` | — | Clear our overlay drawings and the natives our paint layer added, then report what is left. **Does not remove studies added with `chart_add_indicator`** — use `chart_remove_indicator`. | | `chart_reload` | — | Reload every attached console page (picks up new frontend files). Once-per-view. | -| `chart_batch` | `commands: str` (JSON array) | Several actions in one call, in order. Each step is `{"action": "...", ...fields}`; stops at the first failure unless `stop_on_error=false`. One round trip instead of five. | +| `chart_batch` | `commands: str` (JSON array, or a list), `stop_on_error: bool = true` | Several actions in one call, in order. Each step is `{"action": "...", ...fields}`; stops at the first failure unless `stop_on_error=false`. One round trip instead of five. | | `chart_snapshot` | — | Remember the market + indicator set as a restore point for `chart_undo`. | | `chart_undo` | — | Put the chart back to the last snapshot: market first, then the indicator set, reporting the chart's own before → after lists. **Drawings are not restored** — `chart_clear`, then re-draw. | -| `chart_watch` | `seconds: int = 15`, `timeout_s` | Watch for a spell and answer with a **diff** (what changed) rather than a second snapshot. | -| `chart_alert` | `seconds: int = 30, move_pct: float = 0.0` | Wait for the **market** to move. Reuses the heartbeat's own `last`, reports the move (from → to, percent and absolute) as soon as price travels `move_pct` percent from the first reading — `0` means any change. Where `chart_watch` answers "did the chart change", this answers "did price do something", and reports the largest excursion it saw when the threshold is never met. | +| `chart_palette` | `try_apply: bool = false` | What colours the chart is actually wearing (background, candles, console theme). `try_apply=true` asserts the console's palette and reports what landed 300 ms later. | +| `chart_browse` | `family: str = ""`, `show: bool = true` | Open the catalogue in the drawer, optionally narrowed to one family slug (`trend`, `smc-ict`, …). The answer reports the rows the list holds, its family filter and whether the drawer is open; it never applies an indicator. | +| `broker_propose` | `symbol: str`, `side: str` (`buy`/`sell`), `qty: float`, `note: str = ""` | Propose a paper order. It does **not** trade: it puts an Approve/Reject card on the chart and waits. There is deliberately **no approve tool** — only the operator, on the card. Fills at the live price at approval — or the replay cursor price while replay is on (see `chart_replay`). | ## Library / research tools -Read-only, and every one leaves this machine (they reach LuxAlgo's hosted MCP). +Read-only. The `library_*`, `edge_*`, `propfirm*` tools reach LuxAlgo's hosted MCP, so they leave this machine; the `edgestats_*` tools run LuxAlgo's open-source engine **locally** (only `edgestats_setup` downloads, from Binance or Dukascopy). `edgestats_show` and `edgestats_setup` are not read-only: they open a view / start a download. | Tool | Arguments | What it does | |---|---|---| | `library_search` | `query: str`, `kind: str = ""` (`concept`/`indicator`), `limit: int = 8` | Search the Library (concepts + indicators). | -| `library_indicator` | `query: str` | One indicator by name or slug: summary, licence, full Pine source. | +| `library_indicator` | `query: str`, `offset: int = 0` | One indicator by name or slug: summary, licence, Pine source. A source over 60,000 characters is cut **and says so** (`… truncated … offset=N`); a one-word name that is not a slug falls back to a search. | | `library_list` | `family`, `text`, `concept`, `tier`, `sort`, `direction`, `page`, `page_size` | Browse with the same filters and paging the console's own list uses. | | `library_taxonomy` | `what: str = "families"` | The Library's own families (17 measured) or its concept graph — so a filter value is the Library's, not a guess. | | `library_concept` | `slug: str` | One concept by slug, with the indicators that implement it. | -| `library_source` | `slug: str` | Pine source by **exact** slug — no name resolution to get wrong. | +| `library_source` | `slug: str`, `offset: int = 0` | Pine source by **exact** slug — no name resolution to get wrong. Long sources are cut **and say so**; pass `offset` for the rest. | | `edge_presets` | `category: str = ""` | LuxAlgo's measured edge presets (42 measured). | | `edge_report` | `preset: str`, `symbol: str` | One preset's measured performance on one symbol. | | `edge_symbols` | — | The symbols the edge dataset covers. | @@ -96,11 +94,11 @@ Read-only, and every one leaves this machine (they reach LuxAlgo's hosted MCP). | Code | Meaning | |---|---| | `SYMBOL_NOT_SERVED[XAUUSD]` | This console's workspace provider is Binance only, and it never answered for that symbol. The chart is unchanged — use a crypto pair (the op has a 6 s deadline so it refuses instead of hanging). | -| `NOT_RUNNABLE[import/for-in]` | PineTS cannot execute that construct — the script needs a full TradingView engine. Measured: `import` is the real one; `for … in` actually runs. | +| `NOT_RUNNABLE[import]` | The script imports a library, which PineTS cannot do. `while` and `for … in` run (measured 28 Sep). | | `SYNTAX_ERROR` | Pine could not parse the script. The error carries `line` and `col` (1-based) — fix that line; an unclosed bracket is often reported at the end of the file. | | `RUNTIME_CRASH[…]` | The engine threw mid-run (engine bug, not the caller's). | | `TOO_FEW_BARS` | Not enough history loaded — widen the range, retry once. | -| `ENGINE_UNAVAILABLE` | The PineTS module could not be fetched (network). | +| `ENGINE_UNAVAILABLE` | The vendored PineTS engine did not load (nothing is fetched from the network); `chart_reload`, and report it if it persists. | | `TIMEOUT` | The run exceeded its budget. | When no view is attached the command tools answer `✗ no chart view is attached …` instead of hanging. @@ -109,7 +107,7 @@ When no view is attached the command tools answer `✗ no chart view is attached `state` · `shot` · `apply` · `add` · `remove` · `market` · `draw` · `clear` · `script` · `browse` · `open` · `mode` · `reload` · `caps` · `layout` · `studies` · `natives` · `indicators` · -`fullscreen` · `theme` · `replay` · `wait` +`fullscreen` · `theme` · `replay` · `wait` · `drawing` · `view` · `marks` · `edge` ## Notes diff --git a/docs/architecture-latest.html b/docs/architecture-latest.html index af1ccf1..b03601f 100644 --- a/docs/architecture-latest.html +++ b/docs/architecture-latest.html @@ -325,7 +325,7 @@

    The chart runs in a tab, and the agent knocks on a door.

    console 1.0.0 39 MCP tools pinets 0.11.0-fork (vendored) - Vela 0.8.1 + Vela 0.8.3 293 backend tests green
@@ -458,8 +458,8 @@

The chart runs in a tab, and the agent knocks on a door.

index.html — two ways in

-

Vela 0.8.1 and vela-pinets 0.2.15 arrive as vendored global scripts, and an import map then names the ESM builds. The map is also where the engine is pinned.

-
@luxalgo/vela@0.8.1/workspace/providers/binance
+

Vela 0.8.3 and vela-pinets 0.2.15 arrive as vendored global scripts, and an import map then names the ESM builds. The map is also where the engine is pinned.

+
@luxalgo/vela@0.8.3/workspace/providers/binance

workspace.js — the grid

The Vela workspace: real chart cells. Layouts 1 · 2h · 2v · 4 · 8 · g<cols>x<rows>. A grid already in page state wins over the boot preset, so a change made from chat survives a reload.

app.js — console shell

@@ -506,7 +506,7 @@

The chart runs in a tab, and the agent knocks on a door.

what draws, and
what computes
two of three are LuxAlgo’s
-

Vela 0.8.1 — the chart

+

Vela 0.8.3 — the chart

LuxAlgo’s chart package, vendored into the repo. This build ships ~80 natives. addNativeIndicator() genuinely paints; drawings.add() creates a real core-owned drawing and the renderer never paints it — measured on a bare chart and on a cell, after pan and resize.

vela-pinets 0.2.15 — Vela’s Pine engine

diff --git a/docs/desk-engineering-notes.md b/docs/desk-engineering-notes.md new file mode 100644 index 0000000..9515394 --- /dev/null +++ b/docs/desk-engineering-notes.md @@ -0,0 +1,357 @@ +# Trader's Agent desk: engineering notes + +*Moved out of `skills/trader-desk/SKILL.md` on 8 Oct 2026 (audit AS-10). That file is copied into every user's +`~/.hermes/skills/` and is read by the agent on every trigger, so it now holds only what an agent needs to drive the +chart. This file is the history behind it: measurements, root causes and the maintainer's own setup. Some lines are +the maintainer's machine (`~/Projects/luxalgo-web`, `traders-agent-bt.service`) and are not general. Parts are out of +date and say so: the Indicators modal and `reading`/`fold` no longer exist (the drawer replaced them, 3 Oct), and +`while` / `for…in` run in PineTS (only `import` is refused).* + +# Trader's Agent — prompt to chart + +The chart is a live LuxAlgo **Vela** console (`http://127.0.0.1:8787`) in the Trader's Agent pane. +There is no headless mode. Drive it with the **`traders-chart` MCP tools** (preferred) or +`bin/trader-chart` — both hit the same HTTP API. + +Do **not** port or run LuxAlgo Library Pine unless the operator names a script. Prompt-to-chart is +natives + overlay drawings + market/state/shot. + +## MCP stack — auto-use (the operator never names a tool) + +On this desk use **`traders-chart` + `luxalgo`**; **never `tradingview-mcp`** (nor the disabled +hosted `tradingview` entry) — ruled out by the operator (30 Sep). + +- **`traders-chart`** — first reach for anything on or about the chart: `chart_*` (incl. `chart_batch`, + `chart_watch`, `chart_alert`), the Library proxy (`library_*`), edge/prop-firm reads, and the + backtest tier (`bt_*`). Step 0 stays `chart_views`. +- **Backtest tier** — engine is the user service `traders-agent-bt.service` (venv + `~/.local/share/traders-agent/bt/venv`, port 8788, results under `~/Projects/luxalgo-web/_chart/backtest/`). + `bt_run` = MA-cross only; `bt_optimize` = full pair sweep; `bt_status` reads back a run. If a bt tool + answers `backtest_down`, check `systemctl --user status traders-agent-bt` — never hand-start the engine. + Custom vectorbt experiments: `~/.local/share/traders-agent/bt/smc_sweep_bos.py` (liquidity-sweep + BOS demo). +- **Edge Stats** (`edgestats_*`, LuxAlgo's open-source engine running **on this machine**) — "how often did + this setup actually work?" on bars the operator downloaded. It is a different thing from the hosted + `edge_*` reads below (LuxAlgo's published BTC/ETH presets): the local engine answers ANY question over ANY + symbol the store holds. See the Edge Stats section. +- **`luxalgo`** (hosted, keyless) — catalogue truth + wider datasets: `library_search`, + `library_get_source_code`, `library_list_*`, `library_taxonomy`, `propfirms_*`, `edge_*`, `trackers_*`. + Every call needs its 15–25-word third-person `context`. The hosted `edge_*` reads cover BTCUSDT + ETHUSDT only. + There are **no SMC/ICT strategies** in the Library (60 smc-ict *indicators*; the whole catalogue has + one `strategy()` script — moon-phases). +- **OAuth-gated**: `luxalgo_account`, `journal_*` error until `hermes mcp login luxalgo` runs in a + browser — never promise account/journal features. +- Session truth: `curl -s http://127.0.0.1:8787/api/health` → `mcp.connected`; `chart_views` for a live + pane. New MCP tools arrive only with a new session or `/reload-mcp`. + +## Step 0 — is anything listening? + +- `chart_views` first. 0 views → tell the operator to open the Trader's Agent row. Do not queue work + and report it as done. +- Stale frame: `chart_state` reports `build` + `viewer`. Compare with the console (`/api/build`). + If they disagree, `chart_reload` (once-per-view) then re-read. + +## Step 1 — read before you write + +- `chart_state` → symbol, timeframe, last, bars, **indicators on the chart**, build/viewer. +- `chart_caps` → actions **this page** can execute. +- `chart_palette` → colours the chart is wearing (do not guess from a screenshot). + +## Step 2 — put the chart where the analysis needs it + +- `chart_set_market` (symbol + timeframe). The answer already has last price and bars — do not follow + with `chart_state` just to confirm. +- Prefer the timeframe the operator asked for. + +## Step 3 — one study at a time + +1. Take extras off: `chart_remove_indicator(all=True)` for Vela natives the operator or agent added. + `chart_clear` only removes **our overlay + paint layer**, not studies added with `add`. +2. One native: `chart_add_indicator("ema")` **or** one overlay script: `chart_draw` (levels/lines) + **or** `chart_apply_pine` (plots that map to a Vela native). +3. `chart_shot` — say what the picture shows. +4. Only then the next study. + +Never stack "to save time". + +## Step 4 — prove it + +A tool answer is not a picture. `chart_shot` after every mutation. If `ok: false`, the chart did not +change — report that, never "done". + +## Prompt mapping (what to call) + +| Operator says | Tool | +|---|---| +| what symbol / what's on the chart | `chart_state` then maybe `chart_shot` | +| open / switch SOLUSDT 1h | `chart_set_market` | +| split the chart / 2 panes / 4 charts / "multipane" | `chart_set_layout` — no argument **reads** the grid | +| which indicators can this chart take | `chart_natives` — Vela's built-ins for this market, read from the frame | +| what is ON the chart right now | `chart_studies` — every reader, labelled; ask this before calling a chart clean | +| open the Indicators panel / star one / search the catalogue | `chart_indicators` — section `favorites`/`builtins`/`library`, `q`, `family` (one group of the catalogue; `all` clears), `reading SLUG`, `fold FAMILY[:on]`, `star`/`unstar KIND:ID`, `mount` | +| add EMA / MACD / supertrend | `chart_add_indicator` | +| remove indicators / clear studies | `chart_remove_indicator(all=True)` | +| draw PDH/PDL / lines / boxes | `chart_draw` (overlay). Not `chart_apply_pine` for a plain price level. | +| set / change a script's setting ("length 50", "hide the signals", "make the band wider") | `chart_pine_inputs` for the labels, then `chart_apply_pine` / `chart_draw` with `inputs={"Length": 50}` — do **not** edit the Pine source to change a default | +| screenshot | `chart_shot` | +| give the chart the whole screen / come back | `chart_fullscreen` (`on=False` to return) — the console's chrome steps aside and the page asks the browser for fullscreen | +| chart looks stale / old JS | `chart_reload` | +| chart is light/dark | `chart_palette` | +| how often does X happen / did that gap fill / weekday effect / opening-range break | `edgestats_query` (ask) or `edgestats_report` (a catalogue report) — then **read the guards before quoting a number** | +| what can I ask / which reports exist | `edgestats_presets`, `edgestats_fields` | +| show me / put it on screen / which sessions were those | `edgestats_show` (`ask` / `report` / `session`) | +| no data / "it says not installed" / load something to try | `edgestats_status` → `edgestats_setup` | + +## The grid (multi-pane) + +Vela's workspace is a real chart grid. `chart_set_layout(layout)` takes `1` (single), `2h` (2 side by +side), `2v` (2 stacked), `4`, `8`, or a custom `gx` (1–4 each); **no argument reads the +grid** (a read never writes). The answer carries the layout id and every cell's own symbol/timeframe — +quote those, not the id asked for. + +- A console built with `layout: false` sets `monoLayout`, and `setLayout()` is then a **permanent + no-op**: the tool answers truthfully that the page must boot with a preset. Do not call it "broken". +- A grid already in the page's state **wins over the boot preset**, so a change made from chat + survives a reload. +- Cells inherit the active cell's symbol — a wider grid is the same market on other timeframes until + something else is asked. +- `chart_shot` composites only the **visible** cells (`shotCells()` skips hidden hosts), so a capture + taken while a cell still fetches bars shows fewer panes than the grid has. Size is the tell: ~75 KB + one pane, ~167 KB two. +- The topbar's own **Layout** and **Sync** controls are the same `setLayout` call — never claim the + agent did something the operator's own picker cannot do. + +## What is actually on the chart + +`chart_state`'s `natives` list is **Vela's names only** — a script mounted from the Library (Run +PineTS / Add to chart) is not one of them, and it lives on the console's overlay/paint layer. A +natives-only report called a chart clean while CRT boxes and "Manipulation" labels sat on it (26 Sep). +Use `chart_studies`: one row per study, each labelled with the reader that saw it — `study` (the +console's own chip), `cell`, `overlay` (a Library run), `paint`, `native`. + +- `chart_remove_indicator(all=true)` (`trader-chart remove --all`) now reaches all of them: studies + through the chart's ledger, then the overlay/paint layer for script runs, and its answer names what + came off — `overlay cleared: 69/123/17 + 1 run(s)`. Verify with `chart_studies`, then `chart_shot`. +- Removing a **script by name** cannot be surgical: `ChartOverlay` is all-or-nothing. The door says so + instead of a bare "nothing removed"; the way out is `all` (or `clear`, which also wipes drawings). +- `chart_clear` removes our overlay + paint layer only, and reports what still remains. + +## The Indicators surface + +One modal in the chart's top bar (`⌗ Indicators`) holds both halves of "which indicator?":☆ +**Favourites**, **BUILT-INS** (Vela's natives for this market, read live from the frame — 76 on this +build) and **LIBRARY** (the 806-row LuxAlgo catalogue). `chart_indicators` is +the door: `section`, `q`, `family`, `reading`, `fold`, `star`/`unstar "native:supertrend"`/ +`"library:order-blocks"`, `mount "native:ema"`, `show=False` to close. Its answer carries the rows the +grid **painted**, the family groups it drew (name + count + folded) and the reading it left open — +quote those. + +### The catalogue is grouped, and every card has a reading (27 Sep) + +- `/api/catalogue` walks all nine pages (`sort=family`, **13.5 s cold, 42 ms warm**) plus the 853 + concepts, keeps the answer in `console/agents/catalogue.json` for 12 h, and hands the page ONE + payload. The paged loader is gone: a page of sixty cannot count a family it has not paged to, and + it could race a section change. Filtering now happens in memory, so `q` cannot race `section`. +- **Half the catalogue has no family of its own.** Those rows are the older single-name indicators + (`percent-b`, `1-2-3-reversal`); LuxAlgo files them as *concepts*, which carry a **family** AND a + **cluster**. Without the concept walk the rail opens with a 414-row "Unfiled"; with it, 390 of those + 414 land in real groups (Trend 108, Volume & Flow 96, Momentum 89, SMC / ICT 74, …, Unfiled 24). + Never present "Unfiled" as the catalogue's own opinion of those rows — it is ours. +- Picking a family re-groups the grid by that family's **clusters** ("Moving-average lineage", + "Candlestick catalog"); a cluster named "Other" is a remainder and is painted last. +- `reading: "mlma"` unfolds that card's own write-up (`row.description`, 806/806 rows have one) and + paints the card even if its group was beyond the slice; `fold: "trend"` folds a group away + (`fold: "trend/Other"`, `foldOn: false`), `fold: "trend", foldOn: true` opens it again. +- `bin/trader-chart indicators --family trend --reading mlma --fold trend:on` is the CLI spelling. + An omitted `--family` **clears** the filter (same rule as `--q`) — a filter left over from an earlier + call must not silently narrow the next one. +- A `