diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d63065b8..3ce92a5f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,31 +16,30 @@ jobs: gemfile: - test/gemfiles/rails_6_0.gemfile - test/gemfiles/rails_6_1.gemfile - - test/gemfiles/rails_7_0_sassc.gemfile - test/gemfiles/rails_7_0_dartsass.gemfile + - test/gemfiles/rails_7_1.gemfile + - test/gemfiles/rails_7_2.gemfile + - test/gemfiles/rails_8_0.gemfile + - test/gemfiles/rails_8_1.gemfile + # Propshaft + dartsass-rails + importmap-rails, the default stack of `rails new`. + - test/gemfiles/rails_8_1_propshaft.gemfile + exclude: + # Rails 7.2 requires Ruby 3.1+. + - { ruby_version: '2.7', gemfile: test/gemfiles/rails_7_2.gemfile } + - { ruby_version: '3.0', gemfile: test/gemfiles/rails_7_2.gemfile } + # Rails 8 requires Ruby 3.2+. + - { ruby_version: '2.7', gemfile: test/gemfiles/rails_8_0.gemfile } + - { ruby_version: '3.0', gemfile: test/gemfiles/rails_8_0.gemfile } + - { ruby_version: '3.1', gemfile: test/gemfiles/rails_8_0.gemfile } + - { ruby_version: '2.7', gemfile: test/gemfiles/rails_8_1.gemfile } + - { ruby_version: '3.0', gemfile: test/gemfiles/rails_8_1.gemfile } + - { ruby_version: '3.1', gemfile: test/gemfiles/rails_8_1.gemfile } + - { ruby_version: '2.7', gemfile: test/gemfiles/rails_8_1_propshaft.gemfile } + - { ruby_version: '3.0', gemfile: test/gemfiles/rails_8_1_propshaft.gemfile } + - { ruby_version: '3.1', gemfile: test/gemfiles/rails_8_1_propshaft.gemfile } include: - - ruby_version: '2.5' - gemfile: test/gemfiles/rails_4_2.gemfile - ruby_version: '2.6' - gemfile: test/gemfiles/rails_4_2.gemfile - - ruby_version: '2.5' - gemfile: test/gemfiles/rails_5_0.gemfile - - ruby_version: '2.6' - gemfile: test/gemfiles/rails_5_0.gemfile - - ruby_version: '2.7' - gemfile: test/gemfiles/rails_5_0.gemfile - - ruby_version: '2.5' - gemfile: test/gemfiles/rails_5_1.gemfile - - ruby_version: '2.6' - gemfile: test/gemfiles/rails_5_1.gemfile - - ruby_version: '2.7' - gemfile: test/gemfiles/rails_5_1.gemfile - - ruby_version: '2.5' - gemfile: test/gemfiles/rails_5_2.gemfile - - ruby_version: '2.6' - gemfile: test/gemfiles/rails_5_2.gemfile - - ruby_version: '2.7' - gemfile: test/gemfiles/rails_5_2.gemfile + gemfile: test/gemfiles/rails_6_0.gemfile runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 diff --git a/.github/workflows/update-bootstrap.yml b/.github/workflows/update-bootstrap.yml new file mode 100644 index 00000000..35544ced --- /dev/null +++ b/.github/workflows/update-bootstrap.yml @@ -0,0 +1,65 @@ +name: Update Bootstrap + +# Re-import the dist files from an upstream twbs/bootstrap release tag (or +# branch/commit). The gem tracks a fixed pre-release tag, so this no longer +# runs on a schedule: when a new Bootstrap 6 tag is published, dispatch it +# with that tag and bump the `default` below. If the tracked ref differs from +# what is checked in, the assets are re-imported, the version synced, the +# stylesheets verified to still compile, and the result committed. + +on: + workflow_dispatch: + inputs: + ref: + description: Upstream twbs/bootstrap tag (or branch/commit) to import + required: false + default: v6.0.0-alpha.1 + +permissions: + contents: write + +concurrency: + group: update-bootstrap + cancel-in-progress: false + +jobs: + update: + runs-on: ubuntu-latest + env: + BUNDLE_GEMFILE: ${{ github.workspace }}/test/gemfiles/rails_7_0_dartsass.gemfile + UPSTREAM_REF: ${{ github.event.inputs.ref || 'v6.0.0-alpha.1' }} + steps: + - uses: actions/checkout@v6 + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.4' + bundler-cache: true + + - name: Import Bootstrap and sync version + id: update + run: | + bundle exec rake update"[$UPSTREAM_REF]" + bundle exec rake sync_version"[$UPSTREAM_REF]" + # Only consider the update's own outputs, never stray CI artifacts. + if [ -n "$(git status --porcelain -- assets lib/bootstrap/version.rb)" ]; then + echo "changed=true" >> "$GITHUB_OUTPUT" + else + echo "changed=false" >> "$GITHUB_OUTPUT" + echo "Already up to date with twbs/bootstrap@${UPSTREAM_REF}." + fi + + - name: Verify the stylesheets still compile + if: steps.update.outputs.changed == 'true' + run: bundle exec rake debug + + - name: Commit and push + if: steps.update.outputs.changed == 'true' + run: | + sha=$(grep -oE "[0-9a-f]{40}" lib/bootstrap/version.rb | head -1) + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add -A -- assets lib/bootstrap/version.rb + git commit -m "Update Bootstrap to twbs/bootstrap@${UPSTREAM_REF} (${sha})" + git push diff --git a/.gitignore b/.gitignore index ec182536..7ed22e85 100644 --- a/.gitignore +++ b/.gitignore @@ -7,13 +7,15 @@ Gemfile.lock .rvmrc .rbenv-version -# Ignore bundler config -/.bundle +# Ignore bundler config (in the repo root and under test/gemfiles/*) +.bundle/ /vendor/cache /vendor/bundle tmp/ test/screenshots/ test/dummy_rails/log/*.log test/dummy_rails/public/assets/ +test/dummy_propshaft/log/*.log +test/dummy_propshaft/public/assets/ .DS_Store node_modules diff --git a/CHANGELOG.md b/CHANGELOG.md index b0d48127..e3f9d6b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,33 @@ The changelog only includes changes specific to the RubyGem. The Bootstrap framework changes can be found in [the Releases section of twbs/bootstrap](https://github.com/twbs/bootstrap/releases). Release announcement posts on [the official Bootstrap blog](http://blog.getbootstrap.com) contain summaries of the most noteworthy changes made in each release of Bootstrap. +# 6.0.0.alpha.1 + +First pre-release tracking Bootstrap 6 (upstream [`v6.0.0-alpha.1`](https://github.com/twbs/bootstrap/releases/tag/v6.0.0-alpha.1)). **This is an alpha; expect breaking changes.** + +* **Sass module system.** Bootstrap 6 replaced `@import` with `@use`/`@forward`. + Import Bootstrap with `@use "bootstrap"` and customize variables via + `@use "bootstrap" with (...)`. See the [v5→v6 migration guide](https://github.com/twbs/bootstrap/blob/v6.0.0-alpha.1/skills/bootstrap-v5-v6-migration/SKILL.md). +* **Dart Sass is required to compile the stylesheets.** LibSass/SassC + (`sassc-rails`) cannot compile the module system, so `sassc-rails` is no + longer a supported Sass engine. Use `dartsass-sprockets` (a drop-in + replacement), `dartsass-rails`, or `cssbundling-rails`. The minimum Ruby + version is now 2.6 (compiling the stylesheets with a Ruby-side engine + requires a recent Dart Sass, i.e. Ruby 3.1+). +* The standalone `bootstrap-grid`, `bootstrap-reboot`, and `bootstrap-utilities` + Sass entry points were removed upstream; only `bootstrap` remains. +* **JavaScript is now ES-module only.** Bootstrap 6 removed the UMD bundle and + the `window.bootstrap` global, so the `bootstrap-sprockets` Sprockets manifest + and the `globalThis` shim are gone. Load Bootstrap via importmaps (see the + README). +* **Popper replaced by [Floating UI](https://floating-ui.com/).** The `popper_js` + runtime dependency was removed. The self-contained `bootstrap.bundle.{js,min.js}` + builds inline both `@floating-ui/dom` and `vanilla-calendar-pro`, so a single + importmap pin works with no extra dependencies (the recommended path). For + lighter-weight pinning of the non-bundled `bootstrap.{js,min.js}` or individual + component modules, a self-contained ESM build of `@floating-ui/dom` is also + vendored as `floating-ui.js`. + # 5.3.4 * Autoprefixer is now optional. diff --git a/Gemfile b/Gemfile index 9f4cb9a3..a7fb19d7 100644 --- a/Gemfile +++ b/Gemfile @@ -3,7 +3,6 @@ source 'https://rubygems.org' gemspec group :development do - gem 'popper_js', '>= 1.12.3' gem 'dartsass-sprockets' end diff --git a/README.md b/README.md index 493a5c08..adbd32dc 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,18 @@ # Bootstrap Ruby Gem [](https://github.com/twbs/bootstrap-rubygem/actions/workflows/ci.yml) [](https://rubygems.org/gems/bootstrap) -[Bootstrap 5][bootstrap-home] ruby gem for Ruby on Rails (*Sprockets*/*Importmaps*) and Hanami (formerly Lotus). +[Bootstrap 6][bootstrap-home] ruby gem for Ruby on Rails (*Sprockets*/*Importmaps*) and Hanami (formerly Lotus). For Sass versions of Bootstrap 3 and 2 see [bootstrap-sass](https://github.com/twbs/bootstrap-sass) instead. +> **Bootstrap 6 (pre-release):** This is an alpha tracking the upstream +> [`v6.0.0-alpha.1`](https://github.com/twbs/bootstrap/releases/tag/v6.0.0-alpha.1) release. +> Bootstrap 6 moved its Sass to the [module system](https://sass-lang.com/documentation/at-rules/use) +> (`@use`/`@forward`), so its stylesheets require a **Dart Sass** engine to +> compile — LibSass/SassC (`sassc-rails`) cannot compile them and is no longer +> supported by this gem. Its JavaScript is ES-module only and is loaded via +> importmaps. See the [CHANGELOG](CHANGELOG.md). +> For the previous stable release, use `gem 'bootstrap', '~> 5.3.8'`. + **Ruby on Rails Note**: Newer releases of Rails have added additional ways for assets to be processed. The `twbs/bootstrap-rubygem` is for use with Importmaps or Sprockets, but not Webpack. @@ -21,14 +30,16 @@ Please see the appropriate guide for your environment of choice: Add `bootstrap` to your Gemfile: ```ruby -gem 'bootstrap', '~> 5.3.8' +gem 'bootstrap', '~> 6.0.0.alpha1' ``` -This gem requires a Sass engine, so make sure you have **one** of these gems in your Gemfile: -- [`dartsass-sprockets`](https://github.com/tablecheck/dartsass-sprockets): Dart Sass engine, recommended but only works for Ruby 2.6+ and Rails 5+ +This gem requires a Sass engine, so make sure you have **one** of these gems in your Gemfile. +Bootstrap 6 stylesheets use the Sass module system, so a **Dart Sass** engine is +required to compile them — `sassc-rails` (LibSass) cannot compile Bootstrap 6 and +is no longer supported; migrate to one of: +- [`dartsass-sprockets`](https://github.com/tablecheck/dartsass-sprockets): Dart Sass engine, recommended (a drop-in replacement for `sassc-rails`). Compiling Bootstrap 6 requires version 3.1+ and therefore Ruby 3.1+; older versions install on Ruby 2.6+ but bundle a Dart Sass too old for Bootstrap 6. - [`dartsass-rails`](https://github.com/rails/dartsass-rails): Dart Sass engine, recommended for Rails projects that use Propshaft -- [`cssbundling-rails`](https://github.com/rails/cssbundling-rails): External Sass engine -- [`sassc-rails`](https://github.com/sass/sassc-rails): SassC engine, deprecated but compatible with Ruby 2.3+ and Rails 4 +- [`cssbundling-rails`](https://github.com/rails/cssbundling-rails): External Sass engine, runs Dart Sass in Node so it works on any supported Ruby Also ensure that `sprockets-rails` is at least v2.3.2. @@ -37,14 +48,24 @@ If you are using Rails, add the `autoprefixer-rails` gem to your app and ensure `bundle install` and restart your server to make the files available through the pipeline. -Import Bootstrap styles in `app/assets/stylesheets/application.scss`: +Import Bootstrap styles in `app/assets/stylesheets/application.scss` with `@use` +(Bootstrap 6 no longer supports `@import`): + +```scss +@use "bootstrap"; +``` + +To customize Bootstrap's variables, configure them through the `@use ... with` +rule instead of setting globals before an `@import`: ```scss -// Custom bootstrap variables must be set or imported *before* bootstrap. -@import "bootstrap"; +@use "bootstrap" with ( + $primary: #c0ffee, + $enable-rounded: false +); ``` -The available variables can be found [here](assets/stylesheets/bootstrap/_variables.scss). +The available variables can be found in [`bootstrap/_config.scss`](assets/stylesheets/bootstrap/_config.scss). Make sure the file has `.scss` extension (or `.sass` for Sass syntax). If you have just generated a new Rails app, it may come with a `.css` file instead. If this file exists, it will be served instead of Sass, so rename it: @@ -53,57 +74,68 @@ it may come with a `.css` file instead. If this file exists, it will be served i $ mv app/assets/stylesheets/application.css app/assets/stylesheets/application.scss ``` -Then, remove all the `*= require` and `*= require_tree` statements from the Sass file. Instead, use `@import` to import Sass files. +Then, remove all the `*= require` and `*= require_tree` statements from the Sass file. Instead, use `@use` to import Sass files. Do not use `*= require` in Sass or your other stylesheets will not be able to access the Bootstrap mixins and variables. -Bootstrap JavaScript can optionally use jQuery. -If you're using Rails 5.1+, you can add the `jquery-rails` gem to your Gemfile: +### JavaScript -```ruby -gem 'jquery-rails' -``` +Bootstrap 6's JavaScript is **ES-module only** — there is no UMD bundle and no +`window.bootstrap` global, so the old Sprockets `//= require bootstrap-sprockets` +concatenation is gone. Load it through **importmaps** instead. -Bootstrap tooltips and popovers depend on [popper.js] for positioning. -The `bootstrap` gem already depends on the -[popper_js](https://github.com/glebm/popper_js-rubygem) gem. +Bootstrap 6 uses [Floating UI](https://floating-ui.com/) (`@floating-ui/dom`) +for positioning tooltips, popovers, and menus, replacing Popper. A self-contained +ESM build of `@floating-ui/dom` is **vendored in this gem** as `floating-ui.js`, +so you do not need an external dependency for it. #### Importmaps -You can pin either `bootstrap.js` or `bootstrap.min.js` in `config/importmap.rb` -as well as `popper.js`: +The simplest option is the self-contained **bundle** +(`bootstrap.bundle.min.js`), which inlines Floating UI and `vanilla-calendar-pro`, +so it needs no other pins. In `config/importmap.rb`: ```ruby -pin "bootstrap", to: "bootstrap.min.js", preload: true -pin "@popperjs/core", to: "popper.js", preload: true +pin "bootstrap", to: "bootstrap.bundle.min.js", preload: true ``` -Whichever files you pin will need to be added to `config.assets.precompile`: +Then import the components you need from your application's entrypoint: -```ruby -# config/initializers/assets.rb -Rails.application.config.assets.precompile += %w(bootstrap.min.js popper.js) +```js +// app/javascript/application.js +import { Tooltip } from "bootstrap" + +for (const el of document.querySelectorAll('[data-bs-toggle="tooltip"]')) { + new Tooltip(el) +} ``` -#### Sprockets +The data-attribute APIs (`data-bs-toggle`, etc.) work automatically once the +module is loaded. -Add Bootstrap dependencies and Bootstrap to your `application.js`: + +Lighter-weight pinning (without the bundle) -```js -//= require jquery3 -//= require popper -//= require bootstrap-sprockets +If you want to avoid the bundled Floating UI / Datepicker code, pin the +non-bundled `bootstrap.min.js` together with the gem's **vendored** +`@floating-ui/dom` build: + +```ruby +pin "bootstrap", to: "bootstrap.min.js", preload: true +pin "@floating-ui/dom", to: "floating-ui.js", preload: true ``` -While `bootstrap-sprockets` provides individual Bootstrap components -for ease of debugging, you may alternatively require -the concatenated `bootstrap` for faster compilation: +Individual components are also available as separate modules +(e.g. `pin "bootstrap/tooltip", to: "bootstrap/tooltip.js"`) for finer-grained +pinning. The [Datepicker](https://getbootstrap.com/) component additionally +depends on [`vanilla-calendar-pro`](https://www.npmjs.com/package/vanilla-calendar-pro), +which is **not** vendored — if you use it (or the non-bundled `bootstrap.min.js`, +which imports it), pin it from a CDN: -```js -//= require jquery3 -//= require popper -//= require bootstrap +```ruby +pin "vanilla-calendar-pro", to: "https://ga.jspm.io/npm:vanilla-calendar-pro@3.1.0/index.js" ``` + ### b. Other Ruby frameworks @@ -123,13 +155,11 @@ By default all of Bootstrap is imported. You can also import components explicitly. To start with a full list of modules copy [`_bootstrap.scss`](assets/stylesheets/_bootstrap.scss) file into your assets as `_bootstrap-custom.scss`. Then comment out components you do not want from `_bootstrap-custom`. -In the application Sass file, replace `@import 'bootstrap'` with: +In the application Sass file, replace `@use 'bootstrap'` with: ```scss -@import 'bootstrap-custom'; +@use 'bootstrap-custom'; ``` [bootstrap-home]: https://getbootstrap.com -[bootstrap-variables.scss]: https://github.com/twbs/bootstrap-rubygem/blob/master/templates/project/_bootstrap-variables.scss [autoprefixer]: https://github.com/ai/autoprefixer -[popper.js]: https://popper.js.org diff --git a/Rakefile b/Rakefile index 52402cce..29acc5a2 100644 --- a/Rakefile +++ b/Rakefile @@ -7,7 +7,11 @@ $:.unshift(lib_path) unless $:.include?(lib_path) require 'rake/testtask' Rake::TestTask.new do |t| t.libs << 'test' - t.test_files = FileList['test/**/*_test.rb'] + # Only one dummy Rails app can boot per process: the Propshaft one when the + # bundle has Propshaft (test/gemfiles/*_propshaft.gemfile), else the Sprockets one. + t.test_files = FileList['test/**/*_test.rb'].exclude( + Gem.loaded_specs.key?('propshaft') ? 'test/rails_test.rb' : 'test/propshaft_test.rb' + ) t.verbose = false t.warning = false end @@ -58,7 +62,8 @@ task :debug do require './lib/bootstrap' require 'term/ansicolor' path = Bootstrap.stylesheets_path - %w(_bootstrap _bootstrap-reboot _bootstrap-grid).each do |file| + # Bootstrap 6 exposes a single `bootstrap` entry point. + %w(_bootstrap).each do |file| filename = "#{path}/#{file}.scss" css = if defined?(SassC::Engine) SassC::Engine.new(File.read(filename), filename: filename, syntax: :scss).render @@ -71,12 +76,28 @@ task :debug do end end -desc 'Update bootstrap from upstream' +desc 'Update bootstrap from upstream (tag, branch or commit; default main)' task :update, :branch do |t, args| require './tasks/updater' Updater.new(branch: args[:branch]).update_bootstrap end +desc 'Update only bootstrap stylesheets from upstream tag/branch (leaves JS untouched)' +task :update_scss, :branch do |t, args| + require './tasks/updater' + Updater.new(branch: args[:branch], skip_js: true).update_bootstrap +end + +desc 'Sync the gem VERSION to the upstream Bootstrap package.json version' +task :sync_version, :branch do |t, args| + require './tasks/updater' + # npm prerelease versions (e.g. 6.0.0-alpha.1) map to RubyGems (6.0.0.alpha.1). + gem_version = Updater.new(branch: args[:branch]).upstream_version.sub('-', '.') + path = 'lib/bootstrap/version.rb' + File.write(path, File.read(path).sub(/VERSION\s*=\s*'[^']*'/, "VERSION = '#{gem_version}'")) + $stderr.puts "VERSION set to #{gem_version}" +end + desc 'Start a dummy Rails app server' task :rails_server do require 'rack' diff --git a/assets/javascripts/bootstrap-global-this-define.js b/assets/javascripts/bootstrap-global-this-define.js deleted file mode 100644 index f3a3cc13..00000000 --- a/assets/javascripts/bootstrap-global-this-define.js +++ /dev/null @@ -1,6 +0,0 @@ -// Set a `globalThis` so that bootstrap components are defined on window.bootstrap instead of window. -window['bootstrap'] = { - "@popperjs/core": window.Popper, - _originalGlobalThis: window['globalThis'] -}; -window['globalThis'] = window['bootstrap']; diff --git a/assets/javascripts/bootstrap-global-this-undefine.js b/assets/javascripts/bootstrap-global-this-undefine.js deleted file mode 100644 index 6f96eb1d..00000000 --- a/assets/javascripts/bootstrap-global-this-undefine.js +++ /dev/null @@ -1,2 +0,0 @@ -window['globalThis'] = window['bootstrap']._originalGlobalThis; -window['bootstrap']._originalGlobalThis = null; diff --git a/assets/javascripts/bootstrap-sprockets.js b/assets/javascripts/bootstrap-sprockets.js deleted file mode 100644 index 8235e211..00000000 --- a/assets/javascripts/bootstrap-sprockets.js +++ /dev/null @@ -1,28 +0,0 @@ -//= require ./bootstrap-global-this-define -//= require ./bootstrap/dom/data -//= require ./bootstrap/util/index -//= require ./bootstrap/dom/event-handler -//= require ./bootstrap/dom/manipulator -//= require ./bootstrap/util/config -//= require ./bootstrap/base-component -//= require ./bootstrap/util/sanitizer -//= require ./bootstrap/dom/selector-engine -//= require ./bootstrap/util/template-factory -//= require ./bootstrap/tooltip -//= require ./bootstrap/popover -//= require ./bootstrap/util/component-functions -//= require ./bootstrap/alert -//= require ./bootstrap/toast -//= require ./bootstrap/button -//= require ./bootstrap/collapse -//= require ./bootstrap/util/scrollbar -//= require ./bootstrap/tab -//= require ./bootstrap/util/focustrap -//= require ./bootstrap/util/backdrop -//= require ./bootstrap/scrollspy -//= require ./bootstrap/modal -//= require ./bootstrap/offcanvas -//= require ./bootstrap/util/swipe -//= require ./bootstrap/carousel -//= require ./bootstrap/dropdown -//= require ./bootstrap-global-this-undefine diff --git a/assets/javascripts/bootstrap.bundle.js b/assets/javascripts/bootstrap.bundle.js new file mode 100644 index 00000000..b41a6a1b --- /dev/null +++ b/assets/javascripts/bootstrap.bundle.js @@ -0,0 +1,8763 @@ +/*! +* Bootstrap v6.0.0-alpha.1 (https://getbootstrap.com/) +* Copyright 2011-2026 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) +* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) +*/ +//#region js/src/dom/data.ts +/** +* -------------------------------------------------------------------------- +* Bootstrap dom/data.ts +* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) +* -------------------------------------------------------------------------- +*/ +/** +* Constants +*/ +const elementMap = /* @__PURE__ */ new Map(); +var data_default = { + set(element, key, instance) { + if (!elementMap.has(element)) elementMap.set(element, /* @__PURE__ */ new Map()); + const instanceMap = elementMap.get(element); + if (!instanceMap.has(key) && instanceMap.size !== 0) { + console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${[...instanceMap.keys()][0]}.`); + return; + } + instanceMap.set(key, instance); + }, + get(element, key) { + if (element && elementMap.has(element)) return elementMap.get(element).get(key) || null; + return null; + }, + getAny(element) { + if (element && elementMap.has(element)) return elementMap.get(element).values().next().value || null; + return null; + }, + remove(element, key) { + if (!elementMap.has(element)) return; + const instanceMap = elementMap.get(element); + instanceMap.delete(key); + if (instanceMap.size === 0) elementMap.delete(element); + } +}; +//#endregion +//#region js/src/dom/event-handler.ts +/** +* Constants +*/ +const namespaceRegex = /[^.]*(?=\..*)\.|.*/; +const stripNameRegex = /\..*/; +const stripUidRegex = /::\d+$/; +const eventRegistry = {}; +let uidEvent = 1; +const customEvents = { + mouseenter: "mouseover", + mouseleave: "mouseout" +}; +const nativeEvents = /* @__PURE__ */ new Set([ + "click", + "dblclick", + "mouseup", + "mousedown", + "contextmenu", + "mousewheel", + "DOMMouseScroll", + "mouseover", + "mouseout", + "mousemove", + "selectstart", + "selectend", + "keydown", + "keypress", + "keyup", + "input", + "paste", + "orientationchange", + "touchstart", + "touchmove", + "touchend", + "touchcancel", + "pointerdown", + "pointermove", + "pointerup", + "pointerleave", + "pointercancel", + "gesturestart", + "gesturechange", + "gestureend", + "focus", + "blur", + "change", + "reset", + "select", + "submit", + "focusin", + "focusout", + "load", + "unload", + "beforeunload", + "resize", + "move", + "DOMContentLoaded", + "readystatechange", + "error", + "abort", + "scroll", + "scrollend" +]); +/** +* Private methods +*/ +function makeEventUid(element, uid) { + return uid && `${uid}::${uidEvent++}` || element.uidEvent || uidEvent++; +} +function getElementEvents(element) { + const uid = makeEventUid(element); + element.uidEvent = uid; + eventRegistry[uid] = eventRegistry[uid] || {}; + return eventRegistry[uid]; +} +function isMouseEventWithinTarget(event) { + const { delegateTarget, relatedTarget } = event; + return Boolean(relatedTarget && delegateTarget.contains(relatedTarget)); +} +function bootstrapHandler(element, fn, handlerTypeEvent) { + const isCustomMouseEvent = handlerTypeEvent in customEvents; + return function handler(event) { + const bootstrapEvent = hydrateObj(event, { delegateTarget: element }); + if (isCustomMouseEvent && isMouseEventWithinTarget(bootstrapEvent)) return; + if (handler.oneOff) EventHandler.off(element, handlerTypeEvent, fn); + return fn.apply(element, [bootstrapEvent]); + }; +} +function bootstrapDelegationHandler(element, selector, fn, handlerTypeEvent) { + const isCustomMouseEvent = handlerTypeEvent in customEvents; + return function handler(event) { + const domElements = element.querySelectorAll(selector); + for (let { target } = event; target && target !== this; target = target.parentNode) for (const domElement of domElements) { + if (domElement !== target) continue; + const bootstrapEvent = hydrateObj(event, { delegateTarget: target }); + if (isCustomMouseEvent && isMouseEventWithinTarget(bootstrapEvent)) return; + if (handler.oneOff) EventHandler.off(element, handlerTypeEvent, selector, fn); + return fn.apply(target, [bootstrapEvent]); + } + }; +} +function findHandler(events, callable, handlerTypeEvent, delegationSelector = null) { + return Object.values(events).find((event) => event.callable === callable && event.handlerTypeEvent === handlerTypeEvent && event.delegationSelector === delegationSelector); +} +function normalizeParameters(originalTypeEvent, handler, delegationFunction) { + const isDelegated = typeof handler === "string"; + const callable = isDelegated ? delegationFunction : handler || delegationFunction; + const baseTypeEvent = originalTypeEvent.replace(stripNameRegex, ""); + let typeEvent = customEvents[baseTypeEvent] || baseTypeEvent; + if (!nativeEvents.has(typeEvent)) typeEvent = originalTypeEvent; + const handlerTypeEvent = baseTypeEvent in customEvents ? baseTypeEvent : typeEvent; + return { + isDelegated, + callable, + typeEvent, + handlerTypeEvent + }; +} +function addHandler(element, originalTypeEvent, handler, delegationFunction, oneOff) { + if (typeof originalTypeEvent !== "string" || !element) return; + const { isDelegated, callable, typeEvent, handlerTypeEvent } = normalizeParameters(originalTypeEvent, handler, delegationFunction); + const events = getElementEvents(element); + const handlers = events[typeEvent] || (events[typeEvent] = {}); + const previousFunction = findHandler(handlers, callable, handlerTypeEvent, isDelegated ? handler : null); + if (previousFunction) { + previousFunction.oneOff = previousFunction.oneOff && oneOff; + return; + } + const uid = makeEventUid(callable, originalTypeEvent.replace(namespaceRegex, "")); + const fn = isDelegated ? bootstrapDelegationHandler(element, handler, callable, handlerTypeEvent) : bootstrapHandler(element, callable, handlerTypeEvent); + fn.delegationSelector = isDelegated ? handler : null; + fn.callable = callable; + fn.handlerTypeEvent = handlerTypeEvent; + fn.oneOff = oneOff; + fn.uidEvent = uid; + handlers[uid] = fn; + element.addEventListener(typeEvent, fn, isDelegated); +} +function removeHandler(element, events, typeEvent, handler) { + element.removeEventListener(typeEvent, handler, Boolean(handler.delegationSelector)); + delete events[typeEvent][handler.uidEvent]; +} +function removeNamespacedHandlers(element, events, typeEvent, namespace) { + const storeElementEvent = events[typeEvent] || {}; + for (const [handlerKey, event] of Object.entries(storeElementEvent)) if (handlerKey.includes(namespace)) removeHandler(element, events, typeEvent, event); +} +function trigger(element, event, args) { + if (typeof event !== "string" || !element) return null; + const evt = hydrateObj(new Event(event, { + bubbles: true, + cancelable: true + }), args); + element.dispatchEvent(evt); + return evt; +} +const EventHandler = { + on(element, event, handler, delegationFunction) { + addHandler(element, event, handler, delegationFunction, false); + }, + one(element, event, handler, delegationFunction) { + addHandler(element, event, handler, delegationFunction, true); + }, + off(element, originalTypeEvent, handler, delegationFunction) { + if (typeof originalTypeEvent !== "string" || !element) return; + const { isDelegated, callable, typeEvent, handlerTypeEvent } = normalizeParameters(originalTypeEvent, handler, delegationFunction); + const inNamespace = typeEvent !== originalTypeEvent && handlerTypeEvent !== originalTypeEvent; + const events = getElementEvents(element); + const storeElementEvent = events[typeEvent] || {}; + const isNamespace = originalTypeEvent.startsWith("."); + if (typeof callable !== "undefined") { + if (!Object.keys(storeElementEvent).length) return; + const fn = findHandler(storeElementEvent, callable, handlerTypeEvent, isDelegated ? handler : null); + if (fn) removeHandler(element, events, typeEvent, fn); + return; + } + if (isNamespace) for (const elementEvent of Object.keys(events)) removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.slice(1)); + for (const [keyHandlers, event] of Object.entries(storeElementEvent)) { + const handlerKey = keyHandlers.replace(stripUidRegex, ""); + if (event.handlerTypeEvent === handlerTypeEvent && (!inNamespace || originalTypeEvent.includes(handlerKey))) removeHandler(element, events, typeEvent, event); + } + }, + trigger +}; +function hydrateObj(obj, meta = {}) { + for (const [key, value] of Object.entries(meta)) try { + obj[key] = value; + } catch { + Object.defineProperty(obj, key, { + configurable: true, + get() { + return value; + } + }); + } + return obj; +} +//#endregion +//#region js/src/dom/manipulator.ts +/** +* -------------------------------------------------------------------------- +* Bootstrap dom/manipulator.ts +* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) +* -------------------------------------------------------------------------- +*/ +function normalizeData(value) { + if (value === "true") return true; + if (value === "false") return false; + if (value === Number(value).toString()) return Number(value); + if (value === "" || value === "null") return null; + if (typeof value !== "string") return value; + try { + return JSON.parse(decodeURIComponent(value)); + } catch { + return value; + } +} +function normalizeDataKey(key) { + return key.replace(/[A-Z]/g, (chr) => `-${chr.toLowerCase()}`); +} +const Manipulator = { + setDataAttribute(element, key, value) { + element.setAttribute(`data-bs-${normalizeDataKey(key)}`, value); + }, + removeDataAttribute(element, key) { + element.removeAttribute(`data-bs-${normalizeDataKey(key)}`); + }, + getDataAttributes(element) { + if (!element) return {}; + const attributes = {}; + const bsKeys = Object.keys(element.dataset).filter((key) => key.startsWith("bs") && !key.startsWith("bsConfig")); + for (const key of bsKeys) { + let pureKey = key.replace(/^bs/, ""); + pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1); + attributes[pureKey] = normalizeData(element.dataset[key]); + } + return attributes; + }, + getDataAttribute(element, key) { + return normalizeData(element.getAttribute(`data-bs-${normalizeDataKey(key)}`)); + } +}; +//#endregion +//#region js/src/util/index.ts +/** +* -------------------------------------------------------------------------- +* Bootstrap util/index.ts +* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) +* -------------------------------------------------------------------------- +*/ +const MAX_UID = 1e6; +const MILLISECONDS_MULTIPLIER = 1e3; +const TRANSITION_END = "transitionend"; +/** +* Properly escapes ID selectors to handle special characters in IDs +* (e.g. forward slashes, periods) so that they work with `document.querySelector`. +* +* @param selector - The selector to escape +* @returns The escaped selector +*/ +const parseSelector = (selector) => { + if (selector && window.CSS && window.CSS.escape) selector = selector.replace(/#([^\s"#']+)/g, (match, id) => `#${CSS.escape(id)}`); + return selector; +}; +const toType = (object) => { + if (object === null || object === void 0) return `${object}`; + return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase(); +}; +/** +* Public Util API +*/ +const getUID = (prefix) => { + do + prefix += Math.floor(Math.random() * MAX_UID); + while (document.getElementById(prefix)); + return prefix; +}; +const getTransitionDurationFromElement = (element) => { + if (!element) return 0; + let { transitionDuration, transitionDelay } = window.getComputedStyle(element); + if (!Number.parseFloat(transitionDuration) && !Number.parseFloat(transitionDelay)) return 0; + transitionDuration = transitionDuration.split(",")[0]; + transitionDelay = transitionDelay.split(",")[0]; + return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER; +}; +const triggerTransitionEnd = (element) => { + element.dispatchEvent(new Event(TRANSITION_END)); +}; +const isElement$1 = (object) => { + if (!object || typeof object !== "object") return false; + return typeof object.nodeType !== "undefined"; +}; +const getElement = (object) => { + if (isElement$1(object)) return object; + if (typeof object === "string" && object.length > 0) return document.querySelector(parseSelector(object)); + return null; +}; +const isVisible = (element) => { + if (!isElement$1(element) || element.getClientRects().length === 0) return false; + const elementIsVisible = getComputedStyle(element).getPropertyValue("visibility") === "visible"; + const closedDetails = element.closest("details:not([open])"); + if (!closedDetails) return elementIsVisible; + if (closedDetails !== element) { + const summary = element.closest("summary"); + if (summary && summary.parentNode !== closedDetails) return false; + if (summary === null) return false; + } + return elementIsVisible; +}; +const isDisabled = (element) => { + if (!element || element.nodeType !== Node.ELEMENT_NODE) return true; + if (element.classList.contains("disabled")) return true; + const disableableElement = element; + if (typeof disableableElement.disabled !== "undefined") return disableableElement.disabled; + return element.hasAttribute("disabled") && element.getAttribute("disabled") !== "false"; +}; +const setAriaAttribute = (element, name, value) => { + element.setAttribute(name, String(value)); +}; +const findShadowRoot = (element) => { + if (!document.documentElement.attachShadow) return null; + if (typeof element.getRootNode === "function") { + const root = element.getRootNode(); + return root instanceof ShadowRoot ? root : null; + } + if (element instanceof ShadowRoot) return element; + if (!element.parentNode) return null; + return findShadowRoot(element.parentNode); +}; +const noop = () => {}; +const isRTL$1 = () => document.documentElement.dir === "rtl"; +const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => { + return typeof possibleCallback === "function" ? possibleCallback.call(...args) : defaultValue; +}; +const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => { + if (!waitForTransition) { + execute(callback); + return; + } + const emulatedDuration = getTransitionDurationFromElement(transitionElement) + 5; + let called = false; + const handler = ({ target }) => { + if (target !== transitionElement) return; + called = true; + transitionElement.removeEventListener(TRANSITION_END, handler); + execute(callback); + }; + transitionElement.addEventListener(TRANSITION_END, handler); + setTimeout(() => { + if (!called) triggerTransitionEnd(transitionElement); + }, emulatedDuration); +}; +/** +* Return the previous/next element of a list. +* +* @param list - The list of elements to traverse +* @param activeElement - The currently active element +* @param shouldGetNext - Whether to return the next element (`true`) or the previous one (`false`) +* @param isCycleAllowed - Whether to cycle back to the opposite end of the list when reaching the boundary +* @returns The appropriate previous/next element from the list +*/ +const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => { + const listLength = list.length; + let index = list.indexOf(activeElement); + if (index === -1) return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0]; + index += shouldGetNext ? 1 : -1; + if (isCycleAllowed) index = (index + listLength) % listLength; + return list[Math.max(0, Math.min(index, listLength - 1))]; +}; +//#endregion +//#region js/src/util/config.ts +/** +* -------------------------------------------------------------------------- +* Bootstrap util/config.ts +* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) +* -------------------------------------------------------------------------- +*/ +/** +* Class definition +*/ +var Config = class { + static get Default() { + return {}; + } + static get DefaultType() { + return {}; + } + static get NAME() { + throw new Error("You have to implement the static method \"NAME\", for each component!"); + } + _getConfig(config) { + config = this._mergeConfigObj(config); + config = this._configAfterMerge(config); + this._typeCheckConfig(config); + return config; + } + _configAfterMerge(config) { + return config; + } + _mergeConfigObj(config, element) { + const jsonConfig = isElement$1(element) ? Manipulator.getDataAttribute(element, "config") : {}; + return { + ...this.constructor.Default, + ...typeof jsonConfig === "object" ? jsonConfig : {}, + ...isElement$1(element) ? Manipulator.getDataAttributes(element) : {}, + ...typeof config === "object" ? config : {} + }; + } + _typeCheckConfig(config, configTypes = this.constructor.DefaultType) { + for (const [property, expectedTypes] of Object.entries(configTypes)) { + const value = config[property]; + const valueType = isElement$1(value) ? "element" : toType(value); + if (!new RegExp(expectedTypes).test(valueType)) throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`); + } + } +}; +//#endregion +//#region js/src/base-component.ts +/** +* -------------------------------------------------------------------------- +* Bootstrap base-component.ts +* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) +* -------------------------------------------------------------------------- +*/ +/** +* Constants +*/ +const VERSION = "6.0.0-alpha.1"; +/** +* Class definition +*/ +var BaseComponent = class extends Config { + constructor(element, config) { + super(); + element = getElement(element); + if (!element) return; + this._element = element; + this._config = this._getConfig(config); + const existingInstance = data_default.get(this._element, this.constructor.DATA_KEY); + if (existingInstance) existingInstance.dispose(); + data_default.set(this._element, this.constructor.DATA_KEY, this); + } + dispose() { + data_default.remove(this._element, this.constructor.DATA_KEY); + EventHandler.off(this._element, this.constructor.EVENT_KEY); + for (const propertyName of Object.getOwnPropertyNames(this)) this[propertyName] = null; + } + _queueCallback(callback, element, isAnimated = true) { + return new Promise((resolve) => { + executeAfterTransition(() => { + if (this._element) callback(); + resolve(); + }, element, isAnimated); + }); + } + _getConfig(config) { + config = this._mergeConfigObj(config, this._element); + config = this._configAfterMerge(config); + this._typeCheckConfig(config); + return config; + } + static getInstance(element) { + return data_default.get(getElement(element), this.DATA_KEY); + } + static getOrCreateInstance(element, config = {}) { + return this.getInstance(element) || new this(element, typeof config === "object" ? config : null); + } + static get VERSION() { + return VERSION; + } + static get DATA_KEY() { + return `bs.${this.NAME}`; + } + static get EVENT_KEY() { + return `.${this.DATA_KEY}`; + } + static eventName(name) { + return `${name}${this.EVENT_KEY}`; + } +}; +//#endregion +//#region js/src/dom/selector-engine.ts +/** +* -------------------------------------------------------------------------- +* Bootstrap dom/selector-engine.ts +* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) +* -------------------------------------------------------------------------- +*/ +const getSelector = (element) => { + let selector = element.getAttribute("data-bs-target"); + if (!selector || selector === "#") { + let hrefAttribute = element.getAttribute("href"); + if (!hrefAttribute || !hrefAttribute.includes("#") && !hrefAttribute.startsWith(".")) return null; + if (hrefAttribute.includes("#") && !hrefAttribute.startsWith("#")) hrefAttribute = `#${hrefAttribute.split("#")[1]}`; + selector = hrefAttribute && hrefAttribute !== "#" ? hrefAttribute.trim() : null; + } + return selector ? selector.split(",").map((sel) => parseSelector(sel)).join(",") : null; +}; +const SelectorEngine = { + find(selector, element = document.documentElement) { + return [...Element.prototype.querySelectorAll.call(element, selector)]; + }, + findOne(selector, element = document.documentElement) { + return Element.prototype.querySelector.call(element, selector); + }, + parents(element, selector) { + const parents = []; + let ancestor = element.parentNode.closest(selector); + while (ancestor) { + parents.push(ancestor); + ancestor = ancestor.parentNode.closest(selector); + } + return parents; + }, + closest(element, selector) { + return Element.prototype.closest.call(element, selector); + }, + prev(element, selector) { + let previous = element.previousElementSibling; + while (previous) { + if (previous.matches(selector)) return [previous]; + previous = previous.previousElementSibling; + } + return []; + }, + next(element, selector) { + let next = element.nextElementSibling; + while (next) { + if (next.matches(selector)) return [next]; + next = next.nextElementSibling; + } + return []; + }, + getSelectorFromElement(element) { + const selector = getSelector(element); + if (selector) return SelectorEngine.findOne(selector) ? selector : null; + return null; + }, + getElementFromSelector(element) { + const selector = getSelector(element); + return selector ? SelectorEngine.findOne(selector) : null; + }, + getMultipleElementsFromSelector(element) { + const selector = getSelector(element); + return selector ? SelectorEngine.find(selector) : []; + } +}; +//#endregion +//#region js/src/util/component-functions.ts +const enableDismissTrigger = (component, method = "hide") => { + const clickEvent = `click.dismiss${component.EVENT_KEY}`; + const name = component.NAME; + EventHandler.on(document, clickEvent, `[data-bs-dismiss="${name}"]`, function(event) { + if (["A", "AREA"].includes(this.tagName)) event.preventDefault(); + if (isDisabled(this)) return; + const target = SelectorEngine.getElementFromSelector(this) || this.closest(`.${name}, [class*=":${name}"]`); + component.getOrCreateInstance(target)[method](); + }); +}; +const eventActionOnPlugin = (Plugin, onEvent, stringSelector, method, callback = null) => { + eventAction(`${onEvent}.${Plugin.NAME}`, stringSelector, (data) => { + const instances = data.targets.filter(Boolean).map((element) => Plugin.getOrCreateInstance(element)); + if (typeof callback === "function") callback({ + ...data, + instances + }); + for (const instance of instances) instance[method](); + }); +}; +const eventAction = (onEvent, stringSelector, callback) => { + const selector = `${stringSelector}:not(.disabled):not(:disabled)`; + EventHandler.on(document, onEvent, selector, function(event) { + if (["A", "AREA"].includes(this.tagName)) event.preventDefault(); + const selector = SelectorEngine.getSelectorFromElement(this); + callback({ + targets: selector ? SelectorEngine.find(selector) : [this], + event + }); + }); +}; +//#endregion +//#region js/src/alert.ts +/** +* -------------------------------------------------------------------------- +* Bootstrap alert.ts +* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) +* -------------------------------------------------------------------------- +*/ +/** +* Constants +*/ +const NAME$21 = "alert"; +const EVENT_KEY$18 = `.bs.alert`; +const EVENT_CLOSE = `close${EVENT_KEY$18}`; +const EVENT_CLOSED = `closed${EVENT_KEY$18}`; +const CLASS_NAME_HIDING = "hiding"; +const CLASS_NAME_SHOW$7 = "show"; +/** +* Class definition +*/ +var Alert = class extends BaseComponent { + static get NAME() { + return NAME$21; + } + async close() { + if (EventHandler.trigger(this._element, EVENT_CLOSE).defaultPrevented) return; + this._element.classList.remove(CLASS_NAME_SHOW$7); + this._element.classList.add(CLASS_NAME_HIDING); + const isAnimated = getTransitionDurationFromElement(this._element) > 0; + await this._queueCallback(() => this._destroyElement(), this._element, isAnimated); + } + _destroyElement() { + this._element.remove(); + EventHandler.trigger(this._element, EVENT_CLOSED); + this.dispose(); + } +}; +/** +* Data API implementation +*/ +enableDismissTrigger(Alert, "close"); +//#endregion +//#region js/src/button.ts +/** +* -------------------------------------------------------------------------- +* Bootstrap button.ts +* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) +* -------------------------------------------------------------------------- +*/ +/** +* Constants +*/ +const NAME$20 = "button"; +const EVENT_KEY$17 = `.bs.button`; +const DATA_API_KEY$12 = ".data-api"; +const CLASS_NAME_ACTIVE$4 = "active"; +const SELECTOR_DATA_TOGGLE$10 = "[data-bs-toggle=\"button\"]"; +const EVENT_CLICK_DATA_API$8 = `click${EVENT_KEY$17}${DATA_API_KEY$12}`; +const EVENT_DOM_CONTENT_LOADED$1 = `DOMContentLoaded${EVENT_KEY$17}${DATA_API_KEY$12}`; +/** +* Class definition +*/ +var Button = class extends BaseComponent { + static get NAME() { + return NAME$20; + } + toggle() { + setAriaAttribute(this._element, "aria-pressed", this._element.classList.toggle(CLASS_NAME_ACTIVE$4)); + } +}; +/** +* Data API implementation +*/ +EventHandler.on(document, EVENT_CLICK_DATA_API$8, SELECTOR_DATA_TOGGLE$10, (event) => { + event.preventDefault(); + const button = event.target.closest(SELECTOR_DATA_TOGGLE$10); + Button.getOrCreateInstance(button).toggle(); +}); +EventHandler.on(document, EVENT_DOM_CONTENT_LOADED$1, () => { + for (const element of SelectorEngine.find(SELECTOR_DATA_TOGGLE$10)) if (!element.hasAttribute("aria-pressed")) setAriaAttribute(element, "aria-pressed", element.classList.contains(CLASS_NAME_ACTIVE$4)); +}); +//#endregion +//#region js/src/carousel.ts +/** +* -------------------------------------------------------------------------- +* Bootstrap carousel.ts +* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) +* -------------------------------------------------------------------------- +*/ +/** +* Constants +*/ +const NAME$19 = "carousel"; +const EVENT_KEY$16 = `.bs.carousel`; +const DATA_API_KEY$11 = ".data-api"; +const ARROW_LEFT_KEY$2 = "ArrowLeft"; +const ARROW_RIGHT_KEY$2 = "ArrowRight"; +const DIRECTION_LEFT = "left"; +const DIRECTION_RIGHT = "right"; +const EVENT_SLIDE = `slide${EVENT_KEY$16}`; +const EVENT_SLID = `slid${EVENT_KEY$16}`; +const EVENT_KEYDOWN$2 = `keydown${EVENT_KEY$16}`; +const EVENT_MOUSEENTER$2 = `mouseenter${EVENT_KEY$16}`; +const EVENT_MOUSELEAVE$1 = `mouseleave${EVENT_KEY$16}`; +const EVENT_POINTERDOWN$3 = `pointerdown${EVENT_KEY$16}`; +const EVENT_LOAD_DATA_API$3 = `load${EVENT_KEY$16}${DATA_API_KEY$11}`; +const EVENT_CLICK_DATA_API$7 = `click${EVENT_KEY$16}${DATA_API_KEY$11}`; +const CLASS_NAME_CAROUSEL = "carousel"; +const CLASS_NAME_ACTIVE$3 = "active"; +const CLASS_NAME_FADE = "carousel-fade"; +const CLASS_NAME_CENTER = "carousel-center"; +const CLASS_NAME_AUTO = "carousel-auto"; +const CLASS_NAME_CLONE = "carousel-item-clone"; +const CLASS_NAME_PAUSED = "paused"; +const CLASS_NAME_PLAYING = "carousel-playing"; +const PROPERTY_INTERVAL = "--bs-carousel-interval"; +const SCROLL_DURATION = 300; +const ACTIVE_RATIO_TOLERANCE = .05; +const SELECTOR_ACTIVE = ".active"; +const SELECTOR_ITEM = `.carousel-item:not(.${CLASS_NAME_CLONE})`; +const SELECTOR_ACTIVE_ITEM = SELECTOR_ACTIVE + SELECTOR_ITEM; +const SELECTOR_INNER$1 = ".carousel-inner"; +const SELECTOR_INDICATORS = ".carousel-indicators"; +const SELECTOR_PLAY_PAUSE = ".carousel-control-play-pause"; +const SELECTOR_DATA_SLIDE = "[data-bs-slide], [data-bs-slide-to]"; +const SELECTOR_DATA_SLIDE_PREV = "[data-bs-slide=\"prev\"]"; +const SELECTOR_DATA_SLIDE_NEXT = "[data-bs-slide=\"next\"]"; +const SELECTOR_DATA_AUTOPLAY = "[data-bs-autoplay=\"true\"]"; +const KEY_TO_DIRECTION = { + [ARROW_LEFT_KEY$2]: DIRECTION_RIGHT, + [ARROW_RIGHT_KEY$2]: DIRECTION_LEFT +}; +const ENDS_STOP = "stop"; +const ENDS_WRAP = "wrap"; +const ENDS_LOOP = "loop"; +const Default$18 = { + autoplay: false, + ends: ENDS_LOOP, + interval: 5e3, + keyboard: true, + pause: "hover" +}; +const DefaultType$18 = { + autoplay: "boolean", + ends: "string", + interval: "number", + keyboard: "boolean", + pause: "(string|boolean)" +}; +const easeInOutCubic = (progress) => progress < .5 ? 4 * progress * progress * progress : 1 - (-2 * progress + 2) ** 3 / 2; +/** +* Class definition +*/ +var Carousel = class extends BaseComponent { + constructor(element, config) { + super(element, config); + this._viewport = SelectorEngine.findOne(SELECTOR_INNER$1, this._element) || this._element; + this._indicatorsElement = SelectorEngine.findOne(SELECTOR_INDICATORS, this._element); + this._playPauseElement = SelectorEngine.findOne(SELECTOR_PLAY_PAUSE, this._element); + this._prevControls = SelectorEngine.find(SELECTOR_DATA_SLIDE_PREV, this._element); + this._nextControls = SelectorEngine.find(SELECTOR_DATA_SLIDE_NEXT, this._element); + this._interval = null; + this._observer = null; + this._scrollFrame = null; + this._looping = false; + this._visibility = /* @__PURE__ */ new Map(); + this._playing = this._config.autoplay; + this._activeIndex = this._initialActiveIndex(); + this._addEventListeners(); + this._observeItems(); + this._refreshActiveState(); + if (this._playing) this.cycle(); + this._updatePlayPauseControl(); + } + static get Default() { + return Default$18; + } + static get DefaultType() { + return DefaultType$18; + } + static get NAME() { + return NAME$19; + } + next() { + this.to(this._navIndex() + 1); + } + nextWhenVisible() { + if (document.visibilityState === "visible" && isVisible(this._element)) this.next(); + } + prev() { + this.to(this._navIndex() - 1); + } + pause() { + this._clearInterval(); + this._element.classList.remove(CLASS_NAME_PLAYING); + } + cycle() { + this._clearInterval(); + this._scheduleAutoplay(); + this._element.classList.add(CLASS_NAME_PLAYING); + } + to(index) { + if (this._looping) return; + const items = this._getItems(); + const rawIndex = Number.parseInt(index, 10); + if (this._config.ends === ENDS_LOOP && !this._prefersReducedMotion() && this._canLoop()) { + if (rawIndex > items.length - 1) { + this._loopTransition(true); + return; + } + if (rawIndex < 0) { + this._loopTransition(false); + return; + } + } + const targetIndex = this._normalizeIndex(rawIndex, items.length); + const currentIndex = this._navIndex(); + if (targetIndex === null || targetIndex === currentIndex) return; + if (EventHandler.trigger(this._element, EVENT_SLIDE, { + relatedTarget: items[targetIndex], + direction: this._direction(currentIndex, targetIndex), + from: currentIndex, + to: targetIndex + }).defaultPrevented) return; + if (this._isFade()) { + this._fadeTo(targetIndex); + return; + } + this._scrollToIndex(targetIndex); + } + dispose() { + this._clearInterval(); + if (this._observer) this._observer.disconnect(); + if (this._scrollFrame !== null) cancelAnimationFrame(this._scrollFrame); + for (const clone of SelectorEngine.find(`.${CLASS_NAME_CLONE}`, this._viewport)) clone.remove(); + this._viewport.style.scrollSnapType = ""; + EventHandler.off(this._viewport, EVENT_KEY$16); + super.dispose(); + } + _configAfterMerge(config) { + if (![ + ENDS_STOP, + ENDS_WRAP, + ENDS_LOOP + ].includes(config.ends)) config.ends = Default$18.ends; + return config; + } + _initialActiveIndex() { + const active = SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element); + const index = active ? this._getItems().indexOf(active) : 0; + return Math.max(index, 0); + } + _addEventListeners() { + if (this._config.keyboard) EventHandler.on(this._element, EVENT_KEYDOWN$2, (event) => this._keydown(event)); + if (this._config.pause === "hover") { + EventHandler.on(this._element, EVENT_MOUSEENTER$2, () => this.pause()); + EventHandler.on(this._element, EVENT_MOUSELEAVE$1, () => this._maybeEnableCycle()); + } + EventHandler.on(this._viewport, EVENT_POINTERDOWN$3, () => this._pauseFromInteraction()); + } + _keydown(event) { + if (/input|textarea/i.test(event.target.tagName)) return; + const direction = KEY_TO_DIRECTION[event.key]; + if (direction) { + event.preventDefault(); + this._pauseFromInteraction(); + if (direction === DIRECTION_RIGHT) this.prev(); + else this.next(); + } + } + _observeItems() { + if (this._isFade() || typeof IntersectionObserver === "undefined") return; + this._observer = new IntersectionObserver((entries) => this._handleIntersection(entries), { + root: this._viewport, + threshold: [ + 0, + .25, + .5, + .75, + 1 + ] + }); + for (const item of this._getItems()) this._observer.observe(item); + } + _handleIntersection(entries) { + if (this._looping) return; + for (const entry of entries) this._visibility.set(entry.target, entry.isIntersecting ? entry.intersectionRatio : 0); + const ratios = this._getItems().map((item) => this._visibility.get(item) ?? 0); + const maxRatio = Math.max(...ratios); + let bestIndex = this._activeIndex; + if (maxRatio > 0) bestIndex = ratios.findIndex((ratio) => ratio >= maxRatio - ACTIVE_RATIO_TOLERANCE); + this._setActive(bestIndex); + this._updateEndControls(); + } + _navIndex() { + if (this._isFade() || this._viewport.scrollWidth - this._viewport.clientWidth <= 0) return this._activeIndex; + let index = this._activeIndex; + let smallestDelta = Number.POSITIVE_INFINITY; + for (const [itemIndex, item] of this._getItems().entries()) { + const delta = Math.abs(this._scrollDelta(item)); + if (delta < smallestDelta) { + smallestDelta = delta; + index = itemIndex; + } + } + return index; + } + _scrollToIndex(index) { + const item = this._getItems()[index]; + if (!item) return; + const left = this._scrollDelta(item); + if (Math.abs(left) < 1) return; + const targetLeft = this._viewport.scrollLeft + left; + this._viewport.style.scrollSnapType = "none"; + this._animateScroll(targetLeft, () => { + this._viewport.style.scrollSnapType = ""; + if (!this._observer) this._setActive(index); + this._updateEndControls(); + }); + } + _animateScroll(targetLeft, onComplete) { + if (this._scrollFrame !== null) { + cancelAnimationFrame(this._scrollFrame); + this._scrollFrame = null; + } + const startLeft = this._viewport.scrollLeft; + const distance = targetLeft - startLeft; + if (this._prefersReducedMotion() || typeof requestAnimationFrame === "undefined") { + this._viewport.scrollTo({ + left: targetLeft, + behavior: "instant" + }); + onComplete(); + return; + } + let startTime = null; + const step = (now) => { + if (startTime === null) startTime = now; + const progress = Math.min((now - startTime) / SCROLL_DURATION, 1); + this._viewport.scrollTo({ + left: startLeft + distance * easeInOutCubic(progress), + behavior: "instant" + }); + if (progress < 1) { + this._scrollFrame = requestAnimationFrame(step); + return; + } + this._viewport.scrollTo({ + left: targetLeft, + behavior: "instant" + }); + this._scrollFrame = null; + onComplete(); + }; + this._scrollFrame = requestAnimationFrame(step); + } + _scrollDelta(element) { + const viewportRect = this._viewport.getBoundingClientRect(); + const rect = element.getBoundingClientRect(); + if (this._element.classList.contains(CLASS_NAME_CENTER)) return rect.left + rect.width / 2 - (viewportRect.left + viewportRect.width / 2); + const padStart = Number.parseFloat(getComputedStyle(this._viewport).scrollPaddingInlineStart) || 0; + return isRTL$1() ? rect.right - (viewportRect.right - padStart) : rect.left - (viewportRect.left + padStart); + } + _loopTransition(isNext) { + const items = this._getItems(); + const last = items.length - 1; + const fromIndex = this._activeIndex; + const toIndex = isNext ? 0 : last; + const direction = this._loopDirection(isNext); + if (EventHandler.trigger(this._element, EVENT_SLIDE, { + relatedTarget: items[toIndex], + direction, + from: fromIndex, + to: toIndex + }).defaultPrevented) return; + this._looping = true; + const clone = (isNext ? items[0] : items[last]).cloneNode(true); + clone.classList.add(CLASS_NAME_CLONE); + clone.classList.remove(CLASS_NAME_ACTIVE$3); + clone.removeAttribute("id"); + for (const node of SelectorEngine.find("[id]", clone)) node.removeAttribute("id"); + clone.setAttribute("aria-hidden", "true"); + clone.inert = true; + this._viewport.style.scrollSnapType = "none"; + if (isNext) this._viewport.append(clone); + else { + this._viewport.prepend(clone); + this._jumpScroll(this._scrollDelta(items[fromIndex])); + } + this._animateScroll(this._viewport.scrollLeft + this._scrollDelta(clone), () => { + clone.remove(); + this._jumpScroll(this._scrollDelta(items[toIndex])); + this._activeIndex = toIndex; + this._refreshActiveState(); + EventHandler.trigger(this._element, EVENT_SLID, { + relatedTarget: items[toIndex], + direction, + from: fromIndex, + to: toIndex + }); + this._viewport.style.scrollSnapType = ""; + this._looping = false; + }); + } + _loopDirection(isNext) { + if (isRTL$1()) return isNext ? DIRECTION_RIGHT : DIRECTION_LEFT; + return isNext ? DIRECTION_LEFT : DIRECTION_RIGHT; + } + _jumpScroll(delta) { + this._viewport.style.scrollSnapType = "none"; + this._viewport.scrollBy({ + left: delta, + top: 0, + behavior: "instant" + }); + } + _fadeTo(index) { + this._setActive(index); + } + _setActive(index) { + const items = this._getItems(); + if (index === this._activeIndex || !items[index]) return; + const from = this._activeIndex; + this._activeIndex = index; + this._refreshActiveState(); + EventHandler.trigger(this._element, EVENT_SLID, { + relatedTarget: items[index], + direction: this._direction(from, index), + from, + to: index + }); + } + _refreshActiveState() { + const items = this._getItems(); + for (const [index, item] of items.entries()) item.classList.toggle(CLASS_NAME_ACTIVE$3, index === this._activeIndex); + this._setActiveIndicatorElement(this._activeIndex); + this._updateEndControls(); + } + _updateEndControls() { + if (this._config.ends !== ENDS_STOP) return; + const viewport = this._viewport; + const maxScroll = viewport.scrollWidth - viewport.clientWidth; + let atStart; + let atEnd; + if (maxScroll > 0) { + const progress = Math.abs(viewport.scrollLeft); + atStart = progress <= 1; + atEnd = progress >= maxScroll - 1; + } else { + const last = this._getItems().length - 1; + atStart = this._activeIndex <= 0; + atEnd = this._activeIndex >= last; + } + this._setControlsDisabled(this._prevControls, atStart); + this._setControlsDisabled(this._nextControls, atEnd); + } + _setControlsDisabled(controls, disabled) { + for (const control of controls) { + if (disabled && control === document.activeElement) ((controls === this._prevControls ? this._nextControls : this._prevControls)[0] ?? this._viewport).focus({ preventScroll: true }); + control.disabled = disabled; + } + } + _setActiveIndicatorElement(index) { + if (!this._indicatorsElement) return; + const active = SelectorEngine.findOne(SELECTOR_ACTIVE, this._indicatorsElement); + if (active) { + active.classList.remove(CLASS_NAME_ACTIVE$3); + active.removeAttribute("aria-current"); + } + const newActive = SelectorEngine.findOne(`[data-bs-slide-to="${index}"]`, this._indicatorsElement); + if (newActive) { + newActive.classList.add(CLASS_NAME_ACTIVE$3); + newActive.setAttribute("aria-current", "true"); + } + } + _normalizeIndex(index, length) { + if (Number.isNaN(index) || length === 0) return null; + if (index < 0) return this._wrapsAround() ? length - 1 : null; + if (index > length - 1) return this._wrapsAround() ? 0 : null; + return index; + } + _wrapsAround() { + return this._config.ends === ENDS_WRAP || this._config.ends === ENDS_LOOP; + } + _canLoop() { + if (this._isFade() || this._getItems().length < 2) return false; + const styles = getComputedStyle(this._element); + const num = (name) => Number.parseFloat(styles.getPropertyValue(name)) || 0; + return (num("--bs-carousel-items") || 1) === 1 && num("--bs-carousel-items-peek") === 0 && !this._element.classList.contains(CLASS_NAME_CENTER) && !this._element.classList.contains(CLASS_NAME_AUTO); + } + _direction(from, to) { + const isNext = to > from; + if (isRTL$1()) return isNext ? DIRECTION_RIGHT : DIRECTION_LEFT; + return isNext ? DIRECTION_LEFT : DIRECTION_RIGHT; + } + _scheduleAutoplay(index = this._activeIndex) { + const interval = this._itemInterval(index); + this._element.style.setProperty(PROPERTY_INTERVAL, `${interval}ms`); + this._interval = setTimeout(() => { + const upcoming = this._upcomingIndex(); + this.nextWhenVisible(); + if (upcoming === null) { + this.pause(); + return; + } + this._scheduleAutoplay(upcoming); + }, interval); + } + _upcomingIndex() { + return this._normalizeIndex(this._navIndex() + 1, this._getItems().length); + } + _itemInterval(index = this._activeIndex) { + const item = this._getItems()[index]; + const interval = item ? Number.parseInt(item.getAttribute("data-bs-interval"), 10) : NaN; + return Number.isNaN(interval) ? this._config.interval : interval; + } + _maybeEnableCycle() { + if (!this._playing) return; + this.cycle(); + } + _pauseFromInteraction() { + this._playing = false; + this.pause(); + this._updatePlayPauseControl(); + } + _togglePlayPause() { + if (this._playing) { + this._pauseFromInteraction(); + return; + } + this._playing = true; + this.cycle(); + this._updatePlayPauseControl(); + } + _updatePlayPauseControl() { + if (!this._playPauseElement) return; + this._playPauseElement.classList.toggle(CLASS_NAME_PAUSED, !this._playing); + const label = this._playPauseElement.getAttribute(this._playing ? "data-bs-pause-label" : "data-bs-play-label"); + if (label) this._playPauseElement.setAttribute("aria-label", label); + } + _isFade() { + return this._element.classList.contains(CLASS_NAME_FADE); + } + _prefersReducedMotion() { + return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches; + } + _getItems() { + return SelectorEngine.find(SELECTOR_ITEM, this._element); + } + _clearInterval() { + if (this._interval) { + clearTimeout(this._interval); + this._interval = null; + } + } +}; +/** +* Data API implementation +*/ +EventHandler.on(document, EVENT_CLICK_DATA_API$7, SELECTOR_DATA_SLIDE, function(event) { + const target = SelectorEngine.getElementFromSelector(this); + if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) return; + event.preventDefault(); + const carousel = Carousel.getOrCreateInstance(target); + carousel._pauseFromInteraction(); + const slideIndex = this.getAttribute("data-bs-slide-to"); + if (slideIndex) { + carousel.to(slideIndex); + return; + } + if (Manipulator.getDataAttribute(this, "slide") === "next") { + carousel.next(); + return; + } + carousel.prev(); +}); +EventHandler.on(document, EVENT_CLICK_DATA_API$7, SELECTOR_PLAY_PAUSE, function(event) { + const target = SelectorEngine.getElementFromSelector(this); + if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) return; + event.preventDefault(); + Carousel.getOrCreateInstance(target)._togglePlayPause(); +}); +EventHandler.on(window, EVENT_LOAD_DATA_API$3, () => { + const carousels = SelectorEngine.find(SELECTOR_DATA_AUTOPLAY); + for (const carousel of carousels) Carousel.getOrCreateInstance(carousel); +}); +//#endregion +//#region js/src/collapse.ts +/** +* -------------------------------------------------------------------------- +* Bootstrap collapse.ts +* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) +* -------------------------------------------------------------------------- +*/ +/** +* Constants +*/ +const NAME$18 = "collapse"; +const EVENT_KEY$15 = `.bs.collapse`; +const DATA_API_KEY$10 = ".data-api"; +const EVENT_SHOW$7 = `show${EVENT_KEY$15}`; +const EVENT_SHOWN$6 = `shown${EVENT_KEY$15}`; +const EVENT_HIDE$6 = `hide${EVENT_KEY$15}`; +const EVENT_HIDDEN$8 = `hidden${EVENT_KEY$15}`; +const EVENT_CLICK_DATA_API$6 = `click${EVENT_KEY$15}${DATA_API_KEY$10}`; +const CLASS_NAME_SHOW$6 = "show"; +const CLASS_NAME_COLLAPSE = "collapse"; +const CLASS_NAME_DEEPER_CHILDREN = `:scope .${CLASS_NAME_COLLAPSE} .${CLASS_NAME_COLLAPSE}`; +const SELECTOR_ACTIVES = ".collapse.show"; +const SELECTOR_DATA_TOGGLE$9 = "[data-bs-toggle=\"collapse\"]"; +const Default$17 = { parent: null }; +const DefaultType$17 = { parent: "(null|element)" }; +/** +* Class definition +*/ +var Collapse = class Collapse extends BaseComponent { + constructor(element, config) { + super(element, config); + this._isTransitioning = false; + this._triggerArray = []; + const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE$9); + for (const elem of toggleList) { + const selector = SelectorEngine.getSelectorFromElement(elem); + const filterElement = SelectorEngine.find(selector).filter((foundElement) => foundElement === this._element); + if (selector !== null && filterElement.length) this._triggerArray.push(elem); + } + this._initializeChildren(); + if (!this._config.parent) this._setAriaExpanded(this._triggerArray, this._isShown()); + } + static get Default() { + return Default$17; + } + static get DefaultType() { + return DefaultType$17; + } + static get NAME() { + return NAME$18; + } + toggle() { + return this._isShown() ? this.hide() : this.show(); + } + async show() { + if (this._isTransitioning || this._isShown()) return; + let activeChildren = []; + if (this._config.parent) activeChildren = this._getFirstLevelChildren(SELECTOR_ACTIVES).filter((element) => element !== this._element && !this._sharesTrigger(element)).map((element) => Collapse.getOrCreateInstance(element)); + if (activeChildren.length && activeChildren[0]._isTransitioning) return; + if (EventHandler.trigger(this._element, EVENT_SHOW$7).defaultPrevented) return; + for (const activeInstance of activeChildren) activeInstance.hide(); + this._element.classList.add(CLASS_NAME_SHOW$6); + this._setAriaExpanded(this._triggerArray, true); + this._isTransitioning = true; + const complete = () => { + this._isTransitioning = false; + EventHandler.trigger(this._element, EVENT_SHOWN$6); + }; + await this._queueCallback(complete, this._element, this._isAnimated()); + } + async hide() { + if (this._isTransitioning || !this._isShown()) return; + if (EventHandler.trigger(this._element, EVENT_HIDE$6).defaultPrevented) return; + this._element.classList.remove(CLASS_NAME_SHOW$6); + for (const trigger of this._triggerArray) { + const element = SelectorEngine.getElementFromSelector(trigger); + if (element && !this._isShown(element)) this._setAriaExpanded([trigger], false); + } + this._isTransitioning = true; + const complete = () => { + this._isTransitioning = false; + EventHandler.trigger(this._element, EVENT_HIDDEN$8); + }; + await this._queueCallback(complete, this._element, this._isAnimated()); + } + _isShown(element = this._element) { + return element.classList.contains(CLASS_NAME_SHOW$6); + } + _isAnimated() { + return getTransitionDurationFromElement(this._element) > 0; + } + _sharesTrigger(element) { + return this._triggerArray.some((trigger) => SelectorEngine.getMultipleElementsFromSelector(trigger).includes(element)); + } + _configAfterMerge(config) { + config.parent = getElement(config.parent); + return config; + } + _initializeChildren() { + if (!this._config.parent) return; + const children = this._getFirstLevelChildren(SELECTOR_DATA_TOGGLE$9); + for (const element of children) { + const selected = SelectorEngine.getElementFromSelector(element); + if (selected) this._setAriaExpanded([element], this._isShown(selected)); + } + } + _getFirstLevelChildren(selector) { + const children = SelectorEngine.find(CLASS_NAME_DEEPER_CHILDREN, this._config.parent); + return SelectorEngine.find(selector, this._config.parent).filter((element) => !children.includes(element)); + } + _setAriaExpanded(triggerArray, isOpen) { + if (!triggerArray.length) return; + for (const element of triggerArray) setAriaAttribute(element, "aria-expanded", isOpen); + } +}; +/** +* Data API implementation +*/ +EventHandler.on(document, EVENT_CLICK_DATA_API$6, SELECTOR_DATA_TOGGLE$9, function(event) { + if (event.target.tagName === "A" || event.delegateTarget && event.delegateTarget.tagName === "A") event.preventDefault(); + for (const element of SelectorEngine.getMultipleElementsFromSelector(this)) Collapse.getOrCreateInstance(element).toggle(); +}); +//#endregion +//#region node_modules/@floating-ui/utils/dist/floating-ui.utils.mjs +const min = Math.min; +const max = Math.max; +const round = Math.round; +const floor = Math.floor; +const createCoords = (v) => ({ + x: v, + y: v +}); +const oppositeSideMap = { + left: "right", + right: "left", + bottom: "top", + top: "bottom" +}; +function clamp(start, value, end) { + return max(start, min(value, end)); +} +function evaluate(value, param) { + return typeof value === "function" ? value(param) : value; +} +function getSide(placement) { + return placement.split("-")[0]; +} +function getAlignment(placement) { + return placement.split("-")[1]; +} +function getOppositeAxis(axis) { + return axis === "x" ? "y" : "x"; +} +function getAxisLength(axis) { + return axis === "y" ? "height" : "width"; +} +function getSideAxis(placement) { + const firstChar = placement[0]; + return firstChar === "t" || firstChar === "b" ? "y" : "x"; +} +function getAlignmentAxis(placement) { + return getOppositeAxis(getSideAxis(placement)); +} +function getAlignmentSides(placement, rects, rtl) { + if (rtl === void 0) rtl = false; + const alignment = getAlignment(placement); + const alignmentAxis = getAlignmentAxis(placement); + const length = getAxisLength(alignmentAxis); + let mainAlignmentSide = alignmentAxis === "x" ? alignment === (rtl ? "end" : "start") ? "right" : "left" : alignment === "start" ? "bottom" : "top"; + if (rects.reference[length] > rects.floating[length]) mainAlignmentSide = getOppositePlacement(mainAlignmentSide); + return [mainAlignmentSide, getOppositePlacement(mainAlignmentSide)]; +} +function getExpandedPlacements(placement) { + const oppositePlacement = getOppositePlacement(placement); + return [ + getOppositeAlignmentPlacement(placement), + oppositePlacement, + getOppositeAlignmentPlacement(oppositePlacement) + ]; +} +function getOppositeAlignmentPlacement(placement) { + return placement.includes("start") ? placement.replace("start", "end") : placement.replace("end", "start"); +} +const lrPlacement = ["left", "right"]; +const rlPlacement = ["right", "left"]; +const tbPlacement = ["top", "bottom"]; +const btPlacement = ["bottom", "top"]; +function getSideList(side, isStart, rtl) { + switch (side) { + case "top": + case "bottom": + if (rtl) return isStart ? rlPlacement : lrPlacement; + return isStart ? lrPlacement : rlPlacement; + case "left": + case "right": return isStart ? tbPlacement : btPlacement; + default: return []; + } +} +function getOppositeAxisPlacements(placement, flipAlignment, direction, rtl) { + const alignment = getAlignment(placement); + let list = getSideList(getSide(placement), direction === "start", rtl); + if (alignment) { + list = list.map((side) => side + "-" + alignment); + if (flipAlignment) list = list.concat(list.map(getOppositeAlignmentPlacement)); + } + return list; +} +function getOppositePlacement(placement) { + const side = getSide(placement); + return oppositeSideMap[side] + placement.slice(side.length); +} +function expandPaddingObject(padding) { + var _padding$top, _padding$right, _padding$bottom, _padding$left; + return { + top: (_padding$top = padding.top) != null ? _padding$top : 0, + right: (_padding$right = padding.right) != null ? _padding$right : 0, + bottom: (_padding$bottom = padding.bottom) != null ? _padding$bottom : 0, + left: (_padding$left = padding.left) != null ? _padding$left : 0 + }; +} +function getPaddingObject(padding) { + return typeof padding !== "number" ? expandPaddingObject(padding) : { + top: padding, + right: padding, + bottom: padding, + left: padding + }; +} +function rectToClientRect(rect) { + const { x, y, width, height } = rect; + return { + width, + height, + top: y, + left: x, + right: x + width, + bottom: y + height, + x, + y + }; +} +//#endregion +//#region node_modules/@floating-ui/core/dist/floating-ui.core.mjs +function computeCoordsFromPlacement(_ref, placement, rtl) { + let { reference, floating } = _ref; + const sideAxis = getSideAxis(placement); + const alignmentAxis = getAlignmentAxis(placement); + const alignLength = getAxisLength(alignmentAxis); + const side = getSide(placement); + const isVertical = sideAxis === "y"; + const commonX = reference.x + reference.width / 2 - floating.width / 2; + const commonY = reference.y + reference.height / 2 - floating.height / 2; + const commonAlign = reference[alignLength] / 2 - floating[alignLength] / 2; + let coords; + switch (side) { + case "top": + coords = { + x: commonX, + y: reference.y - floating.height + }; + break; + case "bottom": + coords = { + x: commonX, + y: reference.y + reference.height + }; + break; + case "right": + coords = { + x: reference.x + reference.width, + y: commonY + }; + break; + case "left": + coords = { + x: reference.x - floating.width, + y: commonY + }; + break; + default: coords = { + x: reference.x, + y: reference.y + }; + } + const alignment = getAlignment(placement); + if (alignment) coords[alignmentAxis] += commonAlign * (alignment === "end" ? 1 : -1) * (rtl && isVertical ? -1 : 1); + return coords; +} +/** +* Resolves with an object of overflow side offsets that determine how much the +* element is overflowing a given clipping boundary on each side. +* - positive = overflowing the boundary by that number of pixels +* - negative = how many pixels left before it will overflow +* - 0 = lies flush with the boundary +* @see https://floating-ui.com/docs/detectOverflow +*/ +async function detectOverflow(state, options) { + var _await$platform$isEle; + if (options === void 0) options = {}; + const { x, y, platform, rects, elements, strategy } = state; + const { boundary = "clippingAncestors", rootBoundary = "viewport", elementContext = "floating", altBoundary = false, padding = 0 } = evaluate(options, state); + const paddingObject = getPaddingObject(padding); + const element = elements[altBoundary ? elementContext === "floating" ? "reference" : "floating" : elementContext]; + const clippingClientRect = rectToClientRect(await platform.getClippingRect({ + element: ((_await$platform$isEle = await (platform.isElement == null ? void 0 : platform.isElement(element))) != null ? _await$platform$isEle : true) ? element : element.contextElement || await (platform.getDocumentElement == null ? void 0 : platform.getDocumentElement(elements.floating)), + boundary, + rootBoundary, + strategy + })); + const rect = elementContext === "floating" ? { + x, + y, + width: rects.floating.width, + height: rects.floating.height + } : rects.reference; + const offsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(elements.floating)); + const offsetScale = await (platform.isElement == null ? void 0 : platform.isElement(offsetParent)) && await (platform.getScale == null ? void 0 : platform.getScale(offsetParent)) || { + x: 1, + y: 1 + }; + const elementClientRect = rectToClientRect(platform.convertOffsetParentRelativeRectToViewportRelativeRect ? await platform.convertOffsetParentRelativeRectToViewportRelativeRect({ + elements, + rect, + offsetParent, + strategy + }) : rect); + return { + top: (clippingClientRect.top - elementClientRect.top + paddingObject.top) / offsetScale.y, + bottom: (elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom) / offsetScale.y, + left: (clippingClientRect.left - elementClientRect.left + paddingObject.left) / offsetScale.x, + right: (elementClientRect.right - clippingClientRect.right + paddingObject.right) / offsetScale.x + }; +} +const MAX_RESET_COUNT = 50; +/** +* Computes the `x` and `y` coordinates that will place the floating element +* next to a given reference element. +* +* This export does not have any `platform` interface logic. You will need to +* write one for the platform you are using Floating UI with. +*/ +const computePosition$1 = async (reference, floating, config) => { + const { placement = "bottom", strategy = "absolute", middleware = [], platform } = config; + const platformWithDetectOverflow = platform.detectOverflow ? platform : { + ...platform, + detectOverflow + }; + const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(floating)); + let rects = await platform.getElementRects({ + reference, + floating, + strategy + }); + let { x, y } = computeCoordsFromPlacement(rects, placement, rtl); + let statefulPlacement = placement; + let resetCount = 0; + const middlewareData = {}; + for (let i = 0; i < middleware.length; i++) { + const currentMiddleware = middleware[i]; + if (!currentMiddleware) continue; + const { name, fn } = currentMiddleware; + const { x: nextX, y: nextY, data, reset } = await fn({ + x, + y, + initialPlacement: placement, + placement: statefulPlacement, + strategy, + middlewareData, + rects, + platform: platformWithDetectOverflow, + elements: { + reference, + floating + } + }); + x = nextX != null ? nextX : x; + y = nextY != null ? nextY : y; + middlewareData[name] = { + ...middlewareData[name], + ...data + }; + if (reset && resetCount < MAX_RESET_COUNT) { + resetCount++; + if (typeof reset === "object") { + if (reset.placement) statefulPlacement = reset.placement; + if (reset.rects) rects = reset.rects === true ? await platform.getElementRects({ + reference, + floating, + strategy + }) : reset.rects; + ({x, y} = computeCoordsFromPlacement(rects, statefulPlacement, rtl)); + } + i = -1; + } + } + return { + x, + y, + placement: statefulPlacement, + strategy, + middlewareData + }; +}; +/** +* Provides data to position an inner element of the floating element so that it +* appears centered to the reference element. +* @see https://floating-ui.com/docs/arrow +*/ +const arrow$1 = (options) => ({ + name: "arrow", + options, + async fn(state) { + const { x, y, placement, rects, platform, elements, middlewareData } = state; + const { element, padding = 0 } = evaluate(options, state) || {}; + if (element == null) return {}; + const paddingObject = getPaddingObject(padding); + const coords = { + x, + y + }; + const axis = getAlignmentAxis(placement); + const length = getAxisLength(axis); + const arrowDimensions = await platform.getDimensions(element); + const isYAxis = axis === "y"; + const minProp = isYAxis ? "top" : "left"; + const maxProp = isYAxis ? "bottom" : "right"; + const clientProp = isYAxis ? "clientHeight" : "clientWidth"; + const endDiff = rects.reference[length] + rects.reference[axis] - coords[axis] - rects.floating[length]; + const startDiff = coords[axis] - rects.reference[axis]; + const arrowOffsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(element)); + let clientSize = arrowOffsetParent ? arrowOffsetParent[clientProp] : 0; + if (!clientSize || !await (platform.isElement == null ? void 0 : platform.isElement(arrowOffsetParent))) clientSize = elements.floating[clientProp] || rects.floating[length]; + const centerToReference = endDiff / 2 - startDiff / 2; + const largestPossiblePadding = clientSize / 2 - arrowDimensions[length] / 2 - 1; + const minPadding = min(paddingObject[minProp], largestPossiblePadding); + const maxPadding = min(paddingObject[maxProp], largestPossiblePadding); + const max = clientSize - arrowDimensions[length] - maxPadding; + const center = clientSize / 2 - arrowDimensions[length] / 2 + centerToReference; + const offset = clamp(minPadding, center, max); + const shouldAddOffset = !middlewareData.arrow && getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < minPadding ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0; + const alignmentOffset = shouldAddOffset ? center < minPadding ? center - minPadding : center - max : 0; + return { + [axis]: coords[axis] + alignmentOffset, + data: { + [axis]: offset, + centerOffset: center - offset - alignmentOffset, + ...shouldAddOffset && { alignmentOffset } + }, + reset: shouldAddOffset + }; + } +}); +/** +* Optimizes the visibility of the floating element by flipping the `placement` +* in order to keep it in view when the preferred placement(s) will overflow the +* clipping boundary. Alternative to `autoPlacement`. +* @see https://floating-ui.com/docs/flip +*/ +const flip$1 = function(options) { + if (options === void 0) options = {}; + return { + name: "flip", + options, + async fn(state) { + var _middlewareData$arrow, _middlewareData$flip; + const { placement, middlewareData, rects, initialPlacement, platform, elements } = state; + const { mainAxis: checkMainAxis = true, crossAxis: checkCrossAxis = true, fallbackPlacements: specifiedFallbackPlacements, fallbackStrategy = "bestFit", fallbackAxisSideDirection = "none", flipAlignment = true, ...detectOverflowOptions } = evaluate(options, state); + if ((_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) return {}; + const side = getSide(placement); + const initialSideAxis = getSideAxis(initialPlacement); + const isBasePlacement = getSide(initialPlacement) === initialPlacement; + const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating)); + const fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipAlignment ? [getOppositePlacement(initialPlacement)] : getExpandedPlacements(initialPlacement)); + const hasFallbackAxisSideDirection = fallbackAxisSideDirection !== "none"; + if (!specifiedFallbackPlacements && hasFallbackAxisSideDirection) fallbackPlacements.push(...getOppositeAxisPlacements(initialPlacement, flipAlignment, fallbackAxisSideDirection, rtl)); + const placements = [initialPlacement, ...fallbackPlacements]; + const overflow = await platform.detectOverflow(state, detectOverflowOptions); + const overflows = []; + let overflowsData = ((_middlewareData$flip = middlewareData.flip) == null ? void 0 : _middlewareData$flip.overflows) || []; + if (checkMainAxis) overflows.push(overflow[side]); + if (checkCrossAxis) { + const sides = getAlignmentSides(placement, rects, rtl); + overflows.push(overflow[sides[0]], overflow[sides[1]]); + } + overflowsData = [...overflowsData, { + placement, + overflows + }]; + if (!overflows.every((side) => side <= 0)) { + var _middlewareData$flip2, _overflowsData$filter; + const nextIndex = (((_middlewareData$flip2 = middlewareData.flip) == null ? void 0 : _middlewareData$flip2.index) || 0) + 1; + const nextPlacement = placements[nextIndex]; + if (nextPlacement) { + if (!(checkCrossAxis === "alignment" ? initialSideAxis !== getSideAxis(nextPlacement) : false) || overflowsData.every((d) => getSideAxis(d.placement) === initialSideAxis ? d.overflows[0] > 0 : true)) return { + data: { + index: nextIndex, + overflows: overflowsData + }, + reset: { placement: nextPlacement } + }; + } + let resetPlacement = (_overflowsData$filter = overflowsData.filter((d) => d.overflows[0] <= 0).sort((a, b) => a.overflows[1] - b.overflows[1])[0]) == null ? void 0 : _overflowsData$filter.placement; + if (!resetPlacement) switch (fallbackStrategy) { + case "bestFit": { + var _overflowsData$filter2; + const placement = (_overflowsData$filter2 = overflowsData.filter((d) => { + if (hasFallbackAxisSideDirection) { + const currentSideAxis = getSideAxis(d.placement); + return currentSideAxis === initialSideAxis || currentSideAxis === "y"; + } + return true; + }).map((d) => [d.placement, d.overflows.filter((overflow) => overflow > 0).reduce((acc, overflow) => acc + overflow, 0)]).sort((a, b) => a[1] - b[1])[0]) == null ? void 0 : _overflowsData$filter2[0]; + if (placement) resetPlacement = placement; + break; + } + case "initialPlacement": + resetPlacement = initialPlacement; + break; + } + if (placement !== resetPlacement) return { reset: { placement: resetPlacement } }; + } + return {}; + } + }; +}; +const originSides = /*#__PURE__*/ new Set(["left", "top"]); +async function convertValueToCoords(state, options) { + const { placement, platform, elements } = state; + const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating)); + const side = getSide(placement); + const alignment = getAlignment(placement); + const isVertical = getSideAxis(placement) === "y"; + const mainAxisMulti = originSides.has(side) ? -1 : 1; + const crossAxisMulti = rtl && isVertical ? -1 : 1; + const rawValue = evaluate(options, state); + let { mainAxis, crossAxis, alignmentAxis } = typeof rawValue === "number" ? { + mainAxis: rawValue, + crossAxis: 0, + alignmentAxis: null + } : { + mainAxis: rawValue.mainAxis || 0, + crossAxis: rawValue.crossAxis || 0, + alignmentAxis: rawValue.alignmentAxis + }; + if (alignment && typeof alignmentAxis === "number") crossAxis = alignment === "end" ? alignmentAxis * -1 : alignmentAxis; + return isVertical ? { + x: crossAxis * crossAxisMulti, + y: mainAxis * mainAxisMulti + } : { + x: mainAxis * mainAxisMulti, + y: crossAxis * crossAxisMulti + }; +} +/** +* Modifies the placement by translating the floating element along the +* specified axes. +* A number (shorthand for `mainAxis` or distance), or an axes configuration +* object may be passed. +* @see https://floating-ui.com/docs/offset +*/ +const offset$1 = function(options) { + if (options === void 0) options = 0; + return { + name: "offset", + options, + async fn(state) { + var _middlewareData$offse, _middlewareData$arrow; + const { x, y, placement, middlewareData } = state; + const diffCoords = await convertValueToCoords(state, options); + if (placement === ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse.placement) && (_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) return {}; + return { + x: x + diffCoords.x, + y: y + diffCoords.y, + data: { + ...diffCoords, + placement + } + }; + } + }; +}; +/** +* Optimizes the visibility of the floating element by shifting it in order to +* keep it in view when it will overflow the clipping boundary. +* @see https://floating-ui.com/docs/shift +*/ +const shift$1 = function(options) { + if (options === void 0) options = {}; + return { + name: "shift", + options, + async fn(state) { + const { x, y, placement, platform } = state; + const { mainAxis: checkMainAxis = true, crossAxis: checkCrossAxis = false, limiter = { fn: (_ref) => { + let { x, y } = _ref; + return { + x, + y + }; + } }, ...detectOverflowOptions } = evaluate(options, state); + const coords = { + x, + y + }; + const overflow = await platform.detectOverflow(state, detectOverflowOptions); + const crossAxis = getSideAxis(placement); + const mainAxis = getOppositeAxis(crossAxis); + let mainAxisCoord = coords[mainAxis]; + let crossAxisCoord = coords[crossAxis]; + const clampCoord = (axis, coord) => clamp(coord + overflow[axis === "y" ? "top" : "left"], coord, coord - overflow[axis === "y" ? "bottom" : "right"]); + if (checkMainAxis) mainAxisCoord = clampCoord(mainAxis, mainAxisCoord); + if (checkCrossAxis) crossAxisCoord = clampCoord(crossAxis, crossAxisCoord); + const limitedCoords = limiter.fn({ + ...state, + [mainAxis]: mainAxisCoord, + [crossAxis]: crossAxisCoord + }); + return { + ...limitedCoords, + data: { + x: limitedCoords.x - x, + y: limitedCoords.y - y, + enabled: { + [mainAxis]: checkMainAxis, + [crossAxis]: checkCrossAxis + } + } + }; + } + }; +}; +//#endregion +//#region node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.mjs +function hasWindow() { + return typeof window !== "undefined"; +} +function getNodeName(node) { + if (isNode(node)) return (node.nodeName || "").toLowerCase(); + return "#document"; +} +function getWindow(node) { + var _node$ownerDocument; + return (node == null || (_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.defaultView) || window; +} +function getDocumentElement(node) { + var _ref; + return (_ref = (isNode(node) ? node.ownerDocument : node.document) || window.document) == null ? void 0 : _ref.documentElement; +} +function isNode(value) { + if (!hasWindow()) return false; + return value instanceof Node || value instanceof getWindow(value).Node; +} +function isElement(value) { + if (!hasWindow()) return false; + return value instanceof Element || value instanceof getWindow(value).Element; +} +function isHTMLElement(value) { + if (!hasWindow()) return false; + return value instanceof HTMLElement || value instanceof getWindow(value).HTMLElement; +} +function isShadowRoot(value) { + if (!hasWindow() || typeof ShadowRoot === "undefined") return false; + return value instanceof ShadowRoot || value instanceof getWindow(value).ShadowRoot; +} +function isOverflowElement(element) { + const { overflow, overflowX, overflowY, display } = getComputedStyle$1(element); + return /auto|scroll|overlay|hidden|clip/.test(overflow + overflowY + overflowX) && display !== "inline" && display !== "contents"; +} +function isTableElement(element) { + return /^(table|td|th)$/.test(getNodeName(element)); +} +function isTopLayer(element) { + try { + if (element.matches(":popover-open")) return true; + } catch (_e) {} + try { + return element.matches(":modal"); + } catch (_e) { + return false; + } +} +const willChangeRe = /transform|translate|scale|rotate|perspective|filter/; +const containRe = /paint|layout|strict|content/; +const isNotNone = (value) => !!value && value !== "none"; +let isWebKitValue; +function isContainingBlock(elementOrCss) { + const css = isElement(elementOrCss) ? getComputedStyle$1(elementOrCss) : elementOrCss; + return isNotNone(css.transform) || isNotNone(css.translate) || isNotNone(css.scale) || isNotNone(css.rotate) || isNotNone(css.perspective) || !isWebKit() && (isNotNone(css.backdropFilter) || isNotNone(css.filter)) || willChangeRe.test(css.willChange || "") || containRe.test(css.contain || ""); +} +function getContainingBlock(element) { + let currentNode = getParentNode(element); + while (isHTMLElement(currentNode) && !isLastTraversableNode(currentNode)) { + if (isContainingBlock(currentNode)) return currentNode; + else if (isTopLayer(currentNode)) return null; + currentNode = getParentNode(currentNode); + } + return null; +} +function isWebKit() { + if (isWebKitValue == null) isWebKitValue = typeof CSS !== "undefined" && CSS.supports && CSS.supports("-webkit-backdrop-filter", "none"); + return isWebKitValue; +} +function isLastTraversableNode(node) { + return /^(html|body|#document)$/.test(getNodeName(node)); +} +function getComputedStyle$1(element) { + return getWindow(element).getComputedStyle(element); +} +function getNodeScroll(element) { + if (isElement(element)) return { + scrollLeft: element.scrollLeft, + scrollTop: element.scrollTop + }; + return { + scrollLeft: element.scrollX, + scrollTop: element.scrollY + }; +} +function getParentNode(node) { + if (getNodeName(node) === "html") return node; + const result = node.assignedSlot || node.parentNode || isShadowRoot(node) && node.host || getDocumentElement(node); + return isShadowRoot(result) ? result.host : result; +} +function getNearestOverflowAncestor(node) { + const parentNode = getParentNode(node); + if (isLastTraversableNode(parentNode)) return (node.ownerDocument || node).body; + if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) return parentNode; + return getNearestOverflowAncestor(parentNode); +} +function getOverflowAncestors(node, list, traverseIframes) { + var _node$ownerDocument2; + if (list === void 0) list = []; + if (traverseIframes === void 0) traverseIframes = true; + const scrollableAncestor = getNearestOverflowAncestor(node); + const isBody = scrollableAncestor === ((_node$ownerDocument2 = node.ownerDocument) == null ? void 0 : _node$ownerDocument2.body); + const win = getWindow(scrollableAncestor); + if (isBody) { + const frameElement = getFrameElement(win); + return list.concat(win, win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : [], frameElement && traverseIframes ? getOverflowAncestors(frameElement) : []); + } else return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor, [], traverseIframes)); +} +function getFrameElement(win) { + return win.parent && Object.getPrototypeOf(win.parent) ? win.frameElement : null; +} +//#endregion +//#region node_modules/@floating-ui/dom/dist/floating-ui.dom.mjs +function getCssDimensions(element) { + const css = getComputedStyle$1(element); + let width = parseFloat(css.width) || 0; + let height = parseFloat(css.height) || 0; + const hasOffset = isHTMLElement(element); + const offsetWidth = hasOffset ? element.offsetWidth : width; + const offsetHeight = hasOffset ? element.offsetHeight : height; + const shouldFallback = round(width) !== offsetWidth || round(height) !== offsetHeight; + if (shouldFallback) { + width = offsetWidth; + height = offsetHeight; + } + return { + width, + height, + $: shouldFallback + }; +} +function unwrapElement(element) { + return !isElement(element) ? element.contextElement : element; +} +function getScale(element) { + const domElement = unwrapElement(element); + if (!isHTMLElement(domElement)) return createCoords(1); + const rect = domElement.getBoundingClientRect(); + const { width, height, $ } = getCssDimensions(domElement); + let x = ($ ? round(rect.width) : rect.width) / width; + let y = ($ ? round(rect.height) : rect.height) / height; + if (!x || !Number.isFinite(x)) x = 1; + if (!y || !Number.isFinite(y)) y = 1; + return { + x, + y + }; +} +const noOffsets = /*#__PURE__*/ createCoords(0); +function getVisualOffsets(element) { + const win = getWindow(element); + if (!isWebKit() || !win.visualViewport) return noOffsets; + return { + x: win.visualViewport.offsetLeft, + y: win.visualViewport.offsetTop + }; +} +function shouldAddVisualOffsets(element, isFixed, floatingOffsetParent) { + if (isFixed === void 0) isFixed = false; + if (!floatingOffsetParent || isFixed && floatingOffsetParent !== getWindow(element)) return false; + return isFixed; +} +function getBoundingClientRect(element, includeScale, isFixedStrategy, offsetParent) { + if (includeScale === void 0) includeScale = false; + if (isFixedStrategy === void 0) isFixedStrategy = false; + const clientRect = element.getBoundingClientRect(); + const domElement = unwrapElement(element); + let scale = createCoords(1); + if (includeScale) if (offsetParent) { + if (isElement(offsetParent)) scale = getScale(offsetParent); + } else scale = getScale(element); + const visualOffsets = shouldAddVisualOffsets(domElement, isFixedStrategy, offsetParent) ? getVisualOffsets(domElement) : createCoords(0); + let x = (clientRect.left + visualOffsets.x) / scale.x; + let y = (clientRect.top + visualOffsets.y) / scale.y; + let width = clientRect.width / scale.x; + let height = clientRect.height / scale.y; + if (domElement) { + const win = getWindow(domElement); + const offsetWin = offsetParent && isElement(offsetParent) ? getWindow(offsetParent) : offsetParent; + let currentWin = win; + let currentIFrame = getFrameElement(currentWin); + while (currentIFrame && offsetParent && offsetWin !== currentWin) { + const iframeScale = getScale(currentIFrame); + const iframeRect = currentIFrame.getBoundingClientRect(); + const css = getComputedStyle$1(currentIFrame); + const left = iframeRect.left + (currentIFrame.clientLeft + parseFloat(css.paddingLeft)) * iframeScale.x; + const top = iframeRect.top + (currentIFrame.clientTop + parseFloat(css.paddingTop)) * iframeScale.y; + x *= iframeScale.x; + y *= iframeScale.y; + width *= iframeScale.x; + height *= iframeScale.y; + x += left; + y += top; + currentWin = getWindow(currentIFrame); + currentIFrame = getFrameElement(currentWin); + } + } + return rectToClientRect({ + width, + height, + x, + y + }); +} +function getWindowScrollBarX(element, rect) { + const leftScroll = getNodeScroll(element).scrollLeft; + if (!rect) return getBoundingClientRect(getDocumentElement(element)).left + leftScroll; + return rect.left + leftScroll; +} +function getHTMLOffset(documentElement, scroll) { + const htmlRect = documentElement.getBoundingClientRect(); + return { + x: htmlRect.left + scroll.scrollLeft - getWindowScrollBarX(documentElement, htmlRect), + y: htmlRect.top + scroll.scrollTop + }; +} +function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) { + let { elements, rect, offsetParent, strategy } = _ref; + const isFixed = strategy === "fixed"; + const documentElement = getDocumentElement(offsetParent); + const topLayer = elements ? isTopLayer(elements.floating) : false; + if (offsetParent === documentElement || topLayer && isFixed) return rect; + let scroll = { + scrollLeft: 0, + scrollTop: 0 + }; + let scale = createCoords(1); + const offsets = createCoords(0); + const isOffsetParentAnElement = isHTMLElement(offsetParent); + if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) { + if (getNodeName(offsetParent) !== "body" || isOverflowElement(documentElement)) scroll = getNodeScroll(offsetParent); + if (isOffsetParentAnElement) { + const offsetRect = getBoundingClientRect(offsetParent); + scale = getScale(offsetParent); + offsets.x = offsetRect.x + offsetParent.clientLeft; + offsets.y = offsetRect.y + offsetParent.clientTop; + } + } + const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0); + return { + width: rect.width * scale.x, + height: rect.height * scale.y, + x: rect.x * scale.x - scroll.scrollLeft * scale.x + offsets.x + htmlOffset.x, + y: rect.y * scale.y - scroll.scrollTop * scale.y + offsets.y + htmlOffset.y + }; +} +function getClientRects(element) { + return Array.from(element.getClientRects()); +} +function getDocumentRect(element) { + const html = getDocumentElement(element); + const scroll = getNodeScroll(element); + const body = element.ownerDocument.body; + const width = max(html.scrollWidth, html.clientWidth, body.scrollWidth, body.clientWidth); + const height = max(html.scrollHeight, html.clientHeight, body.scrollHeight, body.clientHeight); + let x = -scroll.scrollLeft + getWindowScrollBarX(element); + const y = -scroll.scrollTop; + if (getComputedStyle$1(body).direction === "rtl") x += max(html.clientWidth, body.clientWidth) - width; + return { + width, + height, + x, + y + }; +} +const SCROLLBAR_MAX = 25; +function getViewportRect(element, strategy) { + const win = getWindow(element); + const html = getDocumentElement(element); + const visualViewport = win.visualViewport; + let width = html.clientWidth; + let height = html.clientHeight; + let x = 0; + let y = 0; + if (visualViewport) { + width = visualViewport.width; + height = visualViewport.height; + const visualViewportBased = isWebKit(); + if (!visualViewportBased || visualViewportBased && strategy === "fixed") { + x = visualViewport.offsetLeft; + y = visualViewport.offsetTop; + } + } + const windowScrollbarX = getWindowScrollBarX(html); + if (windowScrollbarX <= 0) { + const doc = html.ownerDocument; + const body = doc.body; + const bodyStyles = getComputedStyle(body); + const bodyMarginInline = doc.compatMode === "CSS1Compat" ? parseFloat(bodyStyles.marginLeft) + parseFloat(bodyStyles.marginRight) || 0 : 0; + const clippingStableScrollbarWidth = Math.abs(html.clientWidth - body.clientWidth - bodyMarginInline); + if (clippingStableScrollbarWidth <= SCROLLBAR_MAX) width -= clippingStableScrollbarWidth; + } else if (windowScrollbarX <= SCROLLBAR_MAX) width += windowScrollbarX; + return { + width, + height, + x, + y + }; +} +function getInnerBoundingClientRect(element, strategy) { + const clientRect = getBoundingClientRect(element, true, strategy === "fixed"); + const top = clientRect.top + element.clientTop; + const left = clientRect.left + element.clientLeft; + const scale = isHTMLElement(element) ? getScale(element) : createCoords(1); + return { + width: element.clientWidth * scale.x, + height: element.clientHeight * scale.y, + x: left * scale.x, + y: top * scale.y + }; +} +function getClientRectFromClippingAncestor(element, clippingAncestor, strategy) { + let rect; + if (clippingAncestor === "viewport") rect = getViewportRect(element, strategy); + else if (clippingAncestor === "document") rect = getDocumentRect(getDocumentElement(element)); + else if (isElement(clippingAncestor)) rect = getInnerBoundingClientRect(clippingAncestor, strategy); + else { + const visualOffsets = getVisualOffsets(element); + rect = { + x: clippingAncestor.x - visualOffsets.x, + y: clippingAncestor.y - visualOffsets.y, + width: clippingAncestor.width, + height: clippingAncestor.height + }; + } + return rectToClientRect(rect); +} +function hasFixedPositionAncestor(element, stopNode) { + const parentNode = getParentNode(element); + if (parentNode === stopNode || !isElement(parentNode) || isLastTraversableNode(parentNode)) return false; + return getComputedStyle$1(parentNode).position === "fixed" || hasFixedPositionAncestor(parentNode, stopNode); +} +function getClippingElementAncestors(element, cache) { + const cachedResult = cache.get(element); + if (cachedResult) return cachedResult; + let result = getOverflowAncestors(element, [], false).filter((el) => isElement(el) && getNodeName(el) !== "body"); + let currentContainingBlockComputedStyle = null; + const elementIsFixed = getComputedStyle$1(element).position === "fixed"; + let currentNode = elementIsFixed ? getParentNode(element) : element; + while (isElement(currentNode) && !isLastTraversableNode(currentNode)) { + const computedStyle = getComputedStyle$1(currentNode); + const currentNodeIsContaining = isContainingBlock(currentNode); + if (!currentNodeIsContaining && computedStyle.position === "fixed") currentContainingBlockComputedStyle = null; + if (elementIsFixed ? !currentNodeIsContaining && !currentContainingBlockComputedStyle : !currentNodeIsContaining && computedStyle.position === "static" && !!currentContainingBlockComputedStyle && (currentContainingBlockComputedStyle.position === "absolute" || currentContainingBlockComputedStyle.position === "fixed") || isOverflowElement(currentNode) && !currentNodeIsContaining && hasFixedPositionAncestor(element, currentNode)) result = result.filter((ancestor) => ancestor !== currentNode); + else currentContainingBlockComputedStyle = computedStyle; + currentNode = getParentNode(currentNode); + } + cache.set(element, result); + return result; +} +function getClippingRect(_ref) { + let { element, boundary, rootBoundary, strategy } = _ref; + const clippingAncestors = [...boundary === "clippingAncestors" ? isTopLayer(element) ? [] : getClippingElementAncestors(element, this._c) : [].concat(boundary), rootBoundary]; + const firstRect = getClientRectFromClippingAncestor(element, clippingAncestors[0], strategy); + let top = firstRect.top; + let right = firstRect.right; + let bottom = firstRect.bottom; + let left = firstRect.left; + for (let i = 1; i < clippingAncestors.length; i++) { + const rect = getClientRectFromClippingAncestor(element, clippingAncestors[i], strategy); + top = max(rect.top, top); + right = min(rect.right, right); + bottom = min(rect.bottom, bottom); + left = max(rect.left, left); + } + return { + width: right - left, + height: bottom - top, + x: left, + y: top + }; +} +function getDimensions(element) { + const { width, height } = getCssDimensions(element); + return { + width, + height + }; +} +function getRectRelativeToOffsetParent(element, offsetParent, strategy) { + const isOffsetParentAnElement = isHTMLElement(offsetParent); + const documentElement = getDocumentElement(offsetParent); + const isFixed = strategy === "fixed"; + const rect = getBoundingClientRect(element, true, isFixed, offsetParent); + let scroll = { + scrollLeft: 0, + scrollTop: 0 + }; + const offsets = createCoords(0); + function setLeftRTLScrollbarOffset() { + offsets.x = getWindowScrollBarX(documentElement); + } + if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) { + if (getNodeName(offsetParent) !== "body" || isOverflowElement(documentElement)) scroll = getNodeScroll(offsetParent); + if (isOffsetParentAnElement) { + const offsetRect = getBoundingClientRect(offsetParent, true, isFixed, offsetParent); + offsets.x = offsetRect.x + offsetParent.clientLeft; + offsets.y = offsetRect.y + offsetParent.clientTop; + } else if (documentElement) setLeftRTLScrollbarOffset(); + } + if (isFixed && !isOffsetParentAnElement && documentElement) setLeftRTLScrollbarOffset(); + const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0); + return { + x: rect.left + scroll.scrollLeft - offsets.x - htmlOffset.x, + y: rect.top + scroll.scrollTop - offsets.y - htmlOffset.y, + width: rect.width, + height: rect.height + }; +} +function isStaticPositioned(element) { + return getComputedStyle$1(element).position === "static"; +} +function getTrueOffsetParent(element, polyfill) { + if (!isHTMLElement(element) || getComputedStyle$1(element).position === "fixed") return null; + if (polyfill) return polyfill(element); + let rawOffsetParent = element.offsetParent; + if (getDocumentElement(element) === rawOffsetParent) rawOffsetParent = rawOffsetParent.ownerDocument.body; + return rawOffsetParent; +} +function getOffsetParent(element, polyfill) { + const win = getWindow(element); + if (isTopLayer(element)) return win; + if (!isHTMLElement(element)) { + let svgOffsetParent = getParentNode(element); + while (svgOffsetParent && !isLastTraversableNode(svgOffsetParent)) { + if (isElement(svgOffsetParent) && !isStaticPositioned(svgOffsetParent)) return svgOffsetParent; + svgOffsetParent = getParentNode(svgOffsetParent); + } + return win; + } + let offsetParent = getTrueOffsetParent(element, polyfill); + while (offsetParent && isTableElement(offsetParent) && isStaticPositioned(offsetParent)) offsetParent = getTrueOffsetParent(offsetParent, polyfill); + if (offsetParent && isLastTraversableNode(offsetParent) && isStaticPositioned(offsetParent) && !isContainingBlock(offsetParent)) return win; + return offsetParent || getContainingBlock(element) || win; +} +const getElementRects = async function(data) { + const getOffsetParentFn = this.getOffsetParent || getOffsetParent; + const getDimensionsFn = this.getDimensions; + const floatingDimensions = await getDimensionsFn(data.floating); + return { + reference: getRectRelativeToOffsetParent(data.reference, await getOffsetParentFn(data.floating), data.strategy), + floating: { + x: 0, + y: 0, + width: floatingDimensions.width, + height: floatingDimensions.height + } + }; +}; +function isRTL(element) { + return getComputedStyle$1(element).direction === "rtl"; +} +const platform = { + convertOffsetParentRelativeRectToViewportRelativeRect, + getDocumentElement, + getClippingRect, + getOffsetParent, + getElementRects, + getClientRects, + getDimensions, + getScale, + isElement, + isRTL +}; +function rectsAreEqual(a, b) { + return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height; +} +function observeMove(element, onMove) { + let io = null; + let timeoutId; + const root = getDocumentElement(element); + function cleanup() { + var _io; + clearTimeout(timeoutId); + (_io = io) == null || _io.disconnect(); + io = null; + } + function refresh(skip, threshold) { + if (skip === void 0) skip = false; + if (threshold === void 0) threshold = 1; + cleanup(); + const elementRectForRootMargin = element.getBoundingClientRect(); + const { left, top, width, height } = elementRectForRootMargin; + if (!skip) onMove(); + if (!width || !height) return; + const insetTop = floor(top); + const insetRight = floor(root.clientWidth - (left + width)); + const insetBottom = floor(root.clientHeight - (top + height)); + const insetLeft = floor(left); + const options = { + rootMargin: -insetTop + "px " + -insetRight + "px " + -insetBottom + "px " + -insetLeft + "px", + threshold: max(0, min(1, threshold)) || 1 + }; + let isFirstUpdate = true; + function handleObserve(entries) { + const ratio = entries[0].intersectionRatio; + if (ratio !== threshold) { + if (!isFirstUpdate) return refresh(); + if (!ratio) timeoutId = setTimeout(() => { + refresh(false, 1e-7); + }, 1e3); + else refresh(false, ratio); + } + if (ratio === 1 && !rectsAreEqual(elementRectForRootMargin, element.getBoundingClientRect())) refresh(); + isFirstUpdate = false; + } + try { + io = new IntersectionObserver(handleObserve, { + ...options, + root: root.ownerDocument + }); + } catch (_e) { + io = new IntersectionObserver(handleObserve, options); + } + io.observe(element); + } + refresh(true); + return cleanup; +} +/** +* Automatically updates the position of the floating element when necessary. +* Should only be called when the floating element is mounted on the DOM or +* visible on the screen. +* @returns cleanup function that should be invoked when the floating element is +* removed from the DOM or hidden from the screen. +* @see https://floating-ui.com/docs/autoUpdate +*/ +function autoUpdate(reference, floating, update, options) { + if (options === void 0) options = {}; + const { ancestorScroll = true, ancestorResize = true, elementResize = typeof ResizeObserver === "function", layoutShift = typeof IntersectionObserver === "function", animationFrame = false } = options; + const referenceEl = unwrapElement(reference); + const ancestors = ancestorScroll || ancestorResize ? [...referenceEl ? getOverflowAncestors(referenceEl) : [], ...floating ? getOverflowAncestors(floating) : []] : []; + ancestors.forEach((ancestor) => { + ancestorScroll && ancestor.addEventListener("scroll", update, { passive: true }); + ancestorResize && ancestor.addEventListener("resize", update); + }); + const cleanupIo = referenceEl && layoutShift ? observeMove(referenceEl, update) : null; + let reobserveFrame = -1; + let resizeObserver = null; + if (elementResize) { + resizeObserver = new ResizeObserver((_ref) => { + let [firstEntry] = _ref; + if (firstEntry && firstEntry.target === referenceEl && resizeObserver && floating) { + resizeObserver.unobserve(floating); + cancelAnimationFrame(reobserveFrame); + reobserveFrame = requestAnimationFrame(() => { + var _resizeObserver; + (_resizeObserver = resizeObserver) == null || _resizeObserver.observe(floating); + }); + } + update(); + }); + if (referenceEl && !animationFrame) resizeObserver.observe(referenceEl); + if (floating) resizeObserver.observe(floating); + } + let frameId; + let prevRefRect = animationFrame ? getBoundingClientRect(reference) : null; + if (animationFrame) frameLoop(); + function frameLoop() { + const nextRefRect = getBoundingClientRect(reference); + if (prevRefRect && !rectsAreEqual(prevRefRect, nextRefRect)) update(); + prevRefRect = nextRefRect; + frameId = requestAnimationFrame(frameLoop); + } + update(); + return () => { + var _resizeObserver2; + ancestors.forEach((ancestor) => { + ancestorScroll && ancestor.removeEventListener("scroll", update); + ancestorResize && ancestor.removeEventListener("resize", update); + }); + cleanupIo?.(); + (_resizeObserver2 = resizeObserver) == null || _resizeObserver2.disconnect(); + resizeObserver = null; + if (animationFrame) cancelAnimationFrame(frameId); + }; +} +/** +* Modifies the placement by translating the floating element along the +* specified axes. +* A number (shorthand for `mainAxis` or distance), or an axes configuration +* object may be passed. +* @see https://floating-ui.com/docs/offset +*/ +const offset = offset$1; +/** +* Optimizes the visibility of the floating element by shifting it in order to +* keep it in view when it will overflow the clipping boundary. +* @see https://floating-ui.com/docs/shift +*/ +const shift = shift$1; +/** +* Optimizes the visibility of the floating element by flipping the `placement` +* in order to keep it in view when the preferred placement(s) will overflow the +* clipping boundary. Alternative to `autoPlacement`. +* @see https://floating-ui.com/docs/flip +*/ +const flip = flip$1; +/** +* Provides data to position an inner element of the floating element so that it +* appears centered to the reference element. +* @see https://floating-ui.com/docs/arrow +*/ +const arrow = arrow$1; +/** +* Computes the `x` and `y` coordinates that will place the floating element +* next to a given reference element. +*/ +const computePosition = (reference, floating, options) => { + const cache = /* @__PURE__ */ new Map(); + const mergedOptions = { + platform, + ...options + }; + const platformWithCache = { + ...mergedOptions.platform, + _c: cache + }; + return computePosition$1(reference, floating, { + ...mergedOptions, + platform: platformWithCache + }); +}; +//#endregion +//#region js/src/util/floating-ui.ts +/** +* Breakpoints for responsive placement (matches SCSS $breakpoints) +*/ +const BREAKPOINTS = { + sm: 576, + md: 768, + lg: 1024, + xl: 1280, + "2xl": 1536 +}; +/** +* Parse a placement string that may contain responsive prefixes +* Example: "bottom-start md:top-end lg:right" returns { xs: 'bottom-start', md: 'top-end', lg: 'right' } +* +* @param placementString - The placement string to parse +* @param defaultPlacement - The default placement to use for xs/base +* @returns Object with breakpoint keys and placement values, or null if not responsive +*/ +const parseResponsivePlacement = (placementString, defaultPlacement = "bottom") => { + if (!placementString || !placementString.includes(":")) return null; + const parts = placementString.split(/\s+/); + const placements = { xs: defaultPlacement }; + for (const part of parts) if (part.includes(":")) { + const [breakpoint, placement] = part.split(":"); + if (BREAKPOINTS[breakpoint] !== void 0) placements[breakpoint] = placement; + } else placements.xs = part; + return placements; +}; +/** +* Get the active placement for the current viewport width +* +* @param responsivePlacements - Object with breakpoint keys and placement values +* @param defaultPlacement - Fallback placement +* @returns The active placement for current viewport +*/ +const getResponsivePlacement = (responsivePlacements, defaultPlacement = "bottom") => { + if (!responsivePlacements) return defaultPlacement; + const viewportWidth = window.innerWidth; + let activePlacement = responsivePlacements.xs || defaultPlacement; + for (const breakpoint of [ + "sm", + "md", + "lg", + "xl", + "2xl" + ]) if (viewportWidth >= BREAKPOINTS[breakpoint] && responsivePlacements[breakpoint]) activePlacement = responsivePlacements[breakpoint]; + return activePlacement; +}; +/** +* Create media query listeners for responsive placement changes +* +* @param callback - Callback to run when breakpoint changes +* @returns Array of { mql, handler } objects for cleanup +*/ +const createBreakpointListeners = (callback) => { + const listeners = []; + for (const breakpoint of Object.keys(BREAKPOINTS)) { + const minWidth = BREAKPOINTS[breakpoint]; + const mql = window.matchMedia(`(min-width: ${minWidth}px)`); + mql.addEventListener("change", callback); + listeners.push({ + mql, + handler: callback + }); + } + return listeners; +}; +/** +* Clean up media query listeners +* +* @param listeners - Array of { mql, handler } objects +*/ +const disposeBreakpointListeners = (listeners) => { + for (const { mql, handler } of listeners) mql.removeEventListener("change", handler); +}; +/** +* Normalize an offset value into Floating UI's offset shape. +* A `[skidding, distance]` array becomes `{ mainAxis: distance, crossAxis: skidding }`; +* numbers and axis objects pass through unchanged. +*/ +const toFloatingOffset = (value) => { + return Array.isArray(value) ? { + mainAxis: value[1] || 0, + crossAxis: value[0] || 0 + } : value; +}; +//#endregion +//#region js/src/menu.ts +/** +* -------------------------------------------------------------------------- +* Bootstrap menu.ts +* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) +* -------------------------------------------------------------------------- +*/ +/** +* Constants +*/ +const NAME$17 = "menu"; +const EVENT_KEY$14 = `.bs.menu`; +const DATA_API_KEY$9 = ".data-api"; +const ESCAPE_KEY$2 = "Escape"; +const TAB_KEY$1 = "Tab"; +const ARROW_UP_KEY$2 = "ArrowUp"; +const ARROW_DOWN_KEY$2 = "ArrowDown"; +const ARROW_LEFT_KEY$1 = "ArrowLeft"; +const ARROW_RIGHT_KEY$1 = "ArrowRight"; +const HOME_KEY$2 = "Home"; +const END_KEY$2 = "End"; +const ENTER_KEY$1 = "Enter"; +const SPACE_KEY$1 = " "; +const RIGHT_MOUSE_BUTTON = 2; +const SUBMENU_CLOSE_DELAY = 100; +const EVENT_HIDE$5 = `hide${EVENT_KEY$14}`; +const EVENT_HIDDEN$7 = `hidden${EVENT_KEY$14}`; +const EVENT_SHOW$6 = `show${EVENT_KEY$14}`; +const EVENT_SHOWN$5 = `shown${EVENT_KEY$14}`; +const EVENT_CLICK_DATA_API$5 = `click${EVENT_KEY$14}${DATA_API_KEY$9}`; +const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY$14}${DATA_API_KEY$9}`; +const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY$14}${DATA_API_KEY$9}`; +const CLASS_NAME_SHOW$5 = "show"; +const SELECTOR_DATA_TOGGLE$8 = "[data-bs-toggle=\"menu\"]:not(.disabled):not(:disabled)"; +const SELECTOR_MENU$3 = ".menu"; +const SELECTOR_SUBMENU = ".submenu"; +const SELECTOR_SUBMENU_TOGGLE = ".submenu > .menu-item"; +const SELECTOR_NAVBAR_NAV = ".navbar-nav"; +const SELECTOR_VISIBLE_ITEMS$1 = ".menu-item:not(.disabled):not(:disabled)"; +const DEFAULT_PLACEMENT = "bottom-start"; +const SUBMENU_PLACEMENT = "end-start"; +const resolveLogicalPlacement = (placement) => { + if (isRTL$1()) return placement.replace(/^start(?=-|$)/, "right").replace(/^end(?=-|$)/, "left"); + return placement.replace(/^start(?=-|$)/, "left").replace(/^end(?=-|$)/, "right"); +}; +const triangleSign = (p1, p2, p3) => (p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y); +const Default$16 = { + autoClose: true, + boundary: "clippingParents", + container: false, + display: "dynamic", + offset: [0, 2], + floatingConfig: null, + menu: null, + placement: DEFAULT_PLACEMENT, + reference: "toggle", + strategy: "absolute", + submenuTrigger: "both", + submenuDelay: SUBMENU_CLOSE_DELAY +}; +const DefaultType$16 = { + autoClose: "(boolean|string)", + boundary: "(string|element)", + container: "(string|element|boolean)", + display: "string", + offset: "(array|string|function)", + floatingConfig: "(null|object|function)", + menu: "(null|element)", + placement: "string", + reference: "(string|element|object)", + strategy: "string", + submenuTrigger: "string", + submenuDelay: "number" +}; +/** +* Class definition +*/ +var Menu = class Menu extends BaseComponent { + static _openInstances = /* @__PURE__ */ new Set(); + constructor(element, config) { + if (typeof computePosition === "undefined") throw new TypeError("Bootstrap's menus require Floating UI (https://floating-ui.com)"); + super(element, config); + this._floatingCleanup = null; + this._mediaQueryListeners = []; + this._responsivePlacements = null; + this._parent = this._element.parentNode; + this._openSubmenus = /* @__PURE__ */ new Map(); + this._submenuCloseTimeouts = /* @__PURE__ */ new Map(); + this._hoverIntentData = null; + this._menu = this._config.menu || this._findMenu(); + if (!this._config.menu && this._menu) this._parent = this._findWrapper(this._menu); + this._isSubmenu = this._parent.classList?.contains("submenu"); + this._menuOriginalParent = this._menu?.parentNode; + this._parseResponsivePlacements(); + this._setupSubmenuListeners(); + this._initSubmenuTriggers(); + } + static get Default() { + return Default$16; + } + static get DefaultType() { + return DefaultType$16; + } + static get NAME() { + return NAME$17; + } + toggle() { + return this._isShown() ? this.hide() : this.show(); + } + async show() { + if (isDisabled(this._element) || this._isShown()) return; + const relatedTarget = { relatedTarget: this._element }; + if (EventHandler.trigger(this._element, EVENT_SHOW$6, relatedTarget).defaultPrevented) return; + this._moveMenuToContainer(); + this._createFloating(); + if ("ontouchstart" in document.documentElement && !this._parent.closest(SELECTOR_NAVBAR_NAV)) for (const element of document.body.children) EventHandler.on(element, "mouseover", noop); + this._element.focus({ focusVisible: false }); + this._element.setAttribute("aria-expanded", "true"); + this._menu.classList.add(CLASS_NAME_SHOW$5); + this._element.classList.add(CLASS_NAME_SHOW$5); + if (this._parent) this._parent.classList.add(CLASS_NAME_SHOW$5); + Menu._openInstances.add(this); + await this._queueCallback(() => { + if (this._isShown()) EventHandler.trigger(this._element, EVENT_SHOWN$5, relatedTarget); + }, this._menu, this._isAnimated()); + } + async hide() { + if (isDisabled(this._element) || !this._isShown()) return; + const relatedTarget = { relatedTarget: this._element }; + await this._completeHide(relatedTarget); + } + dispose() { + this._disposeFloating(); + this._restoreMenuToOriginalParent(); + this._disposeMediaQueryListeners(); + this._closeAllSubmenus(); + this._clearAllSubmenuTimeouts(); + Menu._openInstances.delete(this); + super.dispose(); + } + update() { + if (this._floatingCleanup) this._updateFloatingPosition(); + } + _findMenu() { + const wrapper = SelectorEngine.closest(this._element, `:has(${SELECTOR_MENU$3})`); + return SelectorEngine.next(this._element, SELECTOR_MENU$3)[0] || SelectorEngine.prev(this._element, SELECTOR_MENU$3)[0] || SelectorEngine.findOne(SELECTOR_MENU$3, wrapper || this._parent); + } + _findWrapper(menu) { + let wrapper = this._element.parentNode; + while (wrapper instanceof Element && !wrapper.contains(menu)) wrapper = wrapper.parentNode; + return wrapper instanceof Element ? wrapper : this._element.parentNode; + } + async _completeHide(relatedTarget) { + if (EventHandler.trigger(this._element, EVENT_HIDE$5, relatedTarget).defaultPrevented) return; + this._closeAllSubmenus(); + if ("ontouchstart" in document.documentElement) for (const element of document.body.children) EventHandler.off(element, "mouseover", noop); + this._menu.classList.remove(CLASS_NAME_SHOW$5); + this._element.classList.remove(CLASS_NAME_SHOW$5); + if (this._parent) this._parent.classList.remove(CLASS_NAME_SHOW$5); + this._element.setAttribute("aria-expanded", "false"); + Menu._openInstances.delete(this); + await this._queueCallback(() => { + if (this._isShown()) return; + this._disposeFloating(); + this._restoreMenuToOriginalParent(); + Manipulator.removeDataAttribute(this._menu, "placement"); + Manipulator.removeDataAttribute(this._menu, "display"); + EventHandler.trigger(this._element, EVENT_HIDDEN$7, relatedTarget); + }, this._menu, this._isAnimated()); + } + _getConfig(config) { + config = super._getConfig(config); + if (typeof config.reference === "object" && !isElement$1(config.reference) && typeof config.reference.getBoundingClientRect !== "function") throw new TypeError(`${NAME$17.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`); + return config; + } + _createFloating() { + if (this._config.display === "static") { + Manipulator.setDataAttribute(this._menu, "display", "static"); + return; + } + let referenceElement = this._element; + if (this._config.reference === "parent") referenceElement = this._parent; + else if (isElement$1(this._config.reference)) referenceElement = getElement(this._config.reference); + else if (typeof this._config.reference === "object") referenceElement = this._config.reference; + this._updateFloatingPosition(referenceElement); + this._floatingCleanup = autoUpdate(referenceElement, this._menu, () => this._updateFloatingPosition(referenceElement)); + } + async _updateFloatingPosition(referenceElement = null) { + if (!this._menu) return; + if (!referenceElement) if (this._config.reference === "parent") referenceElement = this._parent; + else if (isElement$1(this._config.reference)) referenceElement = getElement(this._config.reference); + else if (typeof this._config.reference === "object") referenceElement = this._config.reference; + else referenceElement = this._element; + const placement = this._getPlacement(); + const middleware = this._getFloatingMiddleware(); + const floatingConfig = this._getFloatingConfig(placement, middleware); + await this._applyFloatingPosition(referenceElement, this._menu, floatingConfig.placement, floatingConfig.middleware, floatingConfig.strategy); + } + _isShown() { + return this._menu.classList.contains(CLASS_NAME_SHOW$5); + } + _isAnimated() { + return getTransitionDurationFromElement(this._menu) > 0; + } + _getPlacement() { + const placement = this._responsivePlacements ? getResponsivePlacement(this._responsivePlacements, DEFAULT_PLACEMENT) : this._config.placement; + return resolveLogicalPlacement(placement); + } + _parseResponsivePlacements() { + this._responsivePlacements = parseResponsivePlacement(this._config.placement, DEFAULT_PLACEMENT); + if (this._responsivePlacements) this._setupMediaQueryListeners(); + } + _setupMediaQueryListeners() { + this._disposeMediaQueryListeners(); + this._mediaQueryListeners = createBreakpointListeners(() => { + if (this._isShown()) this._updateFloatingPosition(); + }); + } + _disposeMediaQueryListeners() { + disposeBreakpointListeners(this._mediaQueryListeners); + this._mediaQueryListeners = []; + } + _getOffset() { + const { offset: offsetConfig } = this._config; + if (typeof offsetConfig === "string") return offsetConfig.split(",").map((value) => Number.parseInt(value, 10)); + if (typeof offsetConfig === "function") return ({ placement, rects }) => { + return toFloatingOffset(offsetConfig({ + placement, + reference: rects.reference, + floating: rects.floating + }, this._element)); + }; + return offsetConfig; + } + _getFloatingMiddleware() { + const offsetValue = this._getOffset(); + return [ + offset(typeof offsetValue === "function" ? offsetValue : toFloatingOffset(offsetValue)), + flip({ + fallbackPlacements: this._getFallbackPlacements(), + fallbackStrategy: "initialPlacement" + }), + shift({ boundary: this._config.boundary === "clippingParents" ? "clippingAncestors" : this._config.boundary }) + ]; + } + _getFallbackPlacements() { + return { + bottom: [ + "top", + "bottom-start", + "bottom-end", + "top-start", + "top-end" + ], + "bottom-start": [ + "top-start", + "bottom-end", + "top-end" + ], + "bottom-end": [ + "top-end", + "bottom-start", + "top-start" + ], + top: [ + "bottom", + "top-start", + "top-end", + "bottom-start", + "bottom-end" + ], + "top-start": [ + "bottom-start", + "top-end", + "bottom-end" + ], + "top-end": [ + "bottom-end", + "top-start", + "bottom-start" + ], + right: [ + "left", + "right-start", + "right-end", + "left-start", + "left-end" + ], + "right-start": [ + "left-start", + "right-end", + "left-end", + "top-start", + "bottom-start" + ], + "right-end": [ + "left-end", + "right-start", + "left-start", + "top-end", + "bottom-end" + ], + left: [ + "right", + "left-start", + "left-end", + "right-start", + "right-end" + ], + "left-start": [ + "right-start", + "left-end", + "right-end", + "top-start", + "bottom-start" + ], + "left-end": [ + "right-end", + "left-start", + "right-start", + "top-end", + "bottom-end" + ] + }[this._getPlacement()] || [ + "top", + "bottom", + "right", + "left" + ]; + } + _getFloatingConfig(placement, middleware) { + const defaultConfig = { + placement, + middleware, + strategy: this._config.strategy + }; + return { + ...defaultConfig, + ...execute(this._config.floatingConfig, [void 0, defaultConfig]) + }; + } + _disposeFloating() { + if (this._floatingCleanup) { + this._floatingCleanup(); + this._floatingCleanup = null; + } + } + _getContainer() { + const { container } = this._config; + if (container === false) return null; + return container === true ? document.body : getElement(container); + } + _moveMenuToContainer() { + const container = this._getContainer(); + if (!container || !this._menu) return; + if (this._menu.parentNode !== container) container.append(this._menu); + } + _restoreMenuToOriginalParent() { + if (!this._menuOriginalParent || !this._menu) return; + if (this._menu.parentNode !== this._menuOriginalParent) this._menuOriginalParent.append(this._menu); + } + async _applyFloatingPosition(reference, floating, placement, middleware, strategy = "absolute") { + if (!floating.isConnected) return null; + const { x, y, placement: finalPlacement } = await computePosition(reference, floating, { + placement, + middleware, + strategy + }); + if (!floating.isConnected) return null; + Object.assign(floating.style, { + position: strategy, + left: `${x}px`, + top: `${y}px`, + margin: "0" + }); + Manipulator.setDataAttribute(floating, "placement", finalPlacement); + return finalPlacement; + } + _setupSubmenuListeners() { + if (this._config.submenuTrigger === "hover" || this._config.submenuTrigger === "both") { + EventHandler.on(this._menu, "mouseenter", SELECTOR_SUBMENU_TOGGLE, (event) => { + this._onSubmenuTriggerEnter(event); + }); + EventHandler.on(this._menu, "mouseleave", SELECTOR_SUBMENU, (event) => { + this._onSubmenuLeave(event); + }); + EventHandler.on(this._menu, "mousemove", (event) => { + this._trackMousePosition(event); + }); + } + if (this._config.submenuTrigger === "click" || this._config.submenuTrigger === "both") EventHandler.on(this._menu, "click", SELECTOR_SUBMENU_TOGGLE, (event) => { + this._onSubmenuTriggerClick(event); + }); + } + _onSubmenuTriggerEnter(event) { + const trigger = event.target.closest(SELECTOR_SUBMENU_TOGGLE); + if (!trigger) return; + const submenuWrapper = trigger.closest(SELECTOR_SUBMENU); + const submenu = SelectorEngine.findOne(SELECTOR_MENU$3, submenuWrapper); + if (!submenu) return; + this._cancelSubmenuCloseTimeout(submenu); + this._closeSiblingSubmenus(submenuWrapper); + this._openSubmenu(trigger, submenu, submenuWrapper); + } + _onSubmenuLeave(event) { + const submenuWrapper = event.target.closest(SELECTOR_SUBMENU); + const submenu = SelectorEngine.findOne(SELECTOR_MENU$3, submenuWrapper); + if (!submenu || !this._openSubmenus.has(submenu)) return; + if (this._isMovingTowardSubmenu(event, submenu)) return; + this._scheduleSubmenuClose(submenu, submenuWrapper); + } + _onSubmenuTriggerClick(event) { + const trigger = event.target.closest(SELECTOR_SUBMENU_TOGGLE); + if (!trigger) return; + event.preventDefault(); + event.stopPropagation(); + const submenuWrapper = trigger.closest(SELECTOR_SUBMENU); + const submenu = SelectorEngine.findOne(SELECTOR_MENU$3, submenuWrapper); + if (!submenu) return; + if (this._openSubmenus.has(submenu)) this._closeSubmenu(submenu, submenuWrapper); + else { + this._closeSiblingSubmenus(submenuWrapper); + this._openSubmenu(trigger, submenu, submenuWrapper); + } + } + _initSubmenuTriggers() { + if (!this._menu) return; + for (const trigger of SelectorEngine.find(SELECTOR_SUBMENU_TOGGLE, this._menu)) { + if (!SelectorEngine.findOne(SELECTOR_MENU$3, trigger.parentElement)) continue; + trigger.setAttribute("aria-haspopup", "true"); + if (!trigger.hasAttribute("aria-expanded")) trigger.setAttribute("aria-expanded", "false"); + } + } + _openSubmenu(trigger, submenu, submenuWrapper) { + if (this._openSubmenus.has(submenu)) return; + trigger.setAttribute("aria-expanded", "true"); + trigger.setAttribute("aria-haspopup", "true"); + submenu.style.opacity = "0"; + submenu.classList.add(CLASS_NAME_SHOW$5); + submenuWrapper.classList.add(CLASS_NAME_SHOW$5); + const cleanup = this._createSubmenuFloating(trigger, submenu, submenuWrapper); + this._openSubmenus.set(submenu, cleanup); + EventHandler.on(submenu, "mouseenter", () => { + this._cancelSubmenuCloseTimeout(submenu); + }); + } + _closeSubmenu(submenu, submenuWrapper) { + if (!this._openSubmenus.has(submenu)) return; + const nestedSubmenus = SelectorEngine.find(`${SELECTOR_SUBMENU} ${SELECTOR_MENU$3}.${CLASS_NAME_SHOW$5}`, submenu); + for (const nested of nestedSubmenus) { + const nestedWrapper = nested.closest(SELECTOR_SUBMENU); + this._closeSubmenu(nested, nestedWrapper); + } + const trigger = SelectorEngine.findOne(SELECTOR_SUBMENU_TOGGLE, submenuWrapper); + const cleanup = this._openSubmenus.get(submenu); + if (cleanup) cleanup(); + this._openSubmenus.delete(submenu); + EventHandler.off(submenu, "mouseenter"); + if (trigger) trigger.setAttribute("aria-expanded", "false"); + submenu.classList.remove(CLASS_NAME_SHOW$5); + submenuWrapper.classList.remove(CLASS_NAME_SHOW$5); + submenu.style.opacity = ""; + } + _closeAllSubmenus() { + for (const [submenu] of this._openSubmenus) { + const submenuWrapper = submenu.closest(SELECTOR_SUBMENU); + this._closeSubmenu(submenu, submenuWrapper); + } + } + _closeSiblingSubmenus(currentSubmenuWrapper) { + const parent = currentSubmenuWrapper.parentNode; + const siblingSubmenus = SelectorEngine.find(`${SELECTOR_SUBMENU} > ${SELECTOR_MENU$3}.${CLASS_NAME_SHOW$5}`, parent); + for (const siblingMenu of siblingSubmenus) { + const siblingWrapper = siblingMenu.closest(SELECTOR_SUBMENU); + if (siblingWrapper !== currentSubmenuWrapper) this._closeSubmenu(siblingMenu, siblingWrapper); + } + } + _createSubmenuFloating(trigger, submenu, submenuWrapper) { + const referenceElement = submenuWrapper; + const placement = resolveLogicalPlacement(SUBMENU_PLACEMENT); + const middleware = [ + offset({ + mainAxis: 0, + crossAxis: -4 + }), + flip({ fallbackPlacements: [ + resolveLogicalPlacement("start-start"), + resolveLogicalPlacement("end-end"), + resolveLogicalPlacement("start-end") + ] }), + shift({ padding: 8 }) + ]; + const updatePosition = () => this._applyFloatingPosition(referenceElement, submenu, placement, middleware).then((finalPlacement) => { + submenu.style.opacity = ""; + return finalPlacement; + }); + updatePosition(); + return autoUpdate(referenceElement, submenu, updatePosition); + } + _scheduleSubmenuClose(submenu, submenuWrapper) { + this._cancelSubmenuCloseTimeout(submenu); + const timeoutId = setTimeout(() => { + this._closeSubmenu(submenu, submenuWrapper); + this._submenuCloseTimeouts.delete(submenu); + }, this._config.submenuDelay); + this._submenuCloseTimeouts.set(submenu, timeoutId); + } + _cancelSubmenuCloseTimeout(submenu) { + const timeoutId = this._submenuCloseTimeouts.get(submenu); + if (timeoutId) { + clearTimeout(timeoutId); + this._submenuCloseTimeouts.delete(submenu); + } + } + _clearAllSubmenuTimeouts() { + for (const timeoutId of this._submenuCloseTimeouts.values()) clearTimeout(timeoutId); + this._submenuCloseTimeouts.clear(); + } + _trackMousePosition(event) { + this._hoverIntentData = { + x: event.clientX, + y: event.clientY, + timestamp: Date.now() + }; + } + _isMovingTowardSubmenu(event, submenu) { + if (!this._hoverIntentData) return false; + const submenuRect = submenu.getBoundingClientRect(); + const currentPos = { + x: event.clientX, + y: event.clientY + }; + const lastPos = { + x: this._hoverIntentData.x, + y: this._hoverIntentData.y + }; + const targetX = isRTL$1() ? submenuRect.right : submenuRect.left; + const topCorner = { + x: targetX, + y: submenuRect.top + }; + const bottomCorner = { + x: targetX, + y: submenuRect.bottom + }; + return this._pointInTriangle(currentPos, lastPos, topCorner, bottomCorner); + } + _pointInTriangle(point, v1, v2, v3) { + const d1 = triangleSign(point, v1, v2); + const d2 = triangleSign(point, v2, v3); + const d3 = triangleSign(point, v3, v1); + return !((d1 < 0 || d2 < 0 || d3 < 0) && (d1 > 0 || d2 > 0 || d3 > 0)); + } + _getItemsInMenu(menu) { + return SelectorEngine.find(`:scope > ${SELECTOR_VISIBLE_ITEMS$1}, :scope > ${SELECTOR_SUBMENU} > ${SELECTOR_VISIBLE_ITEMS$1}`, menu).filter((element) => isVisible(element)); + } + _selectMenuItem({ key, target }) { + const currentMenu = target.closest(SELECTOR_MENU$3) || this._menu; + const items = this._getItemsInMenu(currentMenu); + if (!items.length) return; + const nextItem = getNextActiveElement(items, target, key === ARROW_DOWN_KEY$2, !items.includes(target)); + nextItem.focus(); + this._closeUnrelatedSubmenus(currentMenu, nextItem); + } + _closeUnrelatedSubmenus(currentMenu, focusedElement) { + for (const [submenu] of this._openSubmenus) { + const submenuWrapper = submenu.closest(SELECTOR_SUBMENU); + if (!submenuWrapper || submenuWrapper.parentElement !== currentMenu || submenuWrapper.contains(focusedElement)) continue; + this._closeSubmenu(submenu, submenuWrapper); + } + } + _handleSubmenuKeydown(event) { + const { key, target } = event; + const isRtl = isRTL$1(); + const enterKey = isRtl ? ARROW_LEFT_KEY$1 : ARROW_RIGHT_KEY$1; + const exitKey = isRtl ? ARROW_RIGHT_KEY$1 : ARROW_LEFT_KEY$1; + const submenuWrapper = target.closest(SELECTOR_SUBMENU); + const isSubmenuToggle = target.matches(SELECTOR_SUBMENU_TOGGLE); + if ((key === ENTER_KEY$1 || key === SPACE_KEY$1 || key === enterKey) && submenuWrapper && isSubmenuToggle) { + event.preventDefault(); + event.stopPropagation(); + const submenu = SelectorEngine.findOne(SELECTOR_MENU$3, submenuWrapper); + if (submenu) { + this._closeSiblingSubmenus(submenuWrapper); + this._openSubmenu(target, submenu, submenuWrapper); + requestAnimationFrame(() => { + const firstItem = SelectorEngine.findOne(SELECTOR_VISIBLE_ITEMS$1, submenu); + if (firstItem) firstItem.focus(); + }); + } + return true; + } + if (key === exitKey) { + const currentMenu = target.closest(SELECTOR_MENU$3); + const parentSubmenuWrapper = currentMenu?.closest(SELECTOR_SUBMENU); + if (parentSubmenuWrapper) { + event.preventDefault(); + event.stopPropagation(); + const parentTrigger = SelectorEngine.findOne(SELECTOR_SUBMENU_TOGGLE, parentSubmenuWrapper); + this._closeSubmenu(currentMenu, parentSubmenuWrapper); + if (parentTrigger) parentTrigger.focus(); + return true; + } + } + if (key === HOME_KEY$2 || key === END_KEY$2) { + event.preventDefault(); + event.stopPropagation(); + const currentMenu = target.closest(SELECTOR_MENU$3); + const items = this._getItemsInMenu(currentMenu); + if (items.length) { + const targetItem = key === HOME_KEY$2 ? items[0] : items.at(-1); + targetItem.focus(); + this._closeUnrelatedSubmenus(currentMenu, targetItem); + } + return true; + } + return false; + } + static clearMenus(event) { + if (event.button === RIGHT_MOUSE_BUTTON || event.type === "keyup" && event.key !== TAB_KEY$1) return; + for (const instance of Menu._openInstances) { + if (instance._config.autoClose === false) continue; + const composedPath = event.composedPath(); + const isMenuTarget = composedPath.includes(instance._menu); + if (composedPath.includes(instance._element) || instance._config.autoClose === "inside" && !isMenuTarget || instance._config.autoClose === "outside" && isMenuTarget) continue; + const formAncestor = event.target.closest?.("form"); + const isInsideMenuForm = Boolean(formAncestor) && instance._menu.contains(formAncestor); + if (instance._menu.contains(event.target) && (event.type === "keyup" && event.key === TAB_KEY$1 || /input|select|option|textarea|form/i.test(event.target.tagName) || isInsideMenuForm)) continue; + const relatedTarget = { relatedTarget: instance._element }; + if (event.type === "click") relatedTarget.clickEvent = event; + instance._completeHide(relatedTarget); + } + } + static _getToggleFromKeydownContext(element, event) { + if (element.matches(SELECTOR_DATA_TOGGLE$8)) return element; + for (const instance of Menu._openInstances) if (instance._element === event.target || instance._menu?.contains(event.target)) return instance._element; + return SelectorEngine.prev(element, SELECTOR_DATA_TOGGLE$8)[0] || SelectorEngine.next(element, SELECTOR_DATA_TOGGLE$8)[0] || SelectorEngine.findOne(SELECTOR_DATA_TOGGLE$8, event.delegateTarget.parentNode); + } + static dataApiKeydownHandler(event) { + const isInput = /input|textarea/i.test(event.target.tagName) || event.target.isContentEditable; + const isEscapeEvent = event.key === ESCAPE_KEY$2; + const isUpOrDownEvent = [ARROW_UP_KEY$2, ARROW_DOWN_KEY$2].includes(event.key); + const isLeftOrRightEvent = [ARROW_LEFT_KEY$1, ARROW_RIGHT_KEY$1].includes(event.key); + const isHomeOrEndEvent = [HOME_KEY$2, END_KEY$2].includes(event.key); + const isEnterOrSpaceEvent = [ENTER_KEY$1, SPACE_KEY$1].includes(event.key); + const isSubmenuTrigger = event.target.matches(SELECTOR_SUBMENU_TOGGLE); + if (!isUpOrDownEvent && !isEscapeEvent && !isLeftOrRightEvent && !isHomeOrEndEvent && !(isEnterOrSpaceEvent && isSubmenuTrigger)) return; + if (isInput && !isEscapeEvent) return; + const getToggleButton = Menu._getToggleFromKeydownContext(this, event); + if (!getToggleButton) return; + const instance = Menu.getOrCreateInstance(getToggleButton); + if ((isLeftOrRightEvent || isHomeOrEndEvent || isEnterOrSpaceEvent && isSubmenuTrigger) && instance._handleSubmenuKeydown(event)) return; + if (isUpOrDownEvent) { + event.preventDefault(); + event.stopPropagation(); + instance.show(); + instance._selectMenuItem(event); + return; + } + if (isEscapeEvent && instance._isShown()) { + event.preventDefault(); + event.stopPropagation(); + const currentMenu = event.target.closest(SELECTOR_MENU$3); + const parentSubmenuWrapper = currentMenu?.closest(SELECTOR_SUBMENU); + if (parentSubmenuWrapper && instance._openSubmenus.size > 0) { + const parentTrigger = SelectorEngine.findOne(SELECTOR_SUBMENU_TOGGLE, parentSubmenuWrapper); + instance._closeSubmenu(currentMenu, parentSubmenuWrapper); + if (parentTrigger) parentTrigger.focus(); + return; + } + instance.hide(); + getToggleButton.focus(); + } + } +}; +/** +* Data API implementation +*/ +EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE$8, Menu.dataApiKeydownHandler); +EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU$3, Menu.dataApiKeydownHandler); +EventHandler.on(document, EVENT_CLICK_DATA_API$5, Menu.clearMenus); +EventHandler.on(document, EVENT_KEYUP_DATA_API, Menu.clearMenus); +EventHandler.on(document, EVENT_CLICK_DATA_API$5, SELECTOR_DATA_TOGGLE$8, function(event) { + event.preventDefault(); + Menu.getOrCreateInstance(this).toggle(); +}); +//#endregion +//#region js/src/combobox.ts +/** +* -------------------------------------------------------------------------- +* Bootstrap combobox.ts +* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) +* -------------------------------------------------------------------------- +*/ +/** +* Constants +*/ +const NAME$16 = "combobox"; +const EVENT_KEY$13 = `.bs.combobox`; +const DATA_API_KEY$8 = ".data-api"; +const ESCAPE_KEY$1 = "Escape"; +const TAB_KEY = "Tab"; +const ARROW_UP_KEY$1 = "ArrowUp"; +const ARROW_DOWN_KEY$1 = "ArrowDown"; +const HOME_KEY$1 = "Home"; +const END_KEY$1 = "End"; +const ENTER_KEY = "Enter"; +const SPACE_KEY = " "; +const EVENT_CHANGE$3 = `change${EVENT_KEY$13}`; +const EVENT_SHOW$5 = `show${EVENT_KEY$13}`; +const EVENT_SHOWN$4 = `shown${EVENT_KEY$13}`; +const EVENT_HIDE$4 = `hide${EVENT_KEY$13}`; +const EVENT_HIDDEN$6 = `hidden${EVENT_KEY$13}`; +const EVENT_CLICK_DATA_API$4 = `click${EVENT_KEY$13}${DATA_API_KEY$8}`; +const CLASS_NAME_SHOW$4 = "show"; +const CLASS_NAME_SELECTED = "selected"; +const CLASS_NAME_PLACEHOLDER = "combobox-placeholder"; +const SELECTOR_DATA_TOGGLE$7 = "[data-bs-toggle=\"combobox\"]"; +const SELECTOR_MENU$2 = ".menu"; +const SELECTOR_MENU_ITEM = ".menu-item[data-bs-value]"; +const SELECTOR_VISIBLE_ITEMS = ".menu-item[data-bs-value]:not(.disabled):not(:disabled)"; +const SELECTOR_VALUE = ".combobox-value"; +const SELECTOR_SEARCH_INPUT = ".combobox-search-input"; +const SELECTOR_NO_RESULTS = ".combobox-no-results"; +const Default$15 = { + boundary: "clippingParents", + multiple: false, + name: null, + offset: [0, 2], + placeholder: "", + placement: "bottom-start", + search: false, + searchNormalize: false +}; +const DefaultType$15 = { + boundary: "(string|element)", + multiple: "boolean", + name: "(string|null)", + offset: "(array|string|function)", + placeholder: "string", + placement: "string", + search: "boolean", + searchNormalize: "boolean" +}; +/** +* Class definition +*/ +var Combobox = class extends BaseComponent { + constructor(element, config) { + super(element, config); + this._toggle = this._element; + this._menu = SelectorEngine.next(this._toggle, SELECTOR_MENU$2)[0]; + this._valueDisplay = SelectorEngine.findOne(SELECTOR_VALUE, this._toggle); + this._searchInput = SelectorEngine.findOne(SELECTOR_SEARCH_INPUT, this._menu); + this._noResults = SelectorEngine.findOne(SELECTOR_NO_RESULTS, this._menu); + this._hiddenInput = null; + this._menuInstance = null; + this._createHiddenInput(); + this._createMenuInstance(); + this._syncInitialSelection(); + this._addEventListeners(); + } + static get Default() { + return Default$15; + } + static get DefaultType() { + return DefaultType$15; + } + static get NAME() { + return NAME$16; + } + toggle() { + return this._isShown() ? this.hide() : this.show(); + } + async show() { + if (isDisabled(this._toggle) || this._isShown()) return; + if (EventHandler.trigger(this._toggle, EVENT_SHOW$5).defaultPrevented) return; + this._menuInstance.show(); + if (this._searchInput) { + this._searchInput.value = ""; + this._filterItems(""); + requestAnimationFrame(() => this._searchInput.focus()); + } + EventHandler.trigger(this._toggle, EVENT_SHOWN$4); + } + async hide() { + if (!this._isShown()) return; + if (EventHandler.trigger(this._toggle, EVENT_HIDE$4).defaultPrevented) return; + this._menuInstance.hide(); + EventHandler.trigger(this._toggle, EVENT_HIDDEN$6); + } + dispose() { + if (this._menuInstance) { + this._menuInstance.dispose(); + this._menuInstance = null; + } + if (this._hiddenInput) { + this._hiddenInput.remove(); + this._hiddenInput = null; + } + EventHandler.off(this._menu, EVENT_KEY$13); + EventHandler.off(this._toggle, EVENT_KEY$13); + EventHandler.off(this._searchInput, EVENT_KEY$13); + super.dispose(); + } + _isShown() { + return this._menu.classList.contains(CLASS_NAME_SHOW$4); + } + _createHiddenInput() { + const { name } = this._config; + if (!name) return; + this._hiddenInput = document.createElement("input"); + this._hiddenInput.type = "hidden"; + this._hiddenInput.name = name; + this._hiddenInput.value = ""; + this._toggle.parentNode.insertBefore(this._hiddenInput, this._toggle); + } + _createMenuInstance() { + this._menuInstance = new Menu(this._toggle, { + menu: this._menu, + autoClose: this._config.multiple ? "outside" : true, + boundary: this._config.boundary, + offset: this._config.offset, + placement: this._config.placement + }); + } + _syncInitialSelection() { + if (this._getSelectedItems().length > 0) { + this._updateToggleText(); + this._updateHiddenInput(); + } else this._showPlaceholder(); + } + _addEventListeners() { + EventHandler.on(this._menu, `click${EVENT_KEY$13}`, SELECTOR_MENU_ITEM, (event) => { + const item = event.target.closest(SELECTOR_MENU_ITEM); + if (!item || isDisabled(item)) return; + event.preventDefault(); + event.stopPropagation(); + this._selectItem(item); + }); + EventHandler.on(this._toggle, `keydown${EVENT_KEY$13}`, (event) => { + this._handleToggleKeydown(event); + }); + EventHandler.on(this._menu, `keydown${EVENT_KEY$13}`, (event) => { + this._handleMenuKeydown(event); + }); + if (this._searchInput) { + EventHandler.on(this._searchInput, `input${EVENT_KEY$13}`, () => { + this._filterItems(this._searchInput.value); + }); + EventHandler.on(this._searchInput, `keydown${EVENT_KEY$13}`, (event) => { + if (event.key === ARROW_DOWN_KEY$1) { + event.preventDefault(); + const items = this._getVisibleItems(); + if (items.length > 0) items[0].focus(); + } + if (event.key === ESCAPE_KEY$1) { + this.hide(); + this._toggle.focus(); + } + }); + } + } + _selectItem(item) { + if (this._config.multiple) { + item.classList.toggle(CLASS_NAME_SELECTED); + setAriaAttribute(item, "aria-selected", item.classList.contains(CLASS_NAME_SELECTED)); + } else { + const previouslySelected = SelectorEngine.find(`.${CLASS_NAME_SELECTED}`, this._menu); + for (const prev of previouslySelected) { + prev.classList.remove(CLASS_NAME_SELECTED); + prev.setAttribute("aria-selected", "false"); + } + item.classList.add(CLASS_NAME_SELECTED); + item.setAttribute("aria-selected", "true"); + } + this._updateToggleText(); + this._updateHiddenInput(); + const value = this._config.multiple ? this._getSelectedItems().map((el) => el.dataset.bsValue) : item.dataset.bsValue; + EventHandler.trigger(this._toggle, EVENT_CHANGE$3, { + value, + item + }); + if (!this._config.multiple) { + this.hide(); + this._toggle.focus(); + } + } + _updateToggleText() { + const selectedItems = this._getSelectedItems(); + if (selectedItems.length === 0) { + this._showPlaceholder(); + return; + } + this._valueDisplay.classList.remove(CLASS_NAME_PLACEHOLDER); + if (this._config.multiple && selectedItems.length > 1) this._valueDisplay.textContent = `${selectedItems.length} selected`; + else { + const item = selectedItems[0]; + const label = SelectorEngine.findOne(".menu-item-content > span:first-child", item); + this._valueDisplay.textContent = label ? label.textContent : item.textContent.trim(); + } + } + _showPlaceholder() { + const { placeholder } = this._config; + if (placeholder) { + this._valueDisplay.textContent = placeholder; + this._valueDisplay.classList.add(CLASS_NAME_PLACEHOLDER); + } + } + _updateHiddenInput() { + if (!this._hiddenInput) return; + const values = this._getSelectedItems().map((el) => el.dataset.bsValue); + this._hiddenInput.value = this._config.multiple ? values.join(",") : values[0] || ""; + } + _getSelectedItems() { + return SelectorEngine.find(`.${CLASS_NAME_SELECTED}`, this._menu); + } + _getVisibleItems() { + return SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter((item) => isVisible(item)); + } + _filterItems(query) { + const normalizedQuery = this._normalizeText(query.toLowerCase().trim()); + const items = SelectorEngine.find(SELECTOR_MENU_ITEM, this._menu); + let visibleCount = 0; + for (const item of items) { + const text = this._normalizeText(item.textContent.toLowerCase().trim()); + const matches = !normalizedQuery || text.includes(normalizedQuery); + item.style.display = matches ? "" : "none"; + if (matches) visibleCount++; + } + if (this._noResults) this._noResults.classList.toggle("d-none", visibleCount > 0); + } + _normalizeText(text) { + if (this._config.searchNormalize) return text.normalize("NFD").replace(/[\u0300-\u036F]/g, ""); + return text; + } + _handleToggleKeydown(event) { + const { key } = event; + if (key === ARROW_DOWN_KEY$1 || key === ARROW_UP_KEY$1) { + event.preventDefault(); + if (!this._isShown()) this.show(); + const items = this._getVisibleItems(); + if (items.length > 0) (key === ARROW_DOWN_KEY$1 ? items[0] : items.at(-1)).focus(); + return; + } + if ((key === ENTER_KEY || key === SPACE_KEY) && !this._isShown()) { + event.preventDefault(); + this.show(); + } + } + _handleMenuKeydown(event) { + const { key, target } = event; + if (key === ESCAPE_KEY$1) { + event.preventDefault(); + event.stopPropagation(); + this.hide(); + this._toggle.focus(); + return; + } + if (key === TAB_KEY) { + this.hide(); + return; + } + const isInput = target.matches("input"); + if (key === ARROW_DOWN_KEY$1 || key === ARROW_UP_KEY$1) { + event.preventDefault(); + const items = this._getVisibleItems(); + if (items.length > 0) getNextActiveElement(items, target, key === ARROW_DOWN_KEY$1, !items.includes(target)).focus(); + return; + } + if (key === HOME_KEY$1 || key === END_KEY$1) { + event.preventDefault(); + const items = this._getVisibleItems(); + if (items.length > 0) (key === HOME_KEY$1 ? items[0] : items.at(-1)).focus(); + return; + } + if ((key === ENTER_KEY || key === SPACE_KEY) && !isInput) { + event.preventDefault(); + const item = target.closest(SELECTOR_MENU_ITEM); + if (item && !isDisabled(item)) this._selectItem(item); + } + } +}; +/** +* Data API implementation +*/ +EventHandler.on(document, EVENT_CLICK_DATA_API$4, SELECTOR_DATA_TOGGLE$7, function(event) { + event.preventDefault(); + Combobox.getOrCreateInstance(this).toggle(); +}); +EventHandler.on(document, "DOMContentLoaded", () => { + for (const toggle of SelectorEngine.find(SELECTOR_DATA_TOGGLE$7)) Combobox.getOrCreateInstance(toggle); +}); +//#endregion +//#region node_modules/vanilla-calendar-pro/index.mjs +/*! name: vanilla-calendar-pro v3.4.0 | url: https://github.com/uvarov-frontend/vanilla-calendar-pro */ +var e = (e) => /* @__PURE__ */ new Date(`${e}T00:00:00`); +var t = (e) => `${e.getFullYear()}-${String(e.getMonth() + 1).padStart(2, "0")}-${String(e.getDate()).padStart(2, "0")}`; +var n = (n, a) => n.reduce((n, l) => { + if (l instanceof Date || "number" == typeof l) { + let e = l instanceof Date ? l : new Date(l); + n.push(t(e)); + } else l.match(/^(\d{4}-\d{2}-\d{2})$/g) ? n.push(l) : l.replace(/(\d{4}-\d{2}-\d{2}).*?(\d{4}-\d{2}-\d{2})/g, (l, o, r) => { + var i; + let s = `${o}:${r}`, c = a ? a.start.getTime() : -Infinity, d = null == a || null == (i = a.cursors) ? void 0 : i.get(s), u = void 0 !== d && d <= c ? new Date(d) : e(o), m = e(r).setHours(23, 59, 59, 999); + if (a) { + if (m < c) return l; + m = Math.min(m, new Date(a.end).setHours(23, 59, 59, 999)); + } + let p = !1; + for (let e = u.getTime(); e <= m; e = u.setDate(u.getDate() + 1)) (!a || e >= c) && (null != a && a.cursors && !p && (a.cursors.set(s, e), p = !0), n.push(t(u))); + return l; + }); + return n; +}, []); +var a = (e, t) => { + if (t && t.values.length === e.length) { + let n = 0; + for (; n < e.length && t.values[n] === e[n];) n++; + if (n === e.length) return t; + } + return { + values: e.slice(), + set: new Set(e) + }; +}; +var l = /* @__PURE__ */ new WeakMap(); +var o = (e) => { + var t; + let o = null != (t = e.selectedHolidays) && t[0] ? e.selectedHolidays : [], r = JSON.stringify(o.map((e) => e instanceof Date ? e.getTime() : e)), i = l.get(e); + l.set(e, { + holidayKey: r, + holidays: (null == i ? void 0 : i.holidayKey) === r ? i.holidays : new Set(n(o)), + selected: a(e.context.selectedDates, null == i ? void 0 : i.selected), + disabled: a(e.context.disableDates, null == i ? void 0 : i.disabled), + enabled: a(e.context.enableDates, null == i ? void 0 : i.enabled), + min: Date.parse(`${e.context.displayDateMin}T00:00:00`), + max: Date.parse(`${e.context.displayDateMax}T00:00:00`), + first: Date.parse(`${e.context.selectedDates[0]}T00:00:00`), + last: Date.parse(`${e.context.selectedDates[e.context.selectedDates.length - 1]}T00:00:00`) + }); +}; +var r = (e) => l.get(e); +var i = [ + "motion", + "time", + "annotations", + "weeks", + "months" +]; +var s = /* @__PURE__ */ new WeakMap(); +var c = {}; +var d = /* @__PURE__ */ Object.freeze([]); +var u = (e) => { + var t; + return null == (t = s.get(e)) ? c : t; +}; +var m = (e, t = e) => { + if (t.extensions && t.extensions !== e.extensions && (new Set(t.extensions).size !== e.extensions.length || t.extensions.some((t) => !e.extensions.includes(t)))) throw Error("Calendar extensions are fixed at construction. Create a new Calendar to change them."); + let n = u(e), a = (e, t, a) => { + if (e && !n[t]) throw Error(`The "${a}" option requires ${t}. Import { ${t} } from 'vanilla-calendar-pro' and add it to extensions: [${t}].`); + }; + a(t.animation || t.enableSwipe, "motion", t.animation ? "animation" : "enableSwipe"), a(t.selectionTimeMode, "time", "selectionTimeMode"), a(t.popups && Object.keys(t.popups).length || t.onCreateDateRangeTooltip, "annotations", t.onCreateDateRangeTooltip ? "onCreateDateRangeTooltip" : "popups"), a("multiple" === t.type, "months", "type"), a("week" === t.type || t.enableCollapse || t.enableWeekNumbers || t.onClickWeekDay, "weeks", "week" === t.type ? "type" : t.enableCollapse ? "enableCollapse" : t.enableWeekNumbers ? "enableWeekNumbers" : "onClickWeekDay"); +}; +var p = (e, t, n) => { + var a; + return null == (a = u(e).annotations) ? void 0 : a.tooltip(e, t, n); +}; +var h = /* @__PURE__ */ new WeakMap(); +var v = (e) => { + let t = h.get(e); + return t || (t = { + lastDateEl: null, + isHovering: !1, + rangeMin: void 0, + rangeMax: void 0, + tooltipEl: null, + timeoutId: null, + frameId: null + }, h.set(e, t)), t; +}; +var y = (e) => { + e.context.mainElement.querySelectorAll("[data-vc-date-hover]").forEach((e) => e.removeAttribute("data-vc-date-hover")); +}; +var g = (e, t, n) => { + e.context[t] = n; +}; +var f = (e, t) => void 0 === t || ("function" == typeof t ? t(e) : t); +var x = (e) => f(e, e.enableDateToggle); +var b = (e) => { + if (e.length < 3 || e.includes(void 0)) return e.sort((e, t) => +new Date(e) - new Date(t)); + let t = e.map((e) => ({ + date: e, + time: +new Date(e) + })); + return t.sort((e, t) => e.time - t.time), t.forEach((t, n) => e[n] = t.date), e; +}; +var D = (e) => { + var t; + let n = h.get(e); + n && (null == (t = n.cleanup) || t.call(n), n.cleanup = void 0, null !== n.timeoutId && clearTimeout(n.timeoutId), null !== n.frameId && cancelAnimationFrame(n.frameId), n.lastDateEl = null, n.tooltipEl = null, n.timeoutId = null, n.frameId = null, h.delete(e)); +}; +var M = (a, l, o = !0) => { + let r = v(a); + if (r.lastDateEl = l, y(a), !r.cleanup) { + let n = a.context.mainElement, l = ((n) => (a) => { + if (!n.context.selectedDates[0] || 1 !== n.context.selectedDates.length && !n.onCreateDateRangeTooltip) return; + let l = v(n); + if (l.isHovering) return; + let o = a.target; + l.isHovering = !0, l.frameId = requestAnimationFrame(() => { + var a; + l.frameId = null, l.isHovering = !1, !n.context.isDestroyed && n.context.mainElement.contains(o) && (1 === n.context.selectedDates.length ? ((n, a) => { + var l; + let o = v(n); + if (n.context.mainElement.hasAttribute("data-vc-dragging") || !a || null == n || null == (l = n.context) || !l.selectedDates[0]) return; + if (!a.closest("[data-vc=\"dates\"]")) return o.lastDateEl = null, p(n, o.tooltipEl, null), void y(n); + let r = a.closest("[data-vc-date]"); + if (!r || o.lastDateEl === r) return; + o.lastDateEl = r, p(n, o.tooltipEl, r), y(n); + let i = r.dataset.vcDate, s = e(n.context.selectedDates[0]), c = e(i), [d, u] = s < c ? [s, c] : [c, s], [m, h] = s < c ? [n.context.selectedDates[0], i] : [i, n.context.selectedDates[0]], g = new Set(n.context.disableDates), f = new Date(d); + for (; f <= u && g.has(t(f));) f.setDate(f.getDate() + 1); + f <= u && n.context.mainElement.querySelectorAll("[data-vc-date]").forEach((t) => { + let n = t.dataset.vcDate; + if (n === m || n === h) t.dataset.vcDateHover = m === h ? "first-and-last" : n === m ? "first" : "last"; + else { + let a = e(n); + a >= d && a <= u && !g.has(n) && (t.dataset.vcDateHover = ""); + } + }); + })(n, o) : n.context.selectedDates[0] && n.onCreateDateRangeTooltip && (null == (a = u(n).annotations) || a.hover(n, o))); + }); + })(a), o = () => ((e) => { + let t = v(e); + null !== t.timeoutId && clearTimeout(t.timeoutId), t.timeoutId = setTimeout(() => { + t.timeoutId = null, !e.context.isDestroyed && (t.lastDateEl = null, p(e, t.tooltipEl, null), y(e)); + }, 50); + })(a), i = (e) => ((e, t) => { + if ("Escape" !== t.key || 1 !== e.context.selectedDates.length) return; + let n = v(e); + n.lastDateEl = null, g(e, "selectedDates", []), p(e, n.tooltipEl, null), y(e); + })(a, e); + n.addEventListener("mousemove", l), n.addEventListener("mouseleave", o), n.addEventListener("keydown", i), r.cleanup = () => { + n.removeEventListener("mousemove", l), n.removeEventListener("mouseleave", o), n.removeEventListener("keydown", i); + }; + } + a.disableDatesGaps && (r.rangeMin ??= a.context.displayDateMin, r.rangeMax ??= a.context.displayDateMax), r.tooltipEl = a.onCreateDateRangeTooltip ? a.context.mainElement.querySelector("[data-vc-date-range-tooltip]") : null; + let i = null == l ? void 0 : l.dataset.vcDate; + if (i) { + let e = 1 === a.context.selectedDates.length && a.context.selectedDates[0].includes(i); + g(a, "selectedDates", e && !x(a) ? [i, i] : e && x(a) ? [] : a.context.selectedDates.length > 1 ? [i] : [...a.context.selectedDates, i]), a.context.selectedDates.length > 1 && b(a.context.selectedDates); + } + ({ + set: () => { + a.disableDatesGaps && ((n) => { + var a, l; + if (null == n || null == (a = n.context) || null == (a = a.selectedDates) || !a[0] || null == (l = n.context.disableDates) || !l[0]) return; + let o = e(n.context.selectedDates[0]), [r, i] = n.context.disableDates.map((t) => e(t)).reduce(([e, t], n) => [o >= n ? n : e, o < n && null === t ? n : t], [null, null]); + r && g(n, "displayDateMin", t(new Date(r.setDate(r.getDate() + 1)))), i && g(n, "displayDateMax", t(new Date(i.setDate(i.getDate() - 1)))), n.disableDatesPast && !n.disableAllDates && e(n.context.displayDateMin) < e(n.context.dateToday) && g(n, "displayDateMin", n.context.dateToday); + })(a), p(a, r.tooltipEl, l); + }, + reset: () => { + if (!o) return; + let [e, t] = [a.context.selectedDates[0], a.context.selectedDates[a.context.selectedDates.length - 1]]; + g(a, "selectedDates", a.context.selectedDates[0] === a.context.selectedDates[a.context.selectedDates.length - 1] ? [a.context.selectedDates[0], a.context.selectedDates[0]] : a.enableEdgeDatesOnly ? [e, t] : (() => { + let l = new Set(a.context.disableDates); + return n([`${e}:${t}`]).filter((e) => !l.has(e)); + })()), a.disableDatesGaps && (g(a, "displayDateMin", r.rangeMin), g(a, "displayDateMax", r.rangeMax)), a.onCreateDateRangeTooltip && p(a, r.tooltipEl, a.context.selectedDates[0] ? l : null); + } + })[1 === a.context.selectedDates.length ? "set" : "reset"](); +}; +var w = (e) => e.getRootNode ? e.getRootNode() : document; +var E = /* @__PURE__ */ new WeakSet(); +var k = "data-vc-prev-tabindex"; +var T = (e) => e.tabIndex >= 0 && !e.hasAttribute("disabled") && "true" !== e.getAttribute("aria-disabled"); +var A = (e) => { + if (e.hasAttribute(k)) return; + let t = e.getAttribute("tabindex"); + e.setAttribute(k, null == t ? "" : t); +}; +var C = (e) => { + if (!e.hasAttribute(k)) return; + let t = e.getAttribute(k); + "" === t || null === t ? e.removeAttribute("tabindex") : e.setAttribute("tabindex", t), e.removeAttribute(k); +}; +var S = (e) => { + e.setAttribute("inert", ""), e.ariaHidden = "true", ((e) => { + T(e) && (A(e), e.tabIndex = -1); + let t = document.createTreeWalker(e, NodeFilter.SHOW_ELEMENT, { acceptNode: (e) => T(e) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP }); + for (; t.nextNode();) { + let e = t.currentNode; + A(e), e.tabIndex = -1; + } + })(e); +}; +var $ = (e) => { + var t; + if (H(e), !e.context.isShowInInputMode || !e.context.currentType) return; + let n = e.context.mainElement.contains(w(e.context.mainElement).activeElement); + e.context.mainElement.dataset.vcCalendarHidden = "", g(e, "isShowInInputMode", !1), e.inputMode && S(e.context.mainElement), null != (t = e.context.inputElement) && t.hasAttribute("aria-expanded") && e.context.inputElement.setAttribute("aria-expanded", "false"), e.context.cleanupHandlers[0] && (e.context.cleanupHandlers.forEach((e) => e()), g(e, "cleanupHandlers", [])), e.inputMode && e.context.inputElement && n && (("function" == typeof e.openOnFocus || !0 === e.openOnFocus) && ((e) => { + E.add(e); + })(e), e.context.inputElement.focus()), e.onHide && e.onHide(e); +}; +function Y(e) { + if (null == e || !e.getBoundingClientRect) return { + top: 0, + bottom: 0, + left: 0, + right: 0 + }; + let t = e.getBoundingClientRect(), n = document.documentElement; + return { + bottom: t.bottom, + right: t.right, + top: t.top + window.scrollY - n.clientTop, + left: t.left + window.scrollX - n.clientLeft + }; +} +function N() { + return { + vw: Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0), + vh: Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0) + }; +} +function I(e, t, n = 5) { + let a = { + top: !0, + bottom: !0, + left: !0, + right: !0 + }, l = []; + if (!t || !e) return { + canShow: a, + parentPositions: l + }; + let { bottom: o, top: r } = function(e) { + let { top: t, left: n } = { + left: window.scrollX || document.documentElement.scrollLeft || 0, + top: window.scrollY || document.documentElement.scrollTop || 0 + }, { top: a, left: l } = Y(e), { vh: o, vw: r } = N(), i = a - t, s = l - n; + return { + top: i, + bottom: o - (i + e.clientHeight), + left: s, + right: r - (s + e.clientWidth) + }; + }(e), { top: i, left: s } = Y(e), { height: c, width: d } = t.getBoundingClientRect(), { vh: u, vw: m } = N(), p = m / 2, h = u / 2; + return [ + { + condition: i < h, + position: "top" + }, + { + condition: i > h, + position: "bottom" + }, + { + condition: s < p, + position: "left" + }, + { + condition: s > p, + position: "right" + } + ].forEach(({ condition: e, position: t }) => { + e && l.push(t); + }), Object.assign(a, { + top: c <= r - n, + bottom: c <= o - n, + left: d <= s, + right: d <= m - s + }), { + canShow: a, + parentPositions: l + }; +} +var L = (e, t, n) => { + if (!e) return; + let a = "auto" === n ? function(e, t) { + let n = "left"; + if (!t || !e) return n; + let { canShow: a, parentPositions: l } = I(e, t), o = a.left && a.right; + return (o && a.bottom ? "center" : o && a.top ? ["top", "center"] : Array.isArray(l) ? ["bottom" === l[0] ? "top" : "bottom", ...l.slice(1)] : l) || n; + }(e, t) : n, l = { + top: -t.offsetHeight, + bottom: e.offsetHeight, + left: 0, + center: e.offsetWidth / 2 - t.offsetWidth / 2, + right: e.offsetWidth - t.offsetWidth + }, o = Array.isArray(a) ? a[0] : "bottom", r = Array.isArray(a) ? a[1] : a; + t.dataset.vcPosition = o; + let { top: i, left: s } = Y(e), c = i + l[o], d = s + l[r], { vw: u } = N(); + if (d + t.clientWidth > u) { + let e = window.innerWidth - document.body.clientWidth; + d = u - t.clientWidth - e; + } else d < 0 && (d = 0); + Object.assign(t.style, { + left: `${d}px`, + top: `${c}px` + }); +}; +var W = /* @__PURE__ */ new WeakMap(); +var H = (e) => { + clearTimeout(W.get(e)), W.delete(e); +}; +var O = (e) => { + H(e), W.set(e, setTimeout(() => { + W.delete(e), e.context.isDestroyed || q(e); + })); +}; +var q = (e) => { + var t, n; + if (H(e), e.context.isShowInInputMode || e.context.isDestroyed) return; + if (!e.context.currentType) return void e.context.mainElement.click(); + g(e, "cleanupHandlers", []), g(e, "isShowInInputMode", !0), e.inputMode && ((n = e.context.mainElement).removeAttribute("inert"), n.removeAttribute("aria-hidden"), ((e) => { + C(e), e.querySelectorAll(`[${k}]`).forEach(C); + })(n)), L(e.context.inputElement, e.context.mainElement, e.positionToInput), e.context.mainElement.removeAttribute("data-vc-calendar-hidden"), null != (t = e.context.inputElement) && t.hasAttribute("aria-expanded") && e.context.inputElement.setAttribute("aria-expanded", "true"); + let a = () => { + L(e.context.inputElement, e.context.mainElement, e.positionToInput); + }; + window.addEventListener("resize", a), e.context.cleanupHandlers.push(() => window.removeEventListener("resize", a)); + let l = (t) => { + "Escape" === t.key && $(e); + }; + document.addEventListener("keydown", l), e.context.cleanupHandlers.push(() => document.removeEventListener("keydown", l)); + let o = (t) => { + var n; + let a = null == (n = t.composedPath()[0]) ? t.target : n; + a === e.context.inputElement || e.context.mainElement.contains(a) || $(e); + }; + document.addEventListener("click", o, { capture: !0 }), e.context.cleanupHandlers.push(() => document.removeEventListener("click", o, { capture: !0 })), e.onShow && e.onShow(e); +}; +var F = "The calendar has not been initialized, please initialize it using the \"init()\" method first."; +var P = "You specified an incorrect language label or did not specify the required number of values for «locale.weekdays» or «locale.months»."; +var _ = (e) => String(e).replace(/[&<>"']/g, (e) => ({ + "&": "&", + "<": "<", + ">": ">", + "\"": """, + "'": "'" +})[e]); +var R = (e, t) => `\n
`s get reset. However, we also reset the -// bottom margin to use `rem` units instead of `em`. - -p { - margin-top: 0; - margin-bottom: $paragraph-margin-bottom; -} - - -// Abbreviations -// -// 1. Add the correct text decoration in Chrome, Edge, Opera, and Safari. -// 2. Add explicit cursor to indicate changed behavior. -// 3. Prevent the text-decoration to be skipped. - -abbr[title] { - text-decoration: underline dotted; // 1 - cursor: help; // 2 - text-decoration-skip-ink: none; // 3 -} - - -// Address - -address { - margin-bottom: 1rem; - font-style: normal; - line-height: inherit; -} - - -// Lists - -ol, -ul { - padding-left: 2rem; -} - -ol, -ul, -dl { - margin-top: 0; - margin-bottom: 1rem; -} - -ol ol, -ul ul, -ol ul, -ul ol { - margin-bottom: 0; -} - -dt { - font-weight: $dt-font-weight; -} - -// 1. Undo browser default - -dd { - margin-bottom: .5rem; - margin-left: 0; // 1 -} - - -// Blockquote - -blockquote { - margin: 0 0 1rem; -} - - -// Strong -// -// Add the correct font weight in Chrome, Edge, and Safari - -b, -strong { - font-weight: $font-weight-bolder; -} - - -// Small -// -// Add the correct font size in all browsers - -small { - @include font-size($small-font-size); -} - - -// Mark - -mark { - padding: $mark-padding; - color: var(--#{$prefix}highlight-color); - background-color: var(--#{$prefix}highlight-bg); -} - - -// Sub and Sup -// -// Prevent `sub` and `sup` elements from affecting the line height in -// all browsers. - -sub, -sup { - position: relative; - @include font-size($sub-sup-font-size); - line-height: 0; - vertical-align: baseline; -} - -sub { bottom: -.25em; } -sup { top: -.5em; } - - -// Links - -a { - color: rgba(var(--#{$prefix}link-color-rgb), var(--#{$prefix}link-opacity, 1)); - text-decoration: $link-decoration; - - &:hover { - --#{$prefix}link-color-rgb: var(--#{$prefix}link-hover-color-rgb); - text-decoration: $link-hover-decoration; - } -} - -// And undo these styles for placeholder links/named anchors (without href). -// It would be more straightforward to just use a[href] in previous block, but that -// causes specificity issues in many other styles that are too complex to fix. -// See https://github.com/twbs/bootstrap/issues/19402 - -a:not([href]):not([class]) { - &, - &:hover { - color: inherit; - text-decoration: none; - } -} - - -// Code - -pre, -code, -kbd, -samp { - font-family: $font-family-code; - @include font-size(1em); // Correct the odd `em` font sizing in all browsers. -} - -// 1. Remove browser default top margin -// 2. Reset browser default of `1em` to use `rem`s -// 3. Don't allow content to break outside - -pre { - display: block; - margin-top: 0; // 1 - margin-bottom: 1rem; // 2 - overflow: auto; // 3 - @include font-size($code-font-size); - color: $pre-color; - - // Account for some code outputs that place code tags in pre tags - code { - @include font-size(inherit); - color: inherit; - word-break: normal; - } -} - -code { - @include font-size($code-font-size); - color: var(--#{$prefix}code-color); - word-wrap: break-word; - - // Streamline the style when inside anchors to avoid broken underline and more - a > & { - color: inherit; - } -} - -kbd { - padding: $kbd-padding-y $kbd-padding-x; - @include font-size($kbd-font-size); - color: $kbd-color; - background-color: $kbd-bg; - @include border-radius($border-radius-sm); - - kbd { - padding: 0; - @include font-size(1em); - font-weight: $nested-kbd-font-weight; - } -} - - -// Figures -// -// Apply a consistent margin strategy (matches our type styles). - -figure { - margin: 0 0 1rem; -} - - -// Images and content - -img, -svg { - vertical-align: middle; -} - - -// Tables -// -// Prevent double borders - -table { - caption-side: bottom; - border-collapse: collapse; -} - -caption { - padding-top: $table-cell-padding-y; - padding-bottom: $table-cell-padding-y; - color: $table-caption-color; - text-align: left; -} - -// 1. Removes font-weight bold by inheriting -// 2. Matches default `
`s get reset. However, we also reset the + // bottom margin to use `rem` units instead of `em`. + + p { + margin-top: 0; + margin-bottom: var(--paragraph-margin-bottom); + } + + // Abbreviations + // + // 1. Add the correct text decoration in Chrome, Edge, Opera, and Safari. + // 2. Add explicit cursor to indicate changed behavior. + // 3. Prevent the text-decoration to be skipped. + + abbr[title] { + text-decoration: underline dotted; // 1 + cursor: help; // 2 + text-decoration-skip-ink: none; // 3 + } + + // Builds on `abbr` + .initialism { + font-size: var(--initialism-font-size, var(--font-size-xs)); + text-transform: uppercase; + } + + // Address + + address { + margin-bottom: var(--spacer); + font-style: normal; + line-height: inherit; + } + + // Lists + + ol, + ul { + padding-inline-start: var(--list-padding-x); + } + + ol, + ul, + dl { + margin-top: 0; + margin-bottom: var(--spacer); + } + + ol ol, + ul ul, + ol ul, + ul ol { + margin-bottom: 0; + } + + dt { + font-weight: var(--dt-font-weight, var(--font-weight-bold)); + } + + // 1. Undo browser default + + dd { + margin-inline-start: 0; // 1 + margin-bottom: var(--spacer-2); + } + + // Blockquote + + blockquote { + margin: 0 0 var(--spacer); + > * { + margin-block: 0; + } + } + + // Strong + // + // Add the correct font weight in Chrome, Edge, and Safari + + b, + strong { + font-weight: var(--font-weight-bolder); + } + + // Small + // + // Add the correct font size in all browsers + + small, + .small { + font-size: var(--small-font-size, 87.5%); + } + + // Mark + + mark, + .mark { + @include tokens($reboot-mark-tokens); + padding: var(--mark-padding); + color: var(--mark-color); + background-color: var(--mark-bg); + } + + // Sub and Sup + // + // Prevent `sub` and `sup` elements from affecting the line height in + // all browsers. + + sub, + sup { + position: relative; + font-size: var(--sub-sup-font-size, .75em); + line-height: 0; + vertical-align: baseline; + } + + sub { bottom: -.25em; } + sup { top: -.5em; } + + // Links + + a { + color: var(--theme-fg, var(--link-color)); + text-decoration: var(--link-decoration); + text-underline-offset: var(--link-underline-offset); + + &:hover { + color: var(--theme-fg-emphasis, var(--link-hover-color)); + text-decoration: var(--link-hover-decoration, var(--link-decoration)); + } + } + + // And undo these styles for placeholder links/named anchors (without href). + // It would be more straightforward to just use a[href] in previous block, but that + // causes specificity issues in many other styles that are too complex to fix. + // See https://github.com/twbs/bootstrap/issues/19402 + + a:not([href], [class]) { + &, + &:hover { + color: inherit; + text-decoration: none; + } + } + + // Code + + pre, + code, + kbd, + samp { + font-family: var(--font-mono); + font-size: 1em; // Correct the odd `em` font sizing in all browsers. + } + + // 1. Remove browser default top margin + // 2. Reset browser default of `1em` to use `rem`s + // 3. Don't allow content to break outside + // 4. Reserve room for the scrollbar so it cannot sit on top of the last line + + pre { + display: block; + margin-top: 0; // 1 + margin-bottom: var(--spacer); // 2 + overflow: auto; // 3 + font-size: var(--code-font-size); + color: var(--code-color, inherit); + scrollbar-gutter: stable; // 4 + + // Account for some code outputs that place code tags in pre tags + code { + font-size: inherit; + color: inherit; + word-break: normal; + } + } + + code { + font-size: var(--code-font-size); + color: var(--code-color); + word-wrap: break-word; + + // Streamline the style when inside anchors to avoid broken underline and more + a > & { + color: inherit; + } + } + + kbd { + @include tokens($reboot-kbd-tokens); + padding: var(--kbd-padding-y) var(--kbd-padding-x); + font-size: var(--kbd-font-size); + color: var(--kbd-color); + background-color: var(--kbd-bg); + @include border-radius(var(--kbd-border-radius)); + + kbd { + padding: 0; + font-size: 1em; + } + } + + // Figures + // + // Apply a consistent margin strategy (matches our type styles). + + figure { + margin: 0 0 var(--spacer); + } + + // Images and content + + img, + svg { + vertical-align: middle; + } + + // Tables + // + // Prevent double borders + + table { + caption-side: bottom; + border-collapse: collapse; + } + + caption { + padding-block: var(--spacer-2); + color: var(--fg-3); + text-align: start; + } + + // 1. Matches default `