From 1c9ce8db5bde0af412af5baa7182baa0574148c2 Mon Sep 17 00:00:00 2001 From: Mark Otto Date: Sat, 21 Feb 2026 12:42:33 -0800 Subject: [PATCH 1/6] Add custom select component with docs and form integration Introduces a new CustomSelect plugin with searchable rich-option rendering, wires it into JS/SCSS exports, and documents usage in the forms docs/sidebar. Polish theme, control, and code-copy UI details. Adjusts secondary/button visual tokens and control typography while simplifying code snippet copy button labels across docs shortcodes. Improve docs examples layout and interactive snippets. Expands grid column utility coverage in docs, refines docs section-card responsiveness, and updates button playground snippet rendering/highlighting behavior. Made-with: Cursor --- dist/css/bootstrap-reboot.css | 9 +- dist/css/bootstrap-reboot.css.map | 2 +- dist/css/bootstrap-utilities.css | 66 +- dist/css/bootstrap-utilities.css.map | 2 +- dist/css/bootstrap.css | 245 +- dist/css/bootstrap.css.map | 2 +- dist/js/bootstrap.bundle.js | 5101 ++++++++++------- dist/js/bootstrap.bundle.js.map | 2 +- dist/js/bootstrap.js | 1067 +++- dist/js/bootstrap.js.map | 2 +- js/dist/custom-select.js | 734 +++ js/dist/custom-select.js.map | 1 + js/index.js | 1 + js/src/custom-select.js | 830 +++ scss/_dropdown.scss | 2 +- scss/_theme.scss | 6 +- scss/_utilities.scss | 3 + scss/buttons/_button.scss | 3 +- scss/content/_reboot.scss | 5 + scss/forms/_custom-select.scss | 185 + scss/forms/index.scss | 1 + site/data/plugins.yml | 4 + site/data/sidebar.yml | 1 + .../shortcodes/ButtonPlayground.astro | 60 +- site/src/content/docs/components/buttons.mdx | 3 +- site/src/content/docs/forms/custom-select.mdx | 462 ++ site/src/content/docs/utilities/grid.mdx | 19 +- site/src/layouts/DocsLayout.astro | 3 +- site/src/scss/_component-examples.scss | 30 +- 29 files changed, 6416 insertions(+), 2435 deletions(-) create mode 100644 js/dist/custom-select.js create mode 100644 js/dist/custom-select.js.map create mode 100644 js/src/custom-select.js create mode 100644 scss/forms/_custom-select.scss create mode 100644 site/src/content/docs/forms/custom-select.mdx diff --git a/dist/css/bootstrap-reboot.css b/dist/css/bootstrap-reboot.css index 7637a32e48d4..196378f3e400 100644 --- a/dist/css/bootstrap-reboot.css +++ b/dist/css/bootstrap-reboot.css @@ -378,13 +378,13 @@ --bs-inverse-border: light-dark(var(--bs-gray-400), var(--bs-gray-100)); --bs-inverse-focus-ring: color-mix(in oklch, light-dark(var(--bs-gray-900), var(--bs-gray-100)) 50%, var(--bs-bg-body)); --bs-inverse-contrast: light-dark(var(--bs-white), var(--bs-gray-900)); - --bs-secondary-base: var(--bs-gray-200); + --bs-secondary-base: var(--bs-gray-100); --bs-secondary-text: light-dark(var(--bs-gray-600), var(--bs-gray-400)); --bs-secondary-text-emphasis: light-dark(var(--bs-gray-800), var(--bs-gray-200)); - --bs-secondary-bg: light-dark(var(--bs-gray-100), var(--bs-gray-600)); + --bs-secondary-bg: light-dark(var(--bs-gray-050), var(--bs-gray-600)); --bs-secondary-bg-subtle: light-dark(var(--bs-gray-050), var(--bs-gray-800)); --bs-secondary-bg-muted: light-dark(var(--bs-gray-100), var(--bs-gray-700)); - --bs-secondary-border: light-dark(var(--bs-gray-300), var(--bs-gray-600)); + --bs-secondary-border: light-dark(color-mix(in oklch, var(--bs-gray-100), var(--bs-gray-200)), var(--bs-gray-600)); --bs-secondary-focus-ring: color-mix(in oklch, light-dark(var(--bs-gray-500), var(--bs-gray-300)) 50%, var(--bs-bg-body)); --bs-secondary-contrast: light-dark(var(--bs-gray-900), var(--bs-white)); --bs-bg-body: light-dark(var(--bs-white), var(--bs-gray-975)); @@ -639,6 +639,9 @@ svg { vertical-align: middle; } + svg { + flex-shrink: 0; + } table { caption-side: bottom; border-collapse: collapse; diff --git a/dist/css/bootstrap-reboot.css.map b/dist/css/bootstrap-reboot.css.map index 4fc6fbc9e6a7..3d0b0cf4f6af 100644 --- a/dist/css/bootstrap-reboot.css.map +++ b/dist/css/bootstrap-reboot.css.map @@ -1 +1 @@ -{"version":3,"sources":["../../scss/_banner.scss","../../scss/_colors.scss","../../scss/mixins/_tokens.scss","bootstrap-reboot.css","../../scss/_root.scss","../../scss/content/_reboot.scss","../../scss/_variables.scss","../../scss/mixins/_border-radius.scss"],"names":[],"mappings":"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","file":"bootstrap-reboot.css","sourcesContent":["$file: \"\" !default;\n\n/*!\n * Bootstrap #{$file} v6.0.0-dev (https://getbootstrap.com/)\n * Copyright 2011-2026 The Bootstrap Authors\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n */\n","// stylelint-disable hue-degree-notation, @stylistic/number-leading-zero\n\n@use \"sass:map\";\n@use \"functions\" as *;\n@use \"mixins/tokens\" as *;\n\n// Easily convert colors to oklch() with https://oklch.com/\n\n$white: #fff !default;\n$black: #000 !default;\n\n// scss-docs-start colors-list\n$blue: oklch(60% 0.24 240) !default;\n$indigo: oklch(56% 0.26 288) !default;\n$violet: oklch(56% 0.24 300) !default;\n$purple: oklch(56% 0.24 320) !default;\n$pink: oklch(60% 0.22 4) !default;\n$red: oklch(60% 0.22 20) !default;\n$orange: oklch(70% 0.22 52) !default;\n$amber: oklch(79% 0.2 78) !default;\n$yellow: oklch(88% 0.24 88) !default;\n$lime: oklch(65% 0.24 135) !default;\n$green: oklch(64% 0.22 160) !default;\n$teal: oklch(68% 0.22 190) !default;\n$cyan: oklch(69% 0.22 220) !default;\n$brown: oklch(60% 0.12 54) !default;\n$gray: oklch(60% 0.02 245) !default;\n$pewter: oklch(65% 0.01 290) !default;\n// scss-docs-end colors-list\n\n// scss-docs-start colors-map\n$colors: () !default;\n\n// stylelint-disable-next-line scss/dollar-variable-default\n$colors: defaults(\n (\n \"blue\": $blue,\n \"indigo\": $indigo,\n \"violet\": $violet,\n \"purple\": $purple,\n \"pink\": $pink,\n \"red\": $red,\n \"orange\": $orange,\n \"amber\": $amber,\n \"yellow\": $yellow,\n \"lime\": $lime,\n \"green\": $green,\n \"teal\": $teal,\n \"cyan\": $cyan,\n \"brown\": $brown,\n \"gray\": $gray,\n \"pewter\": $pewter,\n ),\n $colors\n);\n// scss-docs-end colors-map\n\n// scss-docs-start color-mix-options\n$color-mix-space: lab !default;\n$tint-color: var(--white) !default;\n$shade-color: var(--black) !default;\n\n$color-tints: (\n \"025\": 94%,\n \"050\": 90%,\n \"100\": 80%,\n \"200\": 60%,\n \"300\": 40%,\n \"400\": 20%,\n) !default;\n\n$color-shades: (\n \"600\": 16%,\n \"700\": 32%,\n \"800\": 48%,\n \"900\": 64%,\n \"950\": 76%,\n \"975\": 88%,\n) !default;\n// scss-docs-end color-mix-options\n\n// scss-docs-start color-tokens\n$color-tokens: () !default;\n\n$-color-defaults: () !default;\n@each $color, $value in $colors {\n @each $stop, $percent in $color-tints {\n $-color-defaults: map.set($-color-defaults, --#{$color}-#{$stop}, color-mix(in #{$color-mix-space}, #{$tint-color} #{$percent}, #{$value}));\n }\n $-color-defaults: map.set($-color-defaults, --#{$color}-500, #{$value});\n @each $stop, $percent in $color-shades {\n $-color-defaults: map.set($-color-defaults, --#{$color}-#{$stop}, color-mix(in #{$color-mix-space}, #{$shade-color} #{$percent}, #{$value}));\n }\n}\n\n// stylelint-disable-next-line scss/dollar-variable-default\n$color-tokens: defaults($-color-defaults, $color-tokens);\n// scss-docs-end color-tokens\n\n:root {\n @include tokens($color-tokens);\n}\n","// Mixin to output tokens as CSS custom properties\n\n// scss-docs-start mixin-tokens\n@mixin tokens($map) {\n @each $prop, $value in $map {\n #{$prop}: #{$value};\n }\n}\n// scss-docs-end mixin-tokens\n","/*!\n * Bootstrap Reboot v6.0.0-dev (https://getbootstrap.com/)\n * Copyright 2011-2026 The Bootstrap Authors\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n */\n:root {\n --blue-025: color-mix(in lab, var(--white) 94%, oklch(60% 0.24 240deg));\n --blue-050: color-mix(in lab, var(--white) 90%, oklch(60% 0.24 240deg));\n --blue-100: color-mix(in lab, var(--white) 80%, oklch(60% 0.24 240deg));\n --blue-200: color-mix(in lab, var(--white) 60%, oklch(60% 0.24 240deg));\n --blue-300: color-mix(in lab, var(--white) 40%, oklch(60% 0.24 240deg));\n --blue-400: color-mix(in lab, var(--white) 20%, oklch(60% 0.24 240deg));\n --blue-500: oklch(60% 0.24 240deg);\n --blue-600: color-mix(in lab, var(--black) 16%, oklch(60% 0.24 240deg));\n --blue-700: color-mix(in lab, var(--black) 32%, oklch(60% 0.24 240deg));\n --blue-800: color-mix(in lab, var(--black) 48%, oklch(60% 0.24 240deg));\n --blue-900: color-mix(in lab, var(--black) 64%, oklch(60% 0.24 240deg));\n --blue-950: color-mix(in lab, var(--black) 76%, oklch(60% 0.24 240deg));\n --blue-975: color-mix(in lab, var(--black) 88%, oklch(60% 0.24 240deg));\n --indigo-025: color-mix(in lab, var(--white) 94%, oklch(56% 0.26 288deg));\n --indigo-050: color-mix(in lab, var(--white) 90%, oklch(56% 0.26 288deg));\n --indigo-100: color-mix(in lab, var(--white) 80%, oklch(56% 0.26 288deg));\n --indigo-200: color-mix(in lab, var(--white) 60%, oklch(56% 0.26 288deg));\n --indigo-300: color-mix(in lab, var(--white) 40%, oklch(56% 0.26 288deg));\n --indigo-400: color-mix(in lab, var(--white) 20%, oklch(56% 0.26 288deg));\n --indigo-500: oklch(56% 0.26 288deg);\n --indigo-600: color-mix(in lab, var(--black) 16%, oklch(56% 0.26 288deg));\n --indigo-700: color-mix(in lab, var(--black) 32%, oklch(56% 0.26 288deg));\n --indigo-800: color-mix(in lab, var(--black) 48%, oklch(56% 0.26 288deg));\n --indigo-900: color-mix(in lab, var(--black) 64%, oklch(56% 0.26 288deg));\n --indigo-950: color-mix(in lab, var(--black) 76%, oklch(56% 0.26 288deg));\n --indigo-975: color-mix(in lab, var(--black) 88%, oklch(56% 0.26 288deg));\n --violet-025: color-mix(in lab, var(--white) 94%, oklch(56% 0.24 300deg));\n --violet-050: color-mix(in lab, var(--white) 90%, oklch(56% 0.24 300deg));\n --violet-100: color-mix(in lab, var(--white) 80%, oklch(56% 0.24 300deg));\n --violet-200: color-mix(in lab, var(--white) 60%, oklch(56% 0.24 300deg));\n --violet-300: color-mix(in lab, var(--white) 40%, oklch(56% 0.24 300deg));\n --violet-400: color-mix(in lab, var(--white) 20%, oklch(56% 0.24 300deg));\n --violet-500: oklch(56% 0.24 300deg);\n --violet-600: color-mix(in lab, var(--black) 16%, oklch(56% 0.24 300deg));\n --violet-700: color-mix(in lab, var(--black) 32%, oklch(56% 0.24 300deg));\n --violet-800: color-mix(in lab, var(--black) 48%, oklch(56% 0.24 300deg));\n --violet-900: color-mix(in lab, var(--black) 64%, oklch(56% 0.24 300deg));\n --violet-950: color-mix(in lab, var(--black) 76%, oklch(56% 0.24 300deg));\n --violet-975: color-mix(in lab, var(--black) 88%, oklch(56% 0.24 300deg));\n --purple-025: color-mix(in lab, var(--white) 94%, oklch(56% 0.24 320deg));\n --purple-050: color-mix(in lab, var(--white) 90%, oklch(56% 0.24 320deg));\n --purple-100: color-mix(in lab, var(--white) 80%, oklch(56% 0.24 320deg));\n --purple-200: color-mix(in lab, var(--white) 60%, oklch(56% 0.24 320deg));\n --purple-300: color-mix(in lab, var(--white) 40%, oklch(56% 0.24 320deg));\n --purple-400: color-mix(in lab, var(--white) 20%, oklch(56% 0.24 320deg));\n --purple-500: oklch(56% 0.24 320deg);\n --purple-600: color-mix(in lab, var(--black) 16%, oklch(56% 0.24 320deg));\n --purple-700: color-mix(in lab, var(--black) 32%, oklch(56% 0.24 320deg));\n --purple-800: color-mix(in lab, var(--black) 48%, oklch(56% 0.24 320deg));\n --purple-900: color-mix(in lab, var(--black) 64%, oklch(56% 0.24 320deg));\n --purple-950: color-mix(in lab, var(--black) 76%, oklch(56% 0.24 320deg));\n --purple-975: color-mix(in lab, var(--black) 88%, oklch(56% 0.24 320deg));\n --pink-025: color-mix(in lab, var(--white) 94%, oklch(60% 0.22 4deg));\n --pink-050: color-mix(in lab, var(--white) 90%, oklch(60% 0.22 4deg));\n --pink-100: color-mix(in lab, var(--white) 80%, oklch(60% 0.22 4deg));\n --pink-200: color-mix(in lab, var(--white) 60%, oklch(60% 0.22 4deg));\n --pink-300: color-mix(in lab, var(--white) 40%, oklch(60% 0.22 4deg));\n --pink-400: color-mix(in lab, var(--white) 20%, oklch(60% 0.22 4deg));\n --pink-500: oklch(60% 0.22 4deg);\n --pink-600: color-mix(in lab, var(--black) 16%, oklch(60% 0.22 4deg));\n --pink-700: color-mix(in lab, var(--black) 32%, oklch(60% 0.22 4deg));\n --pink-800: color-mix(in lab, var(--black) 48%, oklch(60% 0.22 4deg));\n --pink-900: color-mix(in lab, var(--black) 64%, oklch(60% 0.22 4deg));\n --pink-950: color-mix(in lab, var(--black) 76%, oklch(60% 0.22 4deg));\n --pink-975: color-mix(in lab, var(--black) 88%, oklch(60% 0.22 4deg));\n --red-025: color-mix(in lab, var(--white) 94%, oklch(60% 0.22 20deg));\n --red-050: color-mix(in lab, var(--white) 90%, oklch(60% 0.22 20deg));\n --red-100: color-mix(in lab, var(--white) 80%, oklch(60% 0.22 20deg));\n --red-200: color-mix(in lab, var(--white) 60%, oklch(60% 0.22 20deg));\n --red-300: color-mix(in lab, var(--white) 40%, oklch(60% 0.22 20deg));\n --red-400: color-mix(in lab, var(--white) 20%, oklch(60% 0.22 20deg));\n --red-500: oklch(60% 0.22 20deg);\n --red-600: color-mix(in lab, var(--black) 16%, oklch(60% 0.22 20deg));\n --red-700: color-mix(in lab, var(--black) 32%, oklch(60% 0.22 20deg));\n --red-800: color-mix(in lab, var(--black) 48%, oklch(60% 0.22 20deg));\n --red-900: color-mix(in lab, var(--black) 64%, oklch(60% 0.22 20deg));\n --red-950: color-mix(in lab, var(--black) 76%, oklch(60% 0.22 20deg));\n --red-975: color-mix(in lab, var(--black) 88%, oklch(60% 0.22 20deg));\n --orange-025: color-mix(in lab, var(--white) 94%, oklch(70% 0.22 52deg));\n --orange-050: color-mix(in lab, var(--white) 90%, oklch(70% 0.22 52deg));\n --orange-100: color-mix(in lab, var(--white) 80%, oklch(70% 0.22 52deg));\n --orange-200: color-mix(in lab, var(--white) 60%, oklch(70% 0.22 52deg));\n --orange-300: color-mix(in lab, var(--white) 40%, oklch(70% 0.22 52deg));\n --orange-400: color-mix(in lab, var(--white) 20%, oklch(70% 0.22 52deg));\n --orange-500: oklch(70% 0.22 52deg);\n --orange-600: color-mix(in lab, var(--black) 16%, oklch(70% 0.22 52deg));\n --orange-700: color-mix(in lab, var(--black) 32%, oklch(70% 0.22 52deg));\n --orange-800: color-mix(in lab, var(--black) 48%, oklch(70% 0.22 52deg));\n --orange-900: color-mix(in lab, var(--black) 64%, oklch(70% 0.22 52deg));\n --orange-950: color-mix(in lab, var(--black) 76%, oklch(70% 0.22 52deg));\n --orange-975: color-mix(in lab, var(--black) 88%, oklch(70% 0.22 52deg));\n --amber-025: color-mix(in lab, var(--white) 94%, oklch(79% 0.2 78deg));\n --amber-050: color-mix(in lab, var(--white) 90%, oklch(79% 0.2 78deg));\n --amber-100: color-mix(in lab, var(--white) 80%, oklch(79% 0.2 78deg));\n --amber-200: color-mix(in lab, var(--white) 60%, oklch(79% 0.2 78deg));\n --amber-300: color-mix(in lab, var(--white) 40%, oklch(79% 0.2 78deg));\n --amber-400: color-mix(in lab, var(--white) 20%, oklch(79% 0.2 78deg));\n --amber-500: oklch(79% 0.2 78deg);\n --amber-600: color-mix(in lab, var(--black) 16%, oklch(79% 0.2 78deg));\n --amber-700: color-mix(in lab, var(--black) 32%, oklch(79% 0.2 78deg));\n --amber-800: color-mix(in lab, var(--black) 48%, oklch(79% 0.2 78deg));\n --amber-900: color-mix(in lab, var(--black) 64%, oklch(79% 0.2 78deg));\n --amber-950: color-mix(in lab, var(--black) 76%, oklch(79% 0.2 78deg));\n --amber-975: color-mix(in lab, var(--black) 88%, oklch(79% 0.2 78deg));\n --yellow-025: color-mix(in lab, var(--white) 94%, oklch(88% 0.24 88deg));\n --yellow-050: color-mix(in lab, var(--white) 90%, oklch(88% 0.24 88deg));\n --yellow-100: color-mix(in lab, var(--white) 80%, oklch(88% 0.24 88deg));\n --yellow-200: color-mix(in lab, var(--white) 60%, oklch(88% 0.24 88deg));\n --yellow-300: color-mix(in lab, var(--white) 40%, oklch(88% 0.24 88deg));\n --yellow-400: color-mix(in lab, var(--white) 20%, oklch(88% 0.24 88deg));\n --yellow-500: oklch(88% 0.24 88deg);\n --yellow-600: color-mix(in lab, var(--black) 16%, oklch(88% 0.24 88deg));\n --yellow-700: color-mix(in lab, var(--black) 32%, oklch(88% 0.24 88deg));\n --yellow-800: color-mix(in lab, var(--black) 48%, oklch(88% 0.24 88deg));\n --yellow-900: color-mix(in lab, var(--black) 64%, oklch(88% 0.24 88deg));\n --yellow-950: color-mix(in lab, var(--black) 76%, oklch(88% 0.24 88deg));\n --yellow-975: color-mix(in lab, var(--black) 88%, oklch(88% 0.24 88deg));\n --lime-025: color-mix(in lab, var(--white) 94%, oklch(65% 0.24 135deg));\n --lime-050: color-mix(in lab, var(--white) 90%, oklch(65% 0.24 135deg));\n --lime-100: color-mix(in lab, var(--white) 80%, oklch(65% 0.24 135deg));\n --lime-200: color-mix(in lab, var(--white) 60%, oklch(65% 0.24 135deg));\n --lime-300: color-mix(in lab, var(--white) 40%, oklch(65% 0.24 135deg));\n --lime-400: color-mix(in lab, var(--white) 20%, oklch(65% 0.24 135deg));\n --lime-500: oklch(65% 0.24 135deg);\n --lime-600: color-mix(in lab, var(--black) 16%, oklch(65% 0.24 135deg));\n --lime-700: color-mix(in lab, var(--black) 32%, oklch(65% 0.24 135deg));\n --lime-800: color-mix(in lab, var(--black) 48%, oklch(65% 0.24 135deg));\n --lime-900: color-mix(in lab, var(--black) 64%, oklch(65% 0.24 135deg));\n --lime-950: color-mix(in lab, var(--black) 76%, oklch(65% 0.24 135deg));\n --lime-975: color-mix(in lab, var(--black) 88%, oklch(65% 0.24 135deg));\n --green-025: color-mix(in lab, var(--white) 94%, oklch(64% 0.22 160deg));\n --green-050: color-mix(in lab, var(--white) 90%, oklch(64% 0.22 160deg));\n --green-100: color-mix(in lab, var(--white) 80%, oklch(64% 0.22 160deg));\n --green-200: color-mix(in lab, var(--white) 60%, oklch(64% 0.22 160deg));\n --green-300: color-mix(in lab, var(--white) 40%, oklch(64% 0.22 160deg));\n --green-400: color-mix(in lab, var(--white) 20%, oklch(64% 0.22 160deg));\n --green-500: oklch(64% 0.22 160deg);\n --green-600: color-mix(in lab, var(--black) 16%, oklch(64% 0.22 160deg));\n --green-700: color-mix(in lab, var(--black) 32%, oklch(64% 0.22 160deg));\n --green-800: color-mix(in lab, var(--black) 48%, oklch(64% 0.22 160deg));\n --green-900: color-mix(in lab, var(--black) 64%, oklch(64% 0.22 160deg));\n --green-950: color-mix(in lab, var(--black) 76%, oklch(64% 0.22 160deg));\n --green-975: color-mix(in lab, var(--black) 88%, oklch(64% 0.22 160deg));\n --teal-025: color-mix(in lab, var(--white) 94%, oklch(68% 0.22 190deg));\n --teal-050: color-mix(in lab, var(--white) 90%, oklch(68% 0.22 190deg));\n --teal-100: color-mix(in lab, var(--white) 80%, oklch(68% 0.22 190deg));\n --teal-200: color-mix(in lab, var(--white) 60%, oklch(68% 0.22 190deg));\n --teal-300: color-mix(in lab, var(--white) 40%, oklch(68% 0.22 190deg));\n --teal-400: color-mix(in lab, var(--white) 20%, oklch(68% 0.22 190deg));\n --teal-500: oklch(68% 0.22 190deg);\n --teal-600: color-mix(in lab, var(--black) 16%, oklch(68% 0.22 190deg));\n --teal-700: color-mix(in lab, var(--black) 32%, oklch(68% 0.22 190deg));\n --teal-800: color-mix(in lab, var(--black) 48%, oklch(68% 0.22 190deg));\n --teal-900: color-mix(in lab, var(--black) 64%, oklch(68% 0.22 190deg));\n --teal-950: color-mix(in lab, var(--black) 76%, oklch(68% 0.22 190deg));\n --teal-975: color-mix(in lab, var(--black) 88%, oklch(68% 0.22 190deg));\n --cyan-025: color-mix(in lab, var(--white) 94%, oklch(69% 0.22 220deg));\n --cyan-050: color-mix(in lab, var(--white) 90%, oklch(69% 0.22 220deg));\n --cyan-100: color-mix(in lab, var(--white) 80%, oklch(69% 0.22 220deg));\n --cyan-200: color-mix(in lab, var(--white) 60%, oklch(69% 0.22 220deg));\n --cyan-300: color-mix(in lab, var(--white) 40%, oklch(69% 0.22 220deg));\n --cyan-400: color-mix(in lab, var(--white) 20%, oklch(69% 0.22 220deg));\n --cyan-500: oklch(69% 0.22 220deg);\n --cyan-600: color-mix(in lab, var(--black) 16%, oklch(69% 0.22 220deg));\n --cyan-700: color-mix(in lab, var(--black) 32%, oklch(69% 0.22 220deg));\n --cyan-800: color-mix(in lab, var(--black) 48%, oklch(69% 0.22 220deg));\n --cyan-900: color-mix(in lab, var(--black) 64%, oklch(69% 0.22 220deg));\n --cyan-950: color-mix(in lab, var(--black) 76%, oklch(69% 0.22 220deg));\n --cyan-975: color-mix(in lab, var(--black) 88%, oklch(69% 0.22 220deg));\n --brown-025: color-mix(in lab, var(--white) 94%, oklch(60% 0.12 54deg));\n --brown-050: color-mix(in lab, var(--white) 90%, oklch(60% 0.12 54deg));\n --brown-100: color-mix(in lab, var(--white) 80%, oklch(60% 0.12 54deg));\n --brown-200: color-mix(in lab, var(--white) 60%, oklch(60% 0.12 54deg));\n --brown-300: color-mix(in lab, var(--white) 40%, oklch(60% 0.12 54deg));\n --brown-400: color-mix(in lab, var(--white) 20%, oklch(60% 0.12 54deg));\n --brown-500: oklch(60% 0.12 54deg);\n --brown-600: color-mix(in lab, var(--black) 16%, oklch(60% 0.12 54deg));\n --brown-700: color-mix(in lab, var(--black) 32%, oklch(60% 0.12 54deg));\n --brown-800: color-mix(in lab, var(--black) 48%, oklch(60% 0.12 54deg));\n --brown-900: color-mix(in lab, var(--black) 64%, oklch(60% 0.12 54deg));\n --brown-950: color-mix(in lab, var(--black) 76%, oklch(60% 0.12 54deg));\n --brown-975: color-mix(in lab, var(--black) 88%, oklch(60% 0.12 54deg));\n --gray-025: color-mix(in lab, var(--white) 94%, oklch(60% 0.02 245deg));\n --gray-050: color-mix(in lab, var(--white) 90%, oklch(60% 0.02 245deg));\n --gray-100: color-mix(in lab, var(--white) 80%, oklch(60% 0.02 245deg));\n --gray-200: color-mix(in lab, var(--white) 60%, oklch(60% 0.02 245deg));\n --gray-300: color-mix(in lab, var(--white) 40%, oklch(60% 0.02 245deg));\n --gray-400: color-mix(in lab, var(--white) 20%, oklch(60% 0.02 245deg));\n --gray-500: oklch(60% 0.02 245deg);\n --gray-600: color-mix(in lab, var(--black) 16%, oklch(60% 0.02 245deg));\n --gray-700: color-mix(in lab, var(--black) 32%, oklch(60% 0.02 245deg));\n --gray-800: color-mix(in lab, var(--black) 48%, oklch(60% 0.02 245deg));\n --gray-900: color-mix(in lab, var(--black) 64%, oklch(60% 0.02 245deg));\n --gray-950: color-mix(in lab, var(--black) 76%, oklch(60% 0.02 245deg));\n --gray-975: color-mix(in lab, var(--black) 88%, oklch(60% 0.02 245deg));\n --pewter-025: color-mix(in lab, var(--white) 94%, oklch(65% 0.01 290deg));\n --pewter-050: color-mix(in lab, var(--white) 90%, oklch(65% 0.01 290deg));\n --pewter-100: color-mix(in lab, var(--white) 80%, oklch(65% 0.01 290deg));\n --pewter-200: color-mix(in lab, var(--white) 60%, oklch(65% 0.01 290deg));\n --pewter-300: color-mix(in lab, var(--white) 40%, oklch(65% 0.01 290deg));\n --pewter-400: color-mix(in lab, var(--white) 20%, oklch(65% 0.01 290deg));\n --pewter-500: oklch(65% 0.01 290deg);\n --pewter-600: color-mix(in lab, var(--black) 16%, oklch(65% 0.01 290deg));\n --pewter-700: color-mix(in lab, var(--black) 32%, oklch(65% 0.01 290deg));\n --pewter-800: color-mix(in lab, var(--black) 48%, oklch(65% 0.01 290deg));\n --pewter-900: color-mix(in lab, var(--black) 64%, oklch(65% 0.01 290deg));\n --pewter-950: color-mix(in lab, var(--black) 76%, oklch(65% 0.01 290deg));\n --pewter-975: color-mix(in lab, var(--black) 88%, oklch(65% 0.01 290deg));\n}\n\n@layer colors, theme, config, root, reboot, layout, content, forms, components, custom, helpers, utilities;\n:root {\n --black: #000;\n --white: #fff;\n --gradient: linear-gradient(180deg, color-mix(var(--white) 15%, transparent), color-mix(var(--white) 0%, transparent));\n --font-size-base: 1rem;\n --font-size-xs: 0.75rem;\n --font-size-sm: 0.875rem;\n --font-size-md: 1rem;\n --font-size-lg: clamp(1.25rem, 1rem + 0.625vw, 1.5rem);\n --font-size-xl: clamp(1.5rem, 1.1rem + 0.75vw, 1.75rem);\n --font-size-2xl: clamp(1.75rem, 1.3rem + 1vw, 2rem);\n --font-size-3xl: clamp(2rem, 1.5rem + 1.875vw, 2.5rem);\n --font-size-4xl: clamp(2.25rem, 1.75rem + 2.5vw, 3rem);\n --font-size-5xl: clamp(3rem, 2rem + 5vw, 4rem);\n --font-size-6xl: clamp(3.75rem, 2.5rem + 6.25vw, 5rem);\n --line-height-xs: 1.25;\n --line-height-sm: 1.5;\n --line-height-md: 1.5;\n --line-height-lg: 1.5;\n --line-height-xl: 1.4285714286;\n --line-height-2xl: 1.3333333333;\n --line-height-3xl: 1.2;\n --line-height-4xl: 1.1;\n --line-height-5xl: 1.1;\n --line-height-6xl: 1;\n --font-weight-lighter: lighter;\n --font-weight-light: 300;\n --font-weight-normal: 400;\n --font-weight-medium: 500;\n --font-weight-semibold: 600;\n --font-weight-bold: 700;\n --font-weight-bolder: bolder;\n --body-font-family: system-ui;\n --body-font-size: var(--font-size-base);\n --body-font-weight: 400;\n --body-line-height: 1.5;\n --heading-color: inherit;\n --hr-border-color: var(--border-color);\n --link-color: light-dark(var(--primary-base), var(--primary-text));\n --link-decoration: underline;\n --link-hover-color: color-mix(in oklch, var(--link-color) 90%, #000);\n --font-mono: SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;\n --code-font-size: 95%;\n --code-color: var(--fg-2);\n --border-width: 1px;\n --border-style: solid;\n --border-color: light-dark(color-mix(in oklch, var(--gray-100), var(--gray-200)), var(--gray-700));\n --border-color-translucent: color-mix(in oklch, var(--fg-body) 15%, transparent);\n --border-radius: 0.5rem;\n --border-radius-xs: 0.375rem;\n --border-radius-sm: 0.5rem;\n --border-radius-lg: 0.75rem;\n --border-radius-xl: 1rem;\n --border-radius-2xl: 2rem;\n --border-radius-pill: 50rem;\n --box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);\n --box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);\n --box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);\n --box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);\n --spacer: 1rem;\n --focus-ring-width: 3px;\n --focus-ring-offset: 1px;\n --focus-ring-color: var(--primary-focus-ring);\n --focus-ring: var(--focus-ring-width) solid var(--focus-ring-color);\n --control-checked-bg: var(--primary-base);\n --control-checked-border-color: var(--control-checked-bg);\n --control-active-bg: var(--primary-base);\n --control-active-border-color: var(--control-active-bg);\n --control-disabled-bg: var(--bg-3);\n --control-disabled-opacity: 0.65;\n --btn-input-fg: var(--fg-body);\n --btn-input-bg: var(--bg-body);\n --btn-input-min-height: 2.375rem;\n --btn-input-padding-y: 0.375rem;\n --btn-input-padding-x: 0.75rem;\n --btn-input-font-size: var(--font-size-base);\n --btn-input-line-height: var(--line-height-base);\n --btn-input-border-radius: var(--border-radius);\n --btn-input-xs-min-height: 1.5rem;\n --btn-input-xs-padding-y: 0.125rem;\n --btn-input-xs-padding-x: 0.5rem;\n --btn-input-xs-font-size: var(--font-size-xs);\n --btn-input-xs-line-height: 1.125;\n --btn-input-xs-border-radius: var(--border-radius-xs);\n --btn-input-sm-min-height: 2rem;\n --btn-input-sm-padding-y: 0.25rem;\n --btn-input-sm-padding-x: 0.625rem;\n --btn-input-sm-font-size: var(--font-size-sm);\n --btn-input-sm-line-height: var(--line-height-sm);\n --btn-input-sm-border-radius: var(--border-radius-sm);\n --btn-input-lg-min-height: 2.75rem;\n --btn-input-lg-padding-y: 0.5rem;\n --btn-input-lg-padding-x: 1rem;\n --btn-input-lg-font-size: var(--font-size-md);\n --btn-input-lg-line-height: var(--line-height-md);\n --btn-input-lg-border-radius: var(--border-radius-lg);\n --form-valid-color: var(--success-text);\n --form-valid-border-color: var(--success-text);\n --form-invalid-color: var(--danger-text);\n --form-invalid-border-color: var(--danger-text);\n --primary-base: var(--blue-500);\n --primary-text: light-dark(var(--blue-600), var(--blue-400));\n --primary-text-emphasis: light-dark(var(--blue-800), var(--blue-200));\n --primary-bg: var(--blue-500);\n --primary-bg-subtle: light-dark(var(--blue-100), var(--blue-900));\n --primary-bg-muted: light-dark(var(--blue-200), var(--blue-800));\n --primary-border: light-dark(var(--blue-300), var(--blue-600));\n --primary-focus-ring: light-dark(color-mix(in oklch, var(--blue-500) 50%, var(--bg-body)), color-mix(in oklch, var(--blue-500) 75%, var(--bg-body)));\n --primary-contrast: var(--white);\n --accent-base: var(--indigo-500);\n --accent-text: light-dark(var(--indigo-600), color-mix(in oklch, var(--indigo-400), var(--indigo-300)));\n --accent-text-emphasis: light-dark(var(--indigo-800), var(--indigo-300));\n --accent-bg: var(--indigo-500);\n --accent-bg-subtle: light-dark(var(--indigo-100), var(--indigo-900));\n --accent-bg-muted: light-dark(var(--indigo-200), var(--indigo-800));\n --accent-border: light-dark(var(--indigo-300), var(--indigo-600));\n --accent-focus-ring: light-dark(color-mix(in oklch, var(--indigo-500) 50%, var(--bg-body)), color-mix(in oklch, var(--indigo-500) 75%, var(--bg-body)));\n --accent-contrast: var(--white);\n --success-base: var(--green-500);\n --success-text: light-dark(var(--green-600), var(--green-400));\n --success-text-emphasis: light-dark(var(--green-800), var(--green-300));\n --success-bg: var(--green-500);\n --success-bg-subtle: light-dark(var(--green-100), var(--green-900));\n --success-bg-muted: light-dark(var(--green-200), var(--green-800));\n --success-border: light-dark(var(--green-300), var(--green-600));\n --success-focus-ring: light-dark(color-mix(in oklch, var(--green-500) 50%, var(--bg-body)), color-mix(in oklch, var(--green-500) 75%, var(--bg-body)));\n --success-contrast: var(--white);\n --danger-base: var(--red-500);\n --danger-text: light-dark(var(--red-600), var(--red-400));\n --danger-text-emphasis: light-dark(var(--red-800), var(--red-300));\n --danger-bg: var(--red-500);\n --danger-bg-subtle: light-dark(var(--red-100), var(--red-900));\n --danger-bg-muted: light-dark(var(--red-200), var(--red-800));\n --danger-border: light-dark(var(--red-300), var(--red-600));\n --danger-focus-ring: light-dark(color-mix(in oklch, var(--red-500) 50%, var(--bg-body)), color-mix(in oklch, var(--red-500) 75%, var(--bg-body)));\n --danger-contrast: var(--white);\n --warning-base: var(--yellow-500);\n --warning-text: light-dark(var(--yellow-700), var(--yellow-400));\n --warning-text-emphasis: light-dark(var(--yellow-800), var(--yellow-300));\n --warning-bg: var(--yellow-500);\n --warning-bg-subtle: light-dark(var(--yellow-100), var(--yellow-900));\n --warning-bg-muted: light-dark(var(--yellow-200), var(--yellow-800));\n --warning-border: light-dark(var(--yellow-300), var(--yellow-600));\n --warning-focus-ring: light-dark(color-mix(in oklch, var(--yellow-500) 50%, var(--bg-body)), color-mix(in oklch, var(--yellow-400) 85%, var(--bg-body)));\n --warning-contrast: var(--gray-900);\n --info-base: var(--cyan-500);\n --info-text: light-dark(var(--cyan-600), var(--cyan-400));\n --info-text-emphasis: light-dark(var(--cyan-800), var(--cyan-300));\n --info-bg: var(--cyan-500);\n --info-bg-subtle: light-dark(var(--cyan-100), var(--cyan-900));\n --info-bg-muted: light-dark(var(--cyan-200), var(--cyan-800));\n --info-border: light-dark(var(--cyan-300), var(--cyan-600));\n --info-focus-ring: light-dark(color-mix(in oklch, var(--cyan-500) 50%, var(--bg-body)), color-mix(in oklch, var(--cyan-500) 75%, var(--bg-body)));\n --info-contrast: var(--gray-900);\n --inverse-base: var(--gray-900);\n --inverse-text: light-dark(var(--gray-900), var(--gray-200));\n --inverse-text-emphasis: light-dark(var(--gray-975), var(--white));\n --inverse-bg: light-dark(var(--gray-900), var(--gray-025));\n --inverse-bg-subtle: light-dark(var(--gray-100), var(--gray-900));\n --inverse-bg-muted: light-dark(var(--gray-200), var(--gray-300));\n --inverse-border: light-dark(var(--gray-400), var(--gray-100));\n --inverse-focus-ring: color-mix(in oklch, light-dark(var(--gray-900), var(--gray-100)) 50%, var(--bg-body));\n --inverse-contrast: light-dark(var(--white), var(--gray-900));\n --secondary-base: var(--gray-200);\n --secondary-text: light-dark(var(--gray-600), var(--gray-400));\n --secondary-text-emphasis: light-dark(var(--gray-800), var(--gray-200));\n --secondary-bg: light-dark(var(--gray-100), var(--gray-600));\n --secondary-bg-subtle: light-dark(var(--gray-050), var(--gray-800));\n --secondary-bg-muted: light-dark(var(--gray-100), var(--gray-700));\n --secondary-border: light-dark(var(--gray-300), var(--gray-600));\n --secondary-focus-ring: color-mix(in oklch, light-dark(var(--gray-500), var(--gray-300)) 50%, var(--bg-body));\n --secondary-contrast: light-dark(var(--gray-900), var(--white));\n --bg-body: light-dark(var(--white), var(--gray-975));\n --bg-1: light-dark(var(--gray-025), var(--gray-950));\n --bg-2: light-dark(var(--gray-050), var(--gray-900));\n --bg-3: light-dark(var(--gray-100), var(--gray-800));\n --bg-4: light-dark(var(--gray-200), var(--gray-700));\n --bg-white: var(--white);\n --bg-black: var(--black);\n --bg-transparent: transparent;\n --bg-inherit: inherit;\n --fg-body: light-dark(var(--gray-900), var(--gray-050));\n --fg-1: light-dark(var(--gray-800), var(--gray-200));\n --fg-2: light-dark(var(--gray-700), var(--gray-300));\n --fg-3: light-dark(var(--gray-600), var(--gray-500));\n --fg-4: light-dark(var(--gray-500), var(--gray-600));\n --fg-white: var(--white);\n --fg-black: var(--black);\n --fg-inherit: inherit;\n --border-bg: var(--bg-body);\n --border-body: light-dark(var(--gray-300), var(--gray-800));\n --border-muted: light-dark(var(--gray-200), var(--gray-800));\n --border-subtle: light-dark(var(--gray-100), var(--gray-900));\n --border-emphasized: light-dark(var(--gray-400), var(--gray-600));\n --border-white: var(--white);\n --border-black: var(--black);\n --breakpoint-xs: 0;\n --breakpoint-sm: 576px;\n --breakpoint-md: 768px;\n --breakpoint-lg: 1024px;\n --breakpoint-xl: 1280px;\n --breakpoint-2xl: 1536px;\n color-scheme: light dark;\n}\n\n[data-bs-theme=dark] {\n color-scheme: dark;\n}\n\n[data-bs-theme=light] {\n color-scheme: light;\n}\n\n@layer reboot {\n *,\n *::before,\n *::after {\n box-sizing: border-box;\n }\n :root {\n accent-color: var(--primary-base);\n }\n @media (prefers-reduced-motion: no-preference) {\n :root {\n scroll-behavior: smooth;\n }\n }\n body {\n margin: 0;\n font-family: var(--body-font-family);\n font-size: var(--body-font-size);\n font-weight: var(--body-font-weight);\n line-height: var(--body-line-height);\n color: var(--fg-body);\n text-align: var(--body-text-align);\n background-color: var(--bg-body);\n -webkit-text-size-adjust: 100%;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n }\n hr {\n margin: var(--hr-margin-y, var(--spacer)) 0;\n border: 0;\n border-block-start: var(--border-width) solid var(--hr-border-color);\n }\n h6,\n .h6, h5,\n .h5, h4,\n .h4, h3,\n .h3, h2,\n .h2, h1,\n .h1 {\n margin-top: 0;\n margin-bottom: 0.5rem;\n font-weight: 500;\n line-height: 1.2;\n color: var(--heading-color);\n }\n h1,\n .h1 {\n font-size: var(--font-size-3xl);\n }\n h2,\n .h2 {\n font-size: var(--font-size-2xl);\n }\n h3,\n .h3 {\n font-size: var(--font-size-xl);\n }\n h4,\n .h4 {\n font-size: var(--font-size-lg);\n }\n h5,\n .h5 {\n font-size: var(--font-size-md);\n }\n h6,\n .h6 {\n font-size: var(--font-size-sm);\n }\n p {\n margin-top: 0;\n margin-bottom: 1rem;\n }\n abbr[title] {\n text-decoration: underline dotted;\n cursor: help;\n text-decoration-skip-ink: none;\n }\n address {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n }\n ol,\n ul {\n padding-inline-start: 2rem;\n }\n ol,\n ul,\n dl {\n margin-top: 0;\n margin-bottom: 1rem;\n }\n ol ol,\n ul ul,\n ol ul,\n ul ol {\n margin-bottom: 0;\n }\n dt {\n font-weight: 700;\n }\n dd {\n margin-inline-start: 0;\n margin-bottom: 0.5rem;\n }\n blockquote {\n margin: 0 0 1rem;\n }\n blockquote > * {\n margin-block: 0;\n }\n b,\n strong {\n font-weight: bolder;\n }\n small,\n .small {\n font-size: var(--small-font-size, 87.5%);\n }\n mark,\n .mark {\n --mark-padding: 0.1875em;\n --mark-color: var(--fg-body);\n --mark-bg: light-dark(var(--yellow-100), var(--yellow-900));\n padding: var(--mark-padding);\n color: var(--mark-color);\n background-color: var(--mark-bg);\n }\n sub,\n sup {\n position: relative;\n font-size: var(--sub-sup-font-size, 0.75em);\n line-height: 0;\n vertical-align: baseline;\n }\n sub {\n bottom: -0.25em;\n }\n sup {\n top: -0.5em;\n }\n a {\n color: var(--theme-text, var(--link-color));\n text-decoration: var(--link-decoration);\n text-underline-offset: 0.2em;\n }\n a:hover {\n color: var(--theme-text-emphasis, var(--link-hover-color));\n text-decoration: var(--link-hover-decoration, var(--link-decoration));\n }\n a:not([href]):not([class]), a:not([href]):not([class]):hover {\n color: inherit;\n text-decoration: none;\n }\n pre,\n code,\n kbd,\n samp {\n font-family: var(--font-mono);\n font-size: 1em;\n }\n pre {\n display: block;\n margin-top: 0;\n margin-bottom: 1rem;\n overflow: auto;\n font-size: var(--code-font-size);\n color: var(--code-color, inherit);\n }\n pre code {\n font-size: inherit;\n color: inherit;\n word-break: normal;\n }\n code {\n font-size: var(--code-font-size);\n color: var(--code-color);\n word-wrap: break-word;\n }\n a > code {\n color: inherit;\n }\n kbd {\n --kbd-padding-y: 0.125rem;\n --kbd-padding-x: 0.25rem;\n --kbd-font-size: var(--font-size-xs);\n --kbd-color: var(--bg-body);\n --kbd-bg: var(--fg-2);\n --kbd-border-radius: var(--border-radius-sm);\n padding: var(--kbd-padding-y) var(--kbd-padding-x);\n font-size: var(--kbd-font-size);\n color: var(--kbd-color);\n background-color: var(--kbd-bg);\n border-radius: var(--kbd-border-radius);\n }\n kbd kbd {\n padding: 0;\n font-size: 1em;\n font-weight: inherit;\n }\n figure {\n margin: 0 0 1rem;\n }\n img,\n svg {\n vertical-align: middle;\n }\n table {\n caption-side: bottom;\n border-collapse: collapse;\n }\n caption {\n padding-block: 0.5rem;\n color: var(--fg-3);\n text-align: start;\n }\n th {\n text-align: inherit;\n text-align: -webkit-match-parent;\n }\n thead,\n tbody,\n tfoot,\n tr,\n td,\n th {\n border-color: inherit;\n border-style: solid;\n border-width: 0;\n }\n label {\n display: inline-block;\n }\n button {\n border-radius: 0;\n }\n button:focus:not(:focus-visible) {\n outline: 0;\n }\n input,\n button,\n select,\n optgroup,\n textarea {\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n }\n button,\n select {\n text-transform: none;\n }\n [role=button] {\n cursor: pointer;\n }\n select {\n word-wrap: normal;\n }\n select:disabled {\n opacity: 1;\n }\n [list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {\n display: none !important;\n }\n button,\n [type=button],\n [type=reset],\n [type=submit] {\n -webkit-appearance: button;\n }\n button:not(:disabled),\n [type=button]:not(:disabled),\n [type=reset]:not(:disabled),\n [type=submit]:not(:disabled) {\n cursor: pointer;\n }\n ::-moz-focus-inner {\n padding: 0;\n border-style: none;\n }\n textarea {\n resize: vertical;\n }\n fieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n }\n legend {\n float: inline-start;\n width: 100%;\n padding: 0;\n margin-bottom: 0.5rem;\n font-size: 1.5rem;\n line-height: inherit;\n }\n legend + * {\n clear: inline-start;\n }\n ::-webkit-datetime-edit-fields-wrapper,\n ::-webkit-datetime-edit-text,\n ::-webkit-datetime-edit-millisecond-field,\n ::-webkit-datetime-edit-second-field,\n ::-webkit-datetime-edit-minute-field,\n ::-webkit-datetime-edit-hour-field,\n ::-webkit-datetime-edit-ampm-field,\n ::-webkit-datetime-edit-day-field,\n ::-webkit-datetime-edit-week-field,\n ::-webkit-datetime-edit-month-field,\n ::-webkit-datetime-edit-year-field {\n padding: 0;\n }\n ::-webkit-inner-spin-button {\n height: auto;\n }\n [type=search] {\n -webkit-appearance: textfield;\n outline-offset: -2px;\n }\n [type=search]::-webkit-search-cancel-button {\n cursor: pointer;\n filter: grayscale(1);\n }\n [type=tel],\n [type=url],\n [type=email],\n [type=number] {\n direction: ltr;\n }\n ::-webkit-search-decoration {\n -webkit-appearance: none;\n }\n ::-webkit-color-swatch-wrapper {\n padding: 0;\n }\n ::file-selector-button {\n font: inherit;\n -webkit-appearance: button;\n }\n output {\n display: inline-block;\n }\n iframe {\n border: 0;\n }\n summary {\n display: list-item;\n cursor: pointer;\n }\n progress {\n vertical-align: baseline;\n }\n [hidden] {\n display: none !important;\n }\n}\n\n/*# sourceMappingURL=bootstrap-reboot.css.map */\n","@use \"sass:map\";\n@use \"colors\" as *;\n@use \"config\" as *;\n@use \"functions\" as *;\n@use \"variables\" as *;\n@use \"theme\" as *;\n@use \"mixins/tokens\" as *;\n@use \"forms/form-variables\" as *;\n\n// mdo-do: do we need theme?\n@layer colors, theme, config, root, reboot, layout, content, forms, components, custom, helpers, utilities;\n\n$root-tokens: () !default;\n\n// scss-docs-start root-tokens\n// stylelint-disable @stylistic/value-list-max-empty-lines, @stylistic/function-max-empty-lines\n// stylelint-disable-next-line scss/dollar-variable-default\n$root-tokens: defaults(\n (\n --black: #{$black},\n --white: #{$white},\n\n --gradient: #{$gradient},\n\n // scss-docs-start root-font-size-variables\n --font-size-base: 1rem,\n --font-size-xs: .75rem,\n --font-size-sm: .875rem,\n --font-size-md: 1rem,\n --font-size-lg: clamp(1.25rem, 1rem + .625vw, 1.5rem),\n --font-size-xl: clamp(1.5rem, 1.1rem + .75vw, 1.75rem),\n --font-size-2xl: clamp(1.75rem, 1.3rem + 1vw, 2rem),\n --font-size-3xl: clamp(2rem, 1.5rem + 1.875vw, 2.5rem),\n --font-size-4xl: clamp(2.25rem, 1.75rem + 2.5vw, 3rem),\n --font-size-5xl: clamp(3rem, 2rem + 5vw, 4rem),\n --font-size-6xl: clamp(3.75rem, 2.5rem + 6.25vw, 5rem),\n\n --line-height-xs: 1.25,\n --line-height-sm: 1.5,\n --line-height-md: 1.5,\n --line-height-lg: 1.5,\n --line-height-xl: calc(2.5 / 1.75),\n --line-height-2xl: calc(3 / 2.25),\n --line-height-3xl: 1.2,\n --line-height-4xl: 1.1,\n --line-height-5xl: 1.1,\n --line-height-6xl: 1,\n // scss-docs-end root-font-size-variables\n\n // scss-docs-start root-font-weight-variables\n --font-weight-lighter: lighter,\n --font-weight-light: 300,\n --font-weight-normal: 400,\n --font-weight-medium: 500,\n --font-weight-semibold: 600,\n --font-weight-bold: 700,\n --font-weight-bolder: bolder,\n // scss-docs-end root-font-weight-variables\n\n // scss-docs-start root-body-variables\n --body-font-family: system-ui,\n --body-font-size: var(--font-size-base),\n --body-font-weight: #{$font-weight-base},\n --body-line-height: #{$line-height-base},\n\n --heading-color: #{$headings-color},\n\n --hr-border-color: var(--border-color),\n\n --link-color: light-dark(var(--primary-base), var(--primary-text)),\n --link-decoration: #{$link-decoration},\n --link-hover-color: color-mix(in oklch, var(--link-color) 90%, #000),\n\n --font-mono: \"SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace\",\n --code-font-size: 95%,\n --code-color: var(--fg-2),\n\n // scss-docs-start root-border-var\n --border-width: #{$border-width},\n --border-style: #{$border-style},\n --border-color: light-dark(color-mix(in oklch, var(--gray-100), var(--gray-200)), var(--gray-700)),\n --border-color-translucent: color-mix(in oklch, var(--fg-body) 15%, transparent),\n // scss-docs-end root-border-var\n\n // scss-docs-start root-border-radius-var\n --border-radius: .5rem,\n --border-radius-xs: .375rem,\n --border-radius-sm: .5rem,\n --border-radius-lg: .75rem,\n --border-radius-xl: 1rem,\n --border-radius-2xl: 2rem,\n --border-radius-pill: 50rem,\n // scss-docs-end root-border-radius-var\n\n // scss-docs-start root-box-shadow-variables\n --box-shadow: 0 .5rem 1rem rgb(0 0 0 / 15%),\n --box-shadow-sm: 0 .125rem .25rem rgb(0 0 0 / 7.5%),\n --box-shadow-lg: 0 1rem 3rem rgb(0 0 0 / 17.5%),\n --box-shadow-inset: inset 0 1px 2px rgb(0 0 0 / 7.5%),\n // scss-docs-end root-box-shadow-variables\n\n --spacer: 1rem,\n\n // scss-docs-start root-focus-variables\n --focus-ring-width: 3px,\n --focus-ring-offset: 1px,\n --focus-ring-color: var(--primary-focus-ring),\n --focus-ring: var(--focus-ring-width) solid var(--focus-ring-color),\n // scss-docs-end root-focus-variables\n\n // scss-docs-start root-form-variables\n --control-checked-bg: var(--primary-base),\n --control-checked-border-color: var(--control-checked-bg),\n --control-active-bg: var(--primary-base),\n --control-active-border-color: var(--control-active-bg),\n --control-disabled-bg: var(--bg-3),\n --control-disabled-opacity: .65,\n\n --btn-input-fg: var(--fg-body),\n --btn-input-bg: var(--bg-body),\n\n --btn-input-min-height: 2.375rem,\n --btn-input-padding-y: .375rem,\n --btn-input-padding-x: .75rem,\n --btn-input-font-size: var(--font-size-base),\n --btn-input-line-height: var(--line-height-base),\n --btn-input-border-radius: var(--border-radius),\n\n --btn-input-xs-min-height: 1.5rem,\n --btn-input-xs-padding-y: .125rem,\n --btn-input-xs-padding-x: .5rem,\n --btn-input-xs-font-size: var(--font-size-xs),\n --btn-input-xs-line-height: 1.125,\n --btn-input-xs-border-radius: var(--border-radius-xs),\n\n --btn-input-sm-min-height: 2rem,\n --btn-input-sm-padding-y: .25rem,\n --btn-input-sm-padding-x: .625rem,\n --btn-input-sm-font-size: var(--font-size-sm),\n --btn-input-sm-line-height: var(--line-height-sm),\n --btn-input-sm-border-radius: var(--border-radius-sm),\n\n --btn-input-lg-min-height: 2.75rem,\n --btn-input-lg-padding-y: .5rem,\n --btn-input-lg-padding-x: 1rem,\n --btn-input-lg-font-size: var(--font-size-md),\n --btn-input-lg-line-height: var(--line-height-md),\n --btn-input-lg-border-radius: var(--border-radius-lg),\n // scss-docs-end root-form-variables\n\n // scss-docs-start root-form-validation-variables\n --form-valid-color: #{$form-valid-color},\n --form-valid-border-color: #{$form-valid-border-color},\n --form-invalid-color: #{$form-invalid-color},\n --form-invalid-border-color: #{$form-invalid-border-color},\n // scss-docs-end root-form-validation-variables\n ),\n $root-tokens\n);\n// stylelint-enable @stylistic/value-list-max-empty-lines, @stylistic/function-max-empty-lines\n// scss-docs-end root-tokens\n\n// scss-docs-start root-theme-tokens\n// Generate semantic theme colors\n@each $color-name, $color-map in $theme-colors {\n @each $key, $value in $color-map {\n $root-tokens: map.set($root-tokens, --#{$color-name}-#{$key}, $value);\n }\n}\n\n// Generate background tokens\n@each $key, $value in $theme-bgs {\n $root-tokens: map.set($root-tokens, --bg-#{$key}, $value);\n}\n\n// Generate foreground tokens\n@each $key, $value in $theme-fgs {\n $root-tokens: map.set($root-tokens, --fg-#{$key}, $value);\n}\n\n// Generate border tokens\n@each $key, $value in $theme-borders {\n $root-tokens: map.set($root-tokens, --border-#{$key}, $value);\n}\n// scss-docs-end root-theme-tokens\n\n// Generate breakpoint tokens\n@each $name, $value in $breakpoints {\n $root-tokens: map.set($root-tokens, --breakpoint-#{$name}, $value);\n}\n\n:root {\n @include tokens($root-tokens);\n\n color-scheme: light dark;\n}\n\n[data-bs-theme=\"dark\"] {\n color-scheme: dark;\n}\n\n[data-bs-theme=\"light\"] {\n color-scheme: light;\n}\n","@use \"../colors\" as *;\n@use \"../config\" as *;\n@use \"../functions\" as *;\n@use \"../variables\" as *;\n@use \"../mixins/border-radius\" as *;\n@use \"../mixins/tokens\" as *;\n\n// stylelint-disable declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix\n\n$reboot-kbd-tokens: () !default;\n\n// scss-docs-start reboot-kbd-tokens\n// stylelint-disable-next-line scss/dollar-variable-default\n$reboot-kbd-tokens: defaults(\n (\n --kbd-padding-y: .125rem,\n --kbd-padding-x: .25rem,\n --kbd-font-size: var(--font-size-xs),\n --kbd-color: var(--bg-body),\n --kbd-bg: var(--fg-2),\n --kbd-border-radius: var(--border-radius-sm),\n ),\n $reboot-kbd-tokens\n);\n// scss-docs-end reboot-kbd-tokens\n\n$reboot-mark-tokens: () !default;\n\n// scss-docs-start reboot-mark-tokens\n// stylelint-disable-next-line scss/dollar-variable-default\n$reboot-mark-tokens: defaults(\n (\n --mark-padding: .1875em,\n --mark-color: var(--fg-body),\n --mark-bg: light-dark(var(--yellow-100), var(--yellow-900)),\n ),\n $reboot-mark-tokens\n);\n// scss-docs-end reboot-mark-tokens\n\n@layer reboot {\n // Reboot\n //\n // Normalization of HTML elements, manually forked from Normalize.css to remove\n // styles targeting irrelevant browsers while applying new styles.\n //\n // Normalize is licensed MIT. https://github.com/necolas/normalize.css\n\n // Document\n //\n // Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.\n\n *,\n *::before,\n *::after {\n box-sizing: border-box;\n }\n\n // Root\n //\n // Ability to the value of the root font sizes, affecting the value of `rem`.\n // null by default, thus nothing is generated.\n\n :root {\n // Assume browser default font-size of 16px, or a user's preference\n accent-color: var(--primary-base);\n\n @if $enable-smooth-scroll {\n @media (prefers-reduced-motion: no-preference) {\n scroll-behavior: smooth;\n }\n }\n }\n\n // Body\n //\n // 1. Remove the margin in all browsers.\n // 2. As a best practice, apply a default `background-color`.\n // 3. Prevent adjustments of font size after orientation changes in iOS.\n // 4. Change the default tap highlight to be completely transparent in iOS.\n\n // scss-docs-start reboot-body-rules\n body {\n margin: 0; // 1\n font-family: var(--body-font-family);\n font-size: var(--body-font-size);\n font-weight: var(--body-font-weight);\n line-height: var(--body-line-height);\n color: var(--fg-body);\n text-align: var(--body-text-align);\n background-color: var(--bg-body); // 2\n -webkit-text-size-adjust: 100%; // 3\n -webkit-tap-highlight-color: rgba($black, 0); // 4\n }\n // scss-docs-end reboot-body-rules\n\n hr {\n margin: var(--hr-margin-y, var(--spacer)) 0;\n border: 0;\n border-block-start: var(--border-width) solid var(--hr-border-color);\n }\n\n // Typography\n //\n // 1. Remove top margins from headings\n // By default, `

`-`

` all receive top and bottom margins. We nuke the top\n // margin for easier control within type scales as it avoids margin collapsing.\n\n %heading {\n margin-top: 0; // 1\n margin-bottom: $headings-margin-bottom;\n font-family: $headings-font-family;\n font-style: $headings-font-style;\n font-weight: $headings-font-weight;\n line-height: $headings-line-height;\n color: var(--heading-color);\n }\n\n h1,\n .h1 {\n @extend %heading;\n font-size: $h1-font-size;\n }\n\n h2,\n .h2 {\n @extend %heading;\n font-size: $h2-font-size;\n }\n\n h3,\n .h3 {\n @extend %heading;\n font-size: $h3-font-size;\n }\n\n h4,\n .h4 {\n @extend %heading;\n font-size: $h4-font-size;\n }\n\n h5,\n .h5 {\n @extend %heading;\n font-size: $h5-font-size;\n }\n\n h6,\n .h6 {\n @extend %heading;\n font-size: $h6-font-size;\n }\n\n // Reset margins on paragraphs\n //\n // Similarly, the top margin on `

`s get reset. However, we also reset the\n // bottom margin to use `rem` units instead of `em`.\n\n p {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n }\n\n // Abbreviations\n //\n // 1. Add the correct text decoration in Chrome, Edge, Opera, and Safari.\n // 2. Add explicit cursor to indicate changed behavior.\n // 3. Prevent the text-decoration to be skipped.\n\n abbr[title] {\n text-decoration: underline dotted; // 1\n cursor: help; // 2\n text-decoration-skip-ink: none; // 3\n }\n\n // Address\n\n address {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n }\n\n // Lists\n\n ol,\n ul {\n padding-inline-start: 2rem;\n }\n\n ol,\n ul,\n dl {\n margin-top: 0;\n margin-bottom: 1rem;\n }\n\n ol ol,\n ul ul,\n ol ul,\n ul ol {\n margin-bottom: 0;\n }\n\n dt {\n font-weight: $dt-font-weight;\n }\n\n // 1. Undo browser default\n\n dd {\n margin-inline-start: 0; // 1\n margin-bottom: .5rem;\n }\n\n // Blockquote\n\n blockquote {\n margin: 0 0 1rem;\n > * {\n margin-block: 0;\n }\n }\n\n // Strong\n //\n // Add the correct font weight in Chrome, Edge, and Safari\n\n b,\n strong {\n font-weight: $font-weight-bolder;\n }\n\n // Small\n //\n // Add the correct font size in all browsers\n\n small,\n .small {\n font-size: var(--small-font-size, 87.5%);\n }\n\n // Mark\n\n mark,\n .mark {\n @include tokens($reboot-mark-tokens);\n padding: var(--mark-padding);\n color: var(--mark-color);\n background-color: var(--mark-bg);\n }\n\n // Sub and Sup\n //\n // Prevent `sub` and `sup` elements from affecting the line height in\n // all browsers.\n\n sub,\n sup {\n position: relative;\n font-size: var(--sub-sup-font-size, .75em);\n line-height: 0;\n vertical-align: baseline;\n }\n\n sub { bottom: -.25em; }\n sup { top: -.5em; }\n\n // Links\n\n a {\n color: var(--theme-text, var(--link-color));\n text-decoration: var(--link-decoration);\n text-underline-offset: $link-underline-offset;\n\n &:hover {\n // --link-color: var(--link-hover-color);\n // --link-decoration: var(--link-hover-decoration, var(--link-decoration));\n color: var(--theme-text-emphasis, var(--link-hover-color));\n text-decoration: var(--link-hover-decoration, var(--link-decoration));\n }\n }\n\n // And undo these styles for placeholder links/named anchors (without href).\n // It would be more straightforward to just use a[href] in previous block, but that\n // causes specificity issues in many other styles that are too complex to fix.\n // See https://github.com/twbs/bootstrap/issues/19402\n\n a:not([href]):not([class]) {\n &,\n &:hover {\n color: inherit;\n text-decoration: none;\n }\n }\n\n // Code\n\n pre,\n code,\n kbd,\n samp {\n font-family: var(--font-mono);\n font-size: 1em; // Correct the odd `em` font sizing in all browsers.\n }\n\n // 1. Remove browser default top margin\n // 2. Reset browser default of `1em` to use `rem`s\n // 3. Don't allow content to break outside\n\n pre {\n display: block;\n margin-top: 0; // 1\n margin-bottom: 1rem; // 2\n overflow: auto; // 3\n font-size: var(--code-font-size);\n color: var(--code-color, inherit);\n\n // Account for some code outputs that place code tags in pre tags\n code {\n font-size: inherit;\n color: inherit;\n word-break: normal;\n }\n }\n\n code {\n font-size: var(--code-font-size);\n color: var(--code-color);\n word-wrap: break-word;\n\n // Streamline the style when inside anchors to avoid broken underline and more\n a > & {\n color: inherit;\n }\n }\n\n kbd {\n @include tokens($reboot-kbd-tokens);\n padding: var(--kbd-padding-y) var(--kbd-padding-x);\n font-size: var(--kbd-font-size);\n color: var(--kbd-color);\n background-color: var(--kbd-bg);\n @include border-radius(var(--kbd-border-radius));\n\n kbd {\n padding: 0;\n font-size: 1em;\n font-weight: inherit; // mdo-do: check if this is needed\n }\n }\n\n // Figures\n //\n // Apply a consistent margin strategy (matches our type styles).\n\n figure {\n margin: 0 0 1rem;\n }\n\n // Images and content\n\n img,\n svg {\n vertical-align: middle;\n }\n\n // Tables\n //\n // Prevent double borders\n\n table {\n caption-side: bottom;\n border-collapse: collapse;\n }\n\n caption {\n // padding-top: $table-cell-padding-y;\n // padding-bottom: $table-cell-padding-y;\n // color: $table-caption-color;\n padding-block: .5rem;\n color: var(--fg-3);\n text-align: start;\n }\n\n // 1. Removes font-weight bold by inheriting\n // 2. Matches default `` alignment by inheriting `text-align`.\n // 3. Fix alignment for Safari\n\n th {\n // font-weight: $table-th-font-weight; // 1 // mdo-do: it's null by default. maybe we remove?\n text-align: inherit; // 2\n text-align: -webkit-match-parent; // 3\n }\n\n thead,\n tbody,\n tfoot,\n tr,\n td,\n th {\n border-color: inherit;\n border-style: solid;\n border-width: 0;\n }\n\n // Forms\n //\n // 1. Allow labels to use `margin` for spacing.\n\n label {\n display: inline-block; // 1\n }\n\n // Remove the default `border-radius` that macOS Chrome adds.\n // See https://github.com/twbs/bootstrap/issues/24093\n\n button {\n // stylelint-disable-next-line property-disallowed-list\n border-radius: 0;\n }\n\n // Explicitly remove focus outline in Chromium when it shouldn't be\n // visible (e.g. as result of mouse click or touch tap). It already\n // should be doing this automatically, but seems to currently be\n // confused and applies its very visible two-tone outline anyway.\n\n button:focus:not(:focus-visible) {\n outline: 0;\n }\n\n // 1. Remove the margin in Firefox and Safari\n\n input,\n button,\n select,\n optgroup,\n textarea {\n margin: 0; // 1\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n }\n\n // Remove the inheritance of text transform in Firefox\n button,\n select {\n text-transform: none;\n }\n // Set the cursor for non-``,ArrowPrev=(e,t)=>``,ControlTime=e=>e.selectionTimeMode?`

`:"",DateRangeTooltip=e=>e.onCreateDateRangeTooltip?`
`:"",Dates=e=>`
`,Month=e=>``,Months=e=>`
`,Week=e=>`
`,WeekNumbers=e=>e.enableWeekNumbers?`
`:"",Year=e=>``,Years=e=>`
`,components={ArrowNext:ArrowNext,ArrowPrev:ArrowPrev,ControlTime:ControlTime,Dates:Dates,DateRangeTooltip:DateRangeTooltip,Month:Month,Months:Months,Week:Week,WeekNumbers:WeekNumbers,Year:Year,Years:Years},getComponent=e=>components[e],parseLayout=(e,t)=>t.replace(/[\n\t]/g,"").replace(/<#(?!\/?Multiple)(.*?)>/g,((t,n)=>{const a=(n.match(/\[(.*?)\]/)||[])[1],o=n.replace(/[/\s\n\t]|\[(.*?)\]/g,""),l=getComponent(o),s=l?l(e,null!=a?a:null):"";return e.sanitizerHTML(s)})).replace(/[\n\t]/g,""),parseMultipleLayout=(e,t)=>t.replace(new RegExp("<#Multiple>(.*?)<#\\/Multiple>","gs"),((t,n)=>{const a=Array(e.context.displayMonthsCount).fill(n).join("");return e.sanitizerHTML(a)})).replace(/[\n\t]/g,""),createLayouts=(e,t)=>{const n={default:layoutDefault,month:layoutMonths,year:layoutYears,multiple:layoutMultiple};if(Object.keys(n).forEach((t=>{const a=t;e.layouts[a].length||(e.layouts[a]=n[a](e));})),e.context.mainElement.className=e.styles.calendar,e.context.mainElement.dataset.vc="calendar",e.context.mainElement.dataset.vcType=e.context.currentType,e.context.mainElement.role="application",e.context.mainElement.tabIndex=0,e.context.mainElement.ariaLabel=e.labels.application,"multiple"!==e.context.currentType){if("multiple"===e.type&&t){const n=e.context.mainElement.querySelector('[data-vc="controls"]'),a=e.context.mainElement.querySelector('[data-vc="grid"]'),o=t.closest('[data-vc="column"]');return n&&n.remove(),a&&(a.dataset.vcGrid="hidden"),o&&(o.dataset.vcColumn=e.context.currentType),void(o&&(o.innerHTML=e.sanitizerHTML(parseLayout(e,e.layouts[e.context.currentType]))))}e.context.mainElement.innerHTML=e.sanitizerHTML(parseLayout(e,e.layouts[e.context.currentType]));}else e.context.mainElement.innerHTML=e.sanitizerHTML(parseMultipleLayout(e,parseLayout(e,e.layouts[e.context.currentType])));},setVisibilityArrows=(e,t,n,a)=>{e.style.visibility=n?"hidden":"",t.style.visibility=a?"hidden":"";},handleDefaultType=(e,t,n)=>{const a=getDate(getDateString(new Date(e.context.selectedYear,e.context.selectedMonth,1))),o=new Date(a.getTime()),l=new Date(a.getTime());o.setMonth(o.getMonth()-e.monthsToSwitch),l.setMonth(l.getMonth()+e.monthsToSwitch);const s=getDate(e.context.dateMin),i=getDate(e.context.dateMax);e.selectionYearsMode||(s.setFullYear(a.getFullYear()),i.setFullYear(a.getFullYear()));const r=!e.selectionMonthsMode||o.getFullYear()i.getFullYear()||l.getFullYear()===i.getFullYear()&&l.getMonth()>i.getMonth()-(e.context.displayMonthsCount-1);setVisibilityArrows(t,n,r,c);},handleYearType=(e,t,n)=>{const a=getDate(e.context.dateMin),o=getDate(e.context.dateMax),l=!!(a.getFullYear()&&e.context.displayYear-7<=a.getFullYear()),s=!!(o.getFullYear()&&e.context.displayYear+7>=o.getFullYear());setVisibilityArrows(t,n,l,s);},visibilityArrows=e=>{if("month"===e.context.currentType)return;const t=e.context.mainElement.querySelector('[data-vc-arrow="prev"]'),n=e.context.mainElement.querySelector('[data-vc-arrow="next"]');if(!t||!n)return;({default:()=>handleDefaultType(e,t,n),year:()=>handleYearType(e,t,n)})["multiple"===e.context.currentType?"default":e.context.currentType]();},visibilityHandler=(e,t,n,a,o)=>{const l=new Date(a.setFullYear(e.context.selectedYear,e.context.selectedMonth+n)).getFullYear(),s=new Date(a.setMonth(e.context.selectedMonth+n)).getMonth(),i=e.context.locale.months.long[s],r=t.closest('[data-vc="column"]');r&&(r.ariaLabel=`${i} ${l}`);const c={month:{id:s,label:i},year:{id:l,label:l}};t.innerText=String(c[o].label),t.dataset[`vc${o.charAt(0).toUpperCase()+o.slice(1)}`]=String(c[o].id),t.ariaLabel=`${e.labels[o]} ${c[o].label}`;const d={month:e.selectionMonthsMode,year:e.selectionYearsMode},u=false===d[o]||"only-arrows"===d[o];u&&(t.tabIndex=-1),t.disabled=u;},visibilityTitle=e=>{const t=e.context.mainElement.querySelectorAll('[data-vc="month"]'),n=e.context.mainElement.querySelectorAll('[data-vc="year"]'),a=new Date(e.context.selectedYear,e.context.selectedMonth,1);[t,n].forEach((t=>null==t?void 0:t.forEach(((t,n)=>visibilityHandler(e,t,n,a,t.dataset.vc)))));},setYearModifier=(e,t,n,a,o)=>{var l;const s={month:"[data-vc-months-month]",year:"[data-vc-years-year]"},i={month:{selected:"data-vc-months-month-selected",aria:"aria-selected",value:"vcMonthsMonth",selectedProperty:"selectedMonth"},year:{selected:"data-vc-years-year-selected",aria:"aria-selected",value:"vcYearsYear",selectedProperty:"selectedYear"}};o&&(null==(l=e.context.mainElement.querySelectorAll(s[n]))||l.forEach((e=>{e.removeAttribute(i[n].selected),e.removeAttribute(i[n].aria);})),setContext(e,i[n].selectedProperty,Number(t.dataset[i[n].value])),visibilityTitle(e),"year"===n&&visibilityArrows(e)),a&&(t.setAttribute(i[n].selected,""),t.setAttribute(i[n].aria,"true"));},getColumnID=(e,t)=>{var n;if("multiple"!==e.type)return {currentValue:null,columnID:0};const a=e.context.mainElement.querySelectorAll('[data-vc="column"]'),o=Array.from(a).findIndex((e=>e.closest(`[data-vc-column="${t}"]`)));return {currentValue:o>=0?Number(null==(n=a[o].querySelector(`[data-vc="${t}"]`))?void 0:n.getAttribute(`data-vc-${t}`)):null,columnID:Math.max(o,0)}},createMonthEl=(e,t,n,a,o,l,s)=>{const i=t.cloneNode(false);return i.className=e.styles.monthsMonth,i.innerText=a,i.ariaLabel=o,i.role="gridcell",i.dataset.vcMonthsMonth=`${s}`,l&&(i.ariaDisabled="true"),l&&(i.tabIndex=-1),i.disabled=l,setYearModifier(e,i,"month",n===s,false),i},createMonths=(e,t)=>{var n,a;const o=null==(n=null==t?void 0:t.closest('[data-vc="header"]'))?void 0:n.querySelector('[data-vc="year"]'),l=o?Number(o.dataset.vcYear):e.context.selectedYear,s=(null==t?void 0:t.dataset.vcMonth)?Number(t.dataset.vcMonth):e.context.selectedMonth;setContext(e,"currentType","month"),createLayouts(e,t),visibilityTitle(e);const i=e.context.mainElement.querySelector('[data-vc="months"]');if(!e.selectionMonthsMode||!i)return;const r=e.monthsToSwitch>1?e.context.locale.months.long.map(((t,n)=>s-e.monthsToSwitch*n)).concat(e.context.locale.months.long.map(((t,n)=>s+e.monthsToSwitch*n))).filter((e=>e>=0&&e<=12)):Array.from(Array(12).keys()),c=document.createElement("button");c.type="button";for(let t=0;t<12;t++){const n=getDate(e.context.dateMin),a=getDate(e.context.dateMax),o=e.context.displayMonthsCount-1,{columnID:d}=getColumnID(e,"month"),u=l<=n.getFullYear()&&t=a.getFullYear()&&t>a.getMonth()-o+d||l>a.getFullYear()||t!==s&&!r.includes(t),m=createMonthEl(e,c,s,e.context.locale.months.short[t],e.context.locale.months.long[t],u,t);i.appendChild(m),e.onCreateMonthEls&&e.onCreateMonthEls(e,m);}null==(a=e.context.mainElement.querySelector("[data-vc-months-month]:not([disabled])"))||a.focus();},TimeInput=(e,t,n,a,o)=>`\n \n`,TimeRange=(e,t,n,a,o,l,s)=>`\n \n`,handleActions=(e,t,n,a)=>{(({hour:()=>setContext(e,"selectedHours",n),minute:()=>setContext(e,"selectedMinutes",n)}))[a](),setContext(e,"selectedTime",`${e.context.selectedHours}:${e.context.selectedMinutes}${e.context.selectedKeeping?` ${e.context.selectedKeeping}`:""}`),e.onChangeTime&&e.onChangeTime(e,t,false),e.inputMode&&e.context.inputElement&&e.context.mainElement&&e.onChangeToInput&&e.onChangeToInput(e,t);},transformTime24=(e,t)=>{var n;return (null==(n={0:{AM:"00",PM:"12"},1:{AM:"01",PM:"13"},2:{AM:"02",PM:"14"},3:{AM:"03",PM:"15"},4:{AM:"04",PM:"16"},5:{AM:"05",PM:"17"},6:{AM:"06",PM:"18"},7:{AM:"07",PM:"19"},8:{AM:"08",PM:"20"},9:{AM:"09",PM:"21"},10:{AM:"10",PM:"22"},11:{AM:"11",PM:"23"},12:{AM:"00",PM:"12"}}[Number(e)])?void 0:n[t])||String(e)},handleClickKeepingTime=(e,t,n,a,o)=>{const l=l=>{const s="AM"===e.context.selectedKeeping?"PM":"AM",i=transformTime24(e.context.selectedHours,s);Number(i)<=a&&Number(i)>=o?(setContext(e,"selectedKeeping",s),n.value=i,handleActions(e,l,e.context.selectedHours,"hour"),t.ariaLabel=`${e.labels.btnKeeping} ${e.context.selectedKeeping}`,t.innerText=e.context.selectedKeeping):e.onChangeTime&&e.onChangeTime(e,l,true);};return t.addEventListener("click",l),()=>{t.removeEventListener("click",l);}},transformTime12=e=>({0:"12",13:"01",14:"02",15:"03",16:"04",17:"05",18:"06",19:"07",20:"08",21:"09",22:"10",23:"11"}[Number(e)]||String(e)),updateInputAndRange=(e,t,n,a)=>{e.value=n,t.value=a;},updateKeepingTime$1=(e,t,n)=>{t&&n&&(setContext(e,"selectedKeeping",n),t.innerText=n);},handleInput$1=(e,t,n,a,o,l,s)=>{const i={hour:(i,r,c)=>{if(!e.selectionTimeMode)return;({12:()=>{if(!e.context.selectedKeeping)return;const d=Number(transformTime24(r,e.context.selectedKeeping));if(!(d<=l&&d>=s))return updateInputAndRange(n,t,e.context.selectedHours,e.context.selectedHours),void(e.onChangeTime&&e.onChangeTime(e,c,true));updateInputAndRange(n,t,transformTime12(r),transformTime24(r,e.context.selectedKeeping)),i>12&&updateKeepingTime$1(e,a,"PM"),handleActions(e,c,transformTime12(r),o);},24:()=>{if(!(i<=l&&i>=s))return updateInputAndRange(n,t,e.context.selectedHours,e.context.selectedHours),void(e.onChangeTime&&e.onChangeTime(e,c,true));updateInputAndRange(n,t,r,r),handleActions(e,c,r,o);}})[e.selectionTimeMode]();},minute:(a,i,r)=>{if(!(a<=l&&a>=s))return n.value=e.context.selectedMinutes,void(e.onChangeTime&&e.onChangeTime(e,r,true));n.value=i,t.value=i,handleActions(e,r,i,o);}},r=e=>{const t=Number(n.value),a=n.value.padStart(2,"0");i[o]&&i[o](t,a,e);};return n.addEventListener("change",r),()=>{n.removeEventListener("change",r);}},updateInputAndTime=(e,t,n,a,o)=>{t.value=o,handleActions(e,n,o,a);},updateKeepingTime=(e,t,n)=>{t&&(setContext(e,"selectedKeeping",n),t.innerText=n);},handleRange=(e,t,n,a,o)=>{const l=l=>{const s=Number(t.value),i=t.value.padStart(2,"0"),r="hour"===o,c=24===e.selectionTimeMode,d=s>0&&s<12;r&&!c&&updateKeepingTime(e,a,0===s||d?"AM":"PM"),updateInputAndTime(e,n,l,o,!r||c||d?i:transformTime12(t.value));};return t.addEventListener("input",l),()=>{t.removeEventListener("input",l);}},handleMouseOver=e=>e.setAttribute("data-vc-input-focus",""),handleMouseOut=e=>e.removeAttribute("data-vc-input-focus"),handleTime=(e,t)=>{const n=t.querySelector('[data-vc-time-range="hour"] input[name="hour"]'),a=t.querySelector('[data-vc-time-range="minute"] input[name="minute"]'),o=t.querySelector('[data-vc-time-input="hour"] input[name="hour"]'),l=t.querySelector('[data-vc-time-input="minute"] input[name="minute"]'),s=t.querySelector('[data-vc-time="keeping"]');if(!(n&&a&&o&&l))return;const i=e=>{e.target===n&&handleMouseOver(o),e.target===a&&handleMouseOver(l);},r=e=>{e.target===n&&handleMouseOut(o),e.target===a&&handleMouseOut(l);};return t.addEventListener("mouseover",i),t.addEventListener("mouseout",r),handleInput$1(e,n,o,s,"hour",e.timeMaxHour,e.timeMinHour),handleInput$1(e,a,l,s,"minute",e.timeMaxMinute,e.timeMinMinute),handleRange(e,n,o,s,"hour"),handleRange(e,a,l,s,"minute"),s&&handleClickKeepingTime(e,s,n,e.timeMaxHour,e.timeMinHour),()=>{t.removeEventListener("mouseover",i),t.removeEventListener("mouseout",r);}},createTime=e=>{const t=e.context.mainElement.querySelector('[data-vc="time"]');if(!e.selectionTimeMode||!t)return;const[n,a]=[e.timeMinHour,e.timeMaxHour],[o,l]=[e.timeMinMinute,e.timeMaxMinute],s=e.context.selectedKeeping?transformTime24(e.context.selectedHours,e.context.selectedKeeping):e.context.selectedHours,i="range"===e.timeControls;var r;t.innerHTML=e.sanitizerHTML(`\n
\n ${TimeInput("hour",e.styles.timeHour,e.labels,e.context.selectedHours,i)}\n ${TimeInput("minute",e.styles.timeMinute,e.labels,e.context.selectedMinutes,i)}\n ${12===e.selectionTimeMode?(r=e.context.selectedKeeping,``):""}\n
\n
\n ${TimeRange("hour",e.styles.timeRange,e.labels,n,a,e.timeStepHour,s)}\n ${TimeRange("minute",e.styles.timeRange,e.labels,o,l,e.timeStepMinute,e.context.selectedMinutes)}\n
\n `),handleTime(e,t);},createWeek=e=>{const t=e.selectedWeekends?[...e.selectedWeekends]:[],n=[...e.context.locale.weekdays.long].reduce(((n,a,o)=>[...n,{id:o,titleShort:e.context.locale.weekdays.short[o],titleLong:a,isWeekend:t.includes(o)}]),[]),a=[...n.slice(e.firstWeekday),...n.slice(0,e.firstWeekday)];e.context.mainElement.querySelectorAll('[data-vc="week"]').forEach((t=>{const n=e.onClickWeekDay?document.createElement("button"):document.createElement("b");e.onClickWeekDay&&(n.type="button"),a.forEach((a=>{const o=n.cloneNode(true);o.innerText=a.titleShort,o.className=e.styles.weekDay,o.role="columnheader",o.ariaLabel=a.titleLong,o.dataset.vcWeekDay=String(a.id),a.isWeekend&&(o.dataset.vcWeekDayOff=""),t.appendChild(o);}));}));},createYearEl=(e,t,n,a,o)=>{const l=t.cloneNode(false);return l.className=e.styles.yearsYear,l.innerText=String(o),l.ariaLabel=String(o),l.role="gridcell",l.dataset.vcYearsYear=`${o}`,a&&(l.ariaDisabled="true"),a&&(l.tabIndex=-1),l.disabled=a,setYearModifier(e,l,"year",n===o,false),l},createYears=(e,t)=>{var n;const a=(null==t?void 0:t.dataset.vcYear)?Number(t.dataset.vcYear):e.context.selectedYear;setContext(e,"currentType","year"),createLayouts(e,t),visibilityTitle(e),visibilityArrows(e);const o=e.context.mainElement.querySelector('[data-vc="years"]');if(!e.selectionYearsMode||!o)return;const l="multiple"!==e.type||e.context.selectedYear===a?0:1,s=document.createElement("button");s.type="button";for(let t=e.context.displayYear-7;tgetDate(e.context.dateMax).getFullYear(),i=createYearEl(e,s,a,n,t);o.appendChild(i),e.onCreateYearEls&&e.onCreateYearEls(e,i);}null==(n=e.context.mainElement.querySelector("[data-vc-years-year]:not([disabled])"))||n.focus();},trackChangesHTMLElement=(e,t,n)=>{new MutationObserver((e=>{for(let a=0;ahaveListener.value=true,check:()=>haveListener.value},setTheme=(e,t)=>e.dataset.vcTheme=t,trackChangesThemeInSystemSettings=(e,t)=>{if(setTheme(e.context.mainElement,t.matches?"dark":"light"),"system"!==e.selectedTheme||haveListener.check())return;const n=e=>{const t=document.querySelectorAll('[data-vc="calendar"]');null==t||t.forEach((t=>setTheme(t,e.matches?"dark":"light")));};t.addEventListener?t.addEventListener("change",n):t.addListener(n),haveListener.set();},detectTheme=(e,t)=>{const n=e.themeAttrDetect.length?document.querySelector(e.themeAttrDetect):null,a=e.themeAttrDetect.replace(/^.*\[(.+)\]/g,((e,t)=>t));if(!n||"system"===n.getAttribute(a))return void trackChangesThemeInSystemSettings(e,t);const o=n.getAttribute(a);o?(setTheme(e.context.mainElement,o),trackChangesHTMLElement(n,a,(()=>{const t=n.getAttribute(a);t&&setTheme(e.context.mainElement,t);}))):trackChangesThemeInSystemSettings(e,t);},handleTheme=e=>{"not all"!==window.matchMedia("(prefers-color-scheme)").media?"system"===e.selectedTheme?detectTheme(e,window.matchMedia("(prefers-color-scheme: dark)")):setTheme(e.context.mainElement,e.selectedTheme):setTheme(e.context.mainElement,"light");},capitalizeFirstLetter=e=>e.charAt(0).toUpperCase()+e.slice(1).replace(/\./,""),getLocaleWeekday=(e,t,n)=>{const a=new Date(`1978-01-0${t+1}T00:00:00.000Z`),o=a.toLocaleString(n,{weekday:"short",timeZone:"UTC"}),l=a.toLocaleString(n,{weekday:"long",timeZone:"UTC"});e.context.locale.weekdays.short.push(capitalizeFirstLetter(o)),e.context.locale.weekdays.long.push(capitalizeFirstLetter(l));},getLocaleMonth=(e,t,n)=>{const a=new Date(`1978-${String(t+1).padStart(2,"0")}-01T00:00:00.000Z`),o=a.toLocaleString(n,{month:"short",timeZone:"UTC"}),l=a.toLocaleString(n,{month:"long",timeZone:"UTC"});e.context.locale.months.short.push(capitalizeFirstLetter(o)),e.context.locale.months.long.push(capitalizeFirstLetter(l));},getLocale=e=>{var t,n,a,o,l,s,i,r;if(!(e.context.locale.weekdays.short[6]&&e.context.locale.weekdays.long[6]&&e.context.locale.months.short[11]&&e.context.locale.months.long[11]))if("string"==typeof e.locale){if("string"==typeof e.locale&&!e.locale.length)throw new Error(errorMessages.notLocale);Array.from({length:7},((t,n)=>getLocaleWeekday(e,n,e.locale))),Array.from({length:12},((t,n)=>getLocaleMonth(e,n,e.locale)));}else {if(!((null==(n=null==(t=e.locale)?void 0:t.weekdays)?void 0:n.short[6])&&(null==(o=null==(a=e.locale)?void 0:a.weekdays)?void 0:o.long[6])&&(null==(s=null==(l=e.locale)?void 0:l.months)?void 0:s.short[11])&&(null==(r=null==(i=e.locale)?void 0:i.months)?void 0:r.long[11])))throw new Error(errorMessages.notLocale);setContext(e,"locale",__spreadValues({},e.locale));}},create=e=>{const t={default:()=>{createWeek(e),createDates(e);},multiple:()=>{createWeek(e),createDates(e);},month:()=>createMonths(e),year:()=>createYears(e)};handleTheme(e),getLocale(e),createLayouts(e),visibilityTitle(e),visibilityArrows(e),createTime(e),t[e.context.currentType]();},handleArrowKeys=e=>{const t=t=>{var n;const a=t.target;if(!["ArrowUp","ArrowDown","ArrowLeft","ArrowRight"].includes(t.key)||"button"!==a.localName)return;const o=Array.from(e.context.mainElement.querySelectorAll('[data-vc="calendar"] button')),l=o.indexOf(a);if(-1===l)return;const s=(i=o[l]).hasAttribute("data-vc-date-btn")?7:i.hasAttribute("data-vc-months-month")?4:i.hasAttribute("data-vc-years-year")?5:1;var i;const r=(0, {ArrowUp:()=>Math.max(0,l-s),ArrowDown:()=>Math.min(o.length-1,l+s),ArrowLeft:()=>Math.max(0,l-1),ArrowRight:()=>Math.min(o.length-1,l+1)}[t.key])();null==(n=o[r])||n.focus();};return e.context.mainElement.addEventListener("keydown",t),()=>e.context.mainElement.removeEventListener("keydown",t)},handleMonth=(e,t)=>{const n=getDate(getDateString(new Date(e.context.selectedYear,e.context.selectedMonth,1)));(({prev:()=>n.setMonth(n.getMonth()-e.monthsToSwitch),next:()=>n.setMonth(n.getMonth()+e.monthsToSwitch)}))[t](),setContext(e,"selectedMonth",n.getMonth()),setContext(e,"selectedYear",n.getFullYear()),visibilityTitle(e),visibilityArrows(e),createDates(e);},handleClickArrow=(e,t)=>{const n=t.target.closest("[data-vc-arrow]");if(n){if(["default","multiple"].includes(e.context.currentType))handleMonth(e,n.dataset.vcArrow);else if("year"===e.context.currentType&&void 0!==e.context.displayYear){const a={prev:-15,next:15}[n.dataset.vcArrow];setContext(e,"displayYear",e.context.displayYear+a),createYears(e,t.target);}e.onClickArrow&&e.onClickArrow(e,t);}},resolveToggle=(e,t)=>void 0===t||("function"==typeof t?t(e):t),canToggleSelection=e=>resolveToggle(e,e.enableDateToggle),handleSelectDate=(e,t,n)=>{const a=t.dataset.vcDate,o=t.closest("[data-vc-date][data-vc-date-selected]"),l=canToggleSelection(e);if(o&&!l)return;const s=o?e.context.selectedDates.filter((e=>e!==a)):n?[...e.context.selectedDates,a]:[a];setContext(e,"selectedDates",s);},createDateRangeTooltip=(e,t,n)=>{if(!t)return;if(!n)return t.dataset.vcDateRangeTooltip="hidden",void(t.textContent="");const a=e.context.mainElement.getBoundingClientRect(),o=n.getBoundingClientRect();t.style.left=o.left-a.left+o.width/2+"px",t.style.top=o.bottom-a.top-o.height+"px",t.dataset.vcDateRangeTooltip="visible",t.innerHTML=e.sanitizerHTML(e.onCreateDateRangeTooltip(e,n,t,o,a));},state={self:null,lastDateEl:null,isHovering:false,rangeMin:void 0,rangeMax:void 0,tooltipEl:null,timeoutId:null},addHoverEffect=(e,t,n)=>{var a,o,l;if(!(null==(o=null==(a=state.self)?void 0:a.context)?void 0:o.selectedDates[0]))return;const s=getDateString(e);(null==(l=state.self.context.disableDates)?void 0:l.includes(s))||(state.self.context.mainElement.querySelectorAll(`[data-vc-date="${s}"]`).forEach((e=>e.dataset.vcDateHover="")),t.forEach((e=>e.dataset.vcDateHover="first")),n.forEach((e=>{"first"===e.dataset.vcDateHover?e.dataset.vcDateHover="first-and-last":e.dataset.vcDateHover="last";})));},removeHoverEffect=()=>{var e,t;if(!(null==(t=null==(e=state.self)?void 0:e.context)?void 0:t.mainElement))return;state.self.context.mainElement.querySelectorAll("[data-vc-date-hover]").forEach((e=>e.removeAttribute("data-vc-date-hover")));},handleHoverDatesEvent=e=>{var t,n;if(!e||!(null==(n=null==(t=state.self)?void 0:t.context)?void 0:n.selectedDates[0]))return;if(!e.closest('[data-vc="dates"]'))return state.lastDateEl=null,createDateRangeTooltip(state.self,state.tooltipEl,null),void removeHoverEffect();const a=e.closest("[data-vc-date]");if(!a||state.lastDateEl===a)return;state.lastDateEl=a,createDateRangeTooltip(state.self,state.tooltipEl,a),removeHoverEffect();const o=a.dataset.vcDate,l=getDate(state.self.context.selectedDates[0]),s=getDate(o),i=state.self.context.mainElement.querySelectorAll(`[data-vc-date="${state.self.context.selectedDates[0]}"]`),r=state.self.context.mainElement.querySelectorAll(`[data-vc-date="${o}"]`),[c,d]=l{const t=null==e?void 0:e.closest("[data-vc-date-selected]");if(!t&&state.lastDateEl)return state.lastDateEl=null,void createDateRangeTooltip(state.self,state.tooltipEl,null);t&&state.lastDateEl!==t&&(state.lastDateEl=t,createDateRangeTooltip(state.self,state.tooltipEl,t));},optimizedHoverHandler=e=>t=>{const n=t.target;state.isHovering||(state.isHovering=true,requestAnimationFrame((()=>{e(n),state.isHovering=false;})));},optimizedHandleHoverDatesEvent=optimizedHoverHandler(handleHoverDatesEvent),optimizedHandleHoverSelectedDatesRangeEvent=optimizedHoverHandler(handleHoverSelectedDatesRangeEvent),handleCancelSelectionDates=e=>{state.self&&"Escape"===e.key&&(state.lastDateEl=null,setContext(state.self,"selectedDates",[]),state.self.context.mainElement.removeEventListener("mousemove",optimizedHandleHoverDatesEvent),state.self.context.mainElement.removeEventListener("keydown",handleCancelSelectionDates),createDateRangeTooltip(state.self,state.tooltipEl,null),removeHoverEffect());},handleMouseLeave=()=>{null!==state.timeoutId&&clearTimeout(state.timeoutId),state.timeoutId=setTimeout((()=>{state.lastDateEl=null,createDateRangeTooltip(state.self,state.tooltipEl,null),removeHoverEffect();}),50);},updateDisabledDates=()=>{var e,t,n,a;if(!(null==(n=null==(t=null==(e=state.self)?void 0:e.context)?void 0:t.selectedDates)?void 0:n[0])||!(null==(a=state.self.context.disableDates)?void 0:a[0]))return;const o=getDate(state.self.context.selectedDates[0]),[l,s]=state.self.context.disableDates.map((e=>getDate(e))).reduce((([e,t],n)=>[o>=n?n:e,o{state.self=e,state.lastDateEl=t,removeHoverEffect(),e.disableDatesGaps&&(state.rangeMin=state.rangeMin?state.rangeMin:e.context.displayDateMin,state.rangeMax=state.rangeMax?state.rangeMax:e.context.displayDateMax),e.onCreateDateRangeTooltip&&(state.tooltipEl=e.context.mainElement.querySelector("[data-vc-date-range-tooltip]"));const n=null==t?void 0:t.dataset.vcDate;if(n){const t=1===e.context.selectedDates.length&&e.context.selectedDates[0].includes(n),a=t&&!canToggleSelection(e)?[n,n]:t&&canToggleSelection(e)?[]:e.context.selectedDates.length>1?[n]:[...e.context.selectedDates,n];setContext(e,"selectedDates",a),e.context.selectedDates.length>1&&e.context.selectedDates.sort(((e,t)=>+new Date(e)-+new Date(t)));}({set:()=>(e.disableDatesGaps&&updateDisabledDates(),createDateRangeTooltip(state.self,state.tooltipEl,t),state.self.context.mainElement.removeEventListener("mousemove",optimizedHandleHoverSelectedDatesRangeEvent),state.self.context.mainElement.removeEventListener("mouseleave",handleMouseLeave),state.self.context.mainElement.removeEventListener("keydown",handleCancelSelectionDates),state.self.context.mainElement.addEventListener("mousemove",optimizedHandleHoverDatesEvent),state.self.context.mainElement.addEventListener("mouseleave",handleMouseLeave),state.self.context.mainElement.addEventListener("keydown",handleCancelSelectionDates),()=>{state.self.context.mainElement.removeEventListener("mousemove",optimizedHandleHoverDatesEvent),state.self.context.mainElement.removeEventListener("mouseleave",handleMouseLeave),state.self.context.mainElement.removeEventListener("keydown",handleCancelSelectionDates);}),reset:()=>{const[n,a]=[e.context.selectedDates[0],e.context.selectedDates[e.context.selectedDates.length-1]],o=e.context.selectedDates[0]!==e.context.selectedDates[e.context.selectedDates.length-1],l=parseDates([`${n}:${a}`]).filter((t=>!e.context.disableDates.includes(t))),s=o?e.enableEdgeDatesOnly?[n,a]:l:[e.context.selectedDates[0],e.context.selectedDates[0]];if(setContext(e,"selectedDates",s),e.disableDatesGaps&&(setContext(e,"displayDateMin",state.rangeMin),setContext(e,"displayDateMax",state.rangeMax)),state.self.context.mainElement.removeEventListener("mousemove",optimizedHandleHoverDatesEvent),state.self.context.mainElement.removeEventListener("mouseleave",handleMouseLeave),state.self.context.mainElement.removeEventListener("keydown",handleCancelSelectionDates),e.onCreateDateRangeTooltip)return e.context.selectedDates[0]||(state.self.context.mainElement.removeEventListener("mousemove",optimizedHandleHoverSelectedDatesRangeEvent),state.self.context.mainElement.removeEventListener("mouseleave",handleMouseLeave),createDateRangeTooltip(state.self,state.tooltipEl,null)),e.context.selectedDates[0]&&(state.self.context.mainElement.addEventListener("mousemove",optimizedHandleHoverSelectedDatesRangeEvent),state.self.context.mainElement.addEventListener("mouseleave",handleMouseLeave),createDateRangeTooltip(state.self,state.tooltipEl,t)),()=>{state.self.context.mainElement.removeEventListener("mousemove",optimizedHandleHoverSelectedDatesRangeEvent),state.self.context.mainElement.removeEventListener("mouseleave",handleMouseLeave);}}})[1===e.context.selectedDates.length?"set":"reset"]();},updateDateModifier=e=>{e.context.mainElement.querySelectorAll("[data-vc-date]").forEach((t=>{const n=t.querySelector("[data-vc-date-btn]"),a=t.dataset.vcDate,o=getDate(a).getDay();setDateModifier(e,e.context.selectedYear,t,n,o,a,"current");}));},handleClickDate=(e,t)=>{var n;const a=t.target,o=a.closest("[data-vc-date-btn]");if(!e.selectionDatesMode||!["single","multiple","multiple-ranged"].includes(e.selectionDatesMode)||!o)return;const l=o.closest("[data-vc-date]");(({single:()=>handleSelectDate(e,l,false),multiple:()=>handleSelectDate(e,l,true),"multiple-ranged":()=>handleSelectDateRange(e,l)}))[e.selectionDatesMode](),null==(n=e.context.selectedDates)||n.sort(((e,t)=>+new Date(e)-+new Date(t))),e.onClickDate&&e.onClickDate(e,t),e.inputMode&&e.context.inputElement&&e.context.mainElement&&e.onChangeToInput&&e.onChangeToInput(e,t);const s=a.closest('[data-vc-date-month="prev"]'),i=a.closest('[data-vc-date-month="next"]');({prev:()=>e.enableMonthChangeOnDayClick?handleMonth(e,"prev"):updateDateModifier(e),next:()=>e.enableMonthChangeOnDayClick?handleMonth(e,"next"):updateDateModifier(e),current:()=>updateDateModifier(e)})[s?"prev":i?"next":"current"]();},typeClick=["month","year"],getValue=(e,t,n)=>{const{currentValue:a,columnID:o}=getColumnID(e,t);return "month"===e.context.currentType&&o>=0?n-o:"year"===e.context.currentType&&e.context.selectedYear!==a?n-1:n},handleMultipleYearSelection=(e,t)=>{const n=getValue(e,"year",Number(t.dataset.vcYearsYear)),a=getDate(e.context.dateMin),o=getDate(e.context.dateMax),l=e.context.displayMonthsCount-1,{columnID:s}=getColumnID(e,"year"),i=e.context.selectedMontho.getMonth()-l+s&&n>=o.getFullYear(),c=no.getFullYear(),u=i||c?a.getFullYear():r||d?o.getFullYear():n,m=i||c?a.getMonth():r||d?o.getMonth()-l+s:e.context.selectedMonth;setContext(e,"selectedYear",u),setContext(e,"selectedMonth",m);},handleMultipleMonthSelection=(e,t)=>{const n=t.closest('[data-vc-column="month"]').querySelector('[data-vc="year"]'),a=getValue(e,"month",Number(t.dataset.vcMonthsMonth)),o=Number(n.dataset.vcYear),l=getDate(e.context.dateMin),s=getDate(e.context.dateMax),i=as.getMonth()&&o>=s.getFullYear();setContext(e,"selectedYear",o),setContext(e,"selectedMonth",i?l.getMonth():r?s.getMonth():a);},handleItemClick=(e,t,n,a)=>{var o;({year:()=>{if("multiple"===e.type)return handleMultipleYearSelection(e,a);setContext(e,"selectedYear",Number(a.dataset.vcYearsYear));},month:()=>{if("multiple"===e.type)return handleMultipleMonthSelection(e,a);setContext(e,"selectedMonth",Number(a.dataset.vcMonthsMonth));}})[n]();(({year:()=>{var n;return null==(n=e.onClickYear)?void 0:n.call(e,e,t)},month:()=>{var n;return null==(n=e.onClickMonth)?void 0:n.call(e,e,t)}}))[n](),e.context.currentType!==e.type?(setContext(e,"currentType",e.type),create(e),null==(o=e.context.mainElement.querySelector(`[data-vc="${n}"]`))||o.focus()):setYearModifier(e,a,n,true,true);},handleClickType=(e,t,n)=>{var a;const o=t.target,l=o.closest(`[data-vc="${n}"]`),s={year:()=>createYears(e,o),month:()=>createMonths(e,o)};if(l&&e.onClickTitle&&e.onClickTitle(e,t),l&&e.context.currentType!==n)return s[n]();const i=o.closest(`[data-vc-${n}s-${n}]`);if(i)return handleItemClick(e,t,n,i);const r=o.closest('[data-vc="grid"]'),c=o.closest('[data-vc="column"]');(e.context.currentType===n&&l||"multiple"===e.type&&e.context.currentType===n&&r&&!c)&&(setContext(e,"currentType",e.type),create(e),null==(a=e.context.mainElement.querySelector(`[data-vc="${n}"]`))||a.focus());},handleClickMonthOrYear=(e,t)=>{const n={month:e.selectionMonthsMode,year:e.selectionYearsMode};typeClick.forEach((a=>{n[a]&&t.target&&handleClickType(e,t,a);}));},handleClickWeekNumber=(e,t)=>{if(!e.enableWeekNumbers||!e.onClickWeekNumber)return;const n=t.target.closest("[data-vc-week-number]"),a=e.context.mainElement.querySelectorAll("[data-vc-date-week-number]");if(!n||!a[0])return;const o=Number(n.innerText),l=Number(n.dataset.vcWeekYear),s=Array.from(a).filter((e=>Number(e.dataset.vcDateWeekNumber)===o));e.onClickWeekNumber(e,o,l,s,t);},handleClickWeekDay=(e,t)=>{if(!e.onClickWeekDay)return;const n=t.target.closest("[data-vc-week-day]"),a=t.target.closest('[data-vc="column"]'),o=a?a.querySelectorAll("[data-vc-date-week-day]"):e.context.mainElement.querySelectorAll("[data-vc-date-week-day]");if(!n||!o[0])return;const l=Number(n.dataset.vcWeekDay),s=Array.from(o).filter((e=>Number(e.dataset.vcDateWeekDay)===l));e.onClickWeekDay(e,l,s,t);},handleClick=e=>{const t=t=>{handleClickArrow(e,t),handleClickWeekDay(e,t),handleClickWeekNumber(e,t),handleClickDate(e,t),handleClickMonthOrYear(e,t);};return e.context.mainElement.addEventListener("click",t),()=>e.context.mainElement.removeEventListener("click",t)},initMonthsCount=e=>{if("multiple"===e.type&&(e.displayMonthsCount<=1||e.displayMonthsCount>12))throw new Error(errorMessages.incorrectMonthsCount);if("multiple"!==e.type&&e.displayMonthsCount>1)throw new Error(errorMessages.incorrectMonthsCount);setContext(e,"displayMonthsCount",e.displayMonthsCount?e.displayMonthsCount:"multiple"===e.type?2:1);},getLocalDate=()=>{const e=new Date;return new Date(e.getTime()-6e4*e.getTimezoneOffset()).toISOString().substring(0,10)},resolveDate=(e,t)=>"today"===e?getLocalDate():e instanceof Date||"number"==typeof e||"string"==typeof e?parseDates([e])[0]:t,initRange=e=>{var t,n,a;const o=resolveDate(e.dateMin,e.dateMin),l=resolveDate(e.dateMax,e.dateMax),s=resolveDate(e.displayDateMin,o),i=resolveDate(e.displayDateMax,l);setContext(e,"dateToday",resolveDate(e.dateToday,e.dateToday)),setContext(e,"displayDateMin",s?getDate(o)>=getDate(s)?o:s:o),setContext(e,"displayDateMax",i?getDate(l)<=getDate(i)?l:i:l);const r=e.disableDatesPast&&!e.disableAllDates&&getDate(s)1&&e.context.disableDates.sort(((e,t)=>+new Date(e)-+new Date(t))),setContext(e,"enableDates",e.enableDates[0]?parseDates(e.enableDates):[]),(null==(t=e.context.enableDates)?void 0:t[0])&&(null==(n=e.context.disableDates)?void 0:n[0])&&setContext(e,"disableDates",e.context.disableDates.filter((t=>!e.context.enableDates.includes(t)))),e.context.enableDates.length>1&&e.context.enableDates.sort(((e,t)=>+new Date(e)-+new Date(t))),(null==(a=e.context.enableDates)?void 0:a[0])&&e.disableAllDates&&(setContext(e,"displayDateMin",e.context.enableDates[0]),setContext(e,"displayDateMax",e.context.enableDates[e.context.enableDates.length-1])),setContext(e,"dateMin",e.displayDisabledDates?o:e.context.displayDateMin),setContext(e,"dateMax",e.displayDisabledDates?l:e.context.displayDateMax);},initSelectedDates=e=>{var t;setContext(e,"selectedDates",(null==(t=e.selectedDates)?void 0:t[0])?parseDates(e.selectedDates):[]);},displayClosestValidDate=e=>{const t=t=>{const n=new Date(t);setInitialContext(e,n.getMonth(),n.getFullYear());};if(e.displayDateMin&&"today"!==e.displayDateMin&&(n=e.displayDateMin,a=new Date,new Date(n).getTime()>a.getTime())){const n=e.selectedDates.length&&e.selectedDates[0]?parseDates(e.selectedDates)[0]:e.displayDateMin;return t(getDate(resolveDate(n,e.displayDateMin))),true}var n,a;if(e.displayDateMax&&"today"!==e.displayDateMax&&((e,t)=>new Date(e).getTime(){setContext(e,"selectedMonth",t),setContext(e,"selectedYear",n),setContext(e,"displayYear",n);},initSelectedMonthYear=e=>{var t;if(e.enableJumpToSelectedDate&&(null==(t=e.selectedDates)?void 0:t[0])&&void 0===e.selectedMonth&&void 0===e.selectedYear){const t=getDate(parseDates(e.selectedDates)[0]);return void setInitialContext(e,t.getMonth(),t.getFullYear())}if(displayClosestValidDate(e))return;const n=void 0!==e.selectedMonth&&Number(e.selectedMonth)>=0&&Number(e.selectedMonth)<12,a=void 0!==e.selectedYear&&Number(e.selectedYear)>=0&&Number(e.selectedYear)<=9999;setInitialContext(e,n?Number(e.selectedMonth):getDate(e.context.dateToday).getMonth(),a?Number(e.selectedYear):getDate(e.context.dateToday).getFullYear());},initTime=e=>{var t,n,a;if(!e.selectionTimeMode)return;if(![12,24].includes(e.selectionTimeMode))throw new Error(errorMessages.incorrectTime);const o=12===e.selectionTimeMode,l=o?/^(0[1-9]|1[0-2]):([0-5][0-9]) ?(AM|PM)?$/i:/^([0-1]?[0-9]|2[0-3]):([0-5][0-9])$/;let[s,i,r]=null!=(a=null==(n=null==(t=e.selectedTime)?void 0:t.match(l))?void 0:n.slice(1))?a:[];s?o&&!r&&(r="AM"):(s=o?transformTime12(String(e.timeMinHour)):String(e.timeMinHour),i=String(e.timeMinMinute),r=o?Number(transformTime12(String(e.timeMinHour)))>=12?"PM":"AM":null),setContext(e,"selectedHours",s.padStart(2,"0")),setContext(e,"selectedMinutes",i.padStart(2,"0")),setContext(e,"selectedKeeping",r),setContext(e,"selectedTime",`${e.context.selectedHours}:${e.context.selectedMinutes}${r?` ${r}`:""}`);},initAllVariables=e=>{setContext(e,"currentType",e.type),initMonthsCount(e),initRange(e),initSelectedMonthYear(e),initSelectedDates(e),initTime(e);},reset=(e,{year:t,month:n,dates:a,time:o,locale:l},s=true)=>{var i;const r={year:e.selectedYear,month:e.selectedMonth,dates:e.selectedDates,time:e.selectedTime};if(e.selectedYear=t?r.year:e.context.selectedYear,e.selectedMonth=n?r.month:e.context.selectedMonth,e.selectedTime=o?r.time:e.context.selectedTime,e.selectedDates="only-first"===a&&(null==(i=e.context.selectedDates)?void 0:i[0])?[e.context.selectedDates[0]]:true===a?r.dates:e.context.selectedDates,l){setContext(e,"locale",{months:{short:[],long:[]},weekdays:{short:[],long:[]}});}initAllVariables(e),s&&create(e),e.selectedYear=r.year,e.selectedMonth=r.month,e.selectedDates=r.dates,e.selectedTime=r.time,"multiple-ranged"===e.selectionDatesMode&&a&&handleSelectDateRange(e,null);},createToInput=e=>{const t=document.createElement("div");return t.className=e.styles.calendar,t.dataset.vc="calendar",t.dataset.vcInput="",t.dataset.vcCalendarHidden="",setContext(e,"inputModeInit",true),setContext(e,"isShowInInputMode",false),setContext(e,"mainElement",t),document.body.appendChild(e.context.mainElement),reset(e,{year:true,month:true,dates:true,time:true,locale:true}),setTimeout((()=>show(e))),e.onInit&&e.onInit(e),handleArrowKeys(e),handleClick(e)},canOpenOnFocus=e=>resolveToggle(e,e.openOnFocus),handleInput=e=>{setContext(e,"inputElement",e.context.mainElement);const t=()=>{e.context.inputModeInit?setTimeout((()=>show(e))):createToInput(e);};e.context.inputElement.addEventListener("click",t);const n="function"==typeof e.openOnFocus||true===e.openOnFocus,a=()=>{shouldSkipOpenOnFocus(e)?clearSkipOpenOnFocus(e):canOpenOnFocus(e)&&t();};n&&e.context.inputElement.addEventListener("focus",a);const o=t=>{const n="Tab"===t.key&&!t.shiftKey,a=["ArrowUp","ArrowDown","ArrowLeft","ArrowRight"].includes(t.key);(n||a)&&(t=>{var n;if(!e.context.isShowInInputMode)return false;if(document.activeElement!==e.context.inputElement)return false;const a=e=>e.tabIndex>=0&&!e.hasAttribute("disabled")&&"true"!==e.getAttribute("aria-disabled"),o=null!=(n=document.createTreeWalker(e.context.mainElement,NodeFilter.SHOW_ELEMENT,{acceptNode:e=>a(e)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}).nextNode())?n:a(e.context.mainElement)?e.context.mainElement:null;!o||o.tabIndex<0||(t.preventDefault(),o.focus());})(t);};return e.context.inputElement.addEventListener("keydown",o),()=>{e.context.inputElement.removeEventListener("click",t),n&&e.context.inputElement.removeEventListener("focus",a),e.context.inputElement.removeEventListener("keydown",o);}},init=e=>(setContext(e,"originalElement",e.context.mainElement.cloneNode(true)),setContext(e,"isInit",true),e.inputMode?handleInput(e):(initAllVariables(e),create(e),e.onInit&&e.onInit(e),handleArrowKeys(e),handleClick(e))),update=(e,t)=>{if(!e.context.isInit)throw new Error(errorMessages.notInit);reset(e,__spreadValues(__spreadValues({},{year:true,month:true,dates:true,time:true,locale:true}),t),!(e.inputMode&&!e.context.inputModeInit)),e.onUpdate&&e.onUpdate(e);},replaceProperties=(e,t)=>{const n=Object.keys(t);for(let a=0;a{replaceProperties(e,t),e.context.isInit&&update(e,n);};function findBestPickerPosition(e,t){const n="left";if(!t||!e)return n;const{canShow:a,parentPositions:o}=getAvailablePosition(e,t),l=a.left&&a.right;return (l&&a.bottom?"center":l&&a.top?["top","center"]:Array.isArray(o)?["bottom"===o[0]?"top":"bottom",...o.slice(1)]:o)||n}const setPosition=(e,t,n)=>{if(!e)return;const a="auto"===n?findBestPickerPosition(e,t):n,o={top:-t.offsetHeight,bottom:e.offsetHeight,left:0,center:e.offsetWidth/2-t.offsetWidth/2,right:e.offsetWidth-t.offsetWidth},l=Array.isArray(a)?a[0]:"bottom",s=Array.isArray(a)?a[1]:a;t.dataset.vcPosition=l;const{top:i,left:r}=getOffset(e),c=i+o[l];let d=r+o[s];const{vw:u}=getViewportDimensions();if(d+t.clientWidth>u){const 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`});},show=e=>{if(e.context.isShowInInputMode)return;if(!e.context.currentType)return void e.context.mainElement.click();setContext(e,"cleanupHandlers",[]),setContext(e,"isShowInInputMode",true),e.inputMode&&restoreTabbing(e.context.mainElement),setPosition(e.context.inputElement,e.context.mainElement,e.positionToInput),e.context.mainElement.removeAttribute("data-vc-calendar-hidden");const t=()=>{setPosition(e.context.inputElement,e.context.mainElement,e.positionToInput);};window.addEventListener("resize",t),e.context.cleanupHandlers.push((()=>window.removeEventListener("resize",t)));const n=t=>{"Escape"===t.key&&hide(e);};document.addEventListener("keydown",n),e.context.cleanupHandlers.push((()=>document.removeEventListener("keydown",n)));const a=t=>{t.target===e.context.inputElement||e.context.mainElement.contains(t.target)||hide(e);};document.addEventListener("click",a,{capture:true}),e.context.cleanupHandlers.push((()=>document.removeEventListener("click",a,{capture:true}))),e.onShow&&e.onShow(e);},labels={application:"Calendar",navigation:"Calendar Navigation",arrowNext:{month:"Next month",year:"Next list of years"},arrowPrev:{month:"Previous month",year:"Previous list of years"},month:"Select month, current selected month:",months:"List of months",year:"Select year, current selected year:",years:"List of years",week:"Days of the week",weekNumber:"Numbers of weeks in a year",dates:"Dates in the current month",selectingTime:"Selecting a time ",inputHour:"Hours",inputMinute:"Minutes",rangeHour:"Slider for selecting hours",rangeMinute:"Slider for selecting minutes",btnKeeping:"Switch AM/PM, current position:"},styles={calendar:"vc",controls:"vc-controls",grid:"vc-grid",column:"vc-column",header:"vc-header",headerContent:"vc-header__content",month:"vc-month",year:"vc-year",arrowPrev:"vc-arrow vc-arrow_prev",arrowNext:"vc-arrow vc-arrow_next",wrapper:"vc-wrapper",content:"vc-content",months:"vc-months",monthsMonth:"vc-months__month",years:"vc-years",yearsYear:"vc-years__year",week:"vc-week",weekDay:"vc-week__day",weekNumbers:"vc-week-numbers",weekNumbersTitle:"vc-week-numbers__title",weekNumbersContent:"vc-week-numbers__content",weekNumber:"vc-week-number",dates:"vc-dates",datesRow:"vc-dates__row",date:"vc-date",dateBtn:"vc-date__btn",datePopup:"vc-date__popup",dateRangeTooltip:"vc-date-range-tooltip",time:"vc-time",timeContent:"vc-time__content",timeHour:"vc-time__hour",timeMinute:"vc-time__minute",timeKeeping:"vc-time__keeping",timeRanges:"vc-time__ranges",timeRange:"vc-time__range"};class OptionsCalendar{constructor(){__publicField(this,"type","default"),__publicField(this,"inputMode",false),__publicField(this,"openOnFocus",true),__publicField(this,"positionToInput","left"),__publicField(this,"firstWeekday",1),__publicField(this,"monthsToSwitch",1),__publicField(this,"themeAttrDetect","html[data-theme]"),__publicField(this,"locale","en"),__publicField(this,"dateToday","today"),__publicField(this,"dateMin","1970-01-01"),__publicField(this,"dateMax","2470-12-31"),__publicField(this,"displayDateMin"),__publicField(this,"displayDateMax"),__publicField(this,"displayDatesOutside",true),__publicField(this,"displayDisabledDates",false),__publicField(this,"displayMonthsCount"),__publicField(this,"disableDates",[]),__publicField(this,"disableAllDates",false),__publicField(this,"disableDatesPast",false),__publicField(this,"disableDatesGaps",false),__publicField(this,"disableWeekdays",[]),__publicField(this,"disableToday",false),__publicField(this,"enableDates",[]),__publicField(this,"enableEdgeDatesOnly",true),__publicField(this,"enableDateToggle",true),__publicField(this,"enableWeekNumbers",false),__publicField(this,"enableMonthChangeOnDayClick",true),__publicField(this,"enableJumpToSelectedDate",false),__publicField(this,"selectionDatesMode","single"),__publicField(this,"selectionMonthsMode",true),__publicField(this,"selectionYearsMode",true),__publicField(this,"selectionTimeMode",false),__publicField(this,"selectedDates",[]),__publicField(this,"selectedMonth"),__publicField(this,"selectedYear"),__publicField(this,"selectedHolidays",[]),__publicField(this,"selectedWeekends",[0,6]),__publicField(this,"selectedTime"),__publicField(this,"selectedTheme","system"),__publicField(this,"timeMinHour",0),__publicField(this,"timeMaxHour",23),__publicField(this,"timeMinMinute",0),__publicField(this,"timeMaxMinute",59),__publicField(this,"timeControls","all"),__publicField(this,"timeStepHour",1),__publicField(this,"timeStepMinute",1),__publicField(this,"sanitizerHTML",(e=>e)),__publicField(this,"onClickDate"),__publicField(this,"onClickWeekDay"),__publicField(this,"onClickWeekNumber"),__publicField(this,"onClickTitle"),__publicField(this,"onClickMonth"),__publicField(this,"onClickYear"),__publicField(this,"onClickArrow"),__publicField(this,"onChangeTime"),__publicField(this,"onChangeToInput"),__publicField(this,"onCreateDateRangeTooltip"),__publicField(this,"onCreateDateEls"),__publicField(this,"onCreateMonthEls"),__publicField(this,"onCreateYearEls"),__publicField(this,"onInit"),__publicField(this,"onUpdate"),__publicField(this,"onDestroy"),__publicField(this,"onShow"),__publicField(this,"onHide"),__publicField(this,"popups",{}),__publicField(this,"labels",__spreadValues({},labels)),__publicField(this,"layouts",{default:"",multiple:"",month:"",year:""}),__publicField(this,"styles",__spreadValues({},styles));}}const _Calendar=class e extends OptionsCalendar{constructor(t,n){var a;super(),__publicField(this,"init",(()=>init(this))),__publicField(this,"update",(e=>update(this,e))),__publicField(this,"destroy",(()=>destroy(this))),__publicField(this,"show",(()=>show(this))),__publicField(this,"hide",(()=>hide(this))),__publicField(this,"set",((e,t)=>set(this,e,t))),__publicField(this,"context"),this.context=__spreadProps(__spreadValues({},this.context),{locale:{months:{short:[],long:[]},weekdays:{short:[],long:[]}}}),setContext(this,"mainElement","string"==typeof t?null!=(a=e.memoizedElements.get(t))?a:this.queryAndMemoize(t):t),n&&replaceProperties(this,n);}queryAndMemoize(t){const n=document.querySelector(t);if(!n)throw new Error(errorMessages.notFoundSelector(t));return e.memoizedElements.set(t,n),n}};__publicField(_Calendar,"memoizedElements",new Map);let Calendar=_Calendar; - -/** - * -------------------------------------------------------------------------- - * Bootstrap datepicker.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - * -------------------------------------------------------------------------- - */ - - /** - * Constants + * Custom positioning reference element. + * @see https://floating-ui.com/docs/virtual-elements */ -const NAME$f = 'datepicker'; -const DATA_KEY$b = 'bs.datepicker'; -const EVENT_KEY$b = `.${DATA_KEY$b}`; -const DATA_API_KEY$6 = '.data-api'; -const EVENT_CHANGE = `change${EVENT_KEY$b}`; -const EVENT_SHOW$6 = `show${EVENT_KEY$b}`; -const EVENT_SHOWN$6 = `shown${EVENT_KEY$b}`; -const EVENT_HIDE$6 = `hide${EVENT_KEY$b}`; -const EVENT_HIDDEN$6 = `hidden${EVENT_KEY$b}`; -const EVENT_CLICK_DATA_API$4 = `click${EVENT_KEY$b}${DATA_API_KEY$6}`; -const EVENT_FOCUSIN_DATA_API = `focusin${EVENT_KEY$b}${DATA_API_KEY$6}`; -const SELECTOR_DATA_TOGGLE$7 = '[data-bs-toggle="datepicker"]'; -const HIDE_DELAY = 100; // ms delay before hiding after selection - -const Default$e = { - datepickerTheme: null, - // 'light', 'dark', 'auto' - explicit theme for datepicker popover only - dateMin: null, - dateMax: null, - dateFormat: null, - // Intl.DateTimeFormat options, or function(date, locale) => string - displayElement: null, - // Element to show formatted date (defaults to element for buttons) - displayMonthsCount: 1, - // Number of months to display side-by-side - firstWeekday: 1, - // Monday - inline: false, - // Render calendar inline (no popup) - locale: 'default', - positionElement: null, - // Element to position calendar relative to (defaults to input) - selectedDates: [], - selectionMode: 'single', - // 'single', 'multiple', 'multiple-ranged' - placement: 'left', - // 'left', 'center', 'right', 'auto' - vcpOptions: {} // Pass-through for any VCP option +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' }; -const DefaultType$e = { - datepickerTheme: '(null|string)', - dateMin: '(null|string|number|object)', - dateMax: '(null|string|number|object)', - dateFormat: '(null|object|function)', - displayElement: '(null|string|element|boolean)', - displayMonthsCount: 'number', - firstWeekday: 'number', - inline: 'boolean', - locale: 'string', - positionElement: '(null|string|element)', - selectedDates: 'array', - selectionMode: 'string', - placement: 'string', - vcpOptions: 'object' +const oppositeAlignmentMap = { + start: 'end', + end: 'start' }; - -/** - * Class definition - */ - -class Datepicker extends BaseComponent { - constructor(element, config) { - super(element, config); - this._calendar = null; - this._isShown = false; - this._initCalendar(); - } - - // Getters - static get Default() { - return Default$e; - } - static get DefaultType() { - return DefaultType$e; - } - static get NAME() { - return NAME$f; +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'; +} +const yAxisSides = /*#__PURE__*/new Set(['top', 'bottom']); +function getSideAxis(placement) { + return yAxisSides.has(getSide(placement)) ? 'y' : 'x'; +} +function getAlignmentAxis(placement) { + return getOppositeAxis(getSideAxis(placement)); +} +function getAlignmentSides(placement, rects, rtl) { + if (rtl === void 0) { + rtl = false; } - - // Public - toggle() { - if (this._config.inline) { - return; // Inline calendars are always visible - } - return this._isShown ? this.hide() : this.show(); + 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); } - show() { - if (this._config.inline) { - return; // Inline calendars are always visible - } - if (!this._calendar || isDisabled(this._element) || this._isShown) { - return; - } - const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$6); - if (showEvent.defaultPrevented) { - return; - } - this._calendar.show(); - this._isShown = true; - EventHandler.trigger(this._element, EVENT_SHOWN$6); + return [mainAlignmentSide, getOppositePlacement(mainAlignmentSide)]; +} +function getExpandedPlacements(placement) { + const oppositePlacement = getOppositePlacement(placement); + return [getOppositeAlignmentPlacement(placement), oppositePlacement, getOppositeAlignmentPlacement(oppositePlacement)]; +} +function getOppositeAlignmentPlacement(placement) { + return placement.replace(/start|end/g, alignment => oppositeAlignmentMap[alignment]); +} +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 []; } - hide() { - if (this._config.inline) { - return; // Inline calendars are always visible - } - if (!this._calendar || !this._isShown) { - return; - } - const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$6); - if (hideEvent.defaultPrevented) { - 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)); } - this._calendar.hide(); - this._isShown = false; - EventHandler.trigger(this._element, EVENT_HIDDEN$6); } - dispose() { - if (this._themeObserver) { - this._themeObserver.disconnect(); - this._themeObserver = null; - } - if (this._calendar) { - this._calendar.destroy(); - } - this._calendar = null; - super.dispose(); - } - getSelectedDates() { - const dates = this._calendar?.context?.selectedDates; - return dates ? [...dates] : []; - } - setSelectedDates(dates) { - if (this._calendar) { - this._calendar.set({ - selectedDates: dates - }); - } - } - - // Private - _initCalendar() { - this._isInput = this._element.tagName === 'INPUT'; - this._isInline = this._config.inline; - - // For inline mode, look for a hidden input child to bind to - if (this._isInline && !this._isInput) { - this._boundInput = this._element.querySelector('input[type="hidden"], input[name]'); - } - this._positionElement = this._resolvePositionElement(); - this._displayElement = this._resolveDisplayElement(); - const calendarOptions = this._buildCalendarOptions(); - - // Create calendar on the position element (for correct popup positioning) - // but value updates still go to this._element (the input) - this._calendar = new Calendar(this._positionElement, calendarOptions); - this._calendar.init(); - - // Watch for theme changes on ancestor elements (for live theme switching) - this._setupThemeObserver(); - - // Set initial value if input has a value - if (this._isInput && this._element.value) { - this._parseInputValue(); - } + return list; +} +function getOppositePlacement(placement) { + return placement.replace(/left|right|bottom|top/g, side => oppositeSideMap[side]); +} +function expandPaddingObject(padding) { + return { + top: 0, + right: 0, + bottom: 0, + left: 0, + ...padding + }; +} +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 + }; +} - // Populate input/display with preselected dates - this._updateDisplayWithSelectedDates(); +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 + }; } - _updateDisplayWithSelectedDates() { - const { - selectedDates - } = this._config; - if (!selectedDates || selectedDates.length === 0) { - return; - } - const formattedDate = this._formatDateForInput(selectedDates); - if (this._isInput) { - this._element.value = formattedDate; - } - if (this._boundInput) { - this._boundInput.value = selectedDates.join(','); - } - if (this._displayElement) { - this._displayElement.textContent = formattedDate; - } + switch (getAlignment(placement)) { + case 'start': + coords[alignmentAxis] -= commonAlign * (rtl && isVertical ? -1 : 1); + break; + case 'end': + coords[alignmentAxis] += commonAlign * (rtl && isVertical ? -1 : 1); + break; } - _resolvePositionElement() { - let { - positionElement - } = this._config; - if (typeof positionElement === 'string') { - positionElement = document.querySelector(positionElement); - } + return coords; +} - // Use input's parent if in form-adorn - if (!positionElement && this._isInput && !this._isInline) { - const parent = this._element.closest('.form-adorn'); - if (parent) { - positionElement = parent; +/** + * 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 validMiddleware = middleware.filter(Boolean); + 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 middlewareData = {}; + let resetCount = 0; + for (let i = 0; i < validMiddleware.length; i++) { + const { + name, + fn + } = validMiddleware[i]; + const { + x: nextX, + y: nextY, + data, + reset + } = await fn({ + x, + y, + initialPlacement: placement, + placement: statefulPlacement, + strategy, + middlewareData, + rects, + platform, + elements: { + reference, + floating + } + }); + x = nextX != null ? nextX : x; + y = nextY != null ? nextY : y; + middlewareData = { + ...middlewareData, + [name]: { + ...middlewareData[name], + ...data + } + }; + if (reset && resetCount <= 50) { + 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 positionElement || this._element; } - _resolveDisplayElement() { - const { - displayElement - } = this._config; - if (typeof displayElement === 'string') { - return document.querySelector(displayElement); - } + return { + x, + y, + placement: statefulPlacement, + strategy, + middlewareData + }; +}; - // For buttons/non-inputs (not inline), look for a [data-bs-datepicker-display] child - if (displayElement === true || displayElement === null && !this._isInput && !this._isInline) { - const displayChild = this._element.querySelector('[data-bs-datepicker-display]'); - return displayChild || this._element; - } - return displayElement; - } - _getThemeAncestor() { - return this._element.closest('[data-bs-theme]'); +/** + * 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 = {}; } - _getEffectiveTheme() { - // Priority: explicit datepickerTheme config > inherited from ancestor > none + 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 altContext = elementContext === 'floating' ? 'reference' : 'floating'; + const element = elements[altBoundary ? altContext : 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 + } : { + 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 + }; +} + +/** + * 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 { - datepickerTheme - } = this._config; - if (datepickerTheme) { - return datepickerTheme; - } - const ancestor = this._getThemeAncestor(); - return ancestor?.getAttribute('data-bs-theme') || null; - } - _syncThemeAttribute(element) { - if (!element) { - return; - } - const theme = this._getEffectiveTheme(); - if (theme) { - // Copy theme to popover (needed because VCP appends to body, breaking CSS inheritance) - element.setAttribute('data-bs-theme', theme); - } else { - // No theme - remove attribute to allow natural inheritance - element.removeAttribute('data-bs-theme'); + x, + y, + placement, + rects, + platform, + elements, + middlewareData + } = state; + // Since `element` is required, we don't Partial<> the type. + const { + element, + padding = 0 + } = evaluate(options, state) || {}; + if (element == null) { + return {}; } - } - _setupThemeObserver() { - // Watch for theme changes on ancestor elements - const ancestor = this._getThemeAncestor(); - if (!ancestor || this._config.datepickerTheme) { - // No ancestor to watch, or explicit datepickerTheme overrides - 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; + + // DOM platform can return `window` as the `offsetParent`. + if (!clientSize || !(await (platform.isElement == null ? void 0 : platform.isElement(arrowOffsetParent)))) { + clientSize = elements.floating[clientProp] || rects.floating[length]; } - this._themeObserver = new MutationObserver(() => { - this._syncThemeAttribute(this._calendar?.context?.mainElement); - }); - this._themeObserver.observe(ancestor, { - attributes: true, - attributeFilter: ['data-bs-theme'] - }); - } - _buildCalendarOptions() { - // Get theme for VCP - use 'system' for auto-detection if no explicit theme - const theme = this._getEffectiveTheme(); - // VCP uses 'system' for auto, Bootstrap uses 'auto' - const vcpTheme = !theme || theme === 'auto' ? 'system' : theme; - const calendarOptions = { - ...this._config.vcpOptions, - inputMode: !this._isInline, - positionToInput: this._config.placement, - firstWeekday: this._config.firstWeekday, - locale: this._config.locale, - selectionDatesMode: this._config.selectionMode, - selectedDates: this._config.selectedDates, - displayMonthsCount: this._config.displayMonthsCount, - type: this._config.displayMonthsCount > 1 ? 'multiple' : 'default', - selectedTheme: vcpTheme, - themeAttrDetect: '[data-bs-theme]', - onClickDate: (self, event) => this._handleDateClick(self, event), - onInit: self => { - this._syncThemeAttribute(self.context.mainElement); - }, - onShow: () => { - this._isShown = true; - this._syncThemeAttribute(this._calendar.context.mainElement); + const centerToReference = endDiff / 2 - startDiff / 2; + + // If the padding is large enough that it causes the arrow to no longer be + // centered, modify the padding so that it is centered. + const largestPossiblePadding = clientSize / 2 - arrowDimensions[length] / 2 - 1; + const minPadding = min(paddingObject[minProp], largestPossiblePadding); + const maxPadding = min(paddingObject[maxProp], largestPossiblePadding); + + // Make sure the arrow doesn't overflow the floating element if the center + // point is outside the floating element's bounds. + const min$1 = minPadding; + const max = clientSize - arrowDimensions[length] - maxPadding; + const center = clientSize / 2 - arrowDimensions[length] / 2 + centerToReference; + const offset = clamp(min$1, center, max); + + // If the reference is small enough that the arrow's padding causes it to + // to point to nothing for an aligned placement, adjust the offset of the + // floating element itself. To ensure `shift()` continues to take action, + // a single reset is performed when this is true. + const shouldAddOffset = !middlewareData.arrow && getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < min$1 ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0; + const alignmentOffset = shouldAddOffset ? center < min$1 ? center - min$1 : center - max : 0; + return { + [axis]: coords[axis] + alignmentOffset, + data: { + [axis]: offset, + centerOffset: center - offset - alignmentOffset, + ...(shouldAddOffset && { + alignmentOffset + }) }, - onHide: () => { - this._isShown = false; - } + reset: shouldAddOffset }; + } +}); - // Navigate to the month of the first selected date - if (this._config.selectedDates.length > 0) { - const firstDate = this._parseDate(this._config.selectedDates[0]); - calendarOptions.selectedMonth = firstDate.getMonth(); - calendarOptions.selectedYear = firstDate.getFullYear(); - } - if (this._config.dateMin) { - calendarOptions.dateMin = this._config.dateMin; - } - if (this._config.dateMax) { - calendarOptions.dateMax = this._config.dateMax; - } - return calendarOptions; +/** + * 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 = {}; } - _handleDateClick(self, event) { - const selectedDates = [...self.context.selectedDates]; - if (selectedDates.length > 0) { - const formattedDate = this._formatDateForInput(selectedDates); - if (this._isInput) { - this._element.value = formattedDate; + 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 a reset by the arrow was caused due to an alignment offset being + // added, we should skip any logic now since `flip()` has already done its + // work. + // https://github.com/floating-ui/floating-ui/issues/2549#issuecomment-1719601643 + if ((_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) { + return {}; } - if (this._boundInput) { - this._boundInput.value = selectedDates.join(','); + 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)); } - if (this._displayElement) { - this._displayElement.textContent = formattedDate; + const placements = [initialPlacement, ...fallbackPlacements]; + const overflow = await detectOverflow(state, detectOverflowOptions); + const overflows = []; + let overflowsData = ((_middlewareData$flip = middlewareData.flip) == null ? void 0 : _middlewareData$flip.overflows) || []; + if (checkMainAxis) { + overflows.push(overflow[side]); } - } - EventHandler.trigger(this._element, EVENT_CHANGE, { - dates: selectedDates, - event - }); - this._maybeHideAfterSelection(selectedDates); - } - _maybeHideAfterSelection(selectedDates) { - if (this._isInline) { - return; - } - const shouldHide = this._config.selectionMode === 'single' && selectedDates.length > 0 || this._config.selectionMode === 'multiple-ranged' && selectedDates.length >= 2; - if (shouldHide) { - setTimeout(() => this.hide(), HIDE_DELAY); - } - } - _parseDate(dateStr) { - const [year, month, day] = dateStr.split('-'); - return new Date(year, month - 1, day); - } - _formatDate(dateStr) { - const date = this._parseDate(dateStr); - const locale = this._config.locale === 'default' ? undefined : this._config.locale; - const { - dateFormat - } = this._config; + if (checkCrossAxis) { + const sides = getAlignmentSides(placement, rects, rtl); + overflows.push(overflow[sides[0]], overflow[sides[1]]); + } + overflowsData = [...overflowsData, { + placement, + overflows + }]; - // Custom function formatter - if (typeof dateFormat === 'function') { - return dateFormat(date, locale); - } + // One or more sides is overflowing. + 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) { + const ignoreCrossAxisOverflow = checkCrossAxis === 'alignment' ? initialSideAxis !== getSideAxis(nextPlacement) : false; + if (!ignoreCrossAxisOverflow || + // We leave the current main axis only if every placement on that axis + // overflows the main axis. + overflowsData.every(d => getSideAxis(d.placement) === initialSideAxis ? d.overflows[0] > 0 : true)) { + // Try next placement and re-run the lifecycle. + return { + data: { + index: nextIndex, + overflows: overflowsData + }, + reset: { + placement: nextPlacement + } + }; + } + } - // Intl.DateTimeFormat options object - if (dateFormat && typeof dateFormat === 'object') { - return new Intl.DateTimeFormat(locale, dateFormat).format(date); - } + // First, find the candidates that fit on the mainAxis side of overflow, + // then find the placement that fits the best on the main crossAxis side. + 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; - // Default: locale-aware formatting - return date.toLocaleDateString(locale); - } - _formatDateForInput(dates) { - if (dates.length === 0) { - return ''; - } - if (dates.length === 1) { - return this._formatDate(dates[0]); + // Otherwise fallback. + 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 || + // Create a bias to the `y` side axis due to horizontal + // reading directions favoring greater width. + 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 {}; } + }; +}; - // For date ranges, use en-dash; for multiple dates, use comma - const separator = this._config.selectionMode === 'multiple-ranged' ? ' – ' : ', '; - return dates.map(d => this._formatDate(d)).join(separator); - } - _parseInputValue() { - // Try to parse the input value as a date - const value = this._element.value.trim(); - if (!value) { - return; - } - const date = new Date(value); - if (!Number.isNaN(date.getTime())) { - const year = date.getFullYear(); - const month = String(date.getMonth() + 1).padStart(2, '0'); - const day = String(date.getDate()).padStart(2, '0'); - const formatted = `${year}-${month}-${day}`; - this._calendar.set({ - selectedDates: [formatted] - }); - } +const originSides = /*#__PURE__*/new Set(['left', 'top']); + +// For type backwards-compatibility, the `OffsetOptions` type was also +// Derivable. + +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); + + // eslint-disable-next-line prefer-const + 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 + }; } /** - * Data API implementation + * 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 */ - -EventHandler.on(document, EVENT_CLICK_DATA_API$4, SELECTOR_DATA_TOGGLE$7, function (event) { - // Only handle if not an input (inputs use focus) - // Skip inline datepickers (they're always visible) - if (this.tagName === 'INPUT' || this.dataset.bsInline === 'true') { - return; - } - event.preventDefault(); - Datepicker.getOrCreateInstance(this).toggle(); -}); -EventHandler.on(document, EVENT_FOCUSIN_DATA_API, SELECTOR_DATA_TOGGLE$7, function () { - // Handle focus for input elements - if (this.tagName !== 'INPUT') { - return; - } - Datepicker.getOrCreateInstance(this).show(); -}); - -// Auto-initialize inline datepickers on DOMContentLoaded -EventHandler.on(document, `DOMContentLoaded${EVENT_KEY$b}${DATA_API_KEY$6}`, () => { - for (const element of document.querySelectorAll(`${SELECTOR_DATA_TOGGLE$7}[data-bs-inline="true"]`)) { - Datepicker.getOrCreateInstance(element); +const offset$1 = function (options) { + if (options === void 0) { + options = 0; } -}); - -/** - * -------------------------------------------------------------------------- - * Bootstrap dialog.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - * -------------------------------------------------------------------------- - */ + 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 the placement is the same and the arrow caused an alignment offset + // then we don't need to change the positioning coordinates. + 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 + } + }; + } + }; +}; /** - * Constants + * 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 NAME$e = 'dialog'; -const DATA_KEY$a = 'bs.dialog'; -const EVENT_KEY$a = `.${DATA_KEY$a}`; -const DATA_API_KEY$5 = '.data-api'; -const EVENT_SHOW$5 = `show${EVENT_KEY$a}`; -const EVENT_SHOWN$5 = `shown${EVENT_KEY$a}`; -const EVENT_HIDE$5 = `hide${EVENT_KEY$a}`; -const EVENT_HIDDEN$5 = `hidden${EVENT_KEY$a}`; -const EVENT_HIDE_PREVENTED$1 = `hidePrevented${EVENT_KEY$a}`; -const EVENT_CANCEL = `cancel${EVENT_KEY$a}`; -const EVENT_CLICK_DATA_API$3 = `click${EVENT_KEY$a}${DATA_API_KEY$5}`; -const CLASS_NAME_STATIC = 'dialog-static'; -const CLASS_NAME_OPEN = 'dialog-open'; -const CLASS_NAME_NONMODAL = 'dialog-nonmodal'; -const SELECTOR_DATA_TOGGLE$6 = '[data-bs-toggle="dialog"]'; -const SELECTOR_OPEN_MODAL_DIALOG = 'dialog.dialog[open]:not(.dialog-nonmodal)'; -const Default$d = { - backdrop: true, - // true (click dismisses) or 'static' (click does nothing) - only applies to modal dialogs - keyboard: true, - modal: true // true uses showModal(), false uses show() for non-modal dialogs -}; -const DefaultType$d = { - backdrop: '(boolean|string)', - keyboard: 'boolean', - modal: 'boolean' +const shift$1 = function (options) { + if (options === void 0) { + options = {}; + } + return { + name: 'shift', + options, + async fn(state) { + const { + x, + y, + placement + } = 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 detectOverflow(state, detectOverflowOptions); + const crossAxis = getSideAxis(getSide(placement)); + const mainAxis = getOppositeAxis(crossAxis); + let mainAxisCoord = coords[mainAxis]; + let crossAxisCoord = coords[crossAxis]; + if (checkMainAxis) { + const minSide = mainAxis === 'y' ? 'top' : 'left'; + const maxSide = mainAxis === 'y' ? 'bottom' : 'right'; + const min = mainAxisCoord + overflow[minSide]; + const max = mainAxisCoord - overflow[maxSide]; + mainAxisCoord = clamp(min, mainAxisCoord, max); + } + if (checkCrossAxis) { + const minSide = crossAxis === 'y' ? 'top' : 'left'; + const maxSide = crossAxis === 'y' ? 'bottom' : 'right'; + const min = crossAxisCoord + overflow[minSide]; + const max = crossAxisCoord - overflow[maxSide]; + crossAxisCoord = clamp(min, crossAxisCoord, max); + } + 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 + } + } + }; + } + }; }; -/** - * Class definition - */ +function hasWindow() { + return typeof window !== 'undefined'; +} +function getNodeName(node) { + if (isNode(node)) { + return (node.nodeName || '').toLowerCase(); + } + // Mocked nodes in testing environments may not be instances of Node. By + // returning `#document` an infinite loop won't occur. + // https://github.com/floating-ui/floating-ui/issues/2317 + 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; +} +const invalidOverflowDisplayValues = /*#__PURE__*/new Set(['inline', 'contents']); +function isOverflowElement(element) { + const { + overflow, + overflowX, + overflowY, + display + } = getComputedStyle$1(element); + return /auto|scroll|overlay|hidden|clip/.test(overflow + overflowY + overflowX) && !invalidOverflowDisplayValues.has(display); +} +const tableElements = /*#__PURE__*/new Set(['table', 'td', 'th']); +function isTableElement(element) { + return tableElements.has(getNodeName(element)); +} +const topLayerSelectors = [':popover-open', ':modal']; +function isTopLayer(element) { + return topLayerSelectors.some(selector => { + try { + return element.matches(selector); + } catch (_e) { + return false; + } + }); +} +const transformProperties = ['transform', 'translate', 'scale', 'rotate', 'perspective']; +const willChangeValues = ['transform', 'translate', 'scale', 'rotate', 'perspective', 'filter']; +const containValues = ['paint', 'layout', 'strict', 'content']; +function isContainingBlock(elementOrCss) { + const webkit = isWebKit(); + const css = isElement(elementOrCss) ? getComputedStyle$1(elementOrCss) : elementOrCss; -class Dialog extends BaseComponent { - constructor(element, config) { - super(element, config); - this._isTransitioning = false; - this._addEventListeners(); + // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block + // https://drafts.csswg.org/css-transforms-2/#individual-transforms + return transformProperties.some(value => css[value] ? css[value] !== 'none' : false) || (css.containerType ? css.containerType !== 'normal' : false) || !webkit && (css.backdropFilter ? css.backdropFilter !== 'none' : false) || !webkit && (css.filter ? css.filter !== 'none' : false) || willChangeValues.some(value => (css.willChange || '').includes(value)) || containValues.some(value => (css.contain || '').includes(value)); +} +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); } - - // Getters - static get Default() { - return Default$d; + return null; +} +function isWebKit() { + if (typeof CSS === 'undefined' || !CSS.supports) return false; + return CSS.supports('-webkit-backdrop-filter', 'none'); +} +const lastTraversableNodeNames = /*#__PURE__*/new Set(['html', 'body', '#document']); +function isLastTraversableNode(node) { + return lastTraversableNodeNames.has(getNodeName(node)); +} +function getComputedStyle$1(element) { + return getWindow(element).getComputedStyle(element); +} +function getNodeScroll(element) { + if (isElement(element)) { + return { + scrollLeft: element.scrollLeft, + scrollTop: element.scrollTop + }; } - static get DefaultType() { - return DefaultType$d; + return { + scrollLeft: element.scrollX, + scrollTop: element.scrollY + }; +} +function getParentNode(node) { + if (getNodeName(node) === 'html') { + return node; } - static get NAME() { - return NAME$e; + const result = + // Step into the shadow DOM of the parent of a slotted node. + node.assignedSlot || + // DOM Element detected. + node.parentNode || + // ShadowRoot detected. + isShadowRoot(node) && node.host || + // Fallback. + getDocumentElement(node); + return isShadowRoot(result) ? result.host : result; +} +function getNearestOverflowAncestor(node) { + const parentNode = getParentNode(node); + if (isLastTraversableNode(parentNode)) { + return node.ownerDocument ? node.ownerDocument.body : node.body; } - - // Public - toggle(relatedTarget) { - return this._element.open ? this.hide() : this.show(relatedTarget); + if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) { + return parentNode; } - show(relatedTarget) { - if (this._element.open || this._isTransitioning) { - return; - } - const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$5, { - relatedTarget - }); - if (showEvent.defaultPrevented) { - return; - } - this._isTransitioning = true; - if (this._config.modal) { - // Modal dialog: use showModal() for focus trapping, backdrop, and top layer - this._element.showModal(); - // Prevent body scroll for modal dialogs - document.body.classList.add(CLASS_NAME_OPEN); - } else { - // Non-modal dialog: use show() - no backdrop, no focus trap, no top layer - this._element.classList.add(CLASS_NAME_NONMODAL); - this._element.show(); - } - this._queueCallback(() => { - this._isTransitioning = false; - EventHandler.trigger(this._element, EVENT_SHOWN$5, { - relatedTarget - }); - }, this._element, this._isAnimated()); + return getNearestOverflowAncestor(parentNode); +} +function getOverflowAncestors(node, list, traverseIframes) { + var _node$ownerDocument2; + if (list === void 0) { + list = []; } - hide() { - if (!this._element.open || this._isTransitioning) { - return; - } - const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$5); - if (hideEvent.defaultPrevented) { - return; - } - this._isTransitioning = true; - this._queueCallback(() => this._hideDialog(), this._element, this._isAnimated()); + if (traverseIframes === void 0) { + traverseIframes = true; } - dispose() { - EventHandler.off(this._element, EVENT_KEY$a); - super.dispose(); + 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) : []); } - handleUpdate() { - // Provided for API consistency with Modal. - // Native dialogs handle their own positioning. + return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor, [], traverseIframes)); +} +function getFrameElement(win) { + return win.parent && Object.getPrototypeOf(win.parent) ? win.frameElement : null; +} + +function getCssDimensions(element) { + const css = getComputedStyle$1(element); + // In testing environments, the `width` and `height` properties are empty + // strings for SVG elements, returning NaN. Fallback to `0` in this case. + 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 + }; +} - // Private - _hideDialog() { - this._element.close(); - this._element.classList.remove(CLASS_NAME_NONMODAL); - this._isTransitioning = false; +function unwrapElement(element) { + return !isElement(element) ? element.contextElement : element; +} - // Only restore body scroll if no other modal dialogs are open - if (!document.querySelector(SELECTOR_OPEN_MODAL_DIALOG)) { - document.body.classList.remove(CLASS_NAME_OPEN); - } - EventHandler.trigger(this._element, EVENT_HIDDEN$5); - } - _isAnimated() { - return this._element.classList.contains('fade'); - } - _triggerBackdropTransition() { - const hidePreventedEvent = EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED$1); - if (hidePreventedEvent.defaultPrevented) { - return; - } - this._element.classList.add(CLASS_NAME_STATIC); - this._queueCallback(() => { - this._element.classList.remove(CLASS_NAME_STATIC); - }, this._element); +function getScale(element) { + const domElement = unwrapElement(element); + if (!isHTMLElement(domElement)) { + return createCoords(1); } - _addEventListeners() { - // Handle native cancel event (Escape key) - only fires for modal dialogs - EventHandler.on(this._element, 'cancel', event => { - // Prevent native close behavior - we'll handle it - event.preventDefault(); - if (!this._config.keyboard) { - this._triggerBackdropTransition(); - return; - } - EventHandler.trigger(this._element, EVENT_CANCEL); - this.hide(); - }); - - // Handle Escape key for non-modal dialogs (native cancel doesn't fire for show()) - EventHandler.on(this._element, 'keydown', event => { - if (event.key !== 'Escape' || this._config.modal) { - return; - } - event.preventDefault(); - if (!this._config.keyboard) { - return; - } - EventHandler.trigger(this._element, EVENT_CANCEL); - this.hide(); - }); + 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; - // Handle backdrop clicks (only applies to modal dialogs) - // Native fires click on the dialog element when backdrop is clicked - EventHandler.on(this._element, 'click', event => { - // Only handle clicks directly on the dialog (backdrop area) - // Non-modal dialogs don't have a backdrop - if (event.target !== this._element || !this._config.modal) { - return; - } - if (this._config.backdrop === 'static') { - this._triggerBackdropTransition(); - return; - } + // 0, NaN, or Infinity should always fallback to 1. - // Default: click backdrop to dismiss - this.hide(); - }); + if (!x || !Number.isFinite(x)) { + x = 1; + } + if (!y || !Number.isFinite(y)) { + y = 1; } + return { + x, + y + }; } -/** - * Data API implementation - */ +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; +} -EventHandler.on(document, EVENT_CLICK_DATA_API$3, SELECTOR_DATA_TOGGLE$6, function (event) { - const target = SelectorEngine.getElementFromSelector(this); - if (['A', 'AREA'].includes(this.tagName)) { - event.preventDefault(); +function getBoundingClientRect(element, includeScale, isFixedStrategy, offsetParent) { + if (includeScale === void 0) { + includeScale = false; } - EventHandler.one(target, EVENT_SHOW$5, showEvent => { - if (showEvent.defaultPrevented) { - return; - } - EventHandler.one(target, EVENT_HIDDEN$5, () => { - if (isVisible(this)) { - this.focus(); + 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 }); +} - // Get config from trigger's data attributes - const config = Manipulator.getDataAttributes(this); +// If has a CSS width greater than the viewport, then this will be +// incorrect for RTL. +function getWindowScrollBarX(element, rect) { + const leftScroll = getNodeScroll(element).scrollLeft; + if (!rect) { + return getBoundingClientRect(getDocumentElement(element)).left + leftScroll; + } + return rect.left + leftScroll; +} - // Check if trigger is inside an open dialog - const currentDialog = this.closest('dialog[open]'); - const shouldSwap = currentDialog && currentDialog !== target; - if (shouldSwap) { - // Open new dialog first (its backdrop appears over current) - const newDialog = Dialog.getOrCreateInstance(target, config); - newDialog.show(this); +function getHTMLOffset(documentElement, scroll) { + const htmlRect = documentElement.getBoundingClientRect(); + const x = htmlRect.left + scroll.scrollLeft - getWindowScrollBarX(documentElement, htmlRect); + const y = htmlRect.top + scroll.scrollTop; + return { + x, + y + }; +} - // Close the current dialog (no backdrop flash since new one is already open) - const currentInstance = Dialog.getInstance(currentDialog); - if (currentInstance) { - currentInstance.hide(); +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 (isHTMLElement(offsetParent)) { + const offsetRect = getBoundingClientRect(offsetParent); + scale = getScale(offsetParent); + offsets.x = offsetRect.x + offsetParent.clientLeft; + offsets.y = offsetRect.y + offsetParent.clientTop; } - return; } - const data = Dialog.getOrCreateInstance(target, config); - data.toggle(this); -}); -enableDismissTrigger(Dialog); - -/** - * Custom positioning reference element. - * @see https://floating-ui.com/docs/virtual-elements - */ - -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' -}; -const oppositeAlignmentMap = { - start: 'end', - end: 'start' -}; -function clamp(start, value, end) { - return max(start, min(value, end)); -} -function evaluate(value, param) { - return typeof value === 'function' ? value(param) : value; + 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 getSide(placement) { - return placement.split('-')[0]; + +function getClientRects(element) { + return Array.from(element.getClientRects()); } -function getAlignment(placement) { - return placement.split('-')[1]; + +// Gets the entire size of the scrollable document area, even extending outside +// of the `` and `` rect bounds if horizontally scrollable. +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 + }; } -function getOppositeAxis(axis) { - return axis === 'x' ? 'y' : 'x'; + +// Safety check: ensure the scrollbar space is reasonable in case this +// calculation is affected by unusual styles. +// Most scrollbars leave 15-18px of space. +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); + // `overflow: hidden` + `scrollbar-gutter: stable` reduces the + // visual width of the but this is not considered in the size + // of `html.clientWidth`. + 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) { + // If the scrollbar is on the left, the width needs to be extended + // by the scrollbar amount so there isn't extra space on the right. + width += windowScrollbarX; + } + return { + width, + height, + x, + y + }; } -function getAxisLength(axis) { - return axis === 'y' ? 'height' : 'width'; + +const absoluteOrFixed = /*#__PURE__*/new Set(['absolute', 'fixed']); +// Returns the inner client rect, subtracting scrollbars if present. +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); + const width = element.clientWidth * scale.x; + const height = element.clientHeight * scale.y; + const x = left * scale.x; + const y = top * scale.y; + return { + width, + height, + x, + y + }; } -const yAxisSides = /*#__PURE__*/new Set(['top', 'bottom']); -function getSideAxis(placement) { - return yAxisSides.has(getSide(placement)) ? 'y' : 'x'; +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 getAlignmentAxis(placement) { - return getOppositeAxis(getSideAxis(placement)); +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 getAlignmentSides(placement, rects, rtl) { - if (rtl === void 0) { - rtl = false; + +// A "clipping ancestor" is an `overflow` element with the characteristic of +// clipping (or hiding) child elements. This returns all clipping ancestors +// of the given element up the tree. +function getClippingElementAncestors(element, cache) { + const cachedResult = cache.get(element); + if (cachedResult) { + return cachedResult; } - 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); + 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; + + // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block + while (isElement(currentNode) && !isLastTraversableNode(currentNode)) { + const computedStyle = getComputedStyle$1(currentNode); + const currentNodeIsContaining = isContainingBlock(currentNode); + if (!currentNodeIsContaining && computedStyle.position === 'fixed') { + currentContainingBlockComputedStyle = null; + } + const shouldDropCurrentNode = elementIsFixed ? !currentNodeIsContaining && !currentContainingBlockComputedStyle : !currentNodeIsContaining && computedStyle.position === 'static' && !!currentContainingBlockComputedStyle && absoluteOrFixed.has(currentContainingBlockComputedStyle.position) || isOverflowElement(currentNode) && !currentNodeIsContaining && hasFixedPositionAncestor(element, currentNode); + if (shouldDropCurrentNode) { + // Drop non-containing blocks. + result = result.filter(ancestor => ancestor !== currentNode); + } else { + // Record last containing block for next iteration. + currentContainingBlockComputedStyle = computedStyle; + } + currentNode = getParentNode(currentNode); } - return [mainAlignmentSide, getOppositePlacement(mainAlignmentSide)]; + cache.set(element, result); + return result; } -function getExpandedPlacements(placement) { - const oppositePlacement = getOppositePlacement(placement); - return [getOppositeAlignmentPlacement(placement), oppositePlacement, getOppositeAlignmentPlacement(oppositePlacement)]; + +// Gets the maximum area that the element is visible in due to any number of +// clipping ancestors. +function getClippingRect(_ref) { + let { + element, + boundary, + rootBoundary, + strategy + } = _ref; + const elementClippingAncestors = boundary === 'clippingAncestors' ? isTopLayer(element) ? [] : getClippingElementAncestors(element, this._c) : [].concat(boundary); + const clippingAncestors = [...elementClippingAncestors, rootBoundary]; + const firstClippingAncestor = clippingAncestors[0]; + const clippingRect = clippingAncestors.reduce((accRect, clippingAncestor) => { + const rect = getClientRectFromClippingAncestor(element, clippingAncestor, strategy); + accRect.top = max(rect.top, accRect.top); + accRect.right = min(rect.right, accRect.right); + accRect.bottom = min(rect.bottom, accRect.bottom); + accRect.left = max(rect.left, accRect.left); + return accRect; + }, getClientRectFromClippingAncestor(element, firstClippingAncestor, strategy)); + return { + width: clippingRect.right - clippingRect.left, + height: clippingRect.bottom - clippingRect.top, + x: clippingRect.left, + y: clippingRect.top + }; } -function getOppositeAlignmentPlacement(placement) { - return placement.replace(/start|end/g, alignment => oppositeAlignmentMap[alignment]); + +function getDimensions(element) { + const { + width, + height + } = getCssDimensions(element); + return { + width, + height + }; } -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 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); + + // If the scrollbar appears on the left (e.g. RTL systems). Use + // Firefox with layout.scrollbar.side = 3 in about:config to test this. + function setLeftRTLScrollbarOffset() { + offsets.x = getWindowScrollBarX(documentElement); } -} -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)); + 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(); } } - return list; -} -function getOppositePlacement(placement) { - return placement.replace(/left|right|bottom|top/g, side => oppositeSideMap[side]); -} -function expandPaddingObject(padding) { + if (isFixed && !isOffsetParentAnElement && documentElement) { + setLeftRTLScrollbarOffset(); + } + const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0); + const x = rect.left + scroll.scrollLeft - offsets.x - htmlOffset.x; + const y = rect.top + scroll.scrollTop - offsets.y - htmlOffset.y; return { - top: 0, - right: 0, - bottom: 0, - left: 0, - ...padding + x, + y, + width: rect.width, + height: rect.height }; } -function getPaddingObject(padding) { - return typeof padding !== 'number' ? expandPaddingObject(padding) : { - top: padding, - right: padding, - bottom: padding, - left: padding - }; + +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; + + // Firefox returns the element as the offsetParent if it's non-static, + // while Chrome and Safari return the element. The element must + // be used to perform the correct calculations even if the element is + // non-static. + if (getDocumentElement(element) === rawOffsetParent) { + rawOffsetParent = rawOffsetParent.ownerDocument.body; + } + return rawOffsetParent; +} + +// Gets the closest ancestor positioned element. Handles some edge cases, +// such as table ancestors and cross browser bugs. +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; } -function rectToClientRect(rect) { - const { - x, - y, - width, - height - } = rect; + +const getElementRects = async function (data) { + const getOffsetParentFn = this.getOffsetParent || getOffsetParent; + const getDimensionsFn = this.getDimensions; + const floatingDimensions = await getDimensionsFn(data.floating); return { - width, - height, - top: y, - left: x, - right: x + width, - bottom: y + height, - x, - y + 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'; } -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 - }; - } - switch (getAlignment(placement)) { - case 'start': - coords[alignmentAxis] -= commonAlign * (rtl && isVertical ? -1 : 1); - break; - case 'end': - coords[alignmentAxis] += commonAlign * (rtl && isVertical ? -1 : 1); - break; - } - return coords; +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; } -/** - * 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 validMiddleware = middleware.filter(Boolean); - 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 middlewareData = {}; - let resetCount = 0; - for (let i = 0; i < validMiddleware.length; i++) { - const { - name, - fn - } = validMiddleware[i]; +// https://samthor.au/2021/observing-dom/ +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 { - x: nextX, - y: nextY, - data, - reset - } = await fn({ - x, - y, - initialPlacement: placement, - placement: statefulPlacement, - strategy, - middlewareData, - rects, - platform, - elements: { - reference, - floating - } - }); - x = nextX != null ? nextX : x; - y = nextY != null ? nextY : y; - middlewareData = { - ...middlewareData, - [name]: { - ...middlewareData[name], - ...data - } + 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 rootMargin = -insetTop + "px " + -insetRight + "px " + -insetBottom + "px " + -insetLeft + "px"; + const options = { + rootMargin, + threshold: max(0, min(1, threshold)) || 1 }; - if (reset && resetCount <= 50) { - resetCount++; - if (typeof reset === 'object') { - if (reset.placement) { - statefulPlacement = reset.placement; + let isFirstUpdate = true; + function handleObserve(entries) { + const ratio = entries[0].intersectionRatio; + if (ratio !== threshold) { + if (!isFirstUpdate) { + return refresh(); } - if (reset.rects) { - rects = reset.rects === true ? await platform.getElementRects({ - reference, - floating, - strategy - }) : reset.rects; + if (!ratio) { + // If the reference is clipped, the ratio is 0. Throttle the refresh + // to prevent an infinite loop of updates. + timeoutId = setTimeout(() => { + refresh(false, 1e-7); + }, 1000); + } else { + refresh(false, ratio); } - ({ - x, - y - } = computeCoordsFromPlacement(rects, statefulPlacement, rtl)); } - i = -1; + if (ratio === 1 && !rectsAreEqual(elementRectForRootMargin, element.getBoundingClientRect())) { + // It's possible that even though the ratio is reported as 1, the + // element is not actually fully within the IntersectionObserver's root + // area anymore. This can happen under performance constraints. This may + // be a bug in the browser's IntersectionObserver implementation. To + // work around this, we compare the element's bounding rect now with + // what it was at the time we created the IntersectionObserver. If they + // are not equal then the element moved, so we refresh. + refresh(); + } + isFirstUpdate = false; + } + + // Older browsers don't support a `document` as the root and will throw an + // error. + try { + io = new IntersectionObserver(handleObserve, { + ...options, + // Handle