diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 0000000..3eb1314 --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,27 @@ +name: Playwright Tests +on: + push: + branches: [ main, master ] + pull_request: + branches: [ main, master ] +jobs: + test: + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: lts/* + - name: Install dependencies + run: npm ci + - name: Install Playwright Browsers + run: npx playwright install --with-deps + - name: Run Playwright tests + run: npx playwright test + - uses: actions/upload-artifact@v4 + if: ${{ !cancelled() }} + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 diff --git a/.gitignore b/.gitignore index 0cccd58..c2c6b60 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,11 @@ node_modules dist # no need to include @material/web bundled in the repo -md-web \ No newline at end of file +# md-web + +# Playwright +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ +/playwright/.auth/ diff --git a/Cargo.lock b/Cargo.lock index 01c4993..b228a6a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -59,6 +59,12 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +[[package]] +name = "boolinator" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9" + [[package]] name = "builder" version = "0.1.0" @@ -722,6 +728,15 @@ version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +[[package]] +name = "matdemo" +version = "0.1.0" +dependencies = [ + "material-yew", + "wasm-bindgen", + "yew", +] + [[package]] name = "material-yew" version = "0.1.0" @@ -1236,6 +1251,7 @@ dependencies = [ "quote", "syn 2.0.58", "textwrap", + "wasm-bindgen", "yew", "yew-router", ] @@ -1346,7 +1362,8 @@ dependencies = [ [[package]] name = "yew" version = "0.21.0" -source = "git+https://github.com/yewstack/yew#e9739fc9ce4944ba93c77a32072551ab771a2cda" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f1a03f255c70c7aa3e9c62e15292f142ede0564123543c1cc0c7a4f31660cac" dependencies = [ "console_error_panic_hook", "futures", @@ -1370,8 +1387,10 @@ dependencies = [ [[package]] name = "yew-macro" version = "0.21.0" -source = "git+https://github.com/yewstack/yew#e9739fc9ce4944ba93c77a32072551ab771a2cda" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02fd8ca5166d69e59f796500a2ce432ff751edecbbb308ca59fd3fe4d0343de2" dependencies = [ + "boolinator", "once_cell", "prettyplease", "proc-macro-error", @@ -1383,7 +1402,8 @@ dependencies = [ [[package]] name = "yew-router" version = "0.18.0" -source = "git+https://github.com/yewstack/yew#e9739fc9ce4944ba93c77a32072551ab771a2cda" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca1d5052c96e6762b4d6209a8aded597758d442e6c479995faf0c7b5538e0c6" dependencies = [ "gloo 0.10.0", "js-sys", @@ -1401,7 +1421,8 @@ dependencies = [ [[package]] name = "yew-router-macro" version = "0.18.0" -source = "git+https://github.com/yewstack/yew#e9739fc9ce4944ba93c77a32072551ab771a2cda" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42bfd190a07ca8cfde7cd4c52b3ac463803dc07323db8c34daa697e86365978c" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 2a9814c..32b2247 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,16 +9,18 @@ edition = "2021" indexmap = "2.0.2" js-sys = "0.3.64" wasm-bindgen = "0.2.87" -yew = { git = "https://github.com/yewstack/yew", features = ["csr"] } +yew = { version = "0.21", features = ["csr"] } [dependencies.web-sys] version = "0.3.64" features = [ - "HtmlFormElement" + "HtmlFormElement", + "CustomEvent" ] [workspace] members = [ "build", - "usages" + "usages", + "matdemo" ] diff --git a/build/README.md b/build/README.md index a05c1cd..18d3217 100644 --- a/build/README.md +++ b/build/README.md @@ -5,8 +5,8 @@ Generates Rust wrapper for a component from material-web. ## Updating material web submodule 1. Update the submodule to the latest version: `git submodule update --recursive --remote build/material-web` -2. Checkout the new tag: `cd build/material-web && git checkout v1.4.0` -3. Update the submodule reference in the main repository: `git add build/material-web && git commit -m "pin build/material web to v1.4.0"` +2. Checkout the new tag: `cd build/material-web && git checkout v2.4.0` +3. Update the submodule reference in the main repository: `git add build/material-web && git commit -m "pin build/material web to v2.4.0"` 4. Update build/package.json with the tag used in step 2 5. Run `npm install` in the build directory 6. Run `npm run build` in the build directory diff --git a/build/index.html b/build/index.html index 40245e0..2358b74 100644 --- a/build/index.html +++ b/build/index.html @@ -6,7 +6,7 @@ content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> Document - + + + diff --git a/matdemo/src/main.rs b/matdemo/src/main.rs new file mode 100644 index 0000000..801f70b --- /dev/null +++ b/matdemo/src/main.rs @@ -0,0 +1,18 @@ +use yew::prelude::*; +use material_yew::*; + +mod pages; + +#[function_component(App)] +fn app() -> Html { + html! { + <> +

{ "Material Yew Component Demos" }

+ + + } +} + +fn main() { + yew::Renderer::::new().render(); +} diff --git a/matdemo/src/pages.rs b/matdemo/src/pages.rs new file mode 100644 index 0000000..9b80e6d --- /dev/null +++ b/matdemo/src/pages.rs @@ -0,0 +1,103 @@ + +use yew::prelude::*; +use material_yew::*; + +#[function_component(DemoPages)] +pub fn demo_pages() -> Html { + html! { +
+

{ "Button" }

+ + +

{ "Checkbox" }

+ + +

{ "Chip" }

+ + +

{ "Chips" }

+ + +

{ "Circular Progress" }

+ + +

{ "Color" }

+ + +

{ "Dialog" }

+ { "Dialog content here." } + +

{ "Divider" }

+ + +

{ "Elevation" }

+ + +

{ "FAB" }

+ + +

{ "Field" }

+ { "Field content" } + +

{ "Focus" }

+ { "Focusable content" } + +

{ "Icon" }

+ + +

{ "Icon Button" }

+ { "favorite" } + +

{ "Linear Progress" }

+ + +

{ "List" }

+ + { "Item 1" } + { "Item 2" } + + +

{ "List Item" }

+ { "Standalone List Item" } + +

{ "Menu" }

+ + { "Menu Item 1" } + { "Menu Item 2" } + + +

{ "Menu Item" }

+ { "Standalone Menu Item" } + +

{ "Progress" }

+ + +

{ "Radio" }

+ + +

{ "Ripple" }

+ { "Rippled content" } + +

{ "Select" }

+ + +

{ "Slider" }

+ + +

{ "Sub Menu" }

+ { "Sub Menu Content" } + +

{ "Switch" }

+ + +

{ "Tabs" }

+ { "Tab content" } + +

{ "TextField" }

+ +
+ } +} diff --git a/md-web/button.js b/md-web/button.js new file mode 100644 index 0000000..6fe539c --- /dev/null +++ b/md-web/button.js @@ -0,0 +1,292 @@ +export const __dummy_loader = () => {}; + +import { ab as Button, x, i, ac as styles$5, ad as styles$6, _ as __decorate, e } from './core.js'; + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * An elevated button component. + */ +class ElevatedButton extends Button { + renderElevationOrOutline() { + return x ``; + } +} + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./button/internal/elevated-styles.css. +const styles$4 = i `:host{--_container-color: var(--md-elevated-button-container-color, var(--md-sys-color-surface-container-low, #f7f2fa));--_container-elevation: var(--md-elevated-button-container-elevation, 1);--_container-height: var(--md-elevated-button-container-height, 40px);--_container-shadow-color: var(--md-elevated-button-container-shadow-color, var(--md-sys-color-shadow, #000));--_disabled-container-color: var(--md-elevated-button-disabled-container-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-container-elevation: var(--md-elevated-button-disabled-container-elevation, 0);--_disabled-container-opacity: var(--md-elevated-button-disabled-container-opacity, 0.12);--_disabled-label-text-color: var(--md-elevated-button-disabled-label-text-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-label-text-opacity: var(--md-elevated-button-disabled-label-text-opacity, 0.38);--_focus-container-elevation: var(--md-elevated-button-focus-container-elevation, 1);--_focus-label-text-color: var(--md-elevated-button-focus-label-text-color, var(--md-sys-color-primary, #6750a4));--_hover-container-elevation: var(--md-elevated-button-hover-container-elevation, 2);--_hover-label-text-color: var(--md-elevated-button-hover-label-text-color, var(--md-sys-color-primary, #6750a4));--_hover-state-layer-color: var(--md-elevated-button-hover-state-layer-color, var(--md-sys-color-primary, #6750a4));--_hover-state-layer-opacity: var(--md-elevated-button-hover-state-layer-opacity, 0.08);--_label-text-color: var(--md-elevated-button-label-text-color, var(--md-sys-color-primary, #6750a4));--_label-text-font: var(--md-elevated-button-label-text-font, var(--md-sys-typescale-label-large-font, var(--md-ref-typeface-plain, Roboto)));--_label-text-line-height: var(--md-elevated-button-label-text-line-height, var(--md-sys-typescale-label-large-line-height, 1.25rem));--_label-text-size: var(--md-elevated-button-label-text-size, var(--md-sys-typescale-label-large-size, 0.875rem));--_label-text-weight: var(--md-elevated-button-label-text-weight, var(--md-sys-typescale-label-large-weight, var(--md-ref-typeface-weight-medium, 500)));--_pressed-container-elevation: var(--md-elevated-button-pressed-container-elevation, 1);--_pressed-label-text-color: var(--md-elevated-button-pressed-label-text-color, var(--md-sys-color-primary, #6750a4));--_pressed-state-layer-color: var(--md-elevated-button-pressed-state-layer-color, var(--md-sys-color-primary, #6750a4));--_pressed-state-layer-opacity: var(--md-elevated-button-pressed-state-layer-opacity, 0.12);--_disabled-icon-color: var(--md-elevated-button-disabled-icon-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-icon-opacity: var(--md-elevated-button-disabled-icon-opacity, 0.38);--_focus-icon-color: var(--md-elevated-button-focus-icon-color, var(--md-sys-color-primary, #6750a4));--_hover-icon-color: var(--md-elevated-button-hover-icon-color, var(--md-sys-color-primary, #6750a4));--_icon-color: var(--md-elevated-button-icon-color, var(--md-sys-color-primary, #6750a4));--_icon-size: var(--md-elevated-button-icon-size, 18px);--_pressed-icon-color: var(--md-elevated-button-pressed-icon-color, var(--md-sys-color-primary, #6750a4));--_container-shape-start-start: var(--md-elevated-button-container-shape-start-start, var(--md-elevated-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_container-shape-start-end: var(--md-elevated-button-container-shape-start-end, var(--md-elevated-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_container-shape-end-end: var(--md-elevated-button-container-shape-end-end, var(--md-elevated-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_container-shape-end-start: var(--md-elevated-button-container-shape-end-start, var(--md-elevated-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_leading-space: var(--md-elevated-button-leading-space, 24px);--_trailing-space: var(--md-elevated-button-trailing-space, 24px);--_with-leading-icon-leading-space: var(--md-elevated-button-with-leading-icon-leading-space, 16px);--_with-leading-icon-trailing-space: var(--md-elevated-button-with-leading-icon-trailing-space, 24px);--_with-trailing-icon-leading-space: var(--md-elevated-button-with-trailing-icon-leading-space, 24px);--_with-trailing-icon-trailing-space: var(--md-elevated-button-with-trailing-icon-trailing-space, 16px)} +`; + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @summary Buttons help people take action, such as sending an email, sharing a + * document, or liking a comment. + * + * @description + * __Emphasis:__ Medium emphasis – For important actions that don’t distract + * from other onscreen elements. + * + * __Rationale:__ Elevated buttons are essentially filled buttons with a lighter + * background color and a shadow. To prevent shadow creep, only use them when + * absolutely necessary, such as when the button requires visual separation from + * a patterned background. + * + * __Example usages:__ + * - Reply + * - View all + * - Add to cart + * - Take out of trash + * + * @final + * @suppress {visibility} + */ +let MdElevatedButton = class MdElevatedButton extends ElevatedButton { +}; +MdElevatedButton.styles = [ + styles$5, + styles$6, + styles$4, +]; +MdElevatedButton = __decorate([ + e('md-elevated-button') +], MdElevatedButton); + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A filled button component. + */ +class FilledButton extends Button { + renderElevationOrOutline() { + return x ``; + } +} + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./button/internal/filled-styles.css. +const styles$3 = i `:host{--_container-color: var(--md-filled-button-container-color, var(--md-sys-color-primary, #6750a4));--_container-elevation: var(--md-filled-button-container-elevation, 0);--_container-height: var(--md-filled-button-container-height, 40px);--_container-shadow-color: var(--md-filled-button-container-shadow-color, var(--md-sys-color-shadow, #000));--_disabled-container-color: var(--md-filled-button-disabled-container-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-container-elevation: var(--md-filled-button-disabled-container-elevation, 0);--_disabled-container-opacity: var(--md-filled-button-disabled-container-opacity, 0.12);--_disabled-label-text-color: var(--md-filled-button-disabled-label-text-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-label-text-opacity: var(--md-filled-button-disabled-label-text-opacity, 0.38);--_focus-container-elevation: var(--md-filled-button-focus-container-elevation, 0);--_focus-label-text-color: var(--md-filled-button-focus-label-text-color, var(--md-sys-color-on-primary, #fff));--_hover-container-elevation: var(--md-filled-button-hover-container-elevation, 1);--_hover-label-text-color: var(--md-filled-button-hover-label-text-color, var(--md-sys-color-on-primary, #fff));--_hover-state-layer-color: var(--md-filled-button-hover-state-layer-color, var(--md-sys-color-on-primary, #fff));--_hover-state-layer-opacity: var(--md-filled-button-hover-state-layer-opacity, 0.08);--_label-text-color: var(--md-filled-button-label-text-color, var(--md-sys-color-on-primary, #fff));--_label-text-font: var(--md-filled-button-label-text-font, var(--md-sys-typescale-label-large-font, var(--md-ref-typeface-plain, Roboto)));--_label-text-line-height: var(--md-filled-button-label-text-line-height, var(--md-sys-typescale-label-large-line-height, 1.25rem));--_label-text-size: var(--md-filled-button-label-text-size, var(--md-sys-typescale-label-large-size, 0.875rem));--_label-text-weight: var(--md-filled-button-label-text-weight, var(--md-sys-typescale-label-large-weight, var(--md-ref-typeface-weight-medium, 500)));--_pressed-container-elevation: var(--md-filled-button-pressed-container-elevation, 0);--_pressed-label-text-color: var(--md-filled-button-pressed-label-text-color, var(--md-sys-color-on-primary, #fff));--_pressed-state-layer-color: var(--md-filled-button-pressed-state-layer-color, var(--md-sys-color-on-primary, #fff));--_pressed-state-layer-opacity: var(--md-filled-button-pressed-state-layer-opacity, 0.12);--_disabled-icon-color: var(--md-filled-button-disabled-icon-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-icon-opacity: var(--md-filled-button-disabled-icon-opacity, 0.38);--_focus-icon-color: var(--md-filled-button-focus-icon-color, var(--md-sys-color-on-primary, #fff));--_hover-icon-color: var(--md-filled-button-hover-icon-color, var(--md-sys-color-on-primary, #fff));--_icon-color: var(--md-filled-button-icon-color, var(--md-sys-color-on-primary, #fff));--_icon-size: var(--md-filled-button-icon-size, 18px);--_pressed-icon-color: var(--md-filled-button-pressed-icon-color, var(--md-sys-color-on-primary, #fff));--_container-shape-start-start: var(--md-filled-button-container-shape-start-start, var(--md-filled-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_container-shape-start-end: var(--md-filled-button-container-shape-start-end, var(--md-filled-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_container-shape-end-end: var(--md-filled-button-container-shape-end-end, var(--md-filled-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_container-shape-end-start: var(--md-filled-button-container-shape-end-start, var(--md-filled-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_leading-space: var(--md-filled-button-leading-space, 24px);--_trailing-space: var(--md-filled-button-trailing-space, 24px);--_with-leading-icon-leading-space: var(--md-filled-button-with-leading-icon-leading-space, 16px);--_with-leading-icon-trailing-space: var(--md-filled-button-with-leading-icon-trailing-space, 24px);--_with-trailing-icon-leading-space: var(--md-filled-button-with-trailing-icon-leading-space, 24px);--_with-trailing-icon-trailing-space: var(--md-filled-button-with-trailing-icon-trailing-space, 16px)} +`; + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @summary Buttons help people take action, such as sending an email, sharing a + * document, or liking a comment. + * + * @description + * __Emphasis:__ High emphasis – For the primary, most important, or most common + * action on a screen + * + * __Rationale:__ The filled button’s contrasting surface color makes it the + * most prominent button after the FAB. It’s used for final or unblocking + * actions in a flow. + * + * __Example usages:__ + * - Save + * - Confirm + * - Done + * + * @final + * @suppress {visibility} + */ +let MdFilledButton = class MdFilledButton extends FilledButton { +}; +MdFilledButton.styles = [ + styles$5, + styles$6, + styles$3, +]; +MdFilledButton = __decorate([ + e('md-filled-button') +], MdFilledButton); + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A filled tonal button component. + */ +class FilledTonalButton extends Button { + renderElevationOrOutline() { + return x ``; + } +} + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./button/internal/filled-tonal-styles.css. +const styles$2 = i `:host{--_container-color: var(--md-filled-tonal-button-container-color, var(--md-sys-color-secondary-container, #e8def8));--_container-elevation: var(--md-filled-tonal-button-container-elevation, 0);--_container-height: var(--md-filled-tonal-button-container-height, 40px);--_container-shadow-color: var(--md-filled-tonal-button-container-shadow-color, var(--md-sys-color-shadow, #000));--_disabled-container-color: var(--md-filled-tonal-button-disabled-container-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-container-elevation: var(--md-filled-tonal-button-disabled-container-elevation, 0);--_disabled-container-opacity: var(--md-filled-tonal-button-disabled-container-opacity, 0.12);--_disabled-label-text-color: var(--md-filled-tonal-button-disabled-label-text-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-label-text-opacity: var(--md-filled-tonal-button-disabled-label-text-opacity, 0.38);--_focus-container-elevation: var(--md-filled-tonal-button-focus-container-elevation, 0);--_focus-label-text-color: var(--md-filled-tonal-button-focus-label-text-color, var(--md-sys-color-on-secondary-container, #1d192b));--_hover-container-elevation: var(--md-filled-tonal-button-hover-container-elevation, 1);--_hover-label-text-color: var(--md-filled-tonal-button-hover-label-text-color, var(--md-sys-color-on-secondary-container, #1d192b));--_hover-state-layer-color: var(--md-filled-tonal-button-hover-state-layer-color, var(--md-sys-color-on-secondary-container, #1d192b));--_hover-state-layer-opacity: var(--md-filled-tonal-button-hover-state-layer-opacity, 0.08);--_label-text-color: var(--md-filled-tonal-button-label-text-color, var(--md-sys-color-on-secondary-container, #1d192b));--_label-text-font: var(--md-filled-tonal-button-label-text-font, var(--md-sys-typescale-label-large-font, var(--md-ref-typeface-plain, Roboto)));--_label-text-line-height: var(--md-filled-tonal-button-label-text-line-height, var(--md-sys-typescale-label-large-line-height, 1.25rem));--_label-text-size: var(--md-filled-tonal-button-label-text-size, var(--md-sys-typescale-label-large-size, 0.875rem));--_label-text-weight: var(--md-filled-tonal-button-label-text-weight, var(--md-sys-typescale-label-large-weight, var(--md-ref-typeface-weight-medium, 500)));--_pressed-container-elevation: var(--md-filled-tonal-button-pressed-container-elevation, 0);--_pressed-label-text-color: var(--md-filled-tonal-button-pressed-label-text-color, var(--md-sys-color-on-secondary-container, #1d192b));--_pressed-state-layer-color: var(--md-filled-tonal-button-pressed-state-layer-color, var(--md-sys-color-on-secondary-container, #1d192b));--_pressed-state-layer-opacity: var(--md-filled-tonal-button-pressed-state-layer-opacity, 0.12);--_disabled-icon-color: var(--md-filled-tonal-button-disabled-icon-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-icon-opacity: var(--md-filled-tonal-button-disabled-icon-opacity, 0.38);--_focus-icon-color: var(--md-filled-tonal-button-focus-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_hover-icon-color: var(--md-filled-tonal-button-hover-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_icon-color: var(--md-filled-tonal-button-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_icon-size: var(--md-filled-tonal-button-icon-size, 18px);--_pressed-icon-color: var(--md-filled-tonal-button-pressed-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_container-shape-start-start: var(--md-filled-tonal-button-container-shape-start-start, var(--md-filled-tonal-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_container-shape-start-end: var(--md-filled-tonal-button-container-shape-start-end, var(--md-filled-tonal-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_container-shape-end-end: var(--md-filled-tonal-button-container-shape-end-end, var(--md-filled-tonal-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_container-shape-end-start: var(--md-filled-tonal-button-container-shape-end-start, var(--md-filled-tonal-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_leading-space: var(--md-filled-tonal-button-leading-space, 24px);--_trailing-space: var(--md-filled-tonal-button-trailing-space, 24px);--_with-leading-icon-leading-space: var(--md-filled-tonal-button-with-leading-icon-leading-space, 16px);--_with-leading-icon-trailing-space: var(--md-filled-tonal-button-with-leading-icon-trailing-space, 24px);--_with-trailing-icon-leading-space: var(--md-filled-tonal-button-with-trailing-icon-leading-space, 24px);--_with-trailing-icon-trailing-space: var(--md-filled-tonal-button-with-trailing-icon-trailing-space, 16px)} +`; + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @summary Buttons help people take action, such as sending an email, sharing a + * document, or liking a comment. + * + * @description + * __Emphasis:__ Medium emphasis – For important actions that don’t distract + * from other onscreen elements. + * + * __Rationale:__ Filled tonal buttons have a lighter background color and + * darker label color, making them less visually prominent than a regular, + * filled button. They’re still used for final or unblocking actions in a flow, + * but do so with less emphasis. + * + * __Example usages:__ + * - Save + * - Confirm + * - Done + * + * @final + * @suppress {visibility} + */ +let MdFilledTonalButton = class MdFilledTonalButton extends FilledTonalButton { +}; +MdFilledTonalButton.styles = [ + styles$5, + styles$6, + styles$2, +]; +MdFilledTonalButton = __decorate([ + e('md-filled-tonal-button') +], MdFilledTonalButton); + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * An outlined button component. + */ +class OutlinedButton extends Button { + renderElevationOrOutline() { + return x `
`; + } +} + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./button/internal/outlined-styles.css. +const styles$1 = i `:host{--_container-height: var(--md-outlined-button-container-height, 40px);--_disabled-label-text-color: var(--md-outlined-button-disabled-label-text-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-label-text-opacity: var(--md-outlined-button-disabled-label-text-opacity, 0.38);--_disabled-outline-color: var(--md-outlined-button-disabled-outline-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-outline-opacity: var(--md-outlined-button-disabled-outline-opacity, 0.12);--_focus-label-text-color: var(--md-outlined-button-focus-label-text-color, var(--md-sys-color-primary, #6750a4));--_hover-label-text-color: var(--md-outlined-button-hover-label-text-color, var(--md-sys-color-primary, #6750a4));--_hover-state-layer-color: var(--md-outlined-button-hover-state-layer-color, var(--md-sys-color-primary, #6750a4));--_hover-state-layer-opacity: var(--md-outlined-button-hover-state-layer-opacity, 0.08);--_label-text-color: var(--md-outlined-button-label-text-color, var(--md-sys-color-primary, #6750a4));--_label-text-font: var(--md-outlined-button-label-text-font, var(--md-sys-typescale-label-large-font, var(--md-ref-typeface-plain, Roboto)));--_label-text-line-height: var(--md-outlined-button-label-text-line-height, var(--md-sys-typescale-label-large-line-height, 1.25rem));--_label-text-size: var(--md-outlined-button-label-text-size, var(--md-sys-typescale-label-large-size, 0.875rem));--_label-text-weight: var(--md-outlined-button-label-text-weight, var(--md-sys-typescale-label-large-weight, var(--md-ref-typeface-weight-medium, 500)));--_outline-color: var(--md-outlined-button-outline-color, var(--md-sys-color-outline, #79747e));--_outline-width: var(--md-outlined-button-outline-width, 1px);--_pressed-label-text-color: var(--md-outlined-button-pressed-label-text-color, var(--md-sys-color-primary, #6750a4));--_pressed-outline-color: var(--md-outlined-button-pressed-outline-color, var(--md-sys-color-outline, #79747e));--_pressed-state-layer-color: var(--md-outlined-button-pressed-state-layer-color, var(--md-sys-color-primary, #6750a4));--_pressed-state-layer-opacity: var(--md-outlined-button-pressed-state-layer-opacity, 0.12);--_disabled-icon-color: var(--md-outlined-button-disabled-icon-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-icon-opacity: var(--md-outlined-button-disabled-icon-opacity, 0.38);--_focus-icon-color: var(--md-outlined-button-focus-icon-color, var(--md-sys-color-primary, #6750a4));--_hover-icon-color: var(--md-outlined-button-hover-icon-color, var(--md-sys-color-primary, #6750a4));--_icon-color: var(--md-outlined-button-icon-color, var(--md-sys-color-primary, #6750a4));--_icon-size: var(--md-outlined-button-icon-size, 18px);--_pressed-icon-color: var(--md-outlined-button-pressed-icon-color, var(--md-sys-color-primary, #6750a4));--_container-shape-start-start: var(--md-outlined-button-container-shape-start-start, var(--md-outlined-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_container-shape-start-end: var(--md-outlined-button-container-shape-start-end, var(--md-outlined-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_container-shape-end-end: var(--md-outlined-button-container-shape-end-end, var(--md-outlined-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_container-shape-end-start: var(--md-outlined-button-container-shape-end-start, var(--md-outlined-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_leading-space: var(--md-outlined-button-leading-space, 24px);--_trailing-space: var(--md-outlined-button-trailing-space, 24px);--_with-leading-icon-leading-space: var(--md-outlined-button-with-leading-icon-leading-space, 16px);--_with-leading-icon-trailing-space: var(--md-outlined-button-with-leading-icon-trailing-space, 24px);--_with-trailing-icon-leading-space: var(--md-outlined-button-with-trailing-icon-leading-space, 24px);--_with-trailing-icon-trailing-space: var(--md-outlined-button-with-trailing-icon-trailing-space, 16px);--_container-color: none;--_disabled-container-color: none;--_disabled-container-opacity: 0}.outline{inset:0;border-style:solid;position:absolute;box-sizing:border-box;border-color:var(--_outline-color);border-start-start-radius:var(--_container-shape-start-start);border-start-end-radius:var(--_container-shape-start-end);border-end-start-radius:var(--_container-shape-end-start);border-end-end-radius:var(--_container-shape-end-end)}:host(:active) .outline{border-color:var(--_pressed-outline-color)}:host(:is([disabled],[soft-disabled])) .outline{border-color:var(--_disabled-outline-color);opacity:var(--_disabled-outline-opacity)}@media(forced-colors: active){:host(:is([disabled],[soft-disabled])) .background{border-color:GrayText}:host(:is([disabled],[soft-disabled])) .outline{opacity:1}}.outline,md-ripple{border-width:var(--_outline-width)}md-ripple{inline-size:calc(100% - 2*var(--_outline-width));block-size:calc(100% - 2*var(--_outline-width));border-style:solid;border-color:rgba(0,0,0,0)} +`; + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @summary Buttons help people take action, such as sending an email, sharing a + * document, or liking a comment. + * + * @description + * __Emphasis:__ Medium emphasis – For important actions that don’t distract + * from other onscreen elements. + * + * __Rationale:__ Use an outlined button for actions that need attention but + * aren’t the primary action, such as “See all” or “Add to cart.” This is also + * the button to use for giving someone the opportunity to change their mind or + * escape a flow. + * + * __Example usages:__ + * - Reply + * - View all + * - Add to cart + * - Take out of trash + * + * @final + * @suppress {visibility} + */ +let MdOutlinedButton = class MdOutlinedButton extends OutlinedButton { +}; +MdOutlinedButton.styles = [styles$5, styles$1]; +MdOutlinedButton = __decorate([ + e('md-outlined-button') +], MdOutlinedButton); + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A text button component. + */ +class TextButton extends Button { +} + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./button/internal/text-styles.css. +const styles = i `:host{--_container-height: var(--md-text-button-container-height, 40px);--_disabled-label-text-color: var(--md-text-button-disabled-label-text-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-label-text-opacity: var(--md-text-button-disabled-label-text-opacity, 0.38);--_focus-label-text-color: var(--md-text-button-focus-label-text-color, var(--md-sys-color-primary, #6750a4));--_hover-label-text-color: var(--md-text-button-hover-label-text-color, var(--md-sys-color-primary, #6750a4));--_hover-state-layer-color: var(--md-text-button-hover-state-layer-color, var(--md-sys-color-primary, #6750a4));--_hover-state-layer-opacity: var(--md-text-button-hover-state-layer-opacity, 0.08);--_label-text-color: var(--md-text-button-label-text-color, var(--md-sys-color-primary, #6750a4));--_label-text-font: var(--md-text-button-label-text-font, var(--md-sys-typescale-label-large-font, var(--md-ref-typeface-plain, Roboto)));--_label-text-line-height: var(--md-text-button-label-text-line-height, var(--md-sys-typescale-label-large-line-height, 1.25rem));--_label-text-size: var(--md-text-button-label-text-size, var(--md-sys-typescale-label-large-size, 0.875rem));--_label-text-weight: var(--md-text-button-label-text-weight, var(--md-sys-typescale-label-large-weight, var(--md-ref-typeface-weight-medium, 500)));--_pressed-label-text-color: var(--md-text-button-pressed-label-text-color, var(--md-sys-color-primary, #6750a4));--_pressed-state-layer-color: var(--md-text-button-pressed-state-layer-color, var(--md-sys-color-primary, #6750a4));--_pressed-state-layer-opacity: var(--md-text-button-pressed-state-layer-opacity, 0.12);--_disabled-icon-color: var(--md-text-button-disabled-icon-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-icon-opacity: var(--md-text-button-disabled-icon-opacity, 0.38);--_focus-icon-color: var(--md-text-button-focus-icon-color, var(--md-sys-color-primary, #6750a4));--_hover-icon-color: var(--md-text-button-hover-icon-color, var(--md-sys-color-primary, #6750a4));--_icon-color: var(--md-text-button-icon-color, var(--md-sys-color-primary, #6750a4));--_icon-size: var(--md-text-button-icon-size, 18px);--_pressed-icon-color: var(--md-text-button-pressed-icon-color, var(--md-sys-color-primary, #6750a4));--_container-shape-start-start: var(--md-text-button-container-shape-start-start, var(--md-text-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_container-shape-start-end: var(--md-text-button-container-shape-start-end, var(--md-text-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_container-shape-end-end: var(--md-text-button-container-shape-end-end, var(--md-text-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_container-shape-end-start: var(--md-text-button-container-shape-end-start, var(--md-text-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_leading-space: var(--md-text-button-leading-space, 12px);--_trailing-space: var(--md-text-button-trailing-space, 12px);--_with-leading-icon-leading-space: var(--md-text-button-with-leading-icon-leading-space, 12px);--_with-leading-icon-trailing-space: var(--md-text-button-with-leading-icon-trailing-space, 16px);--_with-trailing-icon-leading-space: var(--md-text-button-with-trailing-icon-leading-space, 16px);--_with-trailing-icon-trailing-space: var(--md-text-button-with-trailing-icon-trailing-space, 12px);--_container-color: none;--_disabled-container-color: none;--_disabled-container-opacity: 0} +`; + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @summary Buttons help people take action, such as sending an email, sharing a + * document, or liking a comment. + * + * @description + * __Emphasis:__ Low emphasis – For optional or supplementary actions with the + * least amount of prominence + * + * __Rationale:__ Text buttons have less visual prominence, so should be used + * for low emphasis actions, such as an alternative option. + * + * __Example usages:__ + * - Learn more + * - View all + * - Change account + * - Turn on + * + * @final + * @suppress {visibility} + */ +let MdTextButton = class MdTextButton extends TextButton { +}; +MdTextButton.styles = [styles$5, styles]; +MdTextButton = __decorate([ + e('md-text-button') +], MdTextButton); diff --git a/md-web/checkbox.js b/md-web/checkbox.js new file mode 100644 index 0000000..22d0666 --- /dev/null +++ b/md-web/checkbox.js @@ -0,0 +1,218 @@ +export const __dummy_loader = () => {}; + +import { m as mixinDelegatesAria, a as mixinConstraintValidation, b as mixinFormAssociated, s, _ as __decorate, n, t, c as i, d as isActivationClick, f as dispatchActivationClick, o, x, A, r as redispatchEvent, g as getFormValue, h as getFormState, j as createValidator, k as CheckboxValidator, p as getValidityAnchor, q as mixinElementInternals, i as i$1, e } from './core.js'; + +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Separate variable needed for closure. +const checkboxBaseClass = mixinDelegatesAria(mixinConstraintValidation(mixinFormAssociated(mixinElementInternals(s)))); +/** + * A checkbox component. + * + * + * @fires change {Event} The native `change` event on + * [``](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) + * --bubbles + * @fires input {InputEvent} The native `input` event on + * [``](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event) + * --bubbles --composed + */ +class Checkbox extends checkboxBaseClass { + constructor() { + super(); + /** + * Whether or not the checkbox is selected. + */ + this.checked = false; + /** + * Whether or not the checkbox is indeterminate. + * + * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#indeterminate_state_checkboxes + */ + this.indeterminate = false; + /** + * When true, require the checkbox to be selected when participating in + * form submission. + * + * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#validation + */ + this.required = false; + /** + * The value of the checkbox that is submitted with a form when selected. + * + * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#value + */ + this.value = 'on'; + this.prevChecked = false; + this.prevDisabled = false; + this.prevIndeterminate = false; + { + this.addEventListener('click', (event) => { + if (!isActivationClick(event) || !this.input) { + return; + } + this.focus(); + dispatchActivationClick(this.input); + }); + } + } + update(changed) { + if (changed.has('checked') || + changed.has('disabled') || + changed.has('indeterminate')) { + this.prevChecked = changed.get('checked') ?? this.checked; + this.prevDisabled = changed.get('disabled') ?? this.disabled; + this.prevIndeterminate = + changed.get('indeterminate') ?? this.indeterminate; + } + super.update(changed); + } + render() { + const prevNone = !this.prevChecked && !this.prevIndeterminate; + const prevChecked = this.prevChecked && !this.prevIndeterminate; + const prevIndeterminate = this.prevIndeterminate; + const isChecked = this.checked && !this.indeterminate; + const isIndeterminate = this.indeterminate; + const containerClasses = o({ + 'disabled': this.disabled, + 'selected': isChecked || isIndeterminate, + 'unselected': !isChecked && !isIndeterminate, + 'checked': isChecked, + 'indeterminate': isIndeterminate, + 'prev-unselected': prevNone, + 'prev-checked': prevChecked, + 'prev-indeterminate': prevIndeterminate, + 'prev-disabled': this.prevDisabled, + }); + // Needed for closure conformance + const { ariaLabel, ariaInvalid } = this; + // Note: needs to be rendered before the for + // form.reportValidity() to work in Chrome. + return x ` +
+ + +
+
+ + + +
+ `; + } + handleInput(event) { + const target = event.target; + this.checked = target.checked; + this.indeterminate = target.indeterminate; + // 'input' event bubbles and is composed, don't re-dispatch it. + } + handleChange(event) { + // 'change' event is not composed, re-dispatch it. + redispatchEvent(this, event); + } + [getFormValue]() { + if (!this.checked || this.indeterminate) { + return null; + } + return this.value; + } + [getFormState]() { + return String(this.checked); + } + formResetCallback() { + // The checked property does not reflect, so the original attribute set by + // the user is used to determine the default value. + this.checked = this.hasAttribute('checked'); + } + formStateRestoreCallback(state) { + this.checked = state === 'true'; + } + [createValidator]() { + return new CheckboxValidator(() => this); + } + [getValidityAnchor]() { + return this.input; + } +} +/** @nocollapse */ +Checkbox.shadowRootOptions = { + ...s.shadowRootOptions, + delegatesFocus: true, +}; +__decorate([ + n({ type: Boolean }) +], Checkbox.prototype, "checked", void 0); +__decorate([ + n({ type: Boolean }) +], Checkbox.prototype, "indeterminate", void 0); +__decorate([ + n({ type: Boolean }) +], Checkbox.prototype, "required", void 0); +__decorate([ + n() +], Checkbox.prototype, "value", void 0); +__decorate([ + t() +], Checkbox.prototype, "prevChecked", void 0); +__decorate([ + t() +], Checkbox.prototype, "prevDisabled", void 0); +__decorate([ + t() +], Checkbox.prototype, "prevIndeterminate", void 0); +__decorate([ + i('input') +], Checkbox.prototype, "input", void 0); + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./checkbox/internal/checkbox-styles.css. +const styles = i$1 `:host{border-start-start-radius:var(--md-checkbox-container-shape-start-start, var(--md-checkbox-container-shape, 2px));border-start-end-radius:var(--md-checkbox-container-shape-start-end, var(--md-checkbox-container-shape, 2px));border-end-end-radius:var(--md-checkbox-container-shape-end-end, var(--md-checkbox-container-shape, 2px));border-end-start-radius:var(--md-checkbox-container-shape-end-start, var(--md-checkbox-container-shape, 2px));display:inline-flex;height:var(--md-checkbox-container-size, 18px);position:relative;vertical-align:top;width:var(--md-checkbox-container-size, 18px);-webkit-tap-highlight-color:rgba(0,0,0,0);cursor:pointer}:host([disabled]){cursor:default}:host([touch-target=wrapper]){margin:max(0px,(48px - var(--md-checkbox-container-size, 18px))/2)}md-focus-ring{height:44px;inset:unset;width:44px}input{appearance:none;height:48px;margin:0;opacity:0;outline:none;position:absolute;width:48px;z-index:1;cursor:inherit}:host([touch-target=none]) input{height:100%;width:100%}.container{border-radius:inherit;display:flex;height:100%;place-content:center;place-items:center;position:relative;width:100%}.outline,.background,.icon{inset:0;position:absolute}.outline,.background{border-radius:inherit}.outline{border-color:var(--md-checkbox-outline-color, var(--md-sys-color-on-surface-variant, #49454f));border-style:solid;border-width:var(--md-checkbox-outline-width, 2px);box-sizing:border-box}.background{background-color:var(--md-checkbox-selected-container-color, var(--md-sys-color-primary, #6750a4))}.background,.icon{opacity:0;transition-duration:150ms,50ms;transition-property:transform,opacity;transition-timing-function:cubic-bezier(0.3, 0, 0.8, 0.15),linear;transform:scale(0.6)}:where(.selected) :is(.background,.icon){opacity:1;transition-duration:350ms,50ms;transition-timing-function:cubic-bezier(0.05, 0.7, 0.1, 1),linear;transform:scale(1)}md-ripple{border-radius:var(--md-checkbox-state-layer-shape, var(--md-sys-shape-corner-full, 9999px));height:var(--md-checkbox-state-layer-size, 40px);inset:unset;width:var(--md-checkbox-state-layer-size, 40px);--md-ripple-hover-color: var(--md-checkbox-hover-state-layer-color, var(--md-sys-color-on-surface, #1d1b20));--md-ripple-hover-opacity: var(--md-checkbox-hover-state-layer-opacity, 0.08);--md-ripple-pressed-color: var(--md-checkbox-pressed-state-layer-color, var(--md-sys-color-primary, #6750a4));--md-ripple-pressed-opacity: var(--md-checkbox-pressed-state-layer-opacity, 0.12)}.selected md-ripple{--md-ripple-hover-color: var(--md-checkbox-selected-hover-state-layer-color, var(--md-sys-color-primary, #6750a4));--md-ripple-hover-opacity: var(--md-checkbox-selected-hover-state-layer-opacity, 0.08);--md-ripple-pressed-color: var(--md-checkbox-selected-pressed-state-layer-color, var(--md-sys-color-on-surface, #1d1b20));--md-ripple-pressed-opacity: var(--md-checkbox-selected-pressed-state-layer-opacity, 0.12)}.icon{fill:var(--md-checkbox-selected-icon-color, var(--md-sys-color-on-primary, #fff));height:var(--md-checkbox-icon-size, 18px);width:var(--md-checkbox-icon-size, 18px)}.mark.short{height:2px;transition-property:transform,height;width:2px}.mark.long{height:2px;transition-property:transform,width;width:10px}.mark{animation-duration:150ms;animation-timing-function:cubic-bezier(0.3, 0, 0.8, 0.15);transition-duration:150ms;transition-timing-function:cubic-bezier(0.3, 0, 0.8, 0.15)}.selected .mark{animation-duration:350ms;animation-timing-function:cubic-bezier(0.05, 0.7, 0.1, 1);transition-duration:350ms;transition-timing-function:cubic-bezier(0.05, 0.7, 0.1, 1)}.checked .mark,.prev-checked.unselected .mark{transform:scaleY(-1) translate(7px, -14px) rotate(45deg)}.checked .mark.short,.prev-checked.unselected .mark.short{height:5.6568542495px}.checked .mark.long,.prev-checked.unselected .mark.long{width:11.313708499px}.indeterminate .mark,.prev-indeterminate.unselected .mark{transform:scaleY(-1) translate(4px, -10px) rotate(0deg)}.prev-unselected .mark{transition-property:none}.prev-unselected.checked .mark.long{animation-name:prev-unselected-to-checked}@keyframes prev-unselected-to-checked{from{width:0}}:where(:hover) .outline{border-color:var(--md-checkbox-hover-outline-color, var(--md-sys-color-on-surface, #1d1b20));border-width:var(--md-checkbox-hover-outline-width, 2px)}:where(:hover) .background{background:var(--md-checkbox-selected-hover-container-color, var(--md-sys-color-primary, #6750a4))}:where(:hover) .icon{fill:var(--md-checkbox-selected-hover-icon-color, var(--md-sys-color-on-primary, #fff))}:where(:focus-within) .outline{border-color:var(--md-checkbox-focus-outline-color, var(--md-sys-color-on-surface, #1d1b20));border-width:var(--md-checkbox-focus-outline-width, 2px)}:where(:focus-within) .background{background:var(--md-checkbox-selected-focus-container-color, var(--md-sys-color-primary, #6750a4))}:where(:focus-within) .icon{fill:var(--md-checkbox-selected-focus-icon-color, var(--md-sys-color-on-primary, #fff))}:where(:active) .outline{border-color:var(--md-checkbox-pressed-outline-color, var(--md-sys-color-on-surface, #1d1b20));border-width:var(--md-checkbox-pressed-outline-width, 2px)}:where(:active) .background{background:var(--md-checkbox-selected-pressed-container-color, var(--md-sys-color-primary, #6750a4))}:where(:active) .icon{fill:var(--md-checkbox-selected-pressed-icon-color, var(--md-sys-color-on-primary, #fff))}:where(.disabled,.prev-disabled) :is(.background,.icon,.mark){animation-duration:0s;transition-duration:0s}:where(.disabled) .outline{border-color:var(--md-checkbox-disabled-outline-color, var(--md-sys-color-on-surface, #1d1b20));border-width:var(--md-checkbox-disabled-outline-width, 2px);opacity:var(--md-checkbox-disabled-container-opacity, 0.38)}:where(.selected.disabled) .outline{visibility:hidden}:where(.selected.disabled) .background{background:var(--md-checkbox-selected-disabled-container-color, var(--md-sys-color-on-surface, #1d1b20));opacity:var(--md-checkbox-selected-disabled-container-opacity, 0.38)}:where(.disabled) .icon{fill:var(--md-checkbox-selected-disabled-icon-color, var(--md-sys-color-surface, #fef7ff))}@media(forced-colors: active){.background{background-color:CanvasText}.selected.disabled .background{background-color:GrayText;opacity:1}.outline{border-color:CanvasText}.disabled .outline{border-color:GrayText;opacity:1}.icon{fill:Canvas}} +`; + +/** + * @license + * Copyright 2018 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @summary Checkboxes allow users to select one or more items from a set. + * Checkboxes can turn an option on or off. + * + * @description + * Use checkboxes to: + * - Select one or more options from a list + * - Present a list containing sub-selections + * - Turn an item on or off in a desktop environment + * + * @final + * @suppress {visibility} + */ +let MdCheckbox = class MdCheckbox extends Checkbox { +}; +MdCheckbox.styles = [styles]; +MdCheckbox = __decorate([ + e('md-checkbox') +], MdCheckbox); + +export { MdCheckbox }; diff --git a/md-web/chip.js b/md-web/chip.js new file mode 100644 index 0000000..2d71829 --- /dev/null +++ b/md-web/chip.js @@ -0,0 +1,364 @@ +export const __dummy_loader = () => {}; + +import { i, a4 as styles$4, a5 as styles$5, _ as __decorate, a6 as AssistChip, e, n, c as i$1, a7 as MultiActionChip, x, A, a8 as renderRemoveButton, r as redispatchEvent, a9 as styles$6, aa as styles$7 } from './core.js'; + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./chips/internal/assist-styles.css. +const styles$3 = i `:host{--_container-height: var(--md-assist-chip-container-height, 32px);--_disabled-label-text-color: var(--md-assist-chip-disabled-label-text-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-label-text-opacity: var(--md-assist-chip-disabled-label-text-opacity, 0.38);--_elevated-container-color: var(--md-assist-chip-elevated-container-color, var(--md-sys-color-surface-container-low, #f7f2fa));--_elevated-container-elevation: var(--md-assist-chip-elevated-container-elevation, 1);--_elevated-container-shadow-color: var(--md-assist-chip-elevated-container-shadow-color, var(--md-sys-color-shadow, #000));--_elevated-disabled-container-color: var(--md-assist-chip-elevated-disabled-container-color, var(--md-sys-color-on-surface, #1d1b20));--_elevated-disabled-container-elevation: var(--md-assist-chip-elevated-disabled-container-elevation, 0);--_elevated-disabled-container-opacity: var(--md-assist-chip-elevated-disabled-container-opacity, 0.12);--_elevated-focus-container-elevation: var(--md-assist-chip-elevated-focus-container-elevation, 1);--_elevated-hover-container-elevation: var(--md-assist-chip-elevated-hover-container-elevation, 2);--_elevated-pressed-container-elevation: var(--md-assist-chip-elevated-pressed-container-elevation, 1);--_focus-label-text-color: var(--md-assist-chip-focus-label-text-color, var(--md-sys-color-on-surface, #1d1b20));--_hover-label-text-color: var(--md-assist-chip-hover-label-text-color, var(--md-sys-color-on-surface, #1d1b20));--_hover-state-layer-color: var(--md-assist-chip-hover-state-layer-color, var(--md-sys-color-on-surface, #1d1b20));--_hover-state-layer-opacity: var(--md-assist-chip-hover-state-layer-opacity, 0.08);--_label-text-color: var(--md-assist-chip-label-text-color, var(--md-sys-color-on-surface, #1d1b20));--_label-text-font: var(--md-assist-chip-label-text-font, var(--md-sys-typescale-label-large-font, var(--md-ref-typeface-plain, Roboto)));--_label-text-line-height: var(--md-assist-chip-label-text-line-height, var(--md-sys-typescale-label-large-line-height, 1.25rem));--_label-text-size: var(--md-assist-chip-label-text-size, var(--md-sys-typescale-label-large-size, 0.875rem));--_label-text-weight: var(--md-assist-chip-label-text-weight, var(--md-sys-typescale-label-large-weight, var(--md-ref-typeface-weight-medium, 500)));--_pressed-label-text-color: var(--md-assist-chip-pressed-label-text-color, var(--md-sys-color-on-surface, #1d1b20));--_pressed-state-layer-color: var(--md-assist-chip-pressed-state-layer-color, var(--md-sys-color-on-surface, #1d1b20));--_pressed-state-layer-opacity: var(--md-assist-chip-pressed-state-layer-opacity, 0.12);--_disabled-outline-color: var(--md-assist-chip-disabled-outline-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-outline-opacity: var(--md-assist-chip-disabled-outline-opacity, 0.12);--_focus-outline-color: var(--md-assist-chip-focus-outline-color, var(--md-sys-color-on-surface, #1d1b20));--_outline-color: var(--md-assist-chip-outline-color, var(--md-sys-color-outline, #79747e));--_outline-width: var(--md-assist-chip-outline-width, 1px);--_disabled-leading-icon-color: var(--md-assist-chip-disabled-leading-icon-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-leading-icon-opacity: var(--md-assist-chip-disabled-leading-icon-opacity, 0.38);--_focus-leading-icon-color: var(--md-assist-chip-focus-leading-icon-color, var(--md-sys-color-primary, #6750a4));--_hover-leading-icon-color: var(--md-assist-chip-hover-leading-icon-color, var(--md-sys-color-primary, #6750a4));--_leading-icon-color: var(--md-assist-chip-leading-icon-color, var(--md-sys-color-primary, #6750a4));--_icon-size: var(--md-assist-chip-icon-size, 18px);--_pressed-leading-icon-color: var(--md-assist-chip-pressed-leading-icon-color, var(--md-sys-color-primary, #6750a4));--_container-shape-start-start: var(--md-assist-chip-container-shape-start-start, var(--md-assist-chip-container-shape, var(--md-sys-shape-corner-small, 8px)));--_container-shape-start-end: var(--md-assist-chip-container-shape-start-end, var(--md-assist-chip-container-shape, var(--md-sys-shape-corner-small, 8px)));--_container-shape-end-end: var(--md-assist-chip-container-shape-end-end, var(--md-assist-chip-container-shape, var(--md-sys-shape-corner-small, 8px)));--_container-shape-end-start: var(--md-assist-chip-container-shape-end-start, var(--md-assist-chip-container-shape, var(--md-sys-shape-corner-small, 8px)));--_leading-space: var(--md-assist-chip-leading-space, 16px);--_trailing-space: var(--md-assist-chip-trailing-space, 16px);--_icon-label-space: var(--md-assist-chip-icon-label-space, 8px);--_with-leading-icon-leading-space: var(--md-assist-chip-with-leading-icon-leading-space, 8px)}@media(forced-colors: active){.link .outline{border-color:ActiveText}} +`; + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * TODO(b/243982145): add docs + * + * @final + * @suppress {visibility} + */ +let MdAssistChip = class MdAssistChip extends AssistChip { +}; +MdAssistChip.styles = [styles$4, styles$5, styles$3]; +MdAssistChip = __decorate([ + e('md-assist-chip') +], MdAssistChip); + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A filter chip component. + * + * @fires remove {Event} Dispatched when the remove button is clicked. + */ +class FilterChip extends MultiActionChip { + constructor() { + super(...arguments); + this.elevated = false; + this.removable = false; + this.selected = false; + /** + * Only needed for SSR. + * + * Add this attribute when a filter chip has a `slot="selected-icon"` to avoid + * a Flash Of Unstyled Content. + */ + this.hasSelectedIcon = false; + } + get primaryId() { + return 'button'; + } + getContainerClasses() { + return { + ...super.getContainerClasses(), + elevated: this.elevated, + selected: this.selected, + 'has-trailing': this.removable, + 'has-icon': this.hasIcon || this.selected, + }; + } + renderPrimaryAction(content) { + const { ariaLabel } = this; + return x ` + + `; + } + renderLeadingIcon() { + if (!this.selected) { + return super.renderLeadingIcon(); + } + return x ` + + + + `; + } + renderTrailingAction(focusListener) { + if (this.removable) { + return renderRemoveButton({ + focusListener, + ariaLabel: this.ariaLabelRemove, + disabled: this.disabled || this.softDisabled, + }); + } + return A; + } + renderOutline() { + if (this.elevated) { + return x ``; + } + return super.renderOutline(); + } + handleClickOnChild(event) { + if (this.disabled || this.softDisabled) { + return; + } + // Store prevValue to revert in case `chip.selected` is changed during an + // event listener. + const prevValue = this.selected; + this.selected = !this.selected; + const preventDefault = !redispatchEvent(this, event); + if (preventDefault) { + // We should not do `this.selected = !this.selected`, since a client + // click listener could change its value. Instead, always revert to the + // original value. + this.selected = prevValue; + return; + } + } +} +__decorate([ + n({ type: Boolean }) +], FilterChip.prototype, "elevated", void 0); +__decorate([ + n({ type: Boolean }) +], FilterChip.prototype, "removable", void 0); +__decorate([ + n({ type: Boolean, reflect: true }) +], FilterChip.prototype, "selected", void 0); +__decorate([ + n({ type: Boolean, reflect: true, attribute: 'has-selected-icon' }) +], FilterChip.prototype, "hasSelectedIcon", void 0); +__decorate([ + i$1('.primary.action') +], FilterChip.prototype, "primaryAction", void 0); +__decorate([ + i$1('.trailing.action') +], FilterChip.prototype, "trailingAction", void 0); + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./chips/internal/filter-styles.css. +const styles$2 = i `:host{--_container-height: var(--md-filter-chip-container-height, 32px);--_disabled-label-text-color: var(--md-filter-chip-disabled-label-text-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-label-text-opacity: var(--md-filter-chip-disabled-label-text-opacity, 0.38);--_elevated-container-elevation: var(--md-filter-chip-elevated-container-elevation, 1);--_elevated-container-shadow-color: var(--md-filter-chip-elevated-container-shadow-color, var(--md-sys-color-shadow, #000));--_elevated-disabled-container-color: var(--md-filter-chip-elevated-disabled-container-color, var(--md-sys-color-on-surface, #1d1b20));--_elevated-disabled-container-elevation: var(--md-filter-chip-elevated-disabled-container-elevation, 0);--_elevated-disabled-container-opacity: var(--md-filter-chip-elevated-disabled-container-opacity, 0.12);--_elevated-focus-container-elevation: var(--md-filter-chip-elevated-focus-container-elevation, 1);--_elevated-hover-container-elevation: var(--md-filter-chip-elevated-hover-container-elevation, 2);--_elevated-pressed-container-elevation: var(--md-filter-chip-elevated-pressed-container-elevation, 1);--_elevated-selected-container-color: var(--md-filter-chip-elevated-selected-container-color, var(--md-sys-color-secondary-container, #e8def8));--_label-text-font: var(--md-filter-chip-label-text-font, var(--md-sys-typescale-label-large-font, var(--md-ref-typeface-plain, Roboto)));--_label-text-line-height: var(--md-filter-chip-label-text-line-height, var(--md-sys-typescale-label-large-line-height, 1.25rem));--_label-text-size: var(--md-filter-chip-label-text-size, var(--md-sys-typescale-label-large-size, 0.875rem));--_label-text-weight: var(--md-filter-chip-label-text-weight, var(--md-sys-typescale-label-large-weight, var(--md-ref-typeface-weight-medium, 500)));--_selected-focus-label-text-color: var(--md-filter-chip-selected-focus-label-text-color, var(--md-sys-color-on-secondary-container, #1d192b));--_selected-hover-label-text-color: var(--md-filter-chip-selected-hover-label-text-color, var(--md-sys-color-on-secondary-container, #1d192b));--_selected-hover-state-layer-color: var(--md-filter-chip-selected-hover-state-layer-color, var(--md-sys-color-on-secondary-container, #1d192b));--_selected-hover-state-layer-opacity: var(--md-filter-chip-selected-hover-state-layer-opacity, 0.08);--_selected-label-text-color: var(--md-filter-chip-selected-label-text-color, var(--md-sys-color-on-secondary-container, #1d192b));--_selected-pressed-label-text-color: var(--md-filter-chip-selected-pressed-label-text-color, var(--md-sys-color-on-secondary-container, #1d192b));--_selected-pressed-state-layer-color: var(--md-filter-chip-selected-pressed-state-layer-color, var(--md-sys-color-on-surface-variant, #49454f));--_selected-pressed-state-layer-opacity: var(--md-filter-chip-selected-pressed-state-layer-opacity, 0.12);--_elevated-container-color: var(--md-filter-chip-elevated-container-color, var(--md-sys-color-surface-container-low, #f7f2fa));--_disabled-outline-color: var(--md-filter-chip-disabled-outline-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-outline-opacity: var(--md-filter-chip-disabled-outline-opacity, 0.12);--_disabled-selected-container-color: var(--md-filter-chip-disabled-selected-container-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-selected-container-opacity: var(--md-filter-chip-disabled-selected-container-opacity, 0.12);--_focus-outline-color: var(--md-filter-chip-focus-outline-color, var(--md-sys-color-on-surface-variant, #49454f));--_outline-color: var(--md-filter-chip-outline-color, var(--md-sys-color-outline, #79747e));--_outline-width: var(--md-filter-chip-outline-width, 1px);--_selected-container-color: var(--md-filter-chip-selected-container-color, var(--md-sys-color-secondary-container, #e8def8));--_selected-outline-width: var(--md-filter-chip-selected-outline-width, 0px);--_focus-label-text-color: var(--md-filter-chip-focus-label-text-color, var(--md-sys-color-on-surface-variant, #49454f));--_hover-label-text-color: var(--md-filter-chip-hover-label-text-color, var(--md-sys-color-on-surface-variant, #49454f));--_hover-state-layer-color: var(--md-filter-chip-hover-state-layer-color, var(--md-sys-color-on-surface-variant, #49454f));--_hover-state-layer-opacity: var(--md-filter-chip-hover-state-layer-opacity, 0.08);--_label-text-color: var(--md-filter-chip-label-text-color, var(--md-sys-color-on-surface-variant, #49454f));--_pressed-label-text-color: var(--md-filter-chip-pressed-label-text-color, var(--md-sys-color-on-surface-variant, #49454f));--_pressed-state-layer-color: var(--md-filter-chip-pressed-state-layer-color, var(--md-sys-color-on-secondary-container, #1d192b));--_pressed-state-layer-opacity: var(--md-filter-chip-pressed-state-layer-opacity, 0.12);--_icon-size: var(--md-filter-chip-icon-size, 18px);--_disabled-leading-icon-color: var(--md-filter-chip-disabled-leading-icon-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-leading-icon-opacity: var(--md-filter-chip-disabled-leading-icon-opacity, 0.38);--_selected-focus-leading-icon-color: var(--md-filter-chip-selected-focus-leading-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_selected-hover-leading-icon-color: var(--md-filter-chip-selected-hover-leading-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_selected-leading-icon-color: var(--md-filter-chip-selected-leading-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_selected-pressed-leading-icon-color: var(--md-filter-chip-selected-pressed-leading-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_focus-leading-icon-color: var(--md-filter-chip-focus-leading-icon-color, var(--md-sys-color-primary, #6750a4));--_hover-leading-icon-color: var(--md-filter-chip-hover-leading-icon-color, var(--md-sys-color-primary, #6750a4));--_leading-icon-color: var(--md-filter-chip-leading-icon-color, var(--md-sys-color-primary, #6750a4));--_pressed-leading-icon-color: var(--md-filter-chip-pressed-leading-icon-color, var(--md-sys-color-primary, #6750a4));--_disabled-trailing-icon-color: var(--md-filter-chip-disabled-trailing-icon-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-trailing-icon-opacity: var(--md-filter-chip-disabled-trailing-icon-opacity, 0.38);--_selected-focus-trailing-icon-color: var(--md-filter-chip-selected-focus-trailing-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_selected-hover-trailing-icon-color: var(--md-filter-chip-selected-hover-trailing-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_selected-pressed-trailing-icon-color: var(--md-filter-chip-selected-pressed-trailing-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_selected-trailing-icon-color: var(--md-filter-chip-selected-trailing-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_focus-trailing-icon-color: var(--md-filter-chip-focus-trailing-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_hover-trailing-icon-color: var(--md-filter-chip-hover-trailing-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_pressed-trailing-icon-color: var(--md-filter-chip-pressed-trailing-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_trailing-icon-color: var(--md-filter-chip-trailing-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_container-shape-start-start: var(--md-filter-chip-container-shape-start-start, var(--md-filter-chip-container-shape, var(--md-sys-shape-corner-small, 8px)));--_container-shape-start-end: var(--md-filter-chip-container-shape-start-end, var(--md-filter-chip-container-shape, var(--md-sys-shape-corner-small, 8px)));--_container-shape-end-end: var(--md-filter-chip-container-shape-end-end, var(--md-filter-chip-container-shape, var(--md-sys-shape-corner-small, 8px)));--_container-shape-end-start: var(--md-filter-chip-container-shape-end-start, var(--md-filter-chip-container-shape, var(--md-sys-shape-corner-small, 8px)));--_leading-space: var(--md-filter-chip-leading-space, 16px);--_trailing-space: var(--md-filter-chip-trailing-space, 16px);--_icon-label-space: var(--md-filter-chip-icon-label-space, 8px);--_with-leading-icon-leading-space: var(--md-filter-chip-with-leading-icon-leading-space, 8px);--_with-trailing-icon-trailing-space: var(--md-filter-chip-with-trailing-icon-trailing-space, 8px)}.selected.elevated::before{background:var(--_elevated-selected-container-color)}.checkmark{height:var(--_icon-size);width:var(--_icon-size)}.disabled .checkmark{opacity:var(--_disabled-leading-icon-opacity)}@media(forced-colors: active){.disabled .checkmark{opacity:1}} +`; + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * TODO(b/243982145): add docs + * + * @final + * @suppress {visibility} + */ +let MdFilterChip = class MdFilterChip extends FilterChip { +}; +MdFilterChip.styles = [ + styles$4, + styles$5, + styles$6, + styles$7, + styles$2, +]; +MdFilterChip = __decorate([ + e('md-filter-chip') +], MdFilterChip); + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * An input chip component. + * + * @fires remove {Event} Dispatched when the remove button is clicked. + */ +class InputChip extends MultiActionChip { + constructor() { + super(...arguments); + this.avatar = false; + this.href = ''; + this.target = ''; + this.removeOnly = false; + this.selected = false; + } + get primaryId() { + if (this.href) { + return 'link'; + } + if (this.removeOnly) { + return ''; + } + return 'button'; + } + get rippleDisabled() { + // Link chips cannot be disabled + return !this.href && (this.disabled || this.softDisabled); + } + get primaryAction() { + // Don't use @query() since a remove-only input chip still has a span that + // has "primary action" classes. + if (this.removeOnly) { + return null; + } + return this.renderRoot.querySelector('.primary.action'); + } + getContainerClasses() { + return { + ...super.getContainerClasses(), + avatar: this.avatar, + // Link chips cannot be disabled + disabled: !this.href && (this.disabled || this.softDisabled), + link: !!this.href, + selected: this.selected, + 'has-trailing': true, + }; + } + renderPrimaryAction(content) { + const { ariaLabel } = this; + if (this.href) { + return x ` + ${content} + `; + } + if (this.removeOnly) { + return x ` + + ${content} + + `; + } + return x ` + + `; + } + renderTrailingAction(focusListener) { + return renderRemoveButton({ + focusListener, + ariaLabel: this.ariaLabelRemove, + disabled: !this.href && (this.disabled || this.softDisabled), + tabbable: this.removeOnly, + }); + } +} +__decorate([ + n({ type: Boolean }) +], InputChip.prototype, "avatar", void 0); +__decorate([ + n() +], InputChip.prototype, "href", void 0); +__decorate([ + n() +], InputChip.prototype, "target", void 0); +__decorate([ + n({ type: Boolean, attribute: 'remove-only' }) +], InputChip.prototype, "removeOnly", void 0); +__decorate([ + n({ type: Boolean, reflect: true }) +], InputChip.prototype, "selected", void 0); +__decorate([ + i$1('.trailing.action') +], InputChip.prototype, "trailingAction", void 0); + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./chips/internal/input-styles.css. +const styles$1 = i `:host{--_container-height: var(--md-input-chip-container-height, 32px);--_disabled-label-text-color: var(--md-input-chip-disabled-label-text-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-label-text-opacity: var(--md-input-chip-disabled-label-text-opacity, 0.38);--_disabled-selected-container-color: var(--md-input-chip-disabled-selected-container-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-selected-container-opacity: var(--md-input-chip-disabled-selected-container-opacity, 0.12);--_label-text-font: var(--md-input-chip-label-text-font, var(--md-sys-typescale-label-large-font, var(--md-ref-typeface-plain, Roboto)));--_label-text-line-height: var(--md-input-chip-label-text-line-height, var(--md-sys-typescale-label-large-line-height, 1.25rem));--_label-text-size: var(--md-input-chip-label-text-size, var(--md-sys-typescale-label-large-size, 0.875rem));--_label-text-weight: var(--md-input-chip-label-text-weight, var(--md-sys-typescale-label-large-weight, var(--md-ref-typeface-weight-medium, 500)));--_selected-container-color: var(--md-input-chip-selected-container-color, var(--md-sys-color-secondary-container, #e8def8));--_selected-focus-label-text-color: var(--md-input-chip-selected-focus-label-text-color, var(--md-sys-color-on-secondary-container, #1d192b));--_selected-hover-label-text-color: var(--md-input-chip-selected-hover-label-text-color, var(--md-sys-color-on-secondary-container, #1d192b));--_selected-hover-state-layer-color: var(--md-input-chip-selected-hover-state-layer-color, var(--md-sys-color-on-secondary-container, #1d192b));--_selected-hover-state-layer-opacity: var(--md-input-chip-selected-hover-state-layer-opacity, 0.08);--_selected-label-text-color: var(--md-input-chip-selected-label-text-color, var(--md-sys-color-on-secondary-container, #1d192b));--_selected-outline-width: var(--md-input-chip-selected-outline-width, 0px);--_selected-pressed-label-text-color: var(--md-input-chip-selected-pressed-label-text-color, var(--md-sys-color-on-secondary-container, #1d192b));--_selected-pressed-state-layer-color: var(--md-input-chip-selected-pressed-state-layer-color, var(--md-sys-color-on-secondary-container, #1d192b));--_selected-pressed-state-layer-opacity: var(--md-input-chip-selected-pressed-state-layer-opacity, 0.12);--_disabled-outline-color: var(--md-input-chip-disabled-outline-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-outline-opacity: var(--md-input-chip-disabled-outline-opacity, 0.12);--_focus-label-text-color: var(--md-input-chip-focus-label-text-color, var(--md-sys-color-on-surface-variant, #49454f));--_focus-outline-color: var(--md-input-chip-focus-outline-color, var(--md-sys-color-on-surface-variant, #49454f));--_hover-label-text-color: var(--md-input-chip-hover-label-text-color, var(--md-sys-color-on-surface-variant, #49454f));--_hover-state-layer-color: var(--md-input-chip-hover-state-layer-color, var(--md-sys-color-on-surface-variant, #49454f));--_hover-state-layer-opacity: var(--md-input-chip-hover-state-layer-opacity, 0.08);--_label-text-color: var(--md-input-chip-label-text-color, var(--md-sys-color-on-surface-variant, #49454f));--_outline-color: var(--md-input-chip-outline-color, var(--md-sys-color-outline, #79747e));--_outline-width: var(--md-input-chip-outline-width, 1px);--_pressed-label-text-color: var(--md-input-chip-pressed-label-text-color, var(--md-sys-color-on-surface-variant, #49454f));--_pressed-state-layer-color: var(--md-input-chip-pressed-state-layer-color, var(--md-sys-color-on-surface-variant, #49454f));--_pressed-state-layer-opacity: var(--md-input-chip-pressed-state-layer-opacity, 0.12);--_avatar-shape: var(--md-input-chip-avatar-shape, var(--md-sys-shape-corner-full, 9999px));--_avatar-size: var(--md-input-chip-avatar-size, 24px);--_disabled-avatar-opacity: var(--md-input-chip-disabled-avatar-opacity, 0.38);--_disabled-leading-icon-color: var(--md-input-chip-disabled-leading-icon-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-leading-icon-opacity: var(--md-input-chip-disabled-leading-icon-opacity, 0.38);--_icon-size: var(--md-input-chip-icon-size, 18px);--_selected-focus-leading-icon-color: var(--md-input-chip-selected-focus-leading-icon-color, var(--md-sys-color-primary, #6750a4));--_selected-hover-leading-icon-color: var(--md-input-chip-selected-hover-leading-icon-color, var(--md-sys-color-primary, #6750a4));--_selected-leading-icon-color: var(--md-input-chip-selected-leading-icon-color, var(--md-sys-color-primary, #6750a4));--_selected-pressed-leading-icon-color: var(--md-input-chip-selected-pressed-leading-icon-color, var(--md-sys-color-primary, #6750a4));--_focus-leading-icon-color: var(--md-input-chip-focus-leading-icon-color, var(--md-sys-color-primary, #6750a4));--_hover-leading-icon-color: var(--md-input-chip-hover-leading-icon-color, var(--md-sys-color-primary, #6750a4));--_leading-icon-color: var(--md-input-chip-leading-icon-color, var(--md-sys-color-primary, #6750a4));--_pressed-leading-icon-color: var(--md-input-chip-pressed-leading-icon-color, var(--md-sys-color-primary, #6750a4));--_disabled-trailing-icon-color: var(--md-input-chip-disabled-trailing-icon-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-trailing-icon-opacity: var(--md-input-chip-disabled-trailing-icon-opacity, 0.38);--_selected-focus-trailing-icon-color: var(--md-input-chip-selected-focus-trailing-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_selected-hover-trailing-icon-color: var(--md-input-chip-selected-hover-trailing-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_selected-pressed-trailing-icon-color: var(--md-input-chip-selected-pressed-trailing-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_selected-trailing-icon-color: var(--md-input-chip-selected-trailing-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_focus-trailing-icon-color: var(--md-input-chip-focus-trailing-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_hover-trailing-icon-color: var(--md-input-chip-hover-trailing-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_pressed-trailing-icon-color: var(--md-input-chip-pressed-trailing-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_trailing-icon-color: var(--md-input-chip-trailing-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_container-shape-start-start: var(--md-input-chip-container-shape-start-start, var(--md-input-chip-container-shape, var(--md-sys-shape-corner-small, 8px)));--_container-shape-start-end: var(--md-input-chip-container-shape-start-end, var(--md-input-chip-container-shape, var(--md-sys-shape-corner-small, 8px)));--_container-shape-end-end: var(--md-input-chip-container-shape-end-end, var(--md-input-chip-container-shape, var(--md-sys-shape-corner-small, 8px)));--_container-shape-end-start: var(--md-input-chip-container-shape-end-start, var(--md-input-chip-container-shape, var(--md-sys-shape-corner-small, 8px)));--_leading-space: var(--md-input-chip-leading-space, 16px);--_trailing-space: var(--md-input-chip-trailing-space, 16px);--_icon-label-space: var(--md-input-chip-icon-label-space, 8px);--_with-leading-icon-leading-space: var(--md-input-chip-with-leading-icon-leading-space, 8px);--_with-trailing-icon-trailing-space: var(--md-input-chip-with-trailing-icon-trailing-space, 8px)}:host([avatar]){--_container-shape-start-start: var( --md-input-chip-container-shape-start-start, var(--md-input-chip-container-shape, calc(var(--_container-height) / 2)) );--_container-shape-start-end: var( --md-input-chip-container-shape-start-end, var(--md-input-chip-container-shape, calc(var(--_container-height) / 2)) );--_container-shape-end-end: var( --md-input-chip-container-shape-end-end, var(--md-input-chip-container-shape, calc(var(--_container-height) / 2)) );--_container-shape-end-start: var( --md-input-chip-container-shape-end-start, var(--md-input-chip-container-shape, calc(var(--_container-height) / 2)) )}.avatar .primary.action{padding-inline-start:4px}.avatar .leading.icon ::slotted(:first-child){border-radius:var(--_avatar-shape);height:var(--_avatar-size);width:var(--_avatar-size)}.disabled.avatar .leading.icon{opacity:var(--_disabled-avatar-opacity)}@media(forced-colors: active){.link .outline{border-color:ActiveText}.disabled.avatar .leading.icon{opacity:1}} +`; + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * TODO(b/243982145): add docs + * + * @final + * @suppress {visibility} + */ +let MdInputChip = class MdInputChip extends InputChip { +}; +MdInputChip.styles = [ + styles$4, + styles$6, + styles$7, + styles$1, +]; +MdInputChip = __decorate([ + e('md-input-chip') +], MdInputChip); + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A suggestion chip component. + */ +class SuggestionChip extends AssistChip { +} +// Note: assist and suggestion chips are functionally identical with different +// tokens. + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./chips/internal/suggestion-styles.css. +const styles = i `:host{--_container-height: var(--md-suggestion-chip-container-height, 32px);--_disabled-label-text-color: var(--md-suggestion-chip-disabled-label-text-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-label-text-opacity: var(--md-suggestion-chip-disabled-label-text-opacity, 0.38);--_elevated-container-color: var(--md-suggestion-chip-elevated-container-color, var(--md-sys-color-surface-container-low, #f7f2fa));--_elevated-container-elevation: var(--md-suggestion-chip-elevated-container-elevation, 1);--_elevated-container-shadow-color: var(--md-suggestion-chip-elevated-container-shadow-color, var(--md-sys-color-shadow, #000));--_elevated-disabled-container-color: var(--md-suggestion-chip-elevated-disabled-container-color, var(--md-sys-color-on-surface, #1d1b20));--_elevated-disabled-container-elevation: var(--md-suggestion-chip-elevated-disabled-container-elevation, 0);--_elevated-disabled-container-opacity: var(--md-suggestion-chip-elevated-disabled-container-opacity, 0.12);--_elevated-focus-container-elevation: var(--md-suggestion-chip-elevated-focus-container-elevation, 1);--_elevated-hover-container-elevation: var(--md-suggestion-chip-elevated-hover-container-elevation, 2);--_elevated-pressed-container-elevation: var(--md-suggestion-chip-elevated-pressed-container-elevation, 1);--_focus-label-text-color: var(--md-suggestion-chip-focus-label-text-color, var(--md-sys-color-on-surface-variant, #49454f));--_hover-label-text-color: var(--md-suggestion-chip-hover-label-text-color, var(--md-sys-color-on-surface-variant, #49454f));--_hover-state-layer-color: var(--md-suggestion-chip-hover-state-layer-color, var(--md-sys-color-on-surface-variant, #49454f));--_hover-state-layer-opacity: var(--md-suggestion-chip-hover-state-layer-opacity, 0.08);--_label-text-color: var(--md-suggestion-chip-label-text-color, var(--md-sys-color-on-surface-variant, #49454f));--_label-text-font: var(--md-suggestion-chip-label-text-font, var(--md-sys-typescale-label-large-font, var(--md-ref-typeface-plain, Roboto)));--_label-text-line-height: var(--md-suggestion-chip-label-text-line-height, var(--md-sys-typescale-label-large-line-height, 1.25rem));--_label-text-size: var(--md-suggestion-chip-label-text-size, var(--md-sys-typescale-label-large-size, 0.875rem));--_label-text-weight: var(--md-suggestion-chip-label-text-weight, var(--md-sys-typescale-label-large-weight, var(--md-ref-typeface-weight-medium, 500)));--_pressed-label-text-color: var(--md-suggestion-chip-pressed-label-text-color, var(--md-sys-color-on-surface-variant, #49454f));--_pressed-state-layer-color: var(--md-suggestion-chip-pressed-state-layer-color, var(--md-sys-color-on-surface-variant, #49454f));--_pressed-state-layer-opacity: var(--md-suggestion-chip-pressed-state-layer-opacity, 0.12);--_disabled-outline-color: var(--md-suggestion-chip-disabled-outline-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-outline-opacity: var(--md-suggestion-chip-disabled-outline-opacity, 0.12);--_focus-outline-color: var(--md-suggestion-chip-focus-outline-color, var(--md-sys-color-on-surface-variant, #49454f));--_outline-color: var(--md-suggestion-chip-outline-color, var(--md-sys-color-outline, #79747e));--_outline-width: var(--md-suggestion-chip-outline-width, 1px);--_disabled-leading-icon-color: var(--md-suggestion-chip-disabled-leading-icon-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-leading-icon-opacity: var(--md-suggestion-chip-disabled-leading-icon-opacity, 0.38);--_focus-leading-icon-color: var(--md-suggestion-chip-focus-leading-icon-color, var(--md-sys-color-primary, #6750a4));--_hover-leading-icon-color: var(--md-suggestion-chip-hover-leading-icon-color, var(--md-sys-color-primary, #6750a4));--_leading-icon-color: var(--md-suggestion-chip-leading-icon-color, var(--md-sys-color-primary, #6750a4));--_pressed-leading-icon-color: var(--md-suggestion-chip-pressed-leading-icon-color, var(--md-sys-color-primary, #6750a4));--_icon-size: var(--md-suggestion-chip-icon-size, 18px);--_container-shape-start-start: var(--md-suggestion-chip-container-shape-start-start, var(--md-suggestion-chip-container-shape, var(--md-sys-shape-corner-small, 8px)));--_container-shape-start-end: var(--md-suggestion-chip-container-shape-start-end, var(--md-suggestion-chip-container-shape, var(--md-sys-shape-corner-small, 8px)));--_container-shape-end-end: var(--md-suggestion-chip-container-shape-end-end, var(--md-suggestion-chip-container-shape, var(--md-sys-shape-corner-small, 8px)));--_container-shape-end-start: var(--md-suggestion-chip-container-shape-end-start, var(--md-suggestion-chip-container-shape, var(--md-sys-shape-corner-small, 8px)));--_leading-space: var(--md-suggestion-chip-leading-space, 16px);--_trailing-space: var(--md-suggestion-chip-trailing-space, 16px);--_icon-label-space: var(--md-suggestion-chip-icon-label-space, 8px);--_with-leading-icon-leading-space: var(--md-suggestion-chip-with-leading-icon-leading-space, 8px)}@media(forced-colors: active){.link .outline{border-color:ActiveText}} +`; + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * TODO(b/243982145): add docs + * + * @final + * @suppress {visibility} + */ +let MdSuggestionChip = class MdSuggestionChip extends SuggestionChip { +}; +MdSuggestionChip.styles = [styles$4, styles$5, styles]; +MdSuggestionChip = __decorate([ + e('md-suggestion-chip') +], MdSuggestionChip); diff --git a/md-web/chips.js b/md-web/chips.js new file mode 100644 index 0000000..e8a122a --- /dev/null +++ b/md-web/chips.js @@ -0,0 +1,155 @@ +export const __dummy_loader = () => {}; + +import '@material/web/chips/chip.js'; +import { _ as __decorate, l, s, C as Chip, x, i, e } from './core.js'; + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A chip set component. + */ +class ChipSet extends s { + get chips() { + return this.childElements.filter((child) => child instanceof Chip); + } + constructor() { + super(); + this.internals = + // Cast needed for closure + this.attachInternals(); + { + this.addEventListener('focusin', this.updateTabIndices.bind(this)); + this.addEventListener('update-focus', this.updateTabIndices.bind(this)); + this.addEventListener('keydown', this.handleKeyDown.bind(this)); + this.internals.role = 'toolbar'; + } + } + render() { + return x ``; + } + handleKeyDown(event) { + const isLeft = event.key === 'ArrowLeft'; + const isRight = event.key === 'ArrowRight'; + const isHome = event.key === 'Home'; + const isEnd = event.key === 'End'; + // Ignore non-navigation keys + if (!isLeft && !isRight && !isHome && !isEnd) { + return; + } + const { chips } = this; + // Don't try to select another chip if there aren't any. + if (chips.length < 2) { + return; + } + // Prevent default interactions, such as scrolling. + event.preventDefault(); + if (isHome || isEnd) { + const index = isHome ? 0 : chips.length - 1; + chips[index].focus({ trailing: isEnd }); + this.updateTabIndices(); + return; + } + // Check if moving forwards or backwards + const isRtl = getComputedStyle(this).direction === 'rtl'; + const forwards = isRtl ? isLeft : isRight; + const focusedChip = chips.find((chip) => chip.matches(':focus-within')); + if (!focusedChip) { + // If there is not already a chip focused, select the first or last chip + // based on the direction we're traveling. + const nextChip = forwards ? chips[0] : chips[chips.length - 1]; + nextChip.focus({ trailing: !forwards }); + this.updateTabIndices(); + return; + } + const currentIndex = chips.indexOf(focusedChip); + let nextIndex = forwards ? currentIndex + 1 : currentIndex - 1; + // Search for the next sibling that is not disabled to select. + // If we return to the host index, there is nothing to select. + while (nextIndex !== currentIndex) { + if (nextIndex >= chips.length) { + // Return to start if moving past the last item. + nextIndex = 0; + } + else if (nextIndex < 0) { + // Go to end if moving before the first item. + nextIndex = chips.length - 1; + } + // Check if the next sibling is disabled. If so, + // move the index and continue searching. + // + // Some toolbar items may be focusable when disabled for increased + // visibility. + const nextChip = chips[nextIndex]; + if (nextChip.disabled && !nextChip.alwaysFocusable) { + if (forwards) { + nextIndex++; + } + else { + nextIndex--; + } + continue; + } + nextChip.focus({ trailing: !forwards }); + this.updateTabIndices(); + break; + } + } + updateTabIndices() { + // The chip that should be focusable is either the chip that currently has + // focus or the first chip that can be focused. + const { chips } = this; + let chipToFocus; + for (const chip of chips) { + const isChipFocusable = chip.alwaysFocusable || !chip.disabled; + const chipIsFocused = chip.matches(':focus-within'); + if (chipIsFocused && isChipFocusable) { + // Found the first chip that is actively focused. This overrides the + // first focusable chip found. + chipToFocus = chip; + continue; + } + if (isChipFocusable && !chipToFocus) { + chipToFocus = chip; + } + // Disable non-focused chips. If we disable all of them, we'll grant focus + // to the first focusable child that was found. + chip.tabIndex = -1; + } + if (chipToFocus) { + chipToFocus.tabIndex = 0; + } + } +} +__decorate([ + l() +], ChipSet.prototype, "childElements", void 0); + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./chips/internal/chip-set-styles.css. +const styles = i `:host{display:flex;flex-wrap:wrap;gap:8px} +`; + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * TODO(b/243982145): add docs + * + * @final + * @suppress {visibility} + */ +let MdChipSet = class MdChipSet extends ChipSet { +}; +MdChipSet.styles = [styles]; +MdChipSet = __decorate([ + e('md-chip-set') +], MdChipSet); diff --git a/md-web/circular-progress.js b/md-web/circular-progress.js new file mode 100644 index 0000000..a4fb20f --- /dev/null +++ b/md-web/circular-progress.js @@ -0,0 +1,87 @@ +export const __dummy_loader = () => {}; + +import { P as Progress, x, i, _ as __decorate, e } from './core.js'; + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A circular progress component. + */ +class CircularProgress extends Progress { + renderIndicator() { + if (this.indeterminate) { + return this.renderIndeterminateContainer(); + } + return this.renderDeterminateContainer(); + } + // Determinate mode is rendered with an svg so the progress arc can be + // easily animated via stroke-dashoffset. + renderDeterminateContainer() { + const dashOffset = (1 - this.value / this.max) * 100; + // note, dash-array/offset are relative to Setting `pathLength` but + // Chrome seems to render this inaccurately and using a large viewbox helps. + return x ` + + + + + `; + } + // Indeterminate mode rendered with 2 bordered-divs. The borders are + // clipped into half circles by their containers. The divs are then carefully + // animated to produce changes to the spinner arc size. + // This approach has 4.5x the FPS of rendering via svg on Chrome 111. + // See https://lit.dev/playground/#gist=febb773565272f75408ab06a0eb49746. + renderIndeterminateContainer() { + return x `
+
+
+
+
+
+
+
`; + } +} + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./progress/internal/circular-progress-styles.css. +const styles = i `:host{--_active-indicator-color: var(--md-circular-progress-active-indicator-color, var(--md-sys-color-primary, #6750a4));--_active-indicator-width: var(--md-circular-progress-active-indicator-width, 10);--_four-color-active-indicator-four-color: var(--md-circular-progress-four-color-active-indicator-four-color, var(--md-sys-color-tertiary-container, #ffd8e4));--_four-color-active-indicator-one-color: var(--md-circular-progress-four-color-active-indicator-one-color, var(--md-sys-color-primary, #6750a4));--_four-color-active-indicator-three-color: var(--md-circular-progress-four-color-active-indicator-three-color, var(--md-sys-color-tertiary, #7d5260));--_four-color-active-indicator-two-color: var(--md-circular-progress-four-color-active-indicator-two-color, var(--md-sys-color-primary-container, #eaddff));--_size: var(--md-circular-progress-size, 48px);display:inline-flex;vertical-align:middle;width:var(--_size);height:var(--_size);position:relative;align-items:center;justify-content:center;contain:strict;content-visibility:auto}.progress{flex:1;align-self:stretch;margin:4px}.progress,.spinner,.left,.right,.circle,svg,.track,.active-track{position:absolute;inset:0}svg{transform:rotate(-90deg)}circle{cx:50%;cy:50%;r:calc(50%*(1 - var(--_active-indicator-width)/100));stroke-width:calc(var(--_active-indicator-width)*1%);stroke-dasharray:100;fill:rgba(0,0,0,0)}.active-track{transition:stroke-dashoffset 500ms cubic-bezier(0, 0, 0.2, 1);stroke:var(--_active-indicator-color)}.track{stroke:rgba(0,0,0,0)}.progress.indeterminate{animation:linear infinite linear-rotate;animation-duration:1568.2352941176ms}.spinner{animation:infinite both rotate-arc;animation-duration:5332ms;animation-timing-function:cubic-bezier(0.4, 0, 0.2, 1)}.left{overflow:hidden;inset:0 50% 0 0}.right{overflow:hidden;inset:0 0 0 50%}.circle{box-sizing:border-box;border-radius:50%;border:solid calc(var(--_active-indicator-width)/100*(var(--_size) - 8px));border-color:var(--_active-indicator-color) var(--_active-indicator-color) rgba(0,0,0,0) rgba(0,0,0,0);animation:expand-arc;animation-iteration-count:infinite;animation-fill-mode:both;animation-duration:1333ms,5332ms;animation-timing-function:cubic-bezier(0.4, 0, 0.2, 1)}.four-color .circle{animation-name:expand-arc,four-color}.left .circle{rotate:135deg;inset:0 -100% 0 0}.right .circle{rotate:100deg;inset:0 0 0 -100%;animation-delay:-666.5ms,0ms}@media(forced-colors: active){.active-track{stroke:CanvasText}.circle{border-color:CanvasText CanvasText Canvas Canvas}}@keyframes expand-arc{0%{transform:rotate(265deg)}50%{transform:rotate(130deg)}100%{transform:rotate(265deg)}}@keyframes rotate-arc{12.5%{transform:rotate(135deg)}25%{transform:rotate(270deg)}37.5%{transform:rotate(405deg)}50%{transform:rotate(540deg)}62.5%{transform:rotate(675deg)}75%{transform:rotate(810deg)}87.5%{transform:rotate(945deg)}100%{transform:rotate(1080deg)}}@keyframes linear-rotate{to{transform:rotate(360deg)}}@keyframes four-color{0%{border-top-color:var(--_four-color-active-indicator-one-color);border-right-color:var(--_four-color-active-indicator-one-color)}15%{border-top-color:var(--_four-color-active-indicator-one-color);border-right-color:var(--_four-color-active-indicator-one-color)}25%{border-top-color:var(--_four-color-active-indicator-two-color);border-right-color:var(--_four-color-active-indicator-two-color)}40%{border-top-color:var(--_four-color-active-indicator-two-color);border-right-color:var(--_four-color-active-indicator-two-color)}50%{border-top-color:var(--_four-color-active-indicator-three-color);border-right-color:var(--_four-color-active-indicator-three-color)}65%{border-top-color:var(--_four-color-active-indicator-three-color);border-right-color:var(--_four-color-active-indicator-three-color)}75%{border-top-color:var(--_four-color-active-indicator-four-color);border-right-color:var(--_four-color-active-indicator-four-color)}90%{border-top-color:var(--_four-color-active-indicator-four-color);border-right-color:var(--_four-color-active-indicator-four-color)}100%{border-top-color:var(--_four-color-active-indicator-one-color);border-right-color:var(--_four-color-active-indicator-one-color)}} +`; + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @summary Circular progress indicators display progress by animating along an + * invisible circular track in a clockwise direction. They can be applied + * directly to a surface, such as a button or card. + * + * @description + * Progress indicators inform users about the status of ongoing processes. + * - Determinate indicators display how long a process will take. + * - Indeterminate indicators express an unspecified amount of wait time. + * + * @final + * @suppress {visibility} + */ +let MdCircularProgress = class MdCircularProgress extends CircularProgress { +}; +MdCircularProgress.styles = [styles]; +MdCircularProgress = __decorate([ + e('md-circular-progress') +], MdCircularProgress); + +export { MdCircularProgress }; diff --git a/md-web/core.js b/md-web/core.js new file mode 100644 index 0000000..d277d6b --- /dev/null +++ b/md-web/core.js @@ -0,0 +1,7865 @@ +export const __dummy_loader = () => {}; + +/****************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ +/* global Reflect, Promise, SuppressedError, Symbol */ + + +function __decorate(decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +} + +typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { + var e = new Error(message); + return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; +}; + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +const e$a=e=>n=>"function"==typeof n?((e,n)=>(customElements.define(e,n),n))(e,n):((e,n)=>{const{kind:t,elements:s}=n;return {kind:t,elements:s,finisher(n){customElements.define(e,n);}}})(e,n); + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +const i$6=(i,e)=>"method"===e.kind&&e.descriptor&&!("value"in e.descriptor)?{...e,finisher(n){n.createProperty(e.key,i);}}:{kind:"field",key:Symbol(),placement:"own",descriptor:{},originalKey:e.key,initializer(){"function"==typeof e.initializer&&(this[e.key]=e.initializer.call(this));},finisher(n){n.createProperty(e.key,i);}},e$9=(i,e,n)=>{e.constructor.createProperty(n,i);};function n$7(n){return (t,o)=>void 0!==o?e$9(n,t,o):i$6(n,t)} + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */function t$3(t){return n$7({...t,state:!0})} + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +const o$8=({finisher:e,descriptor:t})=>(o,n)=>{var r;if(void 0===n){const n=null!==(r=o.originalKey)&&void 0!==r?r:o.key,i=null!=t?{kind:"method",placement:"prototype",key:n,descriptor:t(o.key)}:{...o,key:n};return null!=e&&(i.finisher=function(t){e(t,n);}),i}{const r=o.constructor;void 0!==t&&Object.defineProperty(o,n,t(n)),null==e||e(r,n);}}; + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */function i$5(i,n){return o$8({descriptor:o=>{const t={get(){var o,n;return null!==(n=null===(o=this.renderRoot)||void 0===o?void 0:o.querySelector(i))&&void 0!==n?n:null},enumerable:!0,configurable:!0};if(n){const n="symbol"==typeof o?Symbol():"__"+o;t.get=function(){var o,t;return void 0===this[n]&&(this[n]=null!==(t=null===(o=this.renderRoot)||void 0===o?void 0:o.querySelector(i))&&void 0!==t?t:null),this[n]};}return t}})} + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */function e$8(e){return o$8({descriptor:r=>({get(){var r,o;return null!==(o=null===(r=this.renderRoot)||void 0===r?void 0:r.querySelectorAll(e))&&void 0!==o?o:[]},enumerable:!0,configurable:!0})})} + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +function e$7(e){return o$8({descriptor:r=>({async get(){var r;return await this.updateComplete,null===(r=this.renderRoot)||void 0===r?void 0:r.querySelector(e)},enumerable:!0,configurable:!0})})} + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */var n$6;const e$6=null!=(null===(n$6=window.HTMLSlotElement)||void 0===n$6?void 0:n$6.prototype.assignedElements)?(o,n)=>o.assignedElements(n):(o,n)=>o.assignedNodes(n).filter((o=>o.nodeType===Node.ELEMENT_NODE));function l$5(n){const{slot:l,selector:t}=null!=n?n:{};return o$8({descriptor:o=>({get(){var o;const r="slot"+(l?`[name=${l}]`:":not([name])"),i=null===(o=this.renderRoot)||void 0===o?void 0:o.querySelector(r),s=null!=i?e$6(i,n):[];return t?s.filter((o=>o.matches(t))):s},enumerable:!0,configurable:!0})})} + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */function o$7(o,n,r){let l,s=o;return "object"==typeof o?(s=o.slot,l=o):l={flatten:n},r?l$5({slot:s,flatten:n,selector:r}):o$8({descriptor:e=>({get(){var e,t;const o="slot"+(s?`[name=${s}]`:":not([name])"),n=null===(e=this.renderRoot)||void 0===e?void 0:e.querySelector(o);return null!==(t=null==n?void 0:n.assignedNodes(l))&&void 0!==t?t:[]},enumerable:!0,configurable:!0})})} + +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +const t$2=window,e$5=t$2.ShadowRoot&&(void 0===t$2.ShadyCSS||t$2.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,s$5=Symbol(),n$5=new WeakMap;let o$6 = class o{constructor(t,e,n){if(this._$cssResult$=!0,n!==s$5)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e;}get styleSheet(){let t=this.o;const s=this.t;if(e$5&&void 0===t){const e=void 0!==s&&1===s.length;e&&(t=n$5.get(s)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),e&&n$5.set(s,t));}return t}toString(){return this.cssText}};const r$2=t=>new o$6("string"==typeof t?t:t+"",void 0,s$5),i$4=(t,...e)=>{const n=1===t.length?t[0]:e.reduce(((e,s,n)=>e+(t=>{if(!0===t._$cssResult$)return t.cssText;if("number"==typeof t)return t;throw Error("Value passed to 'css' function must be a 'css' function result: "+t+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(s)+t[n+1]),t[0]);return new o$6(n,t,s$5)},S$1=(s,n)=>{e$5?s.adoptedStyleSheets=n.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet)):n.forEach((e=>{const n=document.createElement("style"),o=t$2.litNonce;void 0!==o&&n.setAttribute("nonce",o),n.textContent=e.cssText,s.appendChild(n);}));},c$1=e$5?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const s of t.cssRules)e+=s.cssText;return r$2(e)})(t):t; + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */var s$4;const e$4=window,r$1=e$4.trustedTypes,h$1=r$1?r$1.emptyScript:"",o$5=e$4.reactiveElementPolyfillSupport,n$4={toAttribute(t,i){switch(i){case Boolean:t=t?h$1:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t);}return t},fromAttribute(t,i){let s=t;switch(i){case Boolean:s=null!==t;break;case Number:s=null===t?null:Number(t);break;case Object:case Array:try{s=JSON.parse(t);}catch(t){s=null;}}return s}},a$3=(t,i)=>i!==t&&(i==i||t==t),l$4={attribute:!0,type:String,converter:n$4,reflect:!1,hasChanged:a$3},d$1="finalized";let u$1 = class u extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu();}static addInitializer(t){var i;this.finalize(),(null!==(i=this.h)&&void 0!==i?i:this.h=[]).push(t);}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach(((i,s)=>{const e=this._$Ep(s,i);void 0!==e&&(this._$Ev.set(e,s),t.push(e));})),t}static createProperty(t,i=l$4){if(i.state&&(i.attribute=!1),this.finalize(),this.elementProperties.set(t,i),!i.noAccessor&&!this.prototype.hasOwnProperty(t)){const s="symbol"==typeof t?Symbol():"__"+t,e=this.getPropertyDescriptor(t,s,i);void 0!==e&&Object.defineProperty(this.prototype,t,e);}}static getPropertyDescriptor(t,i,s){return {get(){return this[i]},set(e){const r=this[t];this[i]=e,this.requestUpdate(t,r,s);},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||l$4}static finalize(){if(this.hasOwnProperty(d$1))return !1;this[d$1]=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),void 0!==t.h&&(this.h=[...t.h]),this.elementProperties=new Map(t.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const t=this.properties,i=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const s of i)this.createProperty(s,t[s]);}return this.elementStyles=this.finalizeStyles(this.styles),!0}static finalizeStyles(i){const s=[];if(Array.isArray(i)){const e=new Set(i.flat(1/0).reverse());for(const i of e)s.unshift(c$1(i));}else void 0!==i&&s.push(c$1(i));return s}static _$Ep(t,i){const s=i.attribute;return !1===s?void 0:"string"==typeof s?s:"string"==typeof t?t.toLowerCase():void 0}_$Eu(){var t;this._$E_=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(t=this.constructor.h)||void 0===t||t.forEach((t=>t(this)));}addController(t){var i,s;(null!==(i=this._$ES)&&void 0!==i?i:this._$ES=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(s=t.hostConnected)||void 0===s||s.call(t));}removeController(t){var i;null===(i=this._$ES)||void 0===i||i.splice(this._$ES.indexOf(t)>>>0,1);}_$Eg(){this.constructor.elementProperties.forEach(((t,i)=>{this.hasOwnProperty(i)&&(this._$Ei.set(i,this[i]),delete this[i]);}));}createRenderRoot(){var t;const s=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return S$1(s,this.constructor.elementStyles),s}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var i;return null===(i=t.hostConnected)||void 0===i?void 0:i.call(t)}));}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$ES)||void 0===t||t.forEach((t=>{var i;return null===(i=t.hostDisconnected)||void 0===i?void 0:i.call(t)}));}attributeChangedCallback(t,i,s){this._$AK(t,s);}_$EO(t,i,s=l$4){var e;const r=this.constructor._$Ep(t,s);if(void 0!==r&&!0===s.reflect){const h=(void 0!==(null===(e=s.converter)||void 0===e?void 0:e.toAttribute)?s.converter:n$4).toAttribute(i,s.type);this._$El=t,null==h?this.removeAttribute(r):this.setAttribute(r,h),this._$El=null;}}_$AK(t,i){var s;const e=this.constructor,r=e._$Ev.get(t);if(void 0!==r&&this._$El!==r){const t=e.getPropertyOptions(r),h="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==(null===(s=t.converter)||void 0===s?void 0:s.fromAttribute)?t.converter:n$4;this._$El=r,this[r]=h.fromAttribute(i,t.type),this._$El=null;}}requestUpdate(t,i,s){let e=!0;void 0!==t&&(((s=s||this.constructor.getPropertyOptions(t)).hasChanged||a$3)(this[t],i)?(this._$AL.has(t)||this._$AL.set(t,i),!0===s.reflect&&this._$El!==t&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(t,s))):e=!1),!this.isUpdatePending&&e&&(this._$E_=this._$Ej());}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_;}catch(t){Promise.reject(t);}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach(((t,i)=>this[i]=t)),this._$Ei=void 0);let i=!1;const s=this._$AL;try{i=this.shouldUpdate(s),i?(this.willUpdate(s),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var i;return null===(i=t.hostUpdate)||void 0===i?void 0:i.call(t)})),this.update(s)):this._$Ek();}catch(t){throw i=!1,this._$Ek(),t}i&&this._$AE(s);}willUpdate(t){}_$AE(t){var i;null===(i=this._$ES)||void 0===i||i.forEach((t=>{var i;return null===(i=t.hostUpdated)||void 0===i?void 0:i.call(t)})),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t);}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1;}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(t){return !0}update(t){void 0!==this._$EC&&(this._$EC.forEach(((t,i)=>this._$EO(i,this[i],t))),this._$EC=void 0),this._$Ek();}updated(t){}firstUpdated(t){}};u$1[d$1]=!0,u$1.elementProperties=new Map,u$1.elementStyles=[],u$1.shadowRootOptions={mode:"open"},null==o$5||o$5({ReactiveElement:u$1}),(null!==(s$4=e$4.reactiveElementVersions)&&void 0!==s$4?s$4:e$4.reactiveElementVersions=[]).push("1.6.3"); + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +var t$1;const i$3=window,s$3=i$3.trustedTypes,e$3=s$3?s$3.createPolicy("lit-html",{createHTML:t=>t}):void 0,o$4="$lit$",n$3=`lit$${(Math.random()+"").slice(9)}$`,l$3="?"+n$3,h=`<${l$3}>`,r=document,u=()=>r.createComment(""),d=t=>null===t||"object"!=typeof t&&"function"!=typeof t,c=Array.isArray,v=t=>c(t)||"function"==typeof(null==t?void 0:t[Symbol.iterator]),a$2="[ \t\n\f\r]",f=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,_=/-->/g,m=/>/g,p=RegExp(`>|${a$2}(?:([^\\s"'>=/]+)(${a$2}*=${a$2}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),g=/'/g,$=/"/g,y=/^(?:script|style|textarea|title)$/i,w=t=>(i,...s)=>({_$litType$:t,strings:i,values:s}),x=w(1),T=Symbol.for("lit-noChange"),A=Symbol.for("lit-nothing"),E=new WeakMap,C=r.createTreeWalker(r,129,null,!1);function P(t,i){if(!Array.isArray(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==e$3?e$3.createHTML(i):i}const V=(t,i)=>{const s=t.length-1,e=[];let l,r=2===i?"":"",u=f;for(let i=0;i"===c[0]?(u=null!=l?l:f,v=-1):void 0===c[1]?v=-2:(v=u.lastIndex-c[2].length,d=c[1],u=void 0===c[3]?p:'"'===c[3]?$:g):u===$||u===g?u=p:u===_||u===m?u=f:(u=p,l=void 0);const w=u===p&&t[i+1].startsWith("/>")?" ":"";r+=u===f?s+h:v>=0?(e.push(d),s.slice(0,v)+o$4+s.slice(v)+n$3+w):s+n$3+(-2===v?(e.push(void 0),i):w);}return [P(t,r+(t[s]||"")+(2===i?"":"")),e]};class N{constructor({strings:t,_$litType$:i},e){let h;this.parts=[];let r=0,d=0;const c=t.length-1,v=this.parts,[a,f]=V(t,i);if(this.el=N.createElement(a,e),C.currentNode=this.el.content,2===i){const t=this.el.content,i=t.firstChild;i.remove(),t.append(...i.childNodes);}for(;null!==(h=C.nextNode())&&v.length0){h.textContent=s$3?s$3.emptyScript:"";for(let s=0;s2||""!==s[0]||""!==s[1]?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=A;}get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}_$AI(t,i=this,s,e){const o=this.strings;let n=!1;if(void 0===o)t=S(this,t,i,0),n=!d(t)||t!==this._$AH&&t!==T,n&&(this._$AH=t);else {const e=t;let l,h;for(t=o[0],l=0;l{var e,o;const n=null!==(e=null==s?void 0:s.renderBefore)&&void 0!==e?e:i;let l=n._$litPart$;if(void 0===l){const t=null!==(o=null==s?void 0:s.renderBefore)&&void 0!==o?o:null;n._$litPart$=l=new R(i.insertBefore(u(),t),t,void 0,null!=s?s:{});}return l._$AI(t),l}; + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */var l$2,o$3;let s$2 = class s extends u$1{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0;}createRenderRoot(){var t,e;const i=super.createRenderRoot();return null!==(t=(e=this.renderOptions).renderBefore)&&void 0!==t||(e.renderBefore=i.firstChild),i}update(t){const i=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=D(i,this.renderRoot,this.renderOptions);}connectedCallback(){var t;super.connectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!0);}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!1);}render(){return T}};s$2.finalized=!0,s$2._$litElement$=!0,null===(l$2=globalThis.litElementHydrateSupport)||void 0===l$2||l$2.call(globalThis,{LitElement:s$2});const n$2=globalThis.litElementPolyfillSupport;null==n$2||n$2({LitElement:s$2});(null!==(o$3=globalThis.litElementVersions)&&void 0!==o$3?o$3:globalThis.litElementVersions=[]).push("3.3.3"); + +/** + * @license + * Copyright 2022 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +const o$2=!1; + +/** + * @license + * Copyright 2022 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A component for elevation. + */ +class Elevation extends s$2 { + connectedCallback() { + super.connectedCallback(); + // Needed for VoiceOver, which will create a "group" if the element is a + // sibling to other content. + this.setAttribute('aria-hidden', 'true'); + } + render() { + return x ``; + } +} + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./elevation/internal/elevation-styles.css. +const styles$j = i$4 `:host,.shadow,.shadow::before,.shadow::after{border-radius:inherit;inset:0;position:absolute;transition-duration:inherit;transition-property:inherit;transition-timing-function:inherit}:host{display:flex;pointer-events:none;transition-property:box-shadow,opacity}.shadow::before,.shadow::after{content:"";transition-property:box-shadow,opacity;--_level: var(--md-elevation-level, 0);--_shadow-color: var(--md-elevation-shadow-color, var(--md-sys-color-shadow, #000))}.shadow::before{box-shadow:0px calc(1px*(clamp(0,var(--_level),1) + clamp(0,var(--_level) - 3,1) + 2*clamp(0,var(--_level) - 4,1))) calc(1px*(2*clamp(0,var(--_level),1) + clamp(0,var(--_level) - 2,1) + clamp(0,var(--_level) - 4,1))) 0px var(--_shadow-color);opacity:.3}.shadow::after{box-shadow:0px calc(1px*(clamp(0,var(--_level),1) + clamp(0,var(--_level) - 1,1) + 2*clamp(0,var(--_level) - 2,3))) calc(1px*(3*clamp(0,var(--_level),2) + 2*clamp(0,var(--_level) - 2,3))) calc(1px*(clamp(0,var(--_level),4) + 2*clamp(0,var(--_level) - 4,1))) var(--_shadow-color);opacity:.15} +`; + +/** + * @license + * Copyright 2022 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * The `` custom element with default styles. + * + * Elevation is the relative distance between two surfaces along the z-axis. + * + * @final + * @suppress {visibility} + */ +let MdElevation = class MdElevation extends Elevation { +}; +MdElevation.styles = [styles$j]; +MdElevation = __decorate([ + e$a('md-elevation') +], MdElevation); + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A key to retrieve an `Attachable` element's `AttachableController` from a + * global `MutationObserver`. + */ +const ATTACHABLE_CONTROLLER = Symbol('attachableController'); +let FOR_ATTRIBUTE_OBSERVER; +{ + /** + * A global `MutationObserver` that reacts to `for` attribute changes on + * `Attachable` elements. If the `for` attribute changes, the controller will + * re-attach to the new referenced element. + */ + FOR_ATTRIBUTE_OBSERVER = new MutationObserver((records) => { + for (const record of records) { + // When a control's `for` attribute changes, inform its + // `AttachableController` to update to a new control. + record.target[ATTACHABLE_CONTROLLER]?.hostConnected(); + } + }); +} +/** + * A controller that provides an implementation for `Attachable` elements. + * + * @example + * ```ts + * class MyElement extends LitElement implements Attachable { + * get control() { return this.attachableController.control; } + * + * private readonly attachableController = new AttachableController( + * this, + * (previousControl, newControl) => { + * previousControl?.removeEventListener('click', this.handleClick); + * newControl?.addEventListener('click', this.handleClick); + * } + * ); + * + * // Implement remaining `Attachable` properties/methods that call the + * // controller's properties/methods. + * } + * ``` + */ +class AttachableController { + get htmlFor() { + return this.host.getAttribute('for'); + } + set htmlFor(htmlFor) { + if (htmlFor === null) { + this.host.removeAttribute('for'); + } + else { + this.host.setAttribute('for', htmlFor); + } + } + get control() { + if (this.host.hasAttribute('for')) { + if (!this.htmlFor || !this.host.isConnected) { + return null; + } + return this.host.getRootNode().querySelector(`#${this.htmlFor}`); + } + return this.currentControl || this.host.parentElement; + } + set control(control) { + if (control) { + this.attach(control); + } + else { + this.detach(); + } + } + /** + * Creates a new controller for an `Attachable` element. + * + * @param host The `Attachable` element. + * @param onControlChange A callback with two parameters for the previous and + * next control. An `Attachable` element may perform setup or teardown + * logic whenever the control changes. + */ + constructor(host, onControlChange) { + this.host = host; + this.onControlChange = onControlChange; + this.currentControl = null; + host.addController(this); + host[ATTACHABLE_CONTROLLER] = this; + FOR_ATTRIBUTE_OBSERVER?.observe(host, { attributeFilter: ['for'] }); + } + attach(control) { + if (control === this.currentControl) { + return; + } + this.setCurrentControl(control); + // When imperatively attaching, remove the `for` attribute so + // that the attached control is used instead of a referenced one. + this.host.removeAttribute('for'); + } + detach() { + this.setCurrentControl(null); + // When imperatively detaching, add an empty `for=""` attribute. This will + // ensure the control is `null` rather than the `parentElement`. + this.host.setAttribute('for', ''); + } + /** @private */ + hostConnected() { + this.setCurrentControl(this.control); + } + /** @private */ + hostDisconnected() { + this.setCurrentControl(null); + } + setCurrentControl(control) { + this.onControlChange(this.currentControl, control); + this.currentControl = control; + } +} + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Events that the focus ring listens to. + */ +const EVENTS$1 = ['focusin', 'focusout', 'pointerdown']; +/** + * A focus ring component. + * + * @fires visibility-changed {Event} Fired whenever `visible` changes. + */ +class FocusRing extends s$2 { + constructor() { + super(...arguments); + /** + * Makes the focus ring visible. + */ + this.visible = false; + /** + * Makes the focus ring animate inwards instead of outwards. + */ + this.inward = false; + this.attachableController = new AttachableController(this, this.onControlChange.bind(this)); + } + get htmlFor() { + return this.attachableController.htmlFor; + } + set htmlFor(htmlFor) { + this.attachableController.htmlFor = htmlFor; + } + get control() { + return this.attachableController.control; + } + set control(control) { + this.attachableController.control = control; + } + attach(control) { + this.attachableController.attach(control); + } + detach() { + this.attachableController.detach(); + } + connectedCallback() { + super.connectedCallback(); + // Needed for VoiceOver, which will create a "group" if the element is a + // sibling to other content. + this.setAttribute('aria-hidden', 'true'); + } + /** @private */ + handleEvent(event) { + if (event[HANDLED_BY_FOCUS_RING]) { + // This ensures the focus ring does not activate when multiple focus rings + // are used within a single component. + return; + } + switch (event.type) { + default: + return; + case 'focusin': + this.visible = this.control?.matches(':focus-visible') ?? false; + break; + case 'focusout': + case 'pointerdown': + this.visible = false; + break; + } + event[HANDLED_BY_FOCUS_RING] = true; + } + onControlChange(prev, next) { + for (const event of EVENTS$1) { + prev?.removeEventListener(event, this); + next?.addEventListener(event, this); + } + } + update(changed) { + if (changed.has('visible')) { + // This logic can be removed once the `:has` selector has been introduced + // to Firefox. This is necessary to allow correct submenu styles. + this.dispatchEvent(new Event('visibility-changed')); + } + super.update(changed); + } +} +__decorate([ + n$7({ type: Boolean, reflect: true }) +], FocusRing.prototype, "visible", void 0); +__decorate([ + n$7({ type: Boolean, reflect: true }) +], FocusRing.prototype, "inward", void 0); +const HANDLED_BY_FOCUS_RING = Symbol('handledByFocusRing'); + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./focus/internal/focus-ring-styles.css. +const styles$i = i$4 `:host{animation-delay:0s,calc(var(--md-focus-ring-duration, 600ms)*.25);animation-duration:calc(var(--md-focus-ring-duration, 600ms)*.25),calc(var(--md-focus-ring-duration, 600ms)*.75);animation-timing-function:cubic-bezier(0.2, 0, 0, 1);box-sizing:border-box;color:var(--md-focus-ring-color, var(--md-sys-color-secondary, #625b71));display:none;pointer-events:none;position:absolute}:host([visible]){display:flex}:host(:not([inward])){animation-name:outward-grow,outward-shrink;border-end-end-radius:calc(var(--md-focus-ring-shape-end-end, var(--md-focus-ring-shape, var(--md-sys-shape-corner-full, 9999px))) + var(--md-focus-ring-outward-offset, 2px));border-end-start-radius:calc(var(--md-focus-ring-shape-end-start, var(--md-focus-ring-shape, var(--md-sys-shape-corner-full, 9999px))) + var(--md-focus-ring-outward-offset, 2px));border-start-end-radius:calc(var(--md-focus-ring-shape-start-end, var(--md-focus-ring-shape, var(--md-sys-shape-corner-full, 9999px))) + var(--md-focus-ring-outward-offset, 2px));border-start-start-radius:calc(var(--md-focus-ring-shape-start-start, var(--md-focus-ring-shape, var(--md-sys-shape-corner-full, 9999px))) + var(--md-focus-ring-outward-offset, 2px));inset:calc(-1*var(--md-focus-ring-outward-offset, 2px));outline:var(--md-focus-ring-width, 3px) solid currentColor}:host([inward]){animation-name:inward-grow,inward-shrink;border-end-end-radius:calc(var(--md-focus-ring-shape-end-end, var(--md-focus-ring-shape, var(--md-sys-shape-corner-full, 9999px))) - var(--md-focus-ring-inward-offset, 0px));border-end-start-radius:calc(var(--md-focus-ring-shape-end-start, var(--md-focus-ring-shape, var(--md-sys-shape-corner-full, 9999px))) - var(--md-focus-ring-inward-offset, 0px));border-start-end-radius:calc(var(--md-focus-ring-shape-start-end, var(--md-focus-ring-shape, var(--md-sys-shape-corner-full, 9999px))) - var(--md-focus-ring-inward-offset, 0px));border-start-start-radius:calc(var(--md-focus-ring-shape-start-start, var(--md-focus-ring-shape, var(--md-sys-shape-corner-full, 9999px))) - var(--md-focus-ring-inward-offset, 0px));border:var(--md-focus-ring-width, 3px) solid currentColor;inset:var(--md-focus-ring-inward-offset, 0px)}@keyframes outward-grow{from{outline-width:0}to{outline-width:var(--md-focus-ring-active-width, 8px)}}@keyframes outward-shrink{from{outline-width:var(--md-focus-ring-active-width, 8px)}}@keyframes inward-grow{from{border-width:0}to{border-width:var(--md-focus-ring-active-width, 8px)}}@keyframes inward-shrink{from{border-width:var(--md-focus-ring-active-width, 8px)}}@media(prefers-reduced-motion){:host{animation:none}} +`; + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * TODO(b/267336424): add docs + * + * @final + * @suppress {visibility} + */ +let MdFocusRing = class MdFocusRing extends FocusRing { +}; +MdFocusRing.styles = [styles$i]; +MdFocusRing = __decorate([ + e$a('md-focus-ring') +], MdFocusRing); + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +const t={ATTRIBUTE:1,CHILD:2,PROPERTY:3,BOOLEAN_ATTRIBUTE:4,EVENT:5,ELEMENT:6},e$2=t=>(...e)=>({_$litDirective$:t,values:e});let i$2 = class i{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,i){this._$Ct=t,this._$AM=e,this._$Ci=i;}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}}; + +/** + * @license + * Copyright 2018 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */const o$1=e$2(class extends i$2{constructor(t$1){var i;if(super(t$1),t$1.type!==t.ATTRIBUTE||"class"!==t$1.name||(null===(i=t$1.strings)||void 0===i?void 0:i.length)>2)throw Error("`classMap()` can only be used in the `class` attribute and must be the only part in the attribute.")}render(t){return " "+Object.keys(t).filter((i=>t[i])).join(" ")+" "}update(i,[s]){var r,o;if(void 0===this.it){this.it=new Set,void 0!==i.strings&&(this.nt=new Set(i.strings.join(" ").split(/\s/).filter((t=>""!==t))));for(const t in s)s[t]&&!(null===(r=this.nt)||void 0===r?void 0:r.has(t))&&this.it.add(t);return this.render(s)}const e=i.element.classList;this.it.forEach((t=>{t in s||(e.remove(t),this.it.delete(t));}));for(const t in s){const i=!!s[t];i===this.it.has(t)||(null===(o=this.nt)||void 0===o?void 0:o.has(t))||(i?(e.add(t),this.it.add(t)):(e.remove(t),this.it.delete(t)));}return T}}); + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Easing functions to use for web animations. + * + * **NOTE:** `EASING.EMPHASIZED` is approximated with unknown accuracy. + * + * TODO(b/241113345): replace with tokens + */ +const EASING = { + STANDARD: 'cubic-bezier(0.2, 0, 0, 1)', + STANDARD_ACCELERATE: 'cubic-bezier(.3,0,1,1)', + STANDARD_DECELERATE: 'cubic-bezier(0,0,0,1)', + EMPHASIZED: 'cubic-bezier(.3,0,0,1)', + EMPHASIZED_ACCELERATE: 'cubic-bezier(.3,0,.8,.15)', + EMPHASIZED_DECELERATE: 'cubic-bezier(.05,.7,.1,1)', +}; +/** + * Creates an `AnimationSignal` that can be used to cancel a previous task. + * + * @example + * class MyClass { + * private labelAnimationSignal = createAnimationSignal(); + * + * private async animateLabel() { + * // Start of the task. Previous tasks will be canceled. + * const signal = this.labelAnimationSignal.start(); + * + * // Do async work... + * if (signal.aborted) { + * // Use AbortSignal to check if a request was made to abort after some + * // asynchronous work. + * return; + * } + * + * const animation = this.animate(...); + * // Add event listeners to be notified when the task should be canceled. + * signal.addEventListener('abort', () => { + * animation.cancel(); + * }); + * + * animation.addEventListener('finish', () => { + * // Tell the signal that the current task is finished. + * this.labelAnimationSignal.finish(); + * }); + * } + * } + * + * @return An `AnimationSignal`. + */ +function createAnimationSignal() { + // The current animation's AbortController + let animationAbortController = null; + return { + start() { + // Tell the previous animation to cancel. + animationAbortController?.abort(); + // Set up a new AbortController for the current animation. + animationAbortController = new AbortController(); + // Provide the AbortSignal so that the caller can check aborted status + // and add listeners. + return animationAbortController.signal; + }, + finish() { + animationAbortController = null; + }, + }; +} + +/** + * @license + * Copyright 2022 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const PRESS_GROW_MS = 450; +const MINIMUM_PRESS_MS = 225; +const INITIAL_ORIGIN_SCALE = 0.2; +const PADDING = 10; +const SOFT_EDGE_MINIMUM_SIZE = 75; +const SOFT_EDGE_CONTAINER_RATIO = 0.35; +const PRESS_PSEUDO = '::after'; +const ANIMATION_FILL = 'forwards'; +/** + * Interaction states for the ripple. + * + * On Touch: + * - `INACTIVE -> TOUCH_DELAY -> WAITING_FOR_CLICK -> INACTIVE` + * - `INACTIVE -> TOUCH_DELAY -> HOLDING -> WAITING_FOR_CLICK -> INACTIVE` + * + * On Mouse or Pen: + * - `INACTIVE -> WAITING_FOR_CLICK -> INACTIVE` + */ +var State; +(function (State) { + /** + * Initial state of the control, no touch in progress. + * + * Transitions: + * - on touch down: transition to `TOUCH_DELAY`. + * - on mouse down: transition to `WAITING_FOR_CLICK`. + */ + State[State["INACTIVE"] = 0] = "INACTIVE"; + /** + * Touch down has been received, waiting to determine if it's a swipe or + * scroll. + * + * Transitions: + * - on touch up: begin press; transition to `WAITING_FOR_CLICK`. + * - on cancel: transition to `INACTIVE`. + * - after `TOUCH_DELAY_MS`: begin press; transition to `HOLDING`. + */ + State[State["TOUCH_DELAY"] = 1] = "TOUCH_DELAY"; + /** + * A touch has been deemed to be a press + * + * Transitions: + * - on up: transition to `WAITING_FOR_CLICK`. + */ + State[State["HOLDING"] = 2] = "HOLDING"; + /** + * The user touch has finished, transition into rest state. + * + * Transitions: + * - on click end press; transition to `INACTIVE`. + */ + State[State["WAITING_FOR_CLICK"] = 3] = "WAITING_FOR_CLICK"; +})(State || (State = {})); +/** + * Events that the ripple listens to. + */ +const EVENTS = [ + 'click', + 'contextmenu', + 'pointercancel', + 'pointerdown', + 'pointerenter', + 'pointerleave', + 'pointerup', +]; +/** + * Delay reacting to touch so that we do not show the ripple for a swipe or + * scroll interaction. + */ +const TOUCH_DELAY_MS = 150; +/** + * Used to detect if HCM is active. Events do not process during HCM when the + * ripple is not displayed. + */ +const FORCED_COLORS = window.matchMedia('(forced-colors: active)'); +/** + * A ripple component. + */ +class Ripple extends s$2 { + constructor() { + super(...arguments); + /** + * Disables the ripple. + */ + this.disabled = false; + this.hovered = false; + this.pressed = false; + this.rippleSize = ''; + this.rippleScale = ''; + this.initialSize = 0; + this.state = State.INACTIVE; + this.attachableController = new AttachableController(this, this.onControlChange.bind(this)); + } + get htmlFor() { + return this.attachableController.htmlFor; + } + set htmlFor(htmlFor) { + this.attachableController.htmlFor = htmlFor; + } + get control() { + return this.attachableController.control; + } + set control(control) { + this.attachableController.control = control; + } + attach(control) { + this.attachableController.attach(control); + } + detach() { + this.attachableController.detach(); + } + connectedCallback() { + super.connectedCallback(); + // Needed for VoiceOver, which will create a "group" if the element is a + // sibling to other content. + this.setAttribute('aria-hidden', 'true'); + } + render() { + const classes = { + 'hovered': this.hovered, + 'pressed': this.pressed, + }; + return x `
`; + } + update(changedProps) { + if (changedProps.has('disabled') && this.disabled) { + this.hovered = false; + this.pressed = false; + } + super.update(changedProps); + } + /** + * TODO(b/269799771): make private + * @private only public for slider + */ + handlePointerenter(event) { + if (!this.shouldReactToEvent(event)) { + return; + } + this.hovered = true; + } + /** + * TODO(b/269799771): make private + * @private only public for slider + */ + handlePointerleave(event) { + if (!this.shouldReactToEvent(event)) { + return; + } + this.hovered = false; + // release a held mouse or pen press that moves outside the element + if (this.state !== State.INACTIVE) { + this.endPressAnimation(); + } + } + handlePointerup(event) { + if (!this.shouldReactToEvent(event)) { + return; + } + if (this.state === State.HOLDING) { + this.state = State.WAITING_FOR_CLICK; + return; + } + if (this.state === State.TOUCH_DELAY) { + this.state = State.WAITING_FOR_CLICK; + this.startPressAnimation(this.rippleStartEvent); + return; + } + } + async handlePointerdown(event) { + if (!this.shouldReactToEvent(event)) { + return; + } + this.rippleStartEvent = event; + if (!this.isTouch(event)) { + this.state = State.WAITING_FOR_CLICK; + this.startPressAnimation(event); + return; + } + // Wait for a hold after touch delay + this.state = State.TOUCH_DELAY; + await new Promise((resolve) => { + setTimeout(resolve, TOUCH_DELAY_MS); + }); + if (this.state !== State.TOUCH_DELAY) { + return; + } + this.state = State.HOLDING; + this.startPressAnimation(event); + } + handleClick() { + // Click is a MouseEvent in Firefox and Safari, so we cannot use + // `shouldReactToEvent` + if (this.disabled) { + return; + } + if (this.state === State.WAITING_FOR_CLICK) { + this.endPressAnimation(); + return; + } + if (this.state === State.INACTIVE) { + // keyboard synthesized click event + this.startPressAnimation(); + this.endPressAnimation(); + } + } + handlePointercancel(event) { + if (!this.shouldReactToEvent(event)) { + return; + } + this.endPressAnimation(); + } + handleContextmenu() { + if (this.disabled) { + return; + } + this.endPressAnimation(); + } + determineRippleSize() { + const { height, width } = this.getBoundingClientRect(); + const maxDim = Math.max(height, width); + const softEdgeSize = Math.max(SOFT_EDGE_CONTAINER_RATIO * maxDim, SOFT_EDGE_MINIMUM_SIZE); + // `?? 1` may be removed once `currentCSSZoom` is widely available. + const zoom = this.currentCSSZoom ?? 1; + const initialSize = Math.floor((maxDim * INITIAL_ORIGIN_SCALE) / zoom); + const hypotenuse = Math.sqrt(width ** 2 + height ** 2); + const maxRadius = hypotenuse + PADDING; + this.initialSize = initialSize; + // The dimensions may be altered by CSS `zoom`, which needs to be + // compensated for in the final scale() value. + const maybeZoomedScale = (maxRadius + softEdgeSize) / initialSize; + this.rippleScale = `${maybeZoomedScale / zoom}`; + this.rippleSize = `${initialSize}px`; + } + getNormalizedPointerEventCoords(pointerEvent) { + const { scrollX, scrollY } = window; + const { left, top } = this.getBoundingClientRect(); + const documentX = scrollX + left; + const documentY = scrollY + top; + const { pageX, pageY } = pointerEvent; + // `?? 1` may be removed once `currentCSSZoom` is widely available. + const zoom = this.currentCSSZoom ?? 1; + return { + x: (pageX - documentX) / zoom, + y: (pageY - documentY) / zoom, + }; + } + getTranslationCoordinates(positionEvent) { + const { height, width } = this.getBoundingClientRect(); + // `?? 1` may be removed once `currentCSSZoom` is widely available. + const zoom = this.currentCSSZoom ?? 1; + // end in the center + const endPoint = { + x: (width / zoom - this.initialSize) / 2, + y: (height / zoom - this.initialSize) / 2, + }; + let startPoint; + if (positionEvent instanceof PointerEvent) { + startPoint = this.getNormalizedPointerEventCoords(positionEvent); + } + else { + startPoint = { + x: width / zoom / 2, + y: height / zoom / 2, + }; + } + // center around start point + startPoint = { + x: startPoint.x - this.initialSize / 2, + y: startPoint.y - this.initialSize / 2, + }; + return { startPoint, endPoint }; + } + startPressAnimation(positionEvent) { + if (!this.mdRoot) { + return; + } + this.pressed = true; + this.growAnimation?.cancel(); + this.determineRippleSize(); + const { startPoint, endPoint } = this.getTranslationCoordinates(positionEvent); + const translateStart = `${startPoint.x}px, ${startPoint.y}px`; + const translateEnd = `${endPoint.x}px, ${endPoint.y}px`; + this.growAnimation = this.mdRoot.animate({ + top: [0, 0], + left: [0, 0], + height: [this.rippleSize, this.rippleSize], + width: [this.rippleSize, this.rippleSize], + transform: [ + `translate(${translateStart}) scale(1)`, + `translate(${translateEnd}) scale(${this.rippleScale})`, + ], + }, { + pseudoElement: PRESS_PSEUDO, + duration: PRESS_GROW_MS, + easing: EASING.STANDARD, + fill: ANIMATION_FILL, + }); + } + async endPressAnimation() { + this.rippleStartEvent = undefined; + this.state = State.INACTIVE; + const animation = this.growAnimation; + let pressAnimationPlayState = Infinity; + if (typeof animation?.currentTime === 'number') { + pressAnimationPlayState = animation.currentTime; + } + else if (animation?.currentTime) { + pressAnimationPlayState = animation.currentTime.to('ms').value; + } + if (pressAnimationPlayState >= MINIMUM_PRESS_MS) { + this.pressed = false; + return; + } + await new Promise((resolve) => { + setTimeout(resolve, MINIMUM_PRESS_MS - pressAnimationPlayState); + }); + if (this.growAnimation !== animation) { + // A new press animation was started. The old animation was canceled and + // should not finish the pressed state. + return; + } + this.pressed = false; + } + /** + * Returns `true` if + * - the ripple element is enabled + * - the pointer is primary for the input type + * - the pointer is the pointer that started the interaction, or will start + * the interaction + * - the pointer is a touch, or the pointer state has the primary button + * held, or the pointer is hovering + */ + shouldReactToEvent(event) { + if (this.disabled || !event.isPrimary) { + return false; + } + if (this.rippleStartEvent && + this.rippleStartEvent.pointerId !== event.pointerId) { + return false; + } + if (event.type === 'pointerenter' || event.type === 'pointerleave') { + return !this.isTouch(event); + } + const isPrimaryButton = event.buttons === 1; + return this.isTouch(event) || isPrimaryButton; + } + isTouch({ pointerType }) { + return pointerType === 'touch'; + } + /** @private */ + async handleEvent(event) { + if (FORCED_COLORS?.matches) { + // Skip event logic since the ripple is `display: none`. + return; + } + switch (event.type) { + case 'click': + this.handleClick(); + break; + case 'contextmenu': + this.handleContextmenu(); + break; + case 'pointercancel': + this.handlePointercancel(event); + break; + case 'pointerdown': + await this.handlePointerdown(event); + break; + case 'pointerenter': + this.handlePointerenter(event); + break; + case 'pointerleave': + this.handlePointerleave(event); + break; + case 'pointerup': + this.handlePointerup(event); + break; + } + } + onControlChange(prev, next) { + for (const event of EVENTS) { + prev?.removeEventListener(event, this); + next?.addEventListener(event, this); + } + } +} +__decorate([ + n$7({ type: Boolean, reflect: true }) +], Ripple.prototype, "disabled", void 0); +__decorate([ + t$3() +], Ripple.prototype, "hovered", void 0); +__decorate([ + t$3() +], Ripple.prototype, "pressed", void 0); +__decorate([ + i$5('.surface') +], Ripple.prototype, "mdRoot", void 0); + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./ripple/internal/ripple-styles.css. +const styles$h = i$4 `:host{display:flex;margin:auto;pointer-events:none}:host([disabled]){display:none}@media(forced-colors: active){:host{display:none}}:host,.surface{border-radius:inherit;position:absolute;inset:0;overflow:hidden}.surface{-webkit-tap-highlight-color:rgba(0,0,0,0)}.surface::before,.surface::after{content:"";opacity:0;position:absolute}.surface::before{background-color:var(--md-ripple-hover-color, var(--md-sys-color-on-surface, #1d1b20));inset:0;transition:opacity 15ms linear,background-color 15ms linear}.surface::after{background:radial-gradient(closest-side, var(--md-ripple-pressed-color, var(--md-sys-color-on-surface, #1d1b20)) max(100% - 70px, 65%), transparent 100%);transform-origin:center center;transition:opacity 375ms linear}.hovered::before{background-color:var(--md-ripple-hover-color, var(--md-sys-color-on-surface, #1d1b20));opacity:var(--md-ripple-hover-opacity, 0.08)}.pressed::after{opacity:var(--md-ripple-pressed-opacity, 0.12);transition-duration:105ms} +`; + +/** + * @license + * Copyright 2022 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @summary Ripples, also known as state layers, are visual indicators used to + * communicate the status of a component or interactive element. + * + * @description A state layer is a semi-transparent covering on an element that + * indicates its state. State layers provide a systematic approach to + * visualizing states by using opacity. A layer can be applied to an entire + * element or in a circular shape and only one state layer can be applied at a + * given time. + * + * @final + * @suppress {visibility} + */ +let MdRipple = class MdRipple extends Ripple { +}; +MdRipple.styles = [styles$h]; +MdRipple = __decorate([ + e$a('md-ripple') +], MdRipple); + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Accessibility Object Model reflective aria properties. + */ +const ARIA_PROPERTIES = [ + 'role', + 'ariaAtomic', + 'ariaAutoComplete', + 'ariaBusy', + 'ariaChecked', + 'ariaColCount', + 'ariaColIndex', + 'ariaColSpan', + 'ariaCurrent', + 'ariaDisabled', + 'ariaExpanded', + 'ariaHasPopup', + 'ariaHidden', + 'ariaInvalid', + 'ariaKeyShortcuts', + 'ariaLabel', + 'ariaLevel', + 'ariaLive', + 'ariaModal', + 'ariaMultiLine', + 'ariaMultiSelectable', + 'ariaOrientation', + 'ariaPlaceholder', + 'ariaPosInSet', + 'ariaPressed', + 'ariaReadOnly', + 'ariaRequired', + 'ariaRoleDescription', + 'ariaRowCount', + 'ariaRowIndex', + 'ariaRowSpan', + 'ariaSelected', + 'ariaSetSize', + 'ariaSort', + 'ariaValueMax', + 'ariaValueMin', + 'ariaValueNow', + 'ariaValueText', +]; +/** + * Accessibility Object Model aria attributes. + */ +const ARIA_ATTRIBUTES = ARIA_PROPERTIES.map(ariaPropertyToAttribute); +/** + * Checks if an attribute is one of the AOM aria attributes. + * + * @example + * isAriaAttribute('aria-label'); // true + * + * @param attribute The attribute to check. + * @return True if the attribute is an aria attribute, or false if not. + */ +function isAriaAttribute(attribute) { + return ARIA_ATTRIBUTES.includes(attribute); +} +/** + * Converts an AOM aria property into its corresponding attribute. + * + * @example + * ariaPropertyToAttribute('ariaLabel'); // 'aria-label' + * + * @param property The aria property. + * @return The aria attribute. + */ +function ariaPropertyToAttribute(property) { + return property + .replace('aria', 'aria-') + // IDREF attributes also include an "Element" or "Elements" suffix + .replace(/Elements?/g, '') + .toLowerCase(); +} + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Private symbols +const privateIgnoreAttributeChangesFor = Symbol('privateIgnoreAttributeChangesFor'); +/** + * Mixes in aria delegation for elements that delegate focus and aria to inner + * shadow root elements. + * + * This mixin fixes invalid aria announcements with shadow roots, caused by + * duplicate aria attributes on both the host and the inner shadow root element. + * + * Note: this mixin **does not yet support** ID reference attributes, such as + * `aria-labelledby` or `aria-controls`. + * + * @example + * ```ts + * class MyButton extends mixinDelegatesAria(LitElement) { + * static shadowRootOptions = {mode: 'open', delegatesFocus: true}; + * + * render() { + * return html` + * + * `; + * } + * } + * ``` + * ```html + * +1 + * ``` + * + * Use `ARIAMixinStrict` for lit analyzer strict types, such as the "role" + * attribute. + * + * @example + * ```ts + * return html` + * + * `; + * ``` + * + * In the future, updates to the Accessibility Object Model (AOM) will provide + * built-in aria delegation features that will replace this mixin. + * + * @param base The class to mix functionality into. + * @return The provided class with aria delegation mixed in. + */ +function mixinDelegatesAria(base) { + var _a; + class WithDelegatesAriaElement extends base { + constructor() { + super(...arguments); + this[_a] = new Set(); + } + attributeChangedCallback(name, oldValue, newValue) { + if (!isAriaAttribute(name)) { + super.attributeChangedCallback(name, oldValue, newValue); + return; + } + if (this[privateIgnoreAttributeChangesFor].has(name)) { + return; + } + // Don't trigger another `attributeChangedCallback` once we remove the + // aria attribute from the host. We check the explicit name of the + // attribute to ignore since `attributeChangedCallback` can be called + // multiple times out of an expected order when hydrating an element with + // multiple attributes. + this[privateIgnoreAttributeChangesFor].add(name); + this.removeAttribute(name); + this[privateIgnoreAttributeChangesFor].delete(name); + const dataProperty = ariaAttributeToDataProperty(name); + if (newValue === null) { + delete this.dataset[dataProperty]; + } + else { + this.dataset[dataProperty] = newValue; + } + this.requestUpdate(ariaAttributeToDataProperty(name), oldValue); + } + getAttribute(name) { + if (isAriaAttribute(name)) { + return super.getAttribute(ariaAttributeToDataAttribute(name)); + } + return super.getAttribute(name); + } + removeAttribute(name) { + super.removeAttribute(name); + if (isAriaAttribute(name)) { + super.removeAttribute(ariaAttributeToDataAttribute(name)); + // Since `aria-*` attributes are already removed`, we need to request + // an update because `attributeChangedCallback` will not be called. + this.requestUpdate(); + } + } + } + _a = privateIgnoreAttributeChangesFor; + setupDelegatesAriaProperties(WithDelegatesAriaElement); + return WithDelegatesAriaElement; +} +/** + * Overrides the constructor's native `ARIAMixin` properties to ensure that + * aria properties reflect the values that were shifted to a data attribute. + * + * @param ctor The `ReactiveElement` constructor to patch. + */ +function setupDelegatesAriaProperties(ctor) { + for (const ariaProperty of ARIA_PROPERTIES) { + // The casing between ariaProperty and the dataProperty may be different. + // ex: aria-haspopup -> ariaHasPopup + const ariaAttribute = ariaPropertyToAttribute(ariaProperty); + // ex: aria-haspopup -> data-aria-haspopup + const dataAttribute = ariaAttributeToDataAttribute(ariaAttribute); + // ex: aria-haspopup -> dataset.ariaHaspopup + const dataProperty = ariaAttributeToDataProperty(ariaAttribute); + // Call `ReactiveElement.createProperty()` so that the `aria-*` and `data-*` + // attributes are added to the `static observedAttributes` array. This + // triggers `attributeChangedCallback` for the delegates aria mixin to + // handle. + ctor.createProperty(ariaProperty, { + attribute: ariaAttribute, + noAccessor: true, + }); + ctor.createProperty(Symbol(dataAttribute), { + attribute: dataAttribute, + noAccessor: true, + }); + // Re-define the `ARIAMixin` properties to handle data attribute shifting. + // It is safe to use `Object.defineProperty` here because the properties + // are native and not renamed. + // tslint:disable-next-line:ban-unsafe-reflection + Object.defineProperty(ctor.prototype, ariaProperty, { + configurable: true, + enumerable: true, + get() { + return this.dataset[dataProperty] ?? null; + }, + set(value) { + const prevValue = this.dataset[dataProperty] ?? null; + if (value === prevValue) { + return; + } + if (value === null) { + delete this.dataset[dataProperty]; + } + else { + this.dataset[dataProperty] = value; + } + this.requestUpdate(ariaProperty, prevValue); + }, + }); + } +} +function ariaAttributeToDataAttribute(ariaAttribute) { + // aria-haspopup -> data-aria-haspopup + return `data-${ariaAttribute}`; +} +function ariaAttributeToDataProperty(ariaAttribute) { + // aria-haspopup -> dataset.ariaHaspopup + return ariaAttribute.replace(/-\w/, (dashLetter) => dashLetter[1].toUpperCase()); +} + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A unique symbol used for protected access to an instance's + * `ElementInternals`. + * + * @example + * ```ts + * class MyElement extends mixinElementInternals(LitElement) { + * constructor() { + * super(); + * this[internals].role = 'button'; + * } + * } + * ``` + */ +const internals = Symbol('internals'); +// Private symbols +const privateInternals = Symbol('privateInternals'); +/** + * Mixes in an attached `ElementInternals` instance. + * + * This mixin is only needed when other shared code needs access to a + * component's `ElementInternals`, such as form-associated mixins. + * + * @param base The class to mix functionality into. + * @return The provided class with `WithElementInternals` mixed in. + */ +function mixinElementInternals(base) { + class WithElementInternalsElement extends base { + get [internals]() { + // Create internals in getter so that it can be used in methods called on + // construction in `ReactiveElement`, such as `requestUpdate()`. + if (!this[privateInternals]) { + // Cast needed for closure + this[privateInternals] = this.attachInternals(); + } + return this[privateInternals]; + } + } + return WithElementInternalsElement; +} + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Sets up an element's constructor to enable form submission. The element + * instance should be form associated and have a `type` property. + * + * A click listener is added to each element instance. If the click is not + * default prevented, it will submit the element's form, if any. + * + * @example + * ```ts + * class MyElement extends mixinElementInternals(LitElement) { + * static { + * setupFormSubmitter(MyElement); + * } + * + * static formAssociated = true; + * + * type: FormSubmitterType = 'submit'; + * } + * ``` + * + * @param ctor The form submitter element's constructor. + */ +function setupFormSubmitter(ctor) { + ctor.addInitializer((instance) => { + const submitter = instance; + submitter.addEventListener('click', async (event) => { + const { type, [internals]: elementInternals } = submitter; + const { form } = elementInternals; + if (!form || type === 'button') { + return; + } + // Wait a full task for event bubbling to complete. + await new Promise((resolve) => { + setTimeout(resolve); + }); + if (event.defaultPrevented) { + return; + } + if (type === 'reset') { + form.reset(); + return; + } + // form.requestSubmit(submitter) does not work with form associated custom + // elements. This patches the dispatched submit event to add the correct + // `submitter`. + // See https://github.com/WICG/webcomponents/issues/814 + form.addEventListener('submit', (submitEvent) => { + Object.defineProperty(submitEvent, 'submitter', { + configurable: true, + enumerable: true, + get: () => submitter, + }); + }, { capture: true, once: true }); + elementInternals.setFormValue(submitter.value); + form.requestSubmit(); + }); + }); +} + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Dispatches a click event to the given element that triggers a native action, + * but is not composed and therefore is not seen outside the element. + * + * This is useful for responding to an external click event on the host element + * that should trigger an internal action like a button click. + * + * Note, a helper is provided because setting this up correctly is a bit tricky. + * In particular, calling `click` on an element creates a composed event, which + * is not desirable, and a manually dispatched event must specifically be a + * `MouseEvent` to trigger a native action. + * + * @example + * hostClickListener = (event: MouseEvent) { + * if (isActivationClick(event)) { + * this.dispatchActivationClick(this.buttonElement); + * } + * } + * + */ +function dispatchActivationClick(element) { + const event = new MouseEvent('click', { bubbles: true }); + element.dispatchEvent(event); + return event; +} +/** + * Returns true if the click event should trigger an activation behavior. The + * behavior is defined by the element and is whatever it should do when + * clicked. + * + * Typically when an element needs to handle a click, the click is generated + * from within the element and an event listener within the element implements + * the needed behavior; however, it's possible to fire a click directly + * at the element that the element should handle. This method helps + * distinguish these "external" clicks. + * + * An "external" click can be triggered in a number of ways: via a click + * on an associated label for a form associated element, calling + * `element.click()`, or calling + * `element.dispatchEvent(new MouseEvent('click', ...))`. + * + * Also works around Firefox issue + * https://bugzilla.mozilla.org/show_bug.cgi?id=1804576 by squelching + * events for a microtask after called. + * + * @example + * hostClickListener = (event: MouseEvent) { + * if (isActivationClick(event)) { + * this.dispatchActivationClick(this.buttonElement); + * } + * } + * + */ +function isActivationClick(event) { + // Event must start at the event target. + if (event.currentTarget !== event.target) { + return false; + } + // Event must not be retargeted from shadowRoot. + if (event.composedPath()[0] !== event.target) { + return false; + } + // Target must not be disabled; this should only occur for a synthetically + // dispatched click. + if (event.target.disabled) { + return false; + } + // This is an activation if the event should not be squelched. + return !squelchEvent(event); +} +// TODO(https://bugzilla.mozilla.org/show_bug.cgi?id=1804576) +// Remove when Firefox bug is addressed. +function squelchEvent(event) { + const squelched = isSquelchingEvents; + if (squelched) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + squelchEventsForMicrotask(); + return squelched; +} +// Ignore events for one microtask only. +let isSquelchingEvents = false; +async function squelchEventsForMicrotask() { + isSquelchingEvents = true; + // Need to pause for just one microtask. + // tslint:disable-next-line + await null; + isSquelchingEvents = false; +} + +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Separate variable needed for closure. +const buttonBaseClass = mixinDelegatesAria(mixinElementInternals(s$2)); +/** + * A button component. + */ +class Button extends buttonBaseClass { + get name() { + return this.getAttribute('name') ?? ''; + } + set name(name) { + this.setAttribute('name', name); + } + /** + * The associated form element with which this element's value will submit. + */ + get form() { + return this[internals].form; + } + constructor() { + super(); + /** + * Whether or not the button is disabled. + */ + this.disabled = false; + /** + * Whether or not the button is "soft-disabled" (disabled but still + * focusable). + * + * Use this when a button needs increased visibility when disabled. See + * https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_disabled_controls + * for more guidance on when this is needed. + */ + this.softDisabled = false; + /** + * The URL that the link button points to. + */ + this.href = ''; + /** + * The filename to use when downloading the linked resource. + * If not specified, the browser will determine a filename. + * This is only applicable when the button is used as a link (`href` is set). + */ + this.download = ''; + /** + * Where to display the linked `href` URL for a link button. Common options + * include `_blank` to open in a new tab. + */ + this.target = ''; + /** + * Whether to render the icon at the inline end of the label rather than the + * inline start. + * + * _Note:_ Link buttons cannot have trailing icons. + */ + this.trailingIcon = false; + /** + * Whether to display the icon or not. + */ + this.hasIcon = false; + /** + * The default behavior of the button. May be "button", "reset", or "submit" + * (default). + */ + this.type = 'submit'; + /** + * The value added to a form with the button's name when the button submits a + * form. + */ + this.value = ''; + { + this.addEventListener('click', this.handleClick.bind(this)); + } + } + focus() { + this.buttonElement?.focus(); + } + blur() { + this.buttonElement?.blur(); + } + render() { + const isRippleDisabled = this.disabled || this.softDisabled; + const buttonOrLink = this.href ? this.renderLink() : this.renderButton(); + // TODO(b/310046938): due to a limitation in focus ring/ripple, we can't use + // the same ID for different elements, so we change the ID instead. + const buttonId = this.href ? 'link' : 'button'; + return x ` + ${this.renderElevationOrOutline?.()} +
+ + + ${buttonOrLink} + `; + } + renderButton() { + // Needed for closure conformance + const { ariaLabel, ariaHasPopup, ariaExpanded } = this; + return x ``; + } + renderLink() { + // Needed for closure conformance + const { ariaLabel, ariaHasPopup, ariaExpanded } = this; + return x `${this.renderContent()} + `; + } + renderContent() { + const icon = x ``; + return x ` + + ${this.trailingIcon ? A : icon} + + ${this.trailingIcon ? icon : A} + `; + } + handleClick(event) { + // If the button is soft-disabled or a disabled link, we need to explicitly + // prevent the click from propagating to other event listeners as well as + // prevent the default action. + if (this.softDisabled || (this.disabled && this.href)) { + event.stopImmediatePropagation(); + event.preventDefault(); + return; + } + if (!isActivationClick(event) || !this.buttonElement) { + return; + } + this.focus(); + dispatchActivationClick(this.buttonElement); + } + handleSlotChange() { + this.hasIcon = this.assignedIcons.length > 0; + } +} +(() => { + setupFormSubmitter(Button); +})(); +/** @nocollapse */ +Button.formAssociated = true; +/** @nocollapse */ +Button.shadowRootOptions = { + mode: 'open', + delegatesFocus: true, +}; +__decorate([ + n$7({ type: Boolean, reflect: true }) +], Button.prototype, "disabled", void 0); +__decorate([ + n$7({ type: Boolean, attribute: 'soft-disabled', reflect: true }) +], Button.prototype, "softDisabled", void 0); +__decorate([ + n$7() +], Button.prototype, "href", void 0); +__decorate([ + n$7() +], Button.prototype, "download", void 0); +__decorate([ + n$7() +], Button.prototype, "target", void 0); +__decorate([ + n$7({ type: Boolean, attribute: 'trailing-icon', reflect: true }) +], Button.prototype, "trailingIcon", void 0); +__decorate([ + n$7({ type: Boolean, attribute: 'has-icon', reflect: true }) +], Button.prototype, "hasIcon", void 0); +__decorate([ + n$7() +], Button.prototype, "type", void 0); +__decorate([ + n$7({ reflect: true }) +], Button.prototype, "value", void 0); +__decorate([ + i$5('.button') +], Button.prototype, "buttonElement", void 0); +__decorate([ + l$5({ slot: 'icon', flatten: true }) +], Button.prototype, "assignedIcons", void 0); + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./button/internal/shared-elevation-styles.css. +const styles$g = i$4 `md-elevation{transition-duration:280ms}:host(:is([disabled],[soft-disabled])) md-elevation{transition:none}md-elevation{--md-elevation-level: var(--_container-elevation);--md-elevation-shadow-color: var(--_container-shadow-color)}:host(:focus-within) md-elevation{--md-elevation-level: var(--_focus-container-elevation)}:host(:hover) md-elevation{--md-elevation-level: var(--_hover-container-elevation)}:host(:active) md-elevation{--md-elevation-level: var(--_pressed-container-elevation)}:host(:is([disabled],[soft-disabled])) md-elevation{--md-elevation-level: var(--_disabled-container-elevation)} +`; + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./button/internal/shared-styles.css. +const styles$f = i$4 `:host{border-start-start-radius:var(--_container-shape-start-start);border-start-end-radius:var(--_container-shape-start-end);border-end-start-radius:var(--_container-shape-end-start);border-end-end-radius:var(--_container-shape-end-end);box-sizing:border-box;cursor:pointer;display:inline-flex;gap:8px;min-height:var(--_container-height);outline:none;padding-block:calc((var(--_container-height) - max(var(--_label-text-line-height),var(--_icon-size)))/2);padding-inline-start:var(--_leading-space);padding-inline-end:var(--_trailing-space);place-content:center;place-items:center;position:relative;font-family:var(--_label-text-font);font-size:var(--_label-text-size);line-height:var(--_label-text-line-height);font-weight:var(--_label-text-weight);text-overflow:ellipsis;text-wrap:nowrap;user-select:none;-webkit-tap-highlight-color:rgba(0,0,0,0);vertical-align:top;--md-ripple-hover-color: var(--_hover-state-layer-color);--md-ripple-pressed-color: var(--_pressed-state-layer-color);--md-ripple-hover-opacity: var(--_hover-state-layer-opacity);--md-ripple-pressed-opacity: var(--_pressed-state-layer-opacity)}md-focus-ring{--md-focus-ring-shape-start-start: var(--_container-shape-start-start);--md-focus-ring-shape-start-end: var(--_container-shape-start-end);--md-focus-ring-shape-end-end: var(--_container-shape-end-end);--md-focus-ring-shape-end-start: var(--_container-shape-end-start)}:host(:is([disabled],[soft-disabled])){cursor:default;pointer-events:none}.button{border-radius:inherit;cursor:inherit;display:inline-flex;align-items:center;justify-content:center;border:none;outline:none;-webkit-appearance:none;vertical-align:middle;background:rgba(0,0,0,0);text-decoration:none;min-width:calc(64px - var(--_leading-space) - var(--_trailing-space));width:100%;z-index:0;height:100%;font:inherit;color:var(--_label-text-color);padding:0;gap:inherit;text-transform:inherit}.button::-moz-focus-inner{padding:0;border:0}:host(:hover) .button{color:var(--_hover-label-text-color)}:host(:focus-within) .button{color:var(--_focus-label-text-color)}:host(:active) .button{color:var(--_pressed-label-text-color)}.background{background:var(--_container-color);border-radius:inherit;inset:0;position:absolute}.label{overflow:hidden}:is(.button,.label,.label slot),.label ::slotted(*){text-overflow:inherit}:host(:is([disabled],[soft-disabled])) .label{color:var(--_disabled-label-text-color);opacity:var(--_disabled-label-text-opacity)}:host(:is([disabled],[soft-disabled])) .background{background:var(--_disabled-container-color);opacity:var(--_disabled-container-opacity)}@media(forced-colors: active){.background{border:1px solid CanvasText}:host(:is([disabled],[soft-disabled])){--_disabled-icon-color: GrayText;--_disabled-icon-opacity: 1;--_disabled-container-opacity: 1;--_disabled-label-text-color: GrayText;--_disabled-label-text-opacity: 1}}:host([has-icon]:not([trailing-icon])){padding-inline-start:var(--_with-leading-icon-leading-space);padding-inline-end:var(--_with-leading-icon-trailing-space)}:host([has-icon][trailing-icon]){padding-inline-start:var(--_with-trailing-icon-leading-space);padding-inline-end:var(--_with-trailing-icon-trailing-space)}::slotted([slot=icon]){display:inline-flex;position:relative;writing-mode:horizontal-tb;fill:currentColor;flex-shrink:0;color:var(--_icon-color);font-size:var(--_icon-size);inline-size:var(--_icon-size);block-size:var(--_icon-size)}:host(:hover) ::slotted([slot=icon]){color:var(--_hover-icon-color)}:host(:focus-within) ::slotted([slot=icon]){color:var(--_focus-icon-color)}:host(:active) ::slotted([slot=icon]){color:var(--_pressed-icon-color)}:host(:is([disabled],[soft-disabled])) ::slotted([slot=icon]){color:var(--_disabled-icon-color);opacity:var(--_disabled-icon-opacity)}.touch{position:absolute;top:50%;height:48px;left:0;right:0;transform:translateY(-50%)}:host([touch-target=wrapper]){margin:max(0px,(48px - var(--_container-height))/2) 0}:host([touch-target=none]) .touch{display:none} +`; + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Separate variable needed for closure. +const fabBaseClass = mixinDelegatesAria(s$2); +// tslint:disable-next-line:enforce-comments-on-exported-symbols +class SharedFab extends fabBaseClass { + constructor() { + super(...arguments); + /** + * The size of the FAB. + * + * NOTE: Branded FABs cannot be sized to `small`, and Extended FABs do not + * have different sizes. + */ + this.size = 'medium'; + /** + * The text to display on the FAB. + */ + this.label = ''; + /** + * Lowers the FAB's elevation. + */ + this.lowered = false; + } + render() { + // Needed for closure conformance + const { ariaLabel } = this; + return x ` + + `; + } + getRenderClasses() { + const isExtended = !!this.label; + return { + 'lowered': this.lowered, + 'small': this.size === 'small' && !isExtended, + 'large': this.size === 'large' && !isExtended, + 'extended': isExtended, + }; + } + renderTouchTarget() { + return x `
`; + } + renderLabel() { + return this.label ? x `${this.label}` : ''; + } + renderIcon() { + const { ariaLabel } = this; + return x ` + + + + `; + } +} +/** @nocollapse */ +SharedFab.shadowRootOptions = { + mode: 'open', + delegatesFocus: true, +}; +__decorate([ + n$7({ reflect: true }) +], SharedFab.prototype, "size", void 0); +__decorate([ + n$7() +], SharedFab.prototype, "label", void 0); +__decorate([ + n$7({ type: Boolean }) +], SharedFab.prototype, "lowered", void 0); + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// tslint:disable-next-line:enforce-comments-on-exported-symbols +class Fab extends SharedFab { + constructor() { + super(...arguments); + /** + * The FAB color variant to render. + */ + this.variant = 'surface'; + } + getRenderClasses() { + return { + ...super.getRenderClasses(), + 'primary': this.variant === 'primary', + 'secondary': this.variant === 'secondary', + 'tertiary': this.variant === 'tertiary', + }; + } +} +__decorate([ + n$7() +], Fab.prototype, "variant", void 0); + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./fab/internal/forced-colors-styles.css. +const styles$e = i$4 `@media(forced-colors: active){.fab{border:1px solid ButtonText}.fab.extended{padding-inline-start:15px;padding-inline-end:19px}md-focus-ring{--md-focus-ring-outward-offset: 3px}} +`; + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./fab/internal/shared-styles.css. +const styles$d = i$4 `:host{--md-ripple-hover-opacity: var(--_hover-state-layer-opacity);--md-ripple-pressed-opacity: var(--_pressed-state-layer-opacity);display:inline-flex;-webkit-tap-highlight-color:rgba(0,0,0,0)}:host([size=medium][touch-target=wrapper]){margin:max(0px,48px - var(--_container-height))}:host([size=large][touch-target=wrapper]){margin:max(0px,48px - var(--_large-container-height))}.fab,.icon,.icon ::slotted(*){display:flex}.fab{align-items:center;justify-content:center;vertical-align:middle;padding:0;position:relative;height:var(--_container-height);transition-property:background-color;border-width:0px;outline:none;z-index:0;text-transform:inherit;--md-elevation-level: var(--_container-elevation);--md-elevation-shadow-color: var(--_container-shadow-color);background-color:var(--_container-color);--md-ripple-hover-color: var(--_hover-state-layer-color);--md-ripple-pressed-color: var(--_pressed-state-layer-color)}.fab.extended{width:inherit;box-sizing:border-box;padding-inline-start:16px;padding-inline-end:20px}.fab:not(.extended){width:var(--_container-width)}.fab.large{width:var(--_large-container-width);height:var(--_large-container-height)}.fab.large .icon ::slotted(*){width:var(--_large-icon-size);height:var(--_large-icon-size);font-size:var(--_large-icon-size)}.fab.large,.fab.large .ripple{border-start-start-radius:var(--_large-container-shape-start-start);border-start-end-radius:var(--_large-container-shape-start-end);border-end-start-radius:var(--_large-container-shape-end-start);border-end-end-radius:var(--_large-container-shape-end-end)}.fab.large md-focus-ring{--md-focus-ring-shape-start-start: var(--_large-container-shape-start-start);--md-focus-ring-shape-start-end: var(--_large-container-shape-start-end);--md-focus-ring-shape-end-end: var(--_large-container-shape-end-end);--md-focus-ring-shape-end-start: var(--_large-container-shape-end-start)}.fab:focus{--md-elevation-level: var(--_focus-container-elevation)}.fab:hover{--md-elevation-level: var(--_hover-container-elevation)}.fab:active{--md-elevation-level: var(--_pressed-container-elevation)}.fab.lowered{background-color:var(--_lowered-container-color);--md-elevation-level: var(--_lowered-container-elevation)}.fab.lowered:focus{--md-elevation-level: var(--_lowered-focus-container-elevation)}.fab.lowered:hover{--md-elevation-level: var(--_lowered-hover-container-elevation)}.fab.lowered:active{--md-elevation-level: var(--_lowered-pressed-container-elevation)}.fab .label{color:var(--_label-text-color)}.fab:hover .fab .label{color:var(--_hover-label-text-color)}.fab:focus .fab .label{color:var(--_focus-label-text-color)}.fab:active .fab .label{color:var(--_pressed-label-text-color)}.label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--_label-text-font);font-size:var(--_label-text-size);line-height:var(--_label-text-line-height);font-weight:var(--_label-text-weight)}.fab.extended .icon ::slotted(*){margin-inline-end:12px}.ripple{overflow:hidden}.ripple,md-elevation{z-index:-1}.touch-target{position:absolute;top:50%;height:48px;left:50%;width:48px;transform:translate(-50%, -50%)}:host([touch-target=none]) .touch-target{display:none}md-elevation,.fab{transition-duration:280ms;transition-timing-function:cubic-bezier(0.2, 0, 0, 1)}.fab,.ripple{border-start-start-radius:var(--_container-shape-start-start);border-start-end-radius:var(--_container-shape-start-end);border-end-start-radius:var(--_container-shape-end-start);border-end-end-radius:var(--_container-shape-end-end)}md-focus-ring{--md-focus-ring-shape-start-start: var(--_container-shape-start-start);--md-focus-ring-shape-start-end: var(--_container-shape-start-end);--md-focus-ring-shape-end-end: var(--_container-shape-end-end);--md-focus-ring-shape-end-start: var(--_container-shape-end-start)}.icon ::slotted(*){width:var(--_icon-size);height:var(--_icon-size);font-size:var(--_icon-size)} +`; + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Separate variable needed for closure. +const chipBaseClass = mixinDelegatesAria(s$2); +/** + * A chip component. + * + * @fires update-focus {Event} Dispatched when `disabled` is toggled. --bubbles + */ +class Chip extends chipBaseClass { + /** + * Whether or not the primary ripple is disabled (defaults to `disabled`). + * Some chip actions such as links cannot be disabled. + */ + get rippleDisabled() { + return this.disabled || this.softDisabled; + } + constructor() { + super(); + /** + * Whether or not the chip is disabled. + * + * Disabled chips are not focusable, unless `always-focusable` is set. + */ + this.disabled = false; + /** + * Whether or not the chip is "soft-disabled" (disabled but still + * focusable). + * + * Use this when a chip needs increased visibility when disabled. See + * https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_disabled_controls + * for more guidance on when this is needed. + */ + this.softDisabled = false; + /** + * When true, allow disabled chips to be focused with arrow keys. + * + * Add this when a chip needs increased visibility when disabled. See + * https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_disabled_controls + * for more guidance on when this is needed. + * + * @deprecated Use `softDisabled` instead of `alwaysFocusable` + `disabled`. + */ + this.alwaysFocusable = false; + // TODO(b/350810013): remove the label property. + /** + * The label of the chip. + * + * @deprecated Set text as content of the chip instead. + */ + this.label = ''; + /** + * Only needed for SSR. + * + * Add this attribute when a chip has a `slot="icon"` to avoid a Flash Of + * Unstyled Content. + */ + this.hasIcon = false; + { + this.addEventListener('click', this.handleClick.bind(this)); + } + } + focus(options) { + if (this.disabled && !this.alwaysFocusable) { + return; + } + super.focus(options); + } + render() { + return x ` +
+ ${this.renderContainerContent()} +
+ `; + } + updated(changed) { + if (changed.has('disabled') && changed.get('disabled') !== undefined) { + this.dispatchEvent(new Event('update-focus', { bubbles: true })); + } + } + getContainerClasses() { + return { + 'disabled': this.disabled || this.softDisabled, + 'has-icon': this.hasIcon, + }; + } + renderContainerContent() { + return x ` + ${this.renderOutline()} + + + ${this.renderPrimaryAction(this.renderPrimaryContent())} + `; + } + renderOutline() { + return x ``; + } + renderLeadingIcon() { + return x ``; + } + renderPrimaryContent() { + return x ` + + + + ${this.label ? this.label : x ``} + + + + `; + } + handleIconChange(event) { + const slot = event.target; + this.hasIcon = slot.assignedElements({ flatten: true }).length > 0; + } + handleClick(event) { + // If the chip is soft-disabled or disabled + always-focusable, we need to + // explicitly prevent the click from propagating to other event listeners + // as well as prevent the default action. + if (this.softDisabled || (this.disabled && this.alwaysFocusable)) { + event.stopImmediatePropagation(); + event.preventDefault(); + return; + } + } +} +/** @nocollapse */ +Chip.shadowRootOptions = { + ...s$2.shadowRootOptions, + delegatesFocus: true, +}; +__decorate([ + n$7({ type: Boolean, reflect: true }) +], Chip.prototype, "disabled", void 0); +__decorate([ + n$7({ type: Boolean, attribute: 'soft-disabled', reflect: true }) +], Chip.prototype, "softDisabled", void 0); +__decorate([ + n$7({ type: Boolean, attribute: 'always-focusable' }) +], Chip.prototype, "alwaysFocusable", void 0); +__decorate([ + n$7() +], Chip.prototype, "label", void 0); +__decorate([ + n$7({ type: Boolean, reflect: true, attribute: 'has-icon' }) +], Chip.prototype, "hasIcon", void 0); + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * An assist chip component. + */ +class AssistChip extends Chip { + constructor() { + super(...arguments); + this.elevated = false; + this.href = ''; + /** + * The filename to use when downloading the linked resource. + * If not specified, the browser will determine a filename. + * This is only applicable when the chip is used as a link (`href` is set). + */ + this.download = ''; + this.target = ''; + } + get primaryId() { + return this.href ? 'link' : 'button'; + } + get rippleDisabled() { + // Link chips cannot be disabled + return !this.href && (this.disabled || this.softDisabled); + } + getContainerClasses() { + return { + ...super.getContainerClasses(), + // Link chips cannot be disabled + disabled: !this.href && (this.disabled || this.softDisabled), + elevated: this.elevated, + link: !!this.href, + }; + } + renderPrimaryAction(content) { + const { ariaLabel } = this; + if (this.href) { + return x ` + ${content} + `; + } + return x ` + + `; + } + renderOutline() { + if (this.elevated) { + return x ``; + } + return super.renderOutline(); + } +} +__decorate([ + n$7({ type: Boolean }) +], AssistChip.prototype, "elevated", void 0); +__decorate([ + n$7() +], AssistChip.prototype, "href", void 0); +__decorate([ + n$7() +], AssistChip.prototype, "download", void 0); +__decorate([ + n$7() +], AssistChip.prototype, "target", void 0); + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./chips/internal/elevated-styles.css. +const styles$c = i$4 `.elevated{--md-elevation-level: var(--_elevated-container-elevation);--md-elevation-shadow-color: var(--_elevated-container-shadow-color)}.elevated::before{background:var(--_elevated-container-color)}.elevated:hover{--md-elevation-level: var(--_elevated-hover-container-elevation)}.elevated:focus-within{--md-elevation-level: var(--_elevated-focus-container-elevation)}.elevated:active{--md-elevation-level: var(--_elevated-pressed-container-elevation)}.elevated.disabled{--md-elevation-level: var(--_elevated-disabled-container-elevation)}.elevated.disabled::before{background:var(--_elevated-disabled-container-color);opacity:var(--_elevated-disabled-container-opacity)}@media(forced-colors: active){.elevated md-elevation{border:1px solid CanvasText}.elevated.disabled md-elevation{border-color:GrayText}} +`; + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./chips/internal/shared-styles.css. +const styles$b = i$4 `:host{border-start-start-radius:var(--_container-shape-start-start);border-start-end-radius:var(--_container-shape-start-end);border-end-start-radius:var(--_container-shape-end-start);border-end-end-radius:var(--_container-shape-end-end);display:inline-flex;height:var(--_container-height);cursor:pointer;-webkit-tap-highlight-color:rgba(0,0,0,0);--md-ripple-hover-color: var(--_hover-state-layer-color);--md-ripple-hover-opacity: var(--_hover-state-layer-opacity);--md-ripple-pressed-color: var(--_pressed-state-layer-color);--md-ripple-pressed-opacity: var(--_pressed-state-layer-opacity)}:host(:is([disabled],[soft-disabled])){pointer-events:none}:host([touch-target=wrapper]){margin:max(0px,(48px - var(--_container-height))/2) 0}md-focus-ring{--md-focus-ring-shape-start-start: var(--_container-shape-start-start);--md-focus-ring-shape-start-end: var(--_container-shape-start-end);--md-focus-ring-shape-end-end: var(--_container-shape-end-end);--md-focus-ring-shape-end-start: var(--_container-shape-end-start)}.container{border-radius:inherit;box-sizing:border-box;display:flex;height:100%;position:relative;width:100%}.container::before{border-radius:inherit;content:"";inset:0;pointer-events:none;position:absolute}.container:not(.disabled){cursor:pointer}.container.disabled{pointer-events:none}.cell{display:flex}.action{align-items:baseline;appearance:none;background:none;border:none;border-radius:inherit;display:flex;outline:none;padding:0;position:relative;text-decoration:none}.primary.action{min-width:0;padding-inline-start:var(--_leading-space);padding-inline-end:var(--_trailing-space)}.has-icon .primary.action{padding-inline-start:var(--_with-leading-icon-leading-space)}.touch{height:48px;inset:50% 0 0;position:absolute;transform:translateY(-50%);width:100%}:host([touch-target=none]) .touch{display:none}.outline{border:var(--_outline-width) solid var(--_outline-color);border-radius:inherit;inset:0;pointer-events:none;position:absolute}:where(:focus) .outline{border-color:var(--_focus-outline-color)}:where(.disabled) .outline{border-color:var(--_disabled-outline-color);opacity:var(--_disabled-outline-opacity)}md-ripple{border-radius:inherit}.label,.icon,.touch{z-index:1}.label{align-items:center;color:var(--_label-text-color);display:flex;font-family:var(--_label-text-font);font-size:var(--_label-text-size);font-weight:var(--_label-text-weight);height:100%;line-height:var(--_label-text-line-height);overflow:hidden;user-select:none}.label-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:where(:hover) .label{color:var(--_hover-label-text-color)}:where(:focus) .label{color:var(--_focus-label-text-color)}:where(:active) .label{color:var(--_pressed-label-text-color)}:where(.disabled) .label{color:var(--_disabled-label-text-color);opacity:var(--_disabled-label-text-opacity)}.icon{align-self:center;display:flex;fill:currentColor;position:relative}.icon ::slotted(:first-child){font-size:var(--_icon-size);height:var(--_icon-size);width:var(--_icon-size)}.leading.icon{color:var(--_leading-icon-color)}.leading.icon ::slotted(*),.leading.icon svg{margin-inline-end:var(--_icon-label-space)}:where(:hover) .leading.icon{color:var(--_hover-leading-icon-color)}:where(:focus) .leading.icon{color:var(--_focus-leading-icon-color)}:where(:active) .leading.icon{color:var(--_pressed-leading-icon-color)}:where(.disabled) .leading.icon{color:var(--_disabled-leading-icon-color);opacity:var(--_disabled-leading-icon-opacity)}@media(forced-colors: active){:where(.disabled) :is(.label,.outline,.leading.icon){color:GrayText;opacity:1}}a,button{text-transform:inherit}a,button:not(:disabled,[aria-disabled=true]){cursor:inherit} +`; + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Re-dispatches an event from the provided element. + * + * This function is useful for forwarding non-composed events, such as `change` + * events. + * + * @example + * class MyInput extends LitElement { + * render() { + * return html``; + * } + * + * protected redispatchEvent(event: Event) { + * redispatchEvent(this, event); + * } + * } + * + * @param element The element to dispatch the event from. + * @param event The event to re-dispatch. + * @return Whether or not the event was dispatched (if cancelable). + */ +function redispatchEvent(element, event) { + // For bubbling events in SSR light DOM (or composed), stop their propagation + // and dispatch the copy. + if (event.bubbles && (!element.shadowRoot || event.composed)) { + event.stopPropagation(); + } + const copy = Reflect.construct(event.constructor, [event.type, event]); + const dispatched = element.dispatchEvent(copy); + if (!dispatched) { + event.preventDefault(); + } + return dispatched; +} + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const ARIA_LABEL_REMOVE = 'aria-label-remove'; +/** + * A chip component with multiple actions. + */ +class MultiActionChip extends Chip { + get ariaLabelRemove() { + if (this.hasAttribute(ARIA_LABEL_REMOVE)) { + return this.getAttribute(ARIA_LABEL_REMOVE); + } + const { ariaLabel } = this; + // TODO(b/350810013): remove `this.label` when label property is removed. + if (ariaLabel || this.label) { + return `Remove ${ariaLabel || this.label}`; + } + return null; + } + set ariaLabelRemove(ariaLabel) { + const prev = this.ariaLabelRemove; + if (ariaLabel === prev) { + return; + } + if (ariaLabel === null) { + this.removeAttribute(ARIA_LABEL_REMOVE); + } + else { + this.setAttribute(ARIA_LABEL_REMOVE, ariaLabel); + } + this.requestUpdate(); + } + constructor() { + super(); + this.handleTrailingActionFocus = this.handleTrailingActionFocus.bind(this); + { + this.addEventListener('keydown', this.handleKeyDown.bind(this)); + } + } + focus(options) { + const isFocusable = this.alwaysFocusable || !this.disabled; + if (isFocusable && options?.trailing && this.trailingAction) { + this.trailingAction.focus(options); + return; + } + super.focus(options); + } + renderContainerContent() { + return x ` + ${super.renderContainerContent()} + ${this.renderTrailingAction(this.handleTrailingActionFocus)} + `; + } + handleKeyDown(event) { + const isLeft = event.key === 'ArrowLeft'; + const isRight = event.key === 'ArrowRight'; + // Ignore non-navigation keys. + if (!isLeft && !isRight) { + return; + } + if (!this.primaryAction || !this.trailingAction) { + // Does not have multiple actions. + return; + } + // Check if moving forwards or backwards + const isRtl = getComputedStyle(this).direction === 'rtl'; + const forwards = isRtl ? isLeft : isRight; + const isPrimaryFocused = this.primaryAction?.matches(':focus-within'); + const isTrailingFocused = this.trailingAction?.matches(':focus-within'); + if ((forwards && isTrailingFocused) || (!forwards && isPrimaryFocused)) { + // Moving outside of the chip, it will be handled by the chip set. + return; + } + // Prevent default interactions, such as scrolling. + event.preventDefault(); + // Don't let the chip set handle this navigation event. + event.stopPropagation(); + const actionToFocus = forwards ? this.trailingAction : this.primaryAction; + actionToFocus.focus(); + } + handleTrailingActionFocus() { + const { primaryAction, trailingAction } = this; + if (!primaryAction || !trailingAction) { + return; + } + // Temporarily turn off the primary action's focusability. This allows + // shift+tab from the trailing action to move to the previous chip rather + // than the primary action in the same chip. + primaryAction.tabIndex = -1; + trailingAction.addEventListener('focusout', () => { + primaryAction.tabIndex = 0; + }, { once: true }); + } +} + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** @protected */ +function renderRemoveButton({ ariaLabel, disabled, focusListener, tabbable = false, }) { + // When an aria-label is not provided, we use two spans with aria-labelledby + // to create the "Remove " label for the remove button. The first + // is this #remove-label span, the second is the chip's #label slot span. + return x ` + + + `; +} +function handleRemoveClick(event) { + if (this.disabled || this.softDisabled) { + return; + } + event.stopPropagation(); + const preventDefault = !this.dispatchEvent(new Event('remove', { cancelable: true })); + if (preventDefault) { + return; + } + this.remove(); +} + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./chips/internal/selectable-styles.css. +const styles$a = i$4 `.selected{--md-ripple-hover-color: var(--_selected-hover-state-layer-color);--md-ripple-hover-opacity: var(--_selected-hover-state-layer-opacity);--md-ripple-pressed-color: var(--_selected-pressed-state-layer-color);--md-ripple-pressed-opacity: var(--_selected-pressed-state-layer-opacity)}:where(.selected)::before{background:var(--_selected-container-color)}:where(.selected) .outline{border-width:var(--_selected-outline-width)}:where(.selected.disabled)::before{background:var(--_disabled-selected-container-color);opacity:var(--_disabled-selected-container-opacity)}:where(.selected) .label{color:var(--_selected-label-text-color)}:where(.selected:hover) .label{color:var(--_selected-hover-label-text-color)}:where(.selected:focus) .label{color:var(--_selected-focus-label-text-color)}:where(.selected:active) .label{color:var(--_selected-pressed-label-text-color)}:where(.selected) .leading.icon{color:var(--_selected-leading-icon-color)}:where(.selected:hover) .leading.icon{color:var(--_selected-hover-leading-icon-color)}:where(.selected:focus) .leading.icon{color:var(--_selected-focus-leading-icon-color)}:where(.selected:active) .leading.icon{color:var(--_selected-pressed-leading-icon-color)}@media(forced-colors: active){:where(.selected:not(.elevated))::before{border:1px solid CanvasText}:where(.selected) .outline{border-width:1px}} +`; + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./chips/internal/trailing-icon-styles.css. +const styles$9 = i$4 `.trailing.action{align-items:center;justify-content:center;padding-inline-start:var(--_icon-label-space);padding-inline-end:var(--_with-trailing-icon-trailing-space)}.trailing.action :is(md-ripple,md-focus-ring){border-radius:50%;height:calc(1.3333333333*var(--_icon-size));width:calc(1.3333333333*var(--_icon-size))}.trailing.action md-focus-ring{inset:unset}.has-trailing .primary.action{padding-inline-end:0}.trailing.icon{color:var(--_trailing-icon-color);height:var(--_icon-size);width:var(--_icon-size)}:where(:hover) .trailing.icon{color:var(--_hover-trailing-icon-color)}:where(:focus) .trailing.icon{color:var(--_focus-trailing-icon-color)}:where(:active) .trailing.icon{color:var(--_pressed-trailing-icon-color)}:where(.disabled) .trailing.icon{color:var(--_disabled-trailing-icon-color);opacity:var(--_disabled-trailing-icon-opacity)}:where(.selected) .trailing.icon{color:var(--_selected-trailing-icon-color)}:where(.selected:hover) .trailing.icon{color:var(--_selected-hover-trailing-icon-color)}:where(.selected:focus) .trailing.icon{color:var(--_selected-focus-trailing-icon-color)}:where(.selected:active) .trailing.icon{color:var(--_selected-pressed-trailing-icon-color)}@media(forced-colors: active){.trailing.icon{color:ButtonText}:where(.disabled) .trailing.icon{color:GrayText;opacity:1}} +`; + +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */const e$1=Symbol.for(""),l$1=t=>{if((null==t?void 0:t.r)===e$1)return null==t?void 0:t._$litStatic$},i$1=(t,...r)=>({_$litStatic$:r.reduce(((r,e,l)=>r+(t=>{if(void 0!==t._$litStatic$)return t._$litStatic$;throw Error(`Value passed to 'literal' function must be a 'literal' result: ${t}. Use 'unsafeStatic' to pass non-literal values, but\n take care to ensure page security.`)})(e)+t[l+1]),t[0]),r:e$1}),s$1=new Map,a$1=t=>(r,...e)=>{const o=e.length;let i,a;const n=[],u=[];let c,$=0,f=!1;for(;$ + ${this.renderFocusRing()} + ${this.renderRipple()} + ${!this.selected ? this.renderIcon() : A} + ${this.selected ? this.renderSelectedIcon() : A} + ${this.href ? this.renderLink() : this.renderTouchTarget()} + `; + } + renderLink() { + // Needed for closure conformance + const { ariaLabel } = this; + return x ` + + ${this.renderTouchTarget()} + + `; + } + getRenderClasses() { + return { + 'flip-icon': this.flipIcon, + 'selected': this.toggle && this.selected, + }; + } + renderIcon() { + return x ``; + } + renderSelectedIcon() { + // Use default slot as fallback to not require specifying multiple icons + return x ``; + } + renderTouchTarget() { + return x ``; + } + renderFocusRing() { + // TODO(b/310046938): use the same id for both elements + return x ``; + } + renderRipple() { + const isRippleDisabled = !this.href && (this.disabled || this.softDisabled); + // TODO(b/310046938): use the same id for both elements + return x ``; + } + connectedCallback() { + this.flipIcon = isRtl(this, this.flipIconInRtl); + super.connectedCallback(); + } + /** Handles a click on this element. */ + handleClick(event) { + // If the icon button is soft-disabled, we need to explicitly prevent the + // click from propagating to other event listeners as well as prevent the + // default action. + if (!this.href && this.softDisabled) { + event.stopImmediatePropagation(); + event.preventDefault(); + return; + } + } + /** + * Handles a click on the child
or
+ * Trailing + * image + * + * ``` + * + * When wrapping ``, forward the available slots to use the same slot + * structure for the wrapping component (this is what `` does). + * + * @example + * ```html + * + * + * + * + * + * + * + * + * + * ``` + * + * @final + * @suppress {visibility} + */ +let MdItem = class MdItem extends Item { +}; +MdItem.styles = [styles]; +MdItem = __decorate([ + e$a('md-item') +], MdItem); + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Separate variable needed for closure. +const progressBaseClass = mixinDelegatesAria(s$2); +/** + * A progress component. + */ +class Progress extends progressBaseClass { + constructor() { + super(...arguments); + /** + * Progress to display, a fraction between 0 and `max`. + */ + this.value = 0; + /** + * Maximum progress to display, defaults to 1. + */ + this.max = 1; + /** + * Whether or not to display indeterminate progress, which gives no indication + * to how long an activity will take. + */ + this.indeterminate = false; + /** + * Whether or not to render indeterminate mode using 4 colors instead of one. + */ + this.fourColor = false; + } + render() { + // Needed for closure conformance + const { ariaLabel } = this; + return x ` +
${this.renderIndicator()}
+ `; + } + getRenderClasses() { + return { + 'indeterminate': this.indeterminate, + 'four-color': this.fourColor, + }; + } +} +__decorate([ + n$7({ type: Number }) +], Progress.prototype, "value", void 0); +__decorate([ + n$7({ type: Number }) +], Progress.prototype, "max", void 0); +__decorate([ + n$7({ type: Boolean }) +], Progress.prototype, "indeterminate", void 0); +__decorate([ + n$7({ type: Boolean, attribute: 'four-color' }) +], Progress.prototype, "fourColor", void 0); + +export { styles$3 as $, A, CloseReason as B, Chip as C, createRequestActivationEvent as D, deactivateActiveItem as E, NavigableKeys as F, i$1 as G, n$1 as H, o as I, styles$d as J, KeydownCloseKey as K, ListController as L, styles$e as M, NavigableKey as N, Fab as O, Progress as P, mixinFocusable as Q, o$7 as R, SelectionKey as S, EASING as T, createDefaultCloseMenuEvent as U, isClosableKey as V, Validator as W, internals as X, e$7 as Y, Select as Z, __decorate as _, mixinConstraintValidation as a, TextField as a0, styles$1 as a1, styles$8 as a2, IconButton as a3, styles$b as a4, styles$c as a5, AssistChip as a6, MultiActionChip as a7, renderRemoveButton as a8, styles$9 as a9, styles$a as aa, Button as ab, styles$f as ac, styles$g as ad, MdRipple as ae, MdMenu as af, FocusState as ag, MdDivider as ah, mixinFormAssociated as b, i$5 as c, isActivationClick as d, e$a as e, dispatchActivationClick as f, getFormValue as g, getFormState as h, i$4 as i, createValidator as j, CheckboxValidator as k, l$5 as l, mixinDelegatesAria as m, n$7 as n, o$1 as o, getValidityAnchor as p, mixinElementInternals as q, redispatchEvent as r, s$2 as s, t$3 as t, Corner as u, createActivateTypeaheadEvent as v, createDeactivateItemsEvent as w, x, createDeactivateTypeaheadEvent as y, getFirstActivatableItem as z }; diff --git a/md-web/dialog.js b/md-web/dialog.js new file mode 100644 index 0000000..f208ad3 --- /dev/null +++ b/md-web/dialog.js @@ -0,0 +1,717 @@ +export const __dummy_loader = () => {}; + +import { T as EASING, m as mixinDelegatesAria, _ as __decorate, t, n, c as i, s, x, o, A, r as redispatchEvent, i as i$1, e } from './core.js'; + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * The default dialog open animation. + */ +const DIALOG_DEFAULT_OPEN_ANIMATION = { + dialog: [ + [ + // Dialog slide down + [{ 'transform': 'translateY(-50px)' }, { 'transform': 'translateY(0)' }], + { duration: 500, easing: EASING.EMPHASIZED }, + ], + ], + scrim: [ + [ + // Scrim fade in + [{ 'opacity': 0 }, { 'opacity': 0.32 }], + { duration: 500, easing: 'linear' }, + ], + ], + container: [ + [ + // Container fade in + [{ 'opacity': 0 }, { 'opacity': 1 }], + { duration: 50, easing: 'linear', pseudoElement: '::before' }, + ], + [ + // Container grow + // Note: current spec says to grow from 0dp->100% and shrink from + // 100%->35%. We change this to 35%->100% to simplify the animation that + // is supposed to clip content as it grows. From 0dp it's possible to see + // text/actions appear before the container has fully grown. + [{ 'height': '35%' }, { 'height': '100%' }], + { duration: 500, easing: EASING.EMPHASIZED, pseudoElement: '::before' }, + ], + ], + headline: [ + [ + // Headline fade in + [{ 'opacity': 0 }, { 'opacity': 0, offset: 0.2 }, { 'opacity': 1 }], + { duration: 250, easing: 'linear', fill: 'forwards' }, + ], + ], + content: [ + [ + // Content fade in + [{ 'opacity': 0 }, { 'opacity': 0, offset: 0.2 }, { 'opacity': 1 }], + { duration: 250, easing: 'linear', fill: 'forwards' }, + ], + ], + actions: [ + [ + // Actions fade in + [{ 'opacity': 0 }, { 'opacity': 0, offset: 0.5 }, { 'opacity': 1 }], + { duration: 300, easing: 'linear', fill: 'forwards' }, + ], + ], +}; +/** + * The default dialog close animation. + */ +const DIALOG_DEFAULT_CLOSE_ANIMATION = { + dialog: [ + [ + // Dialog slide up + [{ 'transform': 'translateY(0)' }, { 'transform': 'translateY(-50px)' }], + { duration: 150, easing: EASING.EMPHASIZED_ACCELERATE }, + ], + ], + scrim: [ + [ + // Scrim fade out + [{ 'opacity': 0.32 }, { 'opacity': 0 }], + { duration: 150, easing: 'linear' }, + ], + ], + container: [ + [ + // Container shrink + [{ 'height': '100%' }, { 'height': '35%' }], + { + duration: 150, + easing: EASING.EMPHASIZED_ACCELERATE, + pseudoElement: '::before', + }, + ], + [ + // Container fade out + [{ 'opacity': '1' }, { 'opacity': '0' }], + { delay: 100, duration: 50, easing: 'linear', pseudoElement: '::before' }, + ], + ], + headline: [ + [ + // Headline fade out + [{ 'opacity': 1 }, { 'opacity': 0 }], + { duration: 100, easing: 'linear', fill: 'forwards' }, + ], + ], + content: [ + [ + // Content fade out + [{ 'opacity': 1 }, { 'opacity': 0 }], + { duration: 100, easing: 'linear', fill: 'forwards' }, + ], + ], + actions: [ + [ + // Actions fade out + [{ 'opacity': 1 }, { 'opacity': 0 }], + { duration: 100, easing: 'linear', fill: 'forwards' }, + ], + ], +}; + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Separate variable needed for closure. +const dialogBaseClass = mixinDelegatesAria(s); +/** + * A dialog component. + * + * @fires open {Event} Dispatched when the dialog is opening before any animations. + * @fires opened {Event} Dispatched when the dialog has opened after any animations. + * @fires close {Event} Dispatched when the dialog is closing before any animations. + * @fires closed {Event} Dispatched when the dialog has closed after any animations. + * @fires cancel {Event} Dispatched when the dialog has been canceled by clicking + * on the scrim or pressing Escape. + */ +class Dialog extends dialogBaseClass { + // We do not use `delegatesFocus: true` due to a Chromium bug with + // selecting text. + // See https://bugs.chromium.org/p/chromium/issues/detail?id=950357 + /** + * Opens the dialog when set to `true` and closes it when set to `false`. + */ + get open() { + return this.isOpen; + } + set open(open) { + if (open === this.isOpen) { + return; + } + this.isOpen = open; + if (open) { + this.setAttribute('open', ''); + this.show(); + } + else { + this.removeAttribute('open'); + this.close(); + } + } + constructor() { + super(); + /** + * Skips the opening and closing animations. + */ + this.quick = false; + /** + * Gets or sets the dialog's return value, usually to indicate which button + * a user pressed to close it. + * + * https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/returnValue + */ + this.returnValue = ''; + /** + * Disables focus trapping, which by default keeps keyboard Tab navigation + * within the dialog. + * + * When disabled, after focusing the last element of a dialog, pressing Tab + * again will release focus from the window back to the browser (such as the + * URL bar). + * + * Focus trapping is recommended for accessibility, and should not typically + * be disabled. Only turn this off if the use case of a dialog is more + * accessible without focus trapping. + */ + this.noFocusTrap = false; + /** + * Gets the opening animation for a dialog. Set to a new function to customize + * the animation. + */ + this.getOpenAnimation = () => DIALOG_DEFAULT_OPEN_ANIMATION; + /** + * Gets the closing animation for a dialog. Set to a new function to customize + * the animation. + */ + this.getCloseAnimation = () => DIALOG_DEFAULT_CLOSE_ANIMATION; + this.isOpen = false; + this.isOpening = false; + this.isConnectedPromise = this.getIsConnectedPromise(); + this.isAtScrollTop = false; + this.isAtScrollBottom = false; + this.nextClickIsFromContent = false; + // Dialogs should not be SSR'd while open, so we can just use runtime checks. + this.hasHeadline = false; + this.hasActions = false; + this.hasIcon = false; + // See https://bugs.chromium.org/p/chromium/issues/detail?id=1512224 + // Chrome v120 has a bug where escape keys do not trigger cancels. If we get + // a dialog "close" event that is triggered without a "cancel" after an escape + // keydown, then we need to manually trigger our closing logic. + // + // This bug occurs when pressing escape to close a dialog without first + // interacting with the dialog's content. + // + // Cleanup tracking: + // https://github.com/material-components/material-web/issues/5330 + // This can be removed when full CloseWatcher support added and the above bug + // in Chromium is fixed to fire 'cancel' with one escape press and close with + // multiple. + this.escapePressedWithoutCancel = false; + // This TreeWalker is used to walk through a dialog's children to find + // focusable elements. TreeWalker is faster than `querySelectorAll('*')`. + // We check for isServer because there isn't a "document" during an SSR + // run. + this.treewalker = document.createTreeWalker(this, NodeFilter.SHOW_ELEMENT); + { + this.addEventListener('submit', this.handleSubmit); + } + } + /** + * Opens the dialog and fires a cancelable `open` event. After a dialog's + * animation, an `opened` event is fired. + * + * Add an `autofocus` attribute to a child of the dialog that should + * receive focus after opening. + * + * @return A Promise that resolves after the animation is finished and the + * `opened` event was fired. + */ + async show() { + this.isOpening = true; + // Dialogs can be opened before being attached to the DOM, so we need to + // wait until we're connected before calling `showModal()`. + await this.isConnectedPromise; + await this.updateComplete; + const dialog = this.dialog; + // Check if already opened or if `dialog.close()` was called while awaiting. + if (dialog.open || !this.isOpening) { + this.isOpening = false; + return; + } + const preventOpen = !this.dispatchEvent(new Event('open', { cancelable: true })); + if (preventOpen) { + this.open = false; + this.isOpening = false; + return; + } + // All Material dialogs are modal. + dialog.showModal(); + this.open = true; + // Reset scroll position if re-opening a dialog with the same content. + if (this.scroller) { + this.scroller.scrollTop = 0; + } + // Native modal dialogs ignore autofocus and instead force focus to the + // first focusable child. Override this behavior if there is a child with + // an autofocus attribute. + this.querySelector('[autofocus]')?.focus(); + await this.animateDialog(this.getOpenAnimation()); + this.dispatchEvent(new Event('opened')); + this.isOpening = false; + } + /** + * Closes the dialog and fires a cancelable `close` event. After a dialog's + * animation, a `closed` event is fired. + * + * @param returnValue A return value usually indicating which button was used + * to close a dialog. If a dialog is canceled by clicking the scrim or + * pressing Escape, it will not change the return value after closing. + * @return A Promise that resolves after the animation is finished and the + * `closed` event was fired. + */ + async close(returnValue = this.returnValue) { + this.isOpening = false; + if (!this.isConnected) { + // Disconnected dialogs do not fire close events or animate. + this.open = false; + return; + } + await this.updateComplete; + const dialog = this.dialog; + // Check if already closed or if `dialog.show()` was called while awaiting. + if (!dialog.open || this.isOpening) { + this.open = false; + return; + } + const prevReturnValue = this.returnValue; + this.returnValue = returnValue; + const preventClose = !this.dispatchEvent(new Event('close', { cancelable: true })); + if (preventClose) { + this.returnValue = prevReturnValue; + return; + } + await this.animateDialog(this.getCloseAnimation()); + dialog.close(returnValue); + this.open = false; + this.dispatchEvent(new Event('closed')); + } + connectedCallback() { + super.connectedCallback(); + this.isConnectedPromiseResolve(); + } + disconnectedCallback() { + super.disconnectedCallback(); + this.isConnectedPromise = this.getIsConnectedPromise(); + } + render() { + const scrollable = this.open && !(this.isAtScrollTop && this.isAtScrollBottom); + const classes = { + 'has-headline': this.hasHeadline, + 'has-actions': this.hasActions, + 'has-icon': this.hasIcon, + 'scrollable': scrollable, + 'show-top-divider': scrollable && !this.isAtScrollTop, + 'show-bottom-divider': scrollable && !this.isAtScrollBottom, + }; + // The focus trap sentinels are only added after the dialog opens, since + // dialog.showModal() will try to autofocus them, even with tabindex="-1". + const showFocusTrap = this.open && !this.noFocusTrap; + const focusTrap = x ` + + `; + const { ariaLabel } = this; + return x ` +
+ + ${showFocusTrap ? focusTrap : A} +
+
+ +

+ +

+ +
+
+
+
+ +
+
+
+
+ + +
+
+ ${showFocusTrap ? focusTrap : A} +
+ `; + } + firstUpdated() { + this.intersectionObserver = new IntersectionObserver((entries) => { + for (const entry of entries) { + this.handleAnchorIntersection(entry); + } + }, { root: this.scroller }); + this.intersectionObserver.observe(this.topAnchor); + this.intersectionObserver.observe(this.bottomAnchor); + } + handleDialogClick() { + if (this.nextClickIsFromContent) { + // Avoid doing a layout calculation below if we know the click came from + // content. + this.nextClickIsFromContent = false; + return; + } + // Click originated on the backdrop. Native ``s will not cancel, + // but Material dialogs do. + const preventDefault = !this.dispatchEvent(new Event('cancel', { cancelable: true })); + if (preventDefault) { + return; + } + this.close(); + } + handleContentClick() { + this.nextClickIsFromContent = true; + } + handleSubmit(event) { + const form = event.target; + const { submitter } = event; + if (form.getAttribute('method') !== 'dialog' || !submitter) { + return; + } + // Close reason is the submitter's value attribute, or the dialog's + // `returnValue` if there is no attribute. + this.close(submitter.getAttribute('value') ?? this.returnValue); + } + handleCancel(event) { + if (event.target !== this.dialog) { + // Ignore any cancel events dispatched by content. + return; + } + this.escapePressedWithoutCancel = false; + const preventDefault = !redispatchEvent(this, event); + // We always prevent default on the original dialog event since we'll + // animate closing it before it actually closes. + event.preventDefault(); + if (preventDefault) { + return; + } + this.close(); + } + handleClose() { + if (!this.escapePressedWithoutCancel) { + return; + } + this.escapePressedWithoutCancel = false; + this.dialog?.dispatchEvent(new Event('cancel', { cancelable: true })); + } + handleKeydown(event) { + if (event.key !== 'Escape') { + return; + } + // An escape key was pressed. If a "close" event fires next without a + // "cancel" event first, then we know we're in the Chrome v120 bug. + this.escapePressedWithoutCancel = true; + // Wait a full task for the cancel/close event listeners to fire, then + // reset the flag. + setTimeout(() => { + this.escapePressedWithoutCancel = false; + }); + } + async animateDialog(animation) { + // Always cancel the previous animations. Animations can include `fill` + // modes that need to be cleared when `quick` is toggled. If not, content + // that faded out will remain hidden when a `quick` dialog re-opens after + // previously opening and closing without `quick`. + this.cancelAnimations?.abort(); + this.cancelAnimations = new AbortController(); + if (this.quick) { + return; + } + const { dialog, scrim, container, headline, content, actions } = this; + if (!dialog || !scrim || !container || !headline || !content || !actions) { + return; + } + const { container: containerAnimate, dialog: dialogAnimate, scrim: scrimAnimate, headline: headlineAnimate, content: contentAnimate, actions: actionsAnimate, } = animation; + const elementAndAnimation = [ + [dialog, dialogAnimate ?? []], + [scrim, scrimAnimate ?? []], + [container, containerAnimate ?? []], + [headline, headlineAnimate ?? []], + [content, contentAnimate ?? []], + [actions, actionsAnimate ?? []], + ]; + const animations = []; + for (const [element, animation] of elementAndAnimation) { + for (const animateArgs of animation) { + const animation = element.animate(...animateArgs); + this.cancelAnimations.signal.addEventListener('abort', () => { + animation.cancel(); + }); + animations.push(animation); + } + } + await Promise.all(animations.map((animation) => animation.finished.catch(() => { + // Ignore intentional AbortErrors when calling `animation.cancel()`. + }))); + } + handleHeadlineChange(event) { + const slot = event.target; + this.hasHeadline = slot.assignedElements().length > 0; + } + handleActionsChange(event) { + const slot = event.target; + this.hasActions = slot.assignedElements().length > 0; + } + handleIconChange(event) { + const slot = event.target; + this.hasIcon = slot.assignedElements().length > 0; + } + handleAnchorIntersection(entry) { + const { target, isIntersecting } = entry; + if (target === this.topAnchor) { + this.isAtScrollTop = isIntersecting; + } + if (target === this.bottomAnchor) { + this.isAtScrollBottom = isIntersecting; + } + } + getIsConnectedPromise() { + return new Promise((resolve) => { + this.isConnectedPromiseResolve = resolve; + }); + } + handleFocusTrapFocus(event) { + const [firstFocusableChild, lastFocusableChild] = this.getFirstAndLastFocusableChildren(); + if (!firstFocusableChild || !lastFocusableChild) { + // When a dialog does not have focusable children, the dialog itself + // receives focus. + this.dialog?.focus(); + return; + } + // To determine which child to focus, we need to know which focus trap + // received focus... + const isFirstFocusTrap = event.target === this.firstFocusTrap; + const isLastFocusTrap = !isFirstFocusTrap; + // ...and where the focus came from (what was previously focused). + const focusCameFromFirstChild = event.relatedTarget === firstFocusableChild; + const focusCameFromLastChild = event.relatedTarget === lastFocusableChild; + // Although this is a focus trap, focus can come from outside the trap. + // This can happen when elements are programmatically `focus()`'d. It also + // happens when focus leaves and returns to the window, such as clicking on + // the browser's URL bar and pressing Tab, or switching focus between + // iframes. + const focusCameFromOutsideDialog = !focusCameFromFirstChild && !focusCameFromLastChild; + // Focus the dialog's first child when we reach the end of the dialog and + // focus is moving forward. Or, when focus is moving forwards into the + // dialog from outside of the window. + const shouldFocusFirstChild = (isLastFocusTrap && focusCameFromLastChild) || + (isFirstFocusTrap && focusCameFromOutsideDialog); + if (shouldFocusFirstChild) { + firstFocusableChild.focus(); + return; + } + // Focus the dialog's last child when we reach the beginning of the dialog + // and focus is moving backward. Or, when focus is moving backwards into the + // dialog from outside of the window. + const shouldFocusLastChild = (isFirstFocusTrap && focusCameFromFirstChild) || + (isLastFocusTrap && focusCameFromOutsideDialog); + if (shouldFocusLastChild) { + lastFocusableChild.focus(); + return; + } + // The booleans above are verbose for readability, but code executation + // won't actually reach here. + } + getFirstAndLastFocusableChildren() { + if (!this.treewalker) { + return [null, null]; + } + let firstFocusableChild = null; + let lastFocusableChild = null; + // Reset the current node back to the root host element. + this.treewalker.currentNode = this.treewalker.root; + while (this.treewalker.nextNode()) { + // Cast as Element since the TreeWalker filter only accepts Elements. + const nextChild = this.treewalker.currentNode; + if (!isFocusable(nextChild)) { + continue; + } + if (!firstFocusableChild) { + firstFocusableChild = nextChild; + } + lastFocusableChild = nextChild; + } + // We set lastFocusableChild immediately after finding a + // firstFocusableChild, which means the pair is either both null or both + // non-null. Cast since TypeScript does not recognize this. + return [firstFocusableChild, lastFocusableChild]; + } +} +__decorate([ + n({ type: Boolean }) +], Dialog.prototype, "open", null); +__decorate([ + n({ type: Boolean }) +], Dialog.prototype, "quick", void 0); +__decorate([ + n({ attribute: false }) +], Dialog.prototype, "returnValue", void 0); +__decorate([ + n() +], Dialog.prototype, "type", void 0); +__decorate([ + n({ type: Boolean, attribute: 'no-focus-trap' }) +], Dialog.prototype, "noFocusTrap", void 0); +__decorate([ + i('dialog') +], Dialog.prototype, "dialog", void 0); +__decorate([ + i('.scrim') +], Dialog.prototype, "scrim", void 0); +__decorate([ + i('.container') +], Dialog.prototype, "container", void 0); +__decorate([ + i('.headline') +], Dialog.prototype, "headline", void 0); +__decorate([ + i('.content') +], Dialog.prototype, "content", void 0); +__decorate([ + i('.actions') +], Dialog.prototype, "actions", void 0); +__decorate([ + t() +], Dialog.prototype, "isAtScrollTop", void 0); +__decorate([ + t() +], Dialog.prototype, "isAtScrollBottom", void 0); +__decorate([ + i('.scroller') +], Dialog.prototype, "scroller", void 0); +__decorate([ + i('.top.anchor') +], Dialog.prototype, "topAnchor", void 0); +__decorate([ + i('.bottom.anchor') +], Dialog.prototype, "bottomAnchor", void 0); +__decorate([ + i('.focus-trap') +], Dialog.prototype, "firstFocusTrap", void 0); +__decorate([ + t() +], Dialog.prototype, "hasHeadline", void 0); +__decorate([ + t() +], Dialog.prototype, "hasActions", void 0); +__decorate([ + t() +], Dialog.prototype, "hasIcon", void 0); +function isFocusable(element) { + // Check if the element is a known built-in focusable element: + // - and with `href` attributes. + // - Form controls that are not disabled. + // - `contenteditable` elements. + // - Anything with a non-negative `tabindex`. + const knownFocusableElements = ':is(button,input,select,textarea,object,:is(a,area)[href],[tabindex],[contenteditable=true])'; + const notDisabled = ':not(:disabled,[disabled])'; + const notNegativeTabIndex = ':not([tabindex^="-"])'; + if (element.matches(knownFocusableElements + notDisabled + notNegativeTabIndex)) { + return true; + } + const isCustomElement = element.localName.includes('-'); + if (!isCustomElement) { + return false; + } + // If a custom element does not have a tabindex, it may still be focusable + // if it delegates focus with a shadow root. We also need to check again if + // the custom element is a disabled form control. + if (!element.matches(notDisabled)) { + return false; + } + return element.shadowRoot?.delegatesFocus ?? false; +} + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./dialog/internal/dialog-styles.css. +const styles = i$1 `:host{border-start-start-radius:var(--md-dialog-container-shape-start-start, var(--md-dialog-container-shape, var(--md-sys-shape-corner-extra-large, 28px)));border-start-end-radius:var(--md-dialog-container-shape-start-end, var(--md-dialog-container-shape, var(--md-sys-shape-corner-extra-large, 28px)));border-end-end-radius:var(--md-dialog-container-shape-end-end, var(--md-dialog-container-shape, var(--md-sys-shape-corner-extra-large, 28px)));border-end-start-radius:var(--md-dialog-container-shape-end-start, var(--md-dialog-container-shape, var(--md-sys-shape-corner-extra-large, 28px)));display:contents;margin:auto;max-height:min(560px,100% - 48px);max-width:min(560px,100% - 48px);min-height:140px;min-width:280px;position:fixed;height:fit-content;width:fit-content}dialog{background:rgba(0,0,0,0);border:none;border-radius:inherit;flex-direction:column;height:inherit;margin:inherit;max-height:inherit;max-width:inherit;min-height:inherit;min-width:inherit;outline:none;overflow:visible;padding:0;width:inherit}dialog[open]{display:flex}::backdrop{background:none}.scrim{background:var(--md-sys-color-scrim, #000);display:none;inset:0;opacity:32%;pointer-events:none;position:fixed;z-index:1}:host([open]) .scrim{display:flex}h2{all:unset;align-self:stretch}.headline{align-items:center;color:var(--md-dialog-headline-color, var(--md-sys-color-on-surface, #1d1b20));display:flex;flex-direction:column;font-family:var(--md-dialog-headline-font, var(--md-sys-typescale-headline-small-font, var(--md-ref-typeface-brand, Roboto)));font-size:var(--md-dialog-headline-size, var(--md-sys-typescale-headline-small-size, 1.5rem));line-height:var(--md-dialog-headline-line-height, var(--md-sys-typescale-headline-small-line-height, 2rem));font-weight:var(--md-dialog-headline-weight, var(--md-sys-typescale-headline-small-weight, var(--md-ref-typeface-weight-regular, 400)));position:relative}slot[name=headline]::slotted(*){align-items:center;align-self:stretch;box-sizing:border-box;display:flex;gap:8px;padding:24px 24px 0}.icon{display:flex}slot[name=icon]::slotted(*){color:var(--md-dialog-icon-color, var(--md-sys-color-secondary, #625b71));fill:currentColor;font-size:var(--md-dialog-icon-size, 24px);margin-top:24px;height:var(--md-dialog-icon-size, 24px);width:var(--md-dialog-icon-size, 24px)}.has-icon slot[name=headline]::slotted(*){justify-content:center;padding-top:16px}.scrollable slot[name=headline]::slotted(*){padding-bottom:16px}.scrollable.has-headline slot[name=content]::slotted(*){padding-top:8px}.container{border-radius:inherit;display:flex;flex-direction:column;flex-grow:1;overflow:hidden;position:relative;transform-origin:top}.container::before{background:var(--md-dialog-container-color, var(--md-sys-color-surface-container-high, #ece6f0));border-radius:inherit;content:"";inset:0;position:absolute}.scroller{display:flex;flex:1;flex-direction:column;overflow:hidden;z-index:1}.scrollable .scroller{overflow-y:scroll}.content{color:var(--md-dialog-supporting-text-color, var(--md-sys-color-on-surface-variant, #49454f));font-family:var(--md-dialog-supporting-text-font, var(--md-sys-typescale-body-medium-font, var(--md-ref-typeface-plain, Roboto)));font-size:var(--md-dialog-supporting-text-size, var(--md-sys-typescale-body-medium-size, 0.875rem));line-height:var(--md-dialog-supporting-text-line-height, var(--md-sys-typescale-body-medium-line-height, 1.25rem));flex:1;font-weight:var(--md-dialog-supporting-text-weight, var(--md-sys-typescale-body-medium-weight, var(--md-ref-typeface-weight-regular, 400)));height:min-content;position:relative}slot[name=content]::slotted(*){box-sizing:border-box;padding:24px}.anchor{position:absolute}.top.anchor{top:0}.bottom.anchor{bottom:0}.actions{position:relative}slot[name=actions]::slotted(*){box-sizing:border-box;display:flex;gap:8px;justify-content:flex-end;padding:16px 24px 24px}.has-actions slot[name=content]::slotted(*){padding-bottom:8px}md-divider{display:none;position:absolute}.has-headline.show-top-divider .headline md-divider,.has-actions.show-bottom-divider .actions md-divider{display:flex}.headline md-divider{bottom:0}.actions md-divider{top:0}@media(forced-colors: active){dialog{outline:2px solid WindowText}} +`; + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @summary Dialogs can require an action, communicate information, or help + * users accomplish a task. There are two types of dialogs: basic and + * full-screen. + * + * @description + * A dialog is a modal window that appears in front of app content to provide + * critical information or ask for a decision. Dialogs disable all app + * functionality when they appear, and remain on screen until confirmed, + * dismissed, or a required action has been taken. + * + * Dialogs are purposefully interruptive, so they should be used sparingly. + * A less disruptive alternative is to use a menu, which provides options + * without interrupting a user’s experience. + * + * On mobile devices only, complex dialogs should be displayed fullscreen. + * + * __Example usages:__ + * - Common use cases for basic dialogs include alerts, quick selection, and + * confirmation. + * - More complex dialogs may contain actions that require a series of tasks + * to complete. One example is creating a calendar entry with the event title, + * date, location, and time. + * + * @final + * @suppress {visibility} + */ +let MdDialog = class MdDialog extends Dialog { +}; +MdDialog.styles = [styles]; +MdDialog = __decorate([ + e('md-dialog') +], MdDialog); + +export { MdDialog }; diff --git a/md-web/divider.js b/md-web/divider.js new file mode 100644 index 0000000..4d026d0 --- /dev/null +++ b/md-web/divider.js @@ -0,0 +1,3 @@ +export const __dummy_loader = () => {}; + +export { ah as MdDivider } from './core.js'; diff --git a/md-web/fab.js b/md-web/fab.js new file mode 100644 index 0000000..ef18590 --- /dev/null +++ b/md-web/fab.js @@ -0,0 +1,113 @@ +export const __dummy_loader = () => {}; + +import { i, J as styles$2, M as styles$3, _ as __decorate, O as Fab, e } from './core.js'; + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./fab/internal/fab-styles.css. +const styles$1 = i `:host{--_container-color: var(--md-fab-container-color, var(--md-sys-color-surface-container-high, #ece6f0));--_container-elevation: var(--md-fab-container-elevation, 3);--_container-height: var(--md-fab-container-height, 56px);--_container-shadow-color: var(--md-fab-container-shadow-color, var(--md-sys-color-shadow, #000));--_container-width: var(--md-fab-container-width, 56px);--_focus-container-elevation: var(--md-fab-focus-container-elevation, 3);--_focus-icon-color: var(--md-fab-focus-icon-color, var(--md-sys-color-primary, #6750a4));--_hover-container-elevation: var(--md-fab-hover-container-elevation, 4);--_hover-icon-color: var(--md-fab-hover-icon-color, var(--md-sys-color-primary, #6750a4));--_hover-state-layer-color: var(--md-fab-hover-state-layer-color, var(--md-sys-color-primary, #6750a4));--_hover-state-layer-opacity: var(--md-fab-hover-state-layer-opacity, 0.08);--_icon-color: var(--md-fab-icon-color, var(--md-sys-color-primary, #6750a4));--_icon-size: var(--md-fab-icon-size, 24px);--_lowered-container-color: var(--md-fab-lowered-container-color, var(--md-sys-color-surface-container-low, #f7f2fa));--_lowered-container-elevation: var(--md-fab-lowered-container-elevation, 1);--_lowered-focus-container-elevation: var(--md-fab-lowered-focus-container-elevation, 1);--_lowered-hover-container-elevation: var(--md-fab-lowered-hover-container-elevation, 2);--_lowered-pressed-container-elevation: var(--md-fab-lowered-pressed-container-elevation, 1);--_pressed-container-elevation: var(--md-fab-pressed-container-elevation, 3);--_pressed-icon-color: var(--md-fab-pressed-icon-color, var(--md-sys-color-primary, #6750a4));--_pressed-state-layer-color: var(--md-fab-pressed-state-layer-color, var(--md-sys-color-primary, #6750a4));--_pressed-state-layer-opacity: var(--md-fab-pressed-state-layer-opacity, 0.12);--_focus-label-text-color: var(--md-fab-focus-label-text-color, var(--md-sys-color-primary, #6750a4));--_hover-label-text-color: var(--md-fab-hover-label-text-color, var(--md-sys-color-primary, #6750a4));--_label-text-color: var(--md-fab-label-text-color, var(--md-sys-color-primary, #6750a4));--_label-text-font: var(--md-fab-label-text-font, var(--md-sys-typescale-label-large-font, var(--md-ref-typeface-plain, Roboto)));--_label-text-line-height: var(--md-fab-label-text-line-height, var(--md-sys-typescale-label-large-line-height, 1.25rem));--_label-text-size: var(--md-fab-label-text-size, var(--md-sys-typescale-label-large-size, 0.875rem));--_label-text-weight: var(--md-fab-label-text-weight, var(--md-sys-typescale-label-large-weight, var(--md-ref-typeface-weight-medium, 500)));--_large-container-height: var(--md-fab-large-container-height, 96px);--_large-container-width: var(--md-fab-large-container-width, 96px);--_large-icon-size: var(--md-fab-large-icon-size, 36px);--_pressed-label-text-color: var(--md-fab-pressed-label-text-color, var(--md-sys-color-primary, #6750a4));--_primary-container-color: var(--md-fab-primary-container-color, var(--md-sys-color-primary-container, #eaddff));--_primary-focus-icon-color: var(--md-fab-primary-focus-icon-color, var(--md-sys-color-on-primary-container, #21005d));--_primary-focus-label-text-color: var(--md-fab-primary-focus-label-text-color, var(--md-sys-color-on-primary-container, #21005d));--_primary-hover-icon-color: var(--md-fab-primary-hover-icon-color, var(--md-sys-color-on-primary-container, #21005d));--_primary-hover-label-text-color: var(--md-fab-primary-hover-label-text-color, var(--md-sys-color-on-primary-container, #21005d));--_primary-hover-state-layer-color: var(--md-fab-primary-hover-state-layer-color, var(--md-sys-color-on-primary-container, #21005d));--_primary-icon-color: var(--md-fab-primary-icon-color, var(--md-sys-color-on-primary-container, #21005d));--_primary-label-text-color: var(--md-fab-primary-label-text-color, var(--md-sys-color-on-primary-container, #21005d));--_primary-pressed-icon-color: var(--md-fab-primary-pressed-icon-color, var(--md-sys-color-on-primary-container, #21005d));--_primary-pressed-label-text-color: var(--md-fab-primary-pressed-label-text-color, var(--md-sys-color-on-primary-container, #21005d));--_primary-pressed-state-layer-color: var(--md-fab-primary-pressed-state-layer-color, var(--md-sys-color-on-primary-container, #21005d));--_secondary-container-color: var(--md-fab-secondary-container-color, var(--md-sys-color-secondary-container, #e8def8));--_secondary-focus-icon-color: var(--md-fab-secondary-focus-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_secondary-focus-label-text-color: var(--md-fab-secondary-focus-label-text-color, var(--md-sys-color-on-secondary-container, #1d192b));--_secondary-hover-icon-color: var(--md-fab-secondary-hover-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_secondary-hover-label-text-color: var(--md-fab-secondary-hover-label-text-color, var(--md-sys-color-on-secondary-container, #1d192b));--_secondary-hover-state-layer-color: var(--md-fab-secondary-hover-state-layer-color, var(--md-sys-color-on-secondary-container, #1d192b));--_secondary-icon-color: var(--md-fab-secondary-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_secondary-label-text-color: var(--md-fab-secondary-label-text-color, var(--md-sys-color-on-secondary-container, #1d192b));--_secondary-pressed-icon-color: var(--md-fab-secondary-pressed-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_secondary-pressed-label-text-color: var(--md-fab-secondary-pressed-label-text-color, var(--md-sys-color-on-secondary-container, #1d192b));--_secondary-pressed-state-layer-color: var(--md-fab-secondary-pressed-state-layer-color, var(--md-sys-color-on-secondary-container, #1d192b));--_small-container-height: var(--md-fab-small-container-height, 40px);--_small-container-width: var(--md-fab-small-container-width, 40px);--_small-icon-size: var(--md-fab-small-icon-size, 24px);--_tertiary-container-color: var(--md-fab-tertiary-container-color, var(--md-sys-color-tertiary-container, #ffd8e4));--_tertiary-focus-icon-color: var(--md-fab-tertiary-focus-icon-color, var(--md-sys-color-on-tertiary-container, #31111d));--_tertiary-focus-label-text-color: var(--md-fab-tertiary-focus-label-text-color, var(--md-sys-color-on-tertiary-container, #31111d));--_tertiary-hover-icon-color: var(--md-fab-tertiary-hover-icon-color, var(--md-sys-color-on-tertiary-container, #31111d));--_tertiary-hover-label-text-color: var(--md-fab-tertiary-hover-label-text-color, var(--md-sys-color-on-tertiary-container, #31111d));--_tertiary-hover-state-layer-color: var(--md-fab-tertiary-hover-state-layer-color, var(--md-sys-color-on-tertiary-container, #31111d));--_tertiary-icon-color: var(--md-fab-tertiary-icon-color, var(--md-sys-color-on-tertiary-container, #31111d));--_tertiary-label-text-color: var(--md-fab-tertiary-label-text-color, var(--md-sys-color-on-tertiary-container, #31111d));--_tertiary-pressed-icon-color: var(--md-fab-tertiary-pressed-icon-color, var(--md-sys-color-on-tertiary-container, #31111d));--_tertiary-pressed-label-text-color: var(--md-fab-tertiary-pressed-label-text-color, var(--md-sys-color-on-tertiary-container, #31111d));--_tertiary-pressed-state-layer-color: var(--md-fab-tertiary-pressed-state-layer-color, var(--md-sys-color-on-tertiary-container, #31111d));--_container-shape-start-start: var(--md-fab-container-shape-start-start, var(--md-fab-container-shape, var(--md-sys-shape-corner-large, 16px)));--_container-shape-start-end: var(--md-fab-container-shape-start-end, var(--md-fab-container-shape, var(--md-sys-shape-corner-large, 16px)));--_container-shape-end-end: var(--md-fab-container-shape-end-end, var(--md-fab-container-shape, var(--md-sys-shape-corner-large, 16px)));--_container-shape-end-start: var(--md-fab-container-shape-end-start, var(--md-fab-container-shape, var(--md-sys-shape-corner-large, 16px)));--_large-container-shape-start-start: var(--md-fab-large-container-shape-start-start, var(--md-fab-large-container-shape, var(--md-sys-shape-corner-extra-large, 28px)));--_large-container-shape-start-end: var(--md-fab-large-container-shape-start-end, var(--md-fab-large-container-shape, var(--md-sys-shape-corner-extra-large, 28px)));--_large-container-shape-end-end: var(--md-fab-large-container-shape-end-end, var(--md-fab-large-container-shape, var(--md-sys-shape-corner-extra-large, 28px)));--_large-container-shape-end-start: var(--md-fab-large-container-shape-end-start, var(--md-fab-large-container-shape, var(--md-sys-shape-corner-extra-large, 28px)));--_small-container-shape-start-start: var(--md-fab-small-container-shape-start-start, var(--md-fab-small-container-shape, var(--md-sys-shape-corner-medium, 12px)));--_small-container-shape-start-end: var(--md-fab-small-container-shape-start-end, var(--md-fab-small-container-shape, var(--md-sys-shape-corner-medium, 12px)));--_small-container-shape-end-end: var(--md-fab-small-container-shape-end-end, var(--md-fab-small-container-shape, var(--md-sys-shape-corner-medium, 12px)));--_small-container-shape-end-start: var(--md-fab-small-container-shape-end-start, var(--md-fab-small-container-shape, var(--md-sys-shape-corner-medium, 12px)));cursor:pointer}:host([size=small][touch-target=wrapper]){margin:max(0px,48px - var(--_small-container-height))}.fab{cursor:inherit}.fab .icon ::slotted(*){color:var(--_icon-color)}.fab:focus{color:var(--_focus-icon-color)}.fab:hover{color:var(--_hover-icon-color)}.fab:active{color:var(--_pressed-icon-color)}.fab.primary{background-color:var(--_primary-container-color);--md-ripple-hover-color: var(--_primary-hover-state-layer-color);--md-ripple-pressed-color: var(--_primary-pressed-state-layer-color)}.fab.primary .icon ::slotted(*){color:var(--_primary-icon-color)}.fab.primary:focus{color:var(--_primary-focus-icon-color)}.fab.primary:hover{color:var(--_primary-hover-icon-color)}.fab.primary:active{color:var(--_primary-pressed-icon-color)}.fab.primary .label{color:var(--_primary-label-text-color)}.fab:hover .fab.primary .label{color:var(--_primary-hover-label-text-color)}.fab:focus .fab.primary .label{color:var(--_primary-focus-label-text-color)}.fab:active .fab.primary .label{color:var(--_primary-pressed-label-text-color)}.fab.secondary{background-color:var(--_secondary-container-color);--md-ripple-hover-color: var(--_secondary-hover-state-layer-color);--md-ripple-pressed-color: var(--_secondary-pressed-state-layer-color)}.fab.secondary .icon ::slotted(*){color:var(--_secondary-icon-color)}.fab.secondary:focus{color:var(--_secondary-focus-icon-color)}.fab.secondary:hover{color:var(--_secondary-hover-icon-color)}.fab.secondary:active{color:var(--_secondary-pressed-icon-color)}.fab.secondary .label{color:var(--_secondary-label-text-color)}.fab:hover .fab.secondary .label{color:var(--_secondary-hover-label-text-color)}.fab:focus .fab.secondary .label{color:var(--_secondary-focus-label-text-color)}.fab:active .fab.secondary .label{color:var(--_secondary-pressed-label-text-color)}.fab.tertiary{background-color:var(--_tertiary-container-color);--md-ripple-hover-color: var(--_tertiary-hover-state-layer-color);--md-ripple-pressed-color: var(--_tertiary-pressed-state-layer-color)}.fab.tertiary .icon ::slotted(*){color:var(--_tertiary-icon-color)}.fab.tertiary:focus{color:var(--_tertiary-focus-icon-color)}.fab.tertiary:hover{color:var(--_tertiary-hover-icon-color)}.fab.tertiary:active{color:var(--_tertiary-pressed-icon-color)}.fab.tertiary .label{color:var(--_tertiary-label-text-color)}.fab:hover .fab.tertiary .label{color:var(--_tertiary-hover-label-text-color)}.fab:focus .fab.tertiary .label{color:var(--_tertiary-focus-label-text-color)}.fab:active .fab.tertiary .label{color:var(--_tertiary-pressed-label-text-color)}.fab.extended slot span{padding-inline-start:4px}.fab.small{width:var(--_small-container-width);height:var(--_small-container-height)}.fab.small .icon ::slotted(*){width:var(--_small-icon-size);height:var(--_small-icon-size);font-size:var(--_small-icon-size)}.fab.small,.fab.small .ripple{border-start-start-radius:var(--_small-container-shape-start-start);border-start-end-radius:var(--_small-container-shape-start-end);border-end-start-radius:var(--_small-container-shape-end-start);border-end-end-radius:var(--_small-container-shape-end-end)}.fab.small md-focus-ring{--md-focus-ring-shape-start-start: var(--_small-container-shape-start-start);--md-focus-ring-shape-start-end: var(--_small-container-shape-start-end);--md-focus-ring-shape-end-end: var(--_small-container-shape-end-end);--md-focus-ring-shape-end-start: var(--_small-container-shape-end-start)} +`; + +/** + * @license + * Copyright 2022 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @summary Floating action buttons (FABs) help people take primary actions. + * They’re used to represent the most important action on a screen, such as + * Create or Reply. + * + * @description + * __Emphasis:__ High emphasis – For the primary, most important, or most common + * action on a screen + * + * __Rationale:__ The FAB remains the default component for a screen’s primary + * action. It comes in three sizes: small FAB, FAB, and large FAB. The extended + * FAB’s wider format and text label give it more visual prominence than a FAB. + * It’s often used on larger screens where a FAB would seem too small. + * + * __Example usages:__ + * - FAB + * - Create + * - Compose + * - Extended FAB + * - Create + * - Compose + * - New Thread + * - New File + * + * @final + * @suppress {visibility} + */ +let MdFab = class MdFab extends Fab { +}; +MdFab.styles = [styles$2, styles$1, styles$3]; +MdFab = __decorate([ + e('md-fab') +], MdFab); + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./fab/internal/fab-branded-styles.css. +const styles = i `:host{--_container-color: var(--md-fab-branded-container-color, var(--md-sys-color-surface-container-high, #ece6f0));--_container-elevation: var(--md-fab-branded-container-elevation, 3);--_container-height: var(--md-fab-branded-container-height, 56px);--_container-shadow-color: var(--md-fab-branded-container-shadow-color, var(--md-sys-color-shadow, #000));--_container-width: var(--md-fab-branded-container-width, 56px);--_focus-container-elevation: var(--md-fab-branded-focus-container-elevation, 3);--_hover-container-elevation: var(--md-fab-branded-hover-container-elevation, 4);--_hover-state-layer-color: var(--md-fab-branded-hover-state-layer-color, var(--md-sys-color-primary, #6750a4));--_hover-state-layer-opacity: var(--md-fab-branded-hover-state-layer-opacity, 0.08);--_icon-size: var(--md-fab-branded-icon-size, 36px);--_lowered-container-color: var(--md-fab-branded-lowered-container-color, var(--md-sys-color-surface-container-low, #f7f2fa));--_lowered-container-elevation: var(--md-fab-branded-lowered-container-elevation, 1);--_lowered-focus-container-elevation: var(--md-fab-branded-lowered-focus-container-elevation, 1);--_lowered-hover-container-elevation: var(--md-fab-branded-lowered-hover-container-elevation, 2);--_lowered-pressed-container-elevation: var(--md-fab-branded-lowered-pressed-container-elevation, 1);--_pressed-container-elevation: var(--md-fab-branded-pressed-container-elevation, 3);--_pressed-state-layer-color: var(--md-fab-branded-pressed-state-layer-color, var(--md-sys-color-primary, #6750a4));--_pressed-state-layer-opacity: var(--md-fab-branded-pressed-state-layer-opacity, 0.12);--_focus-label-text-color: var(--md-fab-branded-focus-label-text-color, var(--md-sys-color-primary, #6750a4));--_hover-label-text-color: var(--md-fab-branded-hover-label-text-color, var(--md-sys-color-primary, #6750a4));--_label-text-color: var(--md-fab-branded-label-text-color, var(--md-sys-color-on-surface, #1d1b20));--_label-text-font: var(--md-fab-branded-label-text-font, var(--md-sys-typescale-label-large-font, var(--md-ref-typeface-plain, Roboto)));--_label-text-size: var(--md-fab-branded-label-text-size, var(--md-sys-typescale-label-large-size, 0.875rem));--_label-text-line-height: var(--md-fab-branded-label-text-line-height, var(--md-sys-typescale-label-large-line-height, 1.25rem));--_label-text-weight: var(--md-fab-branded-label-text-weight, var(--md-sys-typescale-label-large-weight, var(--md-ref-typeface-weight-medium, 500)));--_large-container-height: var(--md-fab-branded-large-container-height, 96px);--_large-container-width: var(--md-fab-branded-large-container-width, 96px);--_large-icon-size: var(--md-fab-branded-large-icon-size, 48px);--_pressed-label-text-color: var(--md-fab-branded-pressed-label-text-color, var(--md-sys-color-primary, #6750a4));--_container-shape-start-start: var(--md-fab-branded-container-shape-start-start, var(--md-fab-branded-container-shape, var(--md-sys-shape-corner-large, 16px)));--_container-shape-start-end: var(--md-fab-branded-container-shape-start-end, var(--md-fab-branded-container-shape, var(--md-sys-shape-corner-large, 16px)));--_container-shape-end-end: var(--md-fab-branded-container-shape-end-end, var(--md-fab-branded-container-shape, var(--md-sys-shape-corner-large, 16px)));--_container-shape-end-start: var(--md-fab-branded-container-shape-end-start, var(--md-fab-branded-container-shape, var(--md-sys-shape-corner-large, 16px)));--_large-container-shape-start-start: var(--md-fab-branded-large-container-shape-start-start, var(--md-fab-branded-large-container-shape, var(--md-sys-shape-corner-extra-large, 28px)));--_large-container-shape-start-end: var(--md-fab-branded-large-container-shape-start-end, var(--md-fab-branded-large-container-shape, var(--md-sys-shape-corner-extra-large, 28px)));--_large-container-shape-end-end: var(--md-fab-branded-large-container-shape-end-end, var(--md-fab-branded-large-container-shape, var(--md-sys-shape-corner-extra-large, 28px)));--_large-container-shape-end-start: var(--md-fab-branded-large-container-shape-end-start, var(--md-fab-branded-large-container-shape, var(--md-sys-shape-corner-extra-large, 28px)))} +`; + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @summary Floating action buttons (FABs) help people take primary actions. + * They’re used to represent the most important action on a screen, such as + * Create or Reply. + * + * @description + * __Emphasis:__ High emphasis – For the primary, most important, or most common + * action on a screen + * + * __Rationale:__ The FAB remains the default component for a screen’s primary + * action. It comes in three sizes: small FAB, FAB, and large FAB. The extended + * FAB’s wider format and text label give it more visual prominence than a FAB. + * It’s often used on larger screens where a FAB would seem too small. Branded + * FABs are used to specifically call attention to branded logo icons. + * + * __Example usages:__ + * - FAB + * - Create + * - Compose + * - Extended FAB + * - Create + * - Compose + * - New Thread + * - New File + * + * @final + * @suppress {visibility} + */ +let MdBrandedFab = class MdBrandedFab extends Fab { + getRenderClasses() { + return { + ...super.getRenderClasses(), + 'primary': false, + 'secondary': false, + 'tertiary': false, + 'small': false, + }; + } +}; +MdBrandedFab.styles = [ + styles$2, + styles, + styles$3, +]; +MdBrandedFab = __decorate([ + e('md-branded-fab') +], MdBrandedFab); diff --git a/md-web/field.js b/md-web/field.js new file mode 100644 index 0000000..1d09100 --- /dev/null +++ b/md-web/field.js @@ -0,0 +1,3 @@ +export const __dummy_loader = () => {}; + +import './core.js'; diff --git a/md-web/icon-button.js b/md-web/icon-button.js new file mode 100644 index 0000000..6e15251 --- /dev/null +++ b/md-web/icon-button.js @@ -0,0 +1,185 @@ +export const __dummy_loader = () => {}; + +import { i, a2 as styles$4, _ as __decorate, a3 as IconButton, e } from './core.js'; + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./iconbutton/internal/standard-styles.css. +const styles$3 = i `:host{--_disabled-icon-color: var(--md-icon-button-disabled-icon-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-icon-opacity: var(--md-icon-button-disabled-icon-opacity, 0.38);--_icon-size: var(--md-icon-button-icon-size, 24px);--_selected-focus-icon-color: var(--md-icon-button-selected-focus-icon-color, var(--md-sys-color-primary, #6750a4));--_selected-hover-icon-color: var(--md-icon-button-selected-hover-icon-color, var(--md-sys-color-primary, #6750a4));--_selected-hover-state-layer-color: var(--md-icon-button-selected-hover-state-layer-color, var(--md-sys-color-primary, #6750a4));--_selected-hover-state-layer-opacity: var(--md-icon-button-selected-hover-state-layer-opacity, 0.08);--_selected-icon-color: var(--md-icon-button-selected-icon-color, var(--md-sys-color-primary, #6750a4));--_selected-pressed-icon-color: var(--md-icon-button-selected-pressed-icon-color, var(--md-sys-color-primary, #6750a4));--_selected-pressed-state-layer-color: var(--md-icon-button-selected-pressed-state-layer-color, var(--md-sys-color-primary, #6750a4));--_selected-pressed-state-layer-opacity: var(--md-icon-button-selected-pressed-state-layer-opacity, 0.12);--_state-layer-height: var(--md-icon-button-state-layer-height, 40px);--_state-layer-shape: var(--md-icon-button-state-layer-shape, var(--md-sys-shape-corner-full, 9999px));--_state-layer-width: var(--md-icon-button-state-layer-width, 40px);--_focus-icon-color: var(--md-icon-button-focus-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_hover-icon-color: var(--md-icon-button-hover-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_hover-state-layer-color: var(--md-icon-button-hover-state-layer-color, var(--md-sys-color-on-surface-variant, #49454f));--_hover-state-layer-opacity: var(--md-icon-button-hover-state-layer-opacity, 0.08);--_icon-color: var(--md-icon-button-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_pressed-icon-color: var(--md-icon-button-pressed-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_pressed-state-layer-color: var(--md-icon-button-pressed-state-layer-color, var(--md-sys-color-on-surface-variant, #49454f));--_pressed-state-layer-opacity: var(--md-icon-button-pressed-state-layer-opacity, 0.12);--_container-shape-start-start: 0;--_container-shape-start-end: 0;--_container-shape-end-end: 0;--_container-shape-end-start: 0;--_container-height: 0;--_container-width: 0;height:var(--_state-layer-height);width:var(--_state-layer-width)}:host([touch-target=wrapper]){margin:max(0px,(48px - var(--_state-layer-height))/2) max(0px,(48px - var(--_state-layer-width))/2)}md-focus-ring{--md-focus-ring-shape-start-start: var(--_state-layer-shape);--md-focus-ring-shape-start-end: var(--_state-layer-shape);--md-focus-ring-shape-end-end: var(--_state-layer-shape);--md-focus-ring-shape-end-start: var(--_state-layer-shape)}.standard{background-color:rgba(0,0,0,0);color:var(--_icon-color);--md-ripple-hover-color: var(--_hover-state-layer-color);--md-ripple-hover-opacity: var(--_hover-state-layer-opacity);--md-ripple-pressed-color: var(--_pressed-state-layer-color);--md-ripple-pressed-opacity: var(--_pressed-state-layer-opacity)}.standard:hover{color:var(--_hover-icon-color)}.standard:focus{color:var(--_focus-icon-color)}.standard:active{color:var(--_pressed-icon-color)}.standard:is(:disabled,[aria-disabled=true]){color:var(--_disabled-icon-color)}md-ripple{border-radius:var(--_state-layer-shape)}.standard:is(:disabled,[aria-disabled=true]){opacity:var(--_disabled-icon-opacity)}.selected{--md-ripple-hover-color: var(--_selected-hover-state-layer-color);--md-ripple-hover-opacity: var(--_selected-hover-state-layer-opacity);--md-ripple-pressed-color: var(--_selected-pressed-state-layer-color);--md-ripple-pressed-opacity: var(--_selected-pressed-state-layer-opacity)}.selected:not(:disabled,[aria-disabled=true]){color:var(--_selected-icon-color)}.selected:not(:disabled,[aria-disabled=true]):hover{color:var(--_selected-hover-icon-color)}.selected:not(:disabled,[aria-disabled=true]):focus{color:var(--_selected-focus-icon-color)}.selected:not(:disabled,[aria-disabled=true]):active{color:var(--_selected-pressed-icon-color)} +`; + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @summary Icon buttons help people take supplementary actions with a single + * tap. + * + * @description + * __Emphasis:__ Low emphasis – For optional or supplementary actions with the + * least amount of prominence. + * + * __Rationale:__ The most compact and unobtrusive type of button, icon buttons + * are used for optional supplementary actions such as "Bookmark" or "Star." + * + * __Example usages:__ + * - Add to Favorites + * - Print + * + * @final + * @suppress {visibility} + */ +let MdIconButton = class MdIconButton extends IconButton { + getRenderClasses() { + return { + ...super.getRenderClasses(), + 'standard': true, + }; + } +}; +MdIconButton.styles = [styles$4, styles$3]; +MdIconButton = __decorate([ + e('md-icon-button') +], MdIconButton); + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./iconbutton/internal/filled-styles.css. +const styles$2 = i `:host{--_container-color: var(--md-filled-icon-button-container-color, var(--md-sys-color-primary, #6750a4));--_container-height: var(--md-filled-icon-button-container-height, 40px);--_container-width: var(--md-filled-icon-button-container-width, 40px);--_disabled-container-color: var(--md-filled-icon-button-disabled-container-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-container-opacity: var(--md-filled-icon-button-disabled-container-opacity, 0.12);--_disabled-icon-color: var(--md-filled-icon-button-disabled-icon-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-icon-opacity: var(--md-filled-icon-button-disabled-icon-opacity, 0.38);--_focus-icon-color: var(--md-filled-icon-button-focus-icon-color, var(--md-sys-color-on-primary, #fff));--_hover-icon-color: var(--md-filled-icon-button-hover-icon-color, var(--md-sys-color-on-primary, #fff));--_hover-state-layer-color: var(--md-filled-icon-button-hover-state-layer-color, var(--md-sys-color-on-primary, #fff));--_hover-state-layer-opacity: var(--md-filled-icon-button-hover-state-layer-opacity, 0.08);--_icon-color: var(--md-filled-icon-button-icon-color, var(--md-sys-color-on-primary, #fff));--_icon-size: var(--md-filled-icon-button-icon-size, 24px);--_pressed-icon-color: var(--md-filled-icon-button-pressed-icon-color, var(--md-sys-color-on-primary, #fff));--_pressed-state-layer-color: var(--md-filled-icon-button-pressed-state-layer-color, var(--md-sys-color-on-primary, #fff));--_pressed-state-layer-opacity: var(--md-filled-icon-button-pressed-state-layer-opacity, 0.12);--_selected-container-color: var(--md-filled-icon-button-selected-container-color, var(--md-sys-color-primary, #6750a4));--_toggle-selected-focus-icon-color: var(--md-filled-icon-button-toggle-selected-focus-icon-color, var(--md-sys-color-on-primary, #fff));--_toggle-selected-hover-icon-color: var(--md-filled-icon-button-toggle-selected-hover-icon-color, var(--md-sys-color-on-primary, #fff));--_toggle-selected-hover-state-layer-color: var(--md-filled-icon-button-toggle-selected-hover-state-layer-color, var(--md-sys-color-on-primary, #fff));--_toggle-selected-icon-color: var(--md-filled-icon-button-toggle-selected-icon-color, var(--md-sys-color-on-primary, #fff));--_toggle-selected-pressed-icon-color: var(--md-filled-icon-button-toggle-selected-pressed-icon-color, var(--md-sys-color-on-primary, #fff));--_toggle-selected-pressed-state-layer-color: var(--md-filled-icon-button-toggle-selected-pressed-state-layer-color, var(--md-sys-color-on-primary, #fff));--_unselected-container-color: var(--md-filled-icon-button-unselected-container-color, var(--md-sys-color-surface-container-highest, #e6e0e9));--_toggle-focus-icon-color: var(--md-filled-icon-button-toggle-focus-icon-color, var(--md-sys-color-primary, #6750a4));--_toggle-hover-icon-color: var(--md-filled-icon-button-toggle-hover-icon-color, var(--md-sys-color-primary, #6750a4));--_toggle-hover-state-layer-color: var(--md-filled-icon-button-toggle-hover-state-layer-color, var(--md-sys-color-primary, #6750a4));--_toggle-icon-color: var(--md-filled-icon-button-toggle-icon-color, var(--md-sys-color-primary, #6750a4));--_toggle-pressed-icon-color: var(--md-filled-icon-button-toggle-pressed-icon-color, var(--md-sys-color-primary, #6750a4));--_toggle-pressed-state-layer-color: var(--md-filled-icon-button-toggle-pressed-state-layer-color, var(--md-sys-color-primary, #6750a4));--_container-shape-start-start: var(--md-filled-icon-button-container-shape-start-start, var(--md-filled-icon-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_container-shape-start-end: var(--md-filled-icon-button-container-shape-start-end, var(--md-filled-icon-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_container-shape-end-end: var(--md-filled-icon-button-container-shape-end-end, var(--md-filled-icon-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_container-shape-end-start: var(--md-filled-icon-button-container-shape-end-start, var(--md-filled-icon-button-container-shape, var(--md-sys-shape-corner-full, 9999px)))}.icon-button{color:var(--_icon-color);--md-ripple-hover-color: var(--_hover-state-layer-color);--md-ripple-hover-opacity: var(--_hover-state-layer-opacity);--md-ripple-pressed-color: var(--_pressed-state-layer-color);--md-ripple-pressed-opacity: var(--_pressed-state-layer-opacity)}.icon-button:hover{color:var(--_hover-icon-color)}.icon-button:focus{color:var(--_focus-icon-color)}.icon-button:active{color:var(--_pressed-icon-color)}.icon-button:is(:disabled,[aria-disabled=true]){color:var(--_disabled-icon-color)}.icon-button::before{background-color:var(--_container-color);border-radius:inherit;content:"";inset:0;position:absolute;z-index:-1}.icon-button:is(:disabled,[aria-disabled=true])::before{background-color:var(--_disabled-container-color);opacity:var(--_disabled-container-opacity)}.icon-button:is(:disabled,[aria-disabled=true]) .icon{opacity:var(--_disabled-icon-opacity)}.toggle-filled{--md-ripple-hover-color: var(--_toggle-hover-state-layer-color);--md-ripple-pressed-color: var(--_toggle-pressed-state-layer-color)}.toggle-filled:not(:disabled,[aria-disabled=true]){color:var(--_toggle-icon-color)}.toggle-filled:not(:disabled,[aria-disabled=true]):hover{color:var(--_toggle-hover-icon-color)}.toggle-filled:not(:disabled,[aria-disabled=true]):focus{color:var(--_toggle-focus-icon-color)}.toggle-filled:not(:disabled,[aria-disabled=true]):active{color:var(--_toggle-pressed-icon-color)}.toggle-filled:not(:disabled,[aria-disabled=true])::before{background-color:var(--_unselected-container-color)}.selected{--md-ripple-hover-color: var(--_toggle-selected-hover-state-layer-color);--md-ripple-pressed-color: var(--_toggle-selected-pressed-state-layer-color)}.selected:not(:disabled,[aria-disabled=true]){color:var(--_toggle-selected-icon-color)}.selected:not(:disabled,[aria-disabled=true]):hover{color:var(--_toggle-selected-hover-icon-color)}.selected:not(:disabled,[aria-disabled=true]):focus{color:var(--_toggle-selected-focus-icon-color)}.selected:not(:disabled,[aria-disabled=true]):active{color:var(--_toggle-selected-pressed-icon-color)}.selected:not(:disabled,[aria-disabled=true])::before{background-color:var(--_selected-container-color)} +`; + +/** + * @license + * Copyright 2022 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @summary Icon buttons help people take supplementary actions with a single + * tap. + * + * @description + * __Emphasis:__ Low emphasis – For optional or supplementary actions with the + * least amount of prominence. + * + * __Rationale:__ The most compact and unobtrusive type of button, icon buttons + * are used for optional supplementary actions such as "Bookmark" or "Star." + * + * __Example usages:__ + * - Add to Favorites + * - Print + * + * @final + * @suppress {visibility} + */ +let MdFilledIconButton = class MdFilledIconButton extends IconButton { + getRenderClasses() { + return { + ...super.getRenderClasses(), + 'filled': true, + 'toggle-filled': this.toggle, + }; + } +}; +MdFilledIconButton.styles = [styles$4, styles$2]; +MdFilledIconButton = __decorate([ + e('md-filled-icon-button') +], MdFilledIconButton); + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./iconbutton/internal/filled-tonal-styles.css. +const styles$1 = i `:host{--_container-color: var(--md-filled-tonal-icon-button-container-color, var(--md-sys-color-secondary-container, #e8def8));--_container-height: var(--md-filled-tonal-icon-button-container-height, 40px);--_container-width: var(--md-filled-tonal-icon-button-container-width, 40px);--_disabled-container-color: var(--md-filled-tonal-icon-button-disabled-container-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-container-opacity: var(--md-filled-tonal-icon-button-disabled-container-opacity, 0.12);--_disabled-icon-color: var(--md-filled-tonal-icon-button-disabled-icon-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-icon-opacity: var(--md-filled-tonal-icon-button-disabled-icon-opacity, 0.38);--_focus-icon-color: var(--md-filled-tonal-icon-button-focus-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_hover-icon-color: var(--md-filled-tonal-icon-button-hover-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_hover-state-layer-color: var(--md-filled-tonal-icon-button-hover-state-layer-color, var(--md-sys-color-on-secondary-container, #1d192b));--_hover-state-layer-opacity: var(--md-filled-tonal-icon-button-hover-state-layer-opacity, 0.08);--_icon-color: var(--md-filled-tonal-icon-button-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_icon-size: var(--md-filled-tonal-icon-button-icon-size, 24px);--_pressed-icon-color: var(--md-filled-tonal-icon-button-pressed-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_pressed-state-layer-color: var(--md-filled-tonal-icon-button-pressed-state-layer-color, var(--md-sys-color-on-secondary-container, #1d192b));--_pressed-state-layer-opacity: var(--md-filled-tonal-icon-button-pressed-state-layer-opacity, 0.12);--_selected-container-color: var(--md-filled-tonal-icon-button-selected-container-color, var(--md-sys-color-secondary-container, #e8def8));--_toggle-selected-focus-icon-color: var(--md-filled-tonal-icon-button-toggle-selected-focus-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_toggle-selected-hover-icon-color: var(--md-filled-tonal-icon-button-toggle-selected-hover-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_toggle-selected-hover-state-layer-color: var(--md-filled-tonal-icon-button-toggle-selected-hover-state-layer-color, var(--md-sys-color-on-secondary-container, #1d192b));--_toggle-selected-icon-color: var(--md-filled-tonal-icon-button-toggle-selected-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_toggle-selected-pressed-icon-color: var(--md-filled-tonal-icon-button-toggle-selected-pressed-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));--_toggle-selected-pressed-state-layer-color: var(--md-filled-tonal-icon-button-toggle-selected-pressed-state-layer-color, var(--md-sys-color-on-secondary-container, #1d192b));--_unselected-container-color: var(--md-filled-tonal-icon-button-unselected-container-color, var(--md-sys-color-surface-container-highest, #e6e0e9));--_toggle-focus-icon-color: var(--md-filled-tonal-icon-button-toggle-focus-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_toggle-hover-icon-color: var(--md-filled-tonal-icon-button-toggle-hover-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_toggle-hover-state-layer-color: var(--md-filled-tonal-icon-button-toggle-hover-state-layer-color, var(--md-sys-color-on-surface-variant, #49454f));--_toggle-icon-color: var(--md-filled-tonal-icon-button-toggle-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_toggle-pressed-icon-color: var(--md-filled-tonal-icon-button-toggle-pressed-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_toggle-pressed-state-layer-color: var(--md-filled-tonal-icon-button-toggle-pressed-state-layer-color, var(--md-sys-color-on-surface-variant, #49454f));--_container-shape-start-start: var(--md-filled-tonal-icon-button-container-shape-start-start, var(--md-filled-tonal-icon-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_container-shape-start-end: var(--md-filled-tonal-icon-button-container-shape-start-end, var(--md-filled-tonal-icon-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_container-shape-end-end: var(--md-filled-tonal-icon-button-container-shape-end-end, var(--md-filled-tonal-icon-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_container-shape-end-start: var(--md-filled-tonal-icon-button-container-shape-end-start, var(--md-filled-tonal-icon-button-container-shape, var(--md-sys-shape-corner-full, 9999px)))}.icon-button{color:var(--_icon-color);--md-ripple-hover-color: var(--_hover-state-layer-color);--md-ripple-hover-opacity: var(--_hover-state-layer-opacity);--md-ripple-pressed-color: var(--_pressed-state-layer-color);--md-ripple-pressed-opacity: var(--_pressed-state-layer-opacity)}.icon-button:hover{color:var(--_hover-icon-color)}.icon-button:focus{color:var(--_focus-icon-color)}.icon-button:active{color:var(--_pressed-icon-color)}.icon-button:is(:disabled,[aria-disabled=true]){color:var(--_disabled-icon-color)}.icon-button::before{background-color:var(--_container-color);border-radius:inherit;content:"";inset:0;position:absolute;z-index:-1}.icon-button:is(:disabled,[aria-disabled=true])::before{background-color:var(--_disabled-container-color);opacity:var(--_disabled-container-opacity)}.icon-button:is(:disabled,[aria-disabled=true]) .icon{opacity:var(--_disabled-icon-opacity)}.toggle-filled-tonal{--md-ripple-hover-color: var(--_toggle-hover-state-layer-color);--md-ripple-pressed-color: var(--_toggle-pressed-state-layer-color)}.toggle-filled-tonal:not(:disabled,[aria-disabled=true]){color:var(--_toggle-icon-color)}.toggle-filled-tonal:not(:disabled,[aria-disabled=true]):hover{color:var(--_toggle-hover-icon-color)}.toggle-filled-tonal:not(:disabled,[aria-disabled=true]):focus{color:var(--_toggle-focus-icon-color)}.toggle-filled-tonal:not(:disabled,[aria-disabled=true]):active{color:var(--_toggle-pressed-icon-color)}.toggle-filled-tonal:not(:disabled,[aria-disabled=true])::before{background-color:var(--_unselected-container-color)}.selected{--md-ripple-hover-color: var(--_toggle-selected-hover-state-layer-color);--md-ripple-pressed-color: var(--_toggle-selected-pressed-state-layer-color)}.selected:not(:disabled,[aria-disabled=true]){color:var(--_toggle-selected-icon-color)}.selected:not(:disabled,[aria-disabled=true]):hover{color:var(--_toggle-selected-hover-icon-color)}.selected:not(:disabled,[aria-disabled=true]):focus{color:var(--_toggle-selected-focus-icon-color)}.selected:not(:disabled,[aria-disabled=true]):active{color:var(--_toggle-selected-pressed-icon-color)}.selected:not(:disabled,[aria-disabled=true])::before{background-color:var(--_selected-container-color)} +`; + +/** + * @license + * Copyright 2022 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @summary Icon buttons help people take supplementary actions with a single + * tap. + * + * @description + * __Emphasis:__ Low emphasis – For optional or supplementary actions with the + * least amount of prominence. + * + * __Rationale:__ The most compact and unobtrusive type of button, icon buttons + * are used for optional supplementary actions such as "Bookmark" or "Star." + * + * __Example usages:__ + * - Add to Favorites + * - Print + * + * @final + * @suppress {visibility} + */ +let MdFilledTonalIconButton = class MdFilledTonalIconButton extends IconButton { + getRenderClasses() { + return { + ...super.getRenderClasses(), + 'filled-tonal': true, + 'toggle-filled-tonal': this.toggle, + }; + } +}; +MdFilledTonalIconButton.styles = [styles$4, styles$1]; +MdFilledTonalIconButton = __decorate([ + e('md-filled-tonal-icon-button') +], MdFilledTonalIconButton); + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./iconbutton/internal/outlined-styles.css. +const styles = i `:host{--_container-height: var(--md-outlined-icon-button-container-height, 40px);--_container-width: var(--md-outlined-icon-button-container-width, 40px);--_disabled-icon-color: var(--md-outlined-icon-button-disabled-icon-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-icon-opacity: var(--md-outlined-icon-button-disabled-icon-opacity, 0.38);--_disabled-selected-container-color: var(--md-outlined-icon-button-disabled-selected-container-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-selected-container-opacity: var(--md-outlined-icon-button-disabled-selected-container-opacity, 0.12);--_hover-state-layer-opacity: var(--md-outlined-icon-button-hover-state-layer-opacity, 0.08);--_icon-size: var(--md-outlined-icon-button-icon-size, 24px);--_pressed-state-layer-opacity: var(--md-outlined-icon-button-pressed-state-layer-opacity, 0.12);--_selected-container-color: var(--md-outlined-icon-button-selected-container-color, var(--md-sys-color-inverse-surface, #322f35));--_selected-focus-icon-color: var(--md-outlined-icon-button-selected-focus-icon-color, var(--md-sys-color-inverse-on-surface, #f5eff7));--_selected-hover-icon-color: var(--md-outlined-icon-button-selected-hover-icon-color, var(--md-sys-color-inverse-on-surface, #f5eff7));--_selected-hover-state-layer-color: var(--md-outlined-icon-button-selected-hover-state-layer-color, var(--md-sys-color-inverse-on-surface, #f5eff7));--_selected-icon-color: var(--md-outlined-icon-button-selected-icon-color, var(--md-sys-color-inverse-on-surface, #f5eff7));--_selected-pressed-icon-color: var(--md-outlined-icon-button-selected-pressed-icon-color, var(--md-sys-color-inverse-on-surface, #f5eff7));--_selected-pressed-state-layer-color: var(--md-outlined-icon-button-selected-pressed-state-layer-color, var(--md-sys-color-inverse-on-surface, #f5eff7));--_disabled-outline-color: var(--md-outlined-icon-button-disabled-outline-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-outline-opacity: var(--md-outlined-icon-button-disabled-outline-opacity, 0.12);--_focus-icon-color: var(--md-outlined-icon-button-focus-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_hover-icon-color: var(--md-outlined-icon-button-hover-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_hover-state-layer-color: var(--md-outlined-icon-button-hover-state-layer-color, var(--md-sys-color-on-surface-variant, #49454f));--_icon-color: var(--md-outlined-icon-button-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_outline-color: var(--md-outlined-icon-button-outline-color, var(--md-sys-color-outline, #79747e));--_outline-width: var(--md-outlined-icon-button-outline-width, 1px);--_pressed-icon-color: var(--md-outlined-icon-button-pressed-icon-color, var(--md-sys-color-on-surface, #1d1b20));--_pressed-state-layer-color: var(--md-outlined-icon-button-pressed-state-layer-color, var(--md-sys-color-on-surface, #1d1b20));--_container-shape-start-start: var(--md-outlined-icon-button-container-shape-start-start, var(--md-outlined-icon-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_container-shape-start-end: var(--md-outlined-icon-button-container-shape-start-end, var(--md-outlined-icon-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_container-shape-end-end: var(--md-outlined-icon-button-container-shape-end-end, var(--md-outlined-icon-button-container-shape, var(--md-sys-shape-corner-full, 9999px)));--_container-shape-end-start: var(--md-outlined-icon-button-container-shape-end-start, var(--md-outlined-icon-button-container-shape, var(--md-sys-shape-corner-full, 9999px)))}.outlined{background-color:rgba(0,0,0,0);color:var(--_icon-color);--md-ripple-hover-color: var(--_hover-state-layer-color);--md-ripple-hover-opacity: var(--_hover-state-layer-opacity);--md-ripple-pressed-color: var(--_pressed-state-layer-color);--md-ripple-pressed-opacity: var(--_pressed-state-layer-opacity)}.outlined::before{border-color:var(--_outline-color);border-width:var(--_outline-width)}.outlined:hover{color:var(--_hover-icon-color)}.outlined:focus{color:var(--_focus-icon-color)}.outlined:active{color:var(--_pressed-icon-color)}.outlined:is(:disabled,[aria-disabled=true]){color:var(--_disabled-icon-color)}.outlined:is(:disabled,[aria-disabled=true])::before{border-color:var(--_disabled-outline-color);opacity:var(--_disabled-outline-opacity)}.outlined:is(:disabled,[aria-disabled=true]) .icon{opacity:var(--_disabled-icon-opacity)}.outlined::before{block-size:100%;border-style:solid;border-radius:inherit;box-sizing:border-box;content:"";inline-size:100%;inset:0;pointer-events:none;position:absolute;z-index:-1}.outlined.selected::before{border-width:0}.selected{--md-ripple-hover-color: var(--_selected-hover-state-layer-color);--md-ripple-hover-opacity: var(--_hover-state-layer-opacity);--md-ripple-pressed-color: var(--_selected-pressed-state-layer-color);--md-ripple-pressed-opacity: var(--_pressed-state-layer-opacity)}.selected:not(:disabled,[aria-disabled=true]){color:var(--_selected-icon-color)}.selected:not(:disabled,[aria-disabled=true]):hover{color:var(--_selected-hover-icon-color)}.selected:not(:disabled,[aria-disabled=true]):focus{color:var(--_selected-focus-icon-color)}.selected:not(:disabled,[aria-disabled=true]):active{color:var(--_selected-pressed-icon-color)}.selected:not(:disabled,[aria-disabled=true])::before{background-color:var(--_selected-container-color)}.selected:is(:disabled,[aria-disabled=true])::before{background-color:var(--_disabled-selected-container-color);opacity:var(--_disabled-selected-container-opacity)}@media(forced-colors: active){:host(:is([disabled],[soft-disabled])){--_disabled-outline-opacity: 1}.selected::before{border-color:CanvasText;border-width:var(--_outline-width)}.selected:is(:disabled,[aria-disabled=true])::before{border-color:GrayText;opacity:1}} +`; + +/** + * @license + * Copyright 2022 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @summary Icon buttons help people take supplementary actions with a single + * tap. + * + * @description + * __Emphasis:__ Low emphasis – For optional or supplementary actions with the + * least amount of prominence. + * + * __Rationale:__ The most compact and unobtrusive type of button, icon buttons + * are used for optional supplementary actions such as "Bookmark" or "Star." + * + * __Example usages:__ + * - Add to Favorites + * - Print + * + * @final + * @suppress {visibility} + */ +let MdOutlinedIconButton = class MdOutlinedIconButton extends IconButton { + getRenderClasses() { + return { + ...super.getRenderClasses(), + 'outlined': true, + }; + } +}; +MdOutlinedIconButton.styles = [styles$4, styles]; +MdOutlinedIconButton = __decorate([ + e('md-outlined-icon-button') +], MdOutlinedIconButton); diff --git a/md-web/linear-progress.js b/md-web/linear-progress.js new file mode 100644 index 0000000..6fce6cd --- /dev/null +++ b/md-web/linear-progress.js @@ -0,0 +1,87 @@ +export const __dummy_loader = () => {}; + +import { _ as __decorate, n, P as Progress, x, I as o, i, e } from './core.js'; + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A linear progress component. + */ +class LinearProgress extends Progress { + constructor() { + super(...arguments); + /** + * Buffer amount to display, a fraction between 0 and `max`. + * If the value is 0 or negative, the buffer is not displayed. + */ + this.buffer = 0; + } + // Note, the indeterminate animation is rendered with transform %'s + // Previously, this was optimized to use px calculated with the resizeObserver + // due to a now fixed Chrome bug: crbug.com/389359. + renderIndicator() { + const progressStyles = { + transform: `scaleX(${(this.indeterminate ? 1 : this.value / this.max) * 100}%)`, + }; + const bufferValue = this.buffer ?? 0; + const hasBuffer = bufferValue > 0; + const dotSize = this.indeterminate || !hasBuffer ? 1 : bufferValue / this.max; + const dotStyles = { + transform: `scaleX(${dotSize * 100}%)`, + }; + // Only display dots when visible - this prevents invisible infinite + // animation. + const hideDots = this.indeterminate || !hasBuffer || bufferValue >= this.max || this.value >= this.max; + return x ` +
+
+
+
+
+
+
+
+ `; + } +} +__decorate([ + n({ type: Number }) +], LinearProgress.prototype, "buffer", void 0); + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./progress/internal/linear-progress-styles.css. +const styles = i `:host{--_active-indicator-color: var(--md-linear-progress-active-indicator-color, var(--md-sys-color-primary, #6750a4));--_active-indicator-height: var(--md-linear-progress-active-indicator-height, 4px);--_four-color-active-indicator-four-color: var(--md-linear-progress-four-color-active-indicator-four-color, var(--md-sys-color-tertiary-container, #ffd8e4));--_four-color-active-indicator-one-color: var(--md-linear-progress-four-color-active-indicator-one-color, var(--md-sys-color-primary, #6750a4));--_four-color-active-indicator-three-color: var(--md-linear-progress-four-color-active-indicator-three-color, var(--md-sys-color-tertiary, #7d5260));--_four-color-active-indicator-two-color: var(--md-linear-progress-four-color-active-indicator-two-color, var(--md-sys-color-primary-container, #eaddff));--_track-color: var(--md-linear-progress-track-color, var(--md-sys-color-surface-container-highest, #e6e0e9));--_track-height: var(--md-linear-progress-track-height, 4px);--_track-shape: var(--md-linear-progress-track-shape, var(--md-sys-shape-corner-none, 0px));border-radius:var(--_track-shape);display:flex;position:relative;min-width:80px;height:var(--_track-height);content-visibility:auto;contain:strict}.progress,.dots,.inactive-track,.bar,.bar-inner{position:absolute}.progress{direction:ltr;inset:0;border-radius:inherit;overflow:hidden;display:flex;align-items:center}.bar{animation:none;width:100%;height:var(--_active-indicator-height);transform-origin:left center;transition:transform 250ms cubic-bezier(0.4, 0, 0.6, 1)}.secondary-bar{display:none}.bar-inner{inset:0;animation:none;background:var(--_active-indicator-color)}.inactive-track{background:var(--_track-color);inset:0;transition:transform 250ms cubic-bezier(0.4, 0, 0.6, 1);transform-origin:left center}.dots{inset:0;animation:linear infinite 250ms;animation-name:buffering;background-color:var(--_track-color);background-repeat:repeat-x;-webkit-mask-image:url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 5 2' preserveAspectRatio='xMinYMin slice'%3E%3Ccircle cx='1' cy='1' r='1'/%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 5 2' preserveAspectRatio='xMinYMin slice'%3E%3Ccircle cx='1' cy='1' r='1'/%3E%3C/svg%3E");z-index:-1}.dots[hidden]{display:none}.indeterminate .bar{transition:none}.indeterminate .primary-bar{inset-inline-start:-145.167%}.indeterminate .secondary-bar{inset-inline-start:-54.8889%;display:block}.indeterminate .primary-bar{animation:linear infinite 2s;animation-name:primary-indeterminate-translate}.indeterminate .primary-bar>.bar-inner{animation:linear infinite 2s primary-indeterminate-scale}.indeterminate.four-color .primary-bar>.bar-inner{animation-name:primary-indeterminate-scale,four-color;animation-duration:2s,4s}.indeterminate .secondary-bar{animation:linear infinite 2s;animation-name:secondary-indeterminate-translate}.indeterminate .secondary-bar>.bar-inner{animation:linear infinite 2s secondary-indeterminate-scale}.indeterminate.four-color .secondary-bar>.bar-inner{animation-name:secondary-indeterminate-scale,four-color;animation-duration:2s,4s}:host(:dir(rtl)){transform:scale(-1)}@keyframes primary-indeterminate-scale{0%{transform:scaleX(0.08)}36.65%{animation-timing-function:cubic-bezier(0.334731, 0.12482, 0.785844, 1);transform:scaleX(0.08)}69.15%{animation-timing-function:cubic-bezier(0.06, 0.11, 0.6, 1);transform:scaleX(0.661479)}100%{transform:scaleX(0.08)}}@keyframes secondary-indeterminate-scale{0%{animation-timing-function:cubic-bezier(0.205028, 0.057051, 0.57661, 0.453971);transform:scaleX(0.08)}19.15%{animation-timing-function:cubic-bezier(0.152313, 0.196432, 0.648374, 1.00432);transform:scaleX(0.457104)}44.15%{animation-timing-function:cubic-bezier(0.257759, -0.003163, 0.211762, 1.38179);transform:scaleX(0.72796)}100%{transform:scaleX(0.08)}}@keyframes buffering{0%{transform:translateX(calc(var(--_track-height) / 2 * 5))}}@keyframes primary-indeterminate-translate{0%{transform:translateX(0px)}20%{animation-timing-function:cubic-bezier(0.5, 0, 0.701732, 0.495819);transform:translateX(0px)}59.15%{animation-timing-function:cubic-bezier(0.302435, 0.381352, 0.55, 0.956352);transform:translateX(83.6714%)}100%{transform:translateX(200.611%)}}@keyframes secondary-indeterminate-translate{0%{animation-timing-function:cubic-bezier(0.15, 0, 0.515058, 0.409685);transform:translateX(0px)}25%{animation-timing-function:cubic-bezier(0.31033, 0.284058, 0.8, 0.733712);transform:translateX(37.6519%)}48.35%{animation-timing-function:cubic-bezier(0.4, 0.627035, 0.6, 0.902026);transform:translateX(84.3862%)}100%{transform:translateX(160.278%)}}@keyframes four-color{0%{background:var(--_four-color-active-indicator-one-color)}15%{background:var(--_four-color-active-indicator-one-color)}25%{background:var(--_four-color-active-indicator-two-color)}40%{background:var(--_four-color-active-indicator-two-color)}50%{background:var(--_four-color-active-indicator-three-color)}65%{background:var(--_four-color-active-indicator-three-color)}75%{background:var(--_four-color-active-indicator-four-color)}90%{background:var(--_four-color-active-indicator-four-color)}100%{background:var(--_four-color-active-indicator-one-color)}}@media(forced-colors: active){:host{outline:1px solid CanvasText}.bar-inner,.dots{background-color:CanvasText}} +`; + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @summary Linear progress indicators display progress by animating along the + * length of a fixed, visible track. + * + * @description + * Progress indicators inform users about the status of ongoing processes. + * - Determinate indicators display how long a process will take. + * - Indeterminate indicators express an unspecified amount of wait time. + * + * @final + * @suppress {visibility} + */ +let MdLinearProgress = class MdLinearProgress extends LinearProgress { +}; +MdLinearProgress.styles = [styles]; +MdLinearProgress = __decorate([ + e('md-linear-progress') +], MdLinearProgress); + +export { MdLinearProgress }; diff --git a/md-web/list-item.js b/md-web/list-item.js new file mode 100644 index 0000000..37e52a6 --- /dev/null +++ b/md-web/list-item.js @@ -0,0 +1,256 @@ +export const __dummy_loader = () => {}; + +import { m as mixinDelegatesAria, s, _ as __decorate, n, c as i, x, G as i$1, A, H as n$1, o, D as createRequestActivationEvent, i as i$2, e } from './core.js'; + +/** + * @license + * Copyright 2022 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Separate variable needed for closure. +const listItemBaseClass = mixinDelegatesAria(s); +/** + * @fires request-activation {Event} Requests the list to set `tabindex=0` on + * the item and focus it. --bubbles --composed + */ +class ListItemEl extends listItemBaseClass { + constructor() { + super(...arguments); + /** + * Disables the item and makes it non-selectable and non-interactive. + */ + this.disabled = false; + /** + * Sets the behavior of the list item, defaults to "text". Change to "link" or + * "button" for interactive items. + */ + this.type = 'text'; + /** + * READONLY. Sets the `md-list-item` attribute on the element. + */ + this.isListItem = true; + /** + * Sets the underlying `HTMLAnchorElement`'s `href` resource attribute. + */ + this.href = ''; + /** + * Sets the underlying `HTMLAnchorElement`'s `target` attribute when `href` is + * set. + */ + this.target = ''; + } + get isDisabled() { + return this.disabled && this.type !== 'link'; + } + willUpdate(changed) { + if (this.href) { + this.type = 'link'; + } + super.willUpdate(changed); + } + render() { + return this.renderListItem(x ` + +
+ ${this.renderRipple()} ${this.renderFocusRing()} +
+ + + ${this.renderBody()} +
+ `); + } + /** + * Renders the root list item. + * + * @param content the child content of the list item. + */ + renderListItem(content) { + const isAnchor = this.type === 'link'; + let tag; + switch (this.type) { + case 'link': + tag = i$1 `a`; + break; + case 'button': + tag = i$1 `button`; + break; + default: + case 'text': + tag = i$1 `li`; + break; + } + const isInteractive = this.type !== 'text'; + // TODO(b/265339866): announce "button"/"link" inside of a list item. Until + // then all are "listitem" roles for correct announcement. + const target = isAnchor && !!this.target ? this.target : A; + return n$1 ` + <${tag} + id="item" + tabindex="${this.isDisabled || !isInteractive ? -1 : 0}" + ?disabled=${this.isDisabled} + role="listitem" + aria-selected=${this.ariaSelected || A} + aria-checked=${this.ariaChecked || A} + aria-expanded=${this.ariaExpanded || A} + aria-haspopup=${this.ariaHasPopup || A} + class="list-item ${o(this.getRenderClasses())}" + href=${this.href || A} + target=${target} + @focus=${this.onFocus} + >${content} + `; + } + /** + * Handles rendering of the ripple element. + */ + renderRipple() { + if (this.type === 'text') { + return A; + } + return x ` `; + } + /** + * Handles rendering of the focus ring. + */ + renderFocusRing() { + if (this.type === 'text') { + return A; + } + return x ` `; + } + onFocusRingVisibilityChanged(e) { } + /** + * Classes applied to the list item root. + */ + getRenderClasses() { + return { 'disabled': this.isDisabled }; + } + /** + * Handles rendering the headline and supporting text. + */ + renderBody() { + return x ` + + + + + + `; + } + onFocus() { + if (this.tabIndex !== -1) { + return; + } + // Handles the case where the user clicks on the element and then tabs. + this.dispatchEvent(createRequestActivationEvent()); + } + focus() { + // TODO(b/300334509): needed for some cases where delegatesFocus doesn't + // work programmatically like in FF and select-option + this.listItemRoot?.focus(); + } + click() { + if (!this.listItemRoot) { + // If the element has not finished rendering, call super to ensure click + // events are dispatched. + super.click(); + return; + } + // Forward click to the element to ensure link
.click() works correctly. + this.listItemRoot.click(); + } +} +/** @nocollapse */ +ListItemEl.shadowRootOptions = { + ...s.shadowRootOptions, + delegatesFocus: true, +}; +__decorate([ + n({ type: Boolean, reflect: true }) +], ListItemEl.prototype, "disabled", void 0); +__decorate([ + n({ reflect: true }) +], ListItemEl.prototype, "type", void 0); +__decorate([ + n({ type: Boolean, attribute: 'md-list-item', reflect: true }) +], ListItemEl.prototype, "isListItem", void 0); +__decorate([ + n() +], ListItemEl.prototype, "href", void 0); +__decorate([ + n() +], ListItemEl.prototype, "target", void 0); +__decorate([ + i('.list-item') +], ListItemEl.prototype, "listItemRoot", void 0); + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./list/internal/listitem/list-item-styles.css. +const styles = i$2 `:host{display:flex;-webkit-tap-highlight-color:rgba(0,0,0,0);--md-ripple-hover-color: var(--md-list-item-hover-state-layer-color, var(--md-sys-color-on-surface, #1d1b20));--md-ripple-hover-opacity: var(--md-list-item-hover-state-layer-opacity, 0.08);--md-ripple-pressed-color: var(--md-list-item-pressed-state-layer-color, var(--md-sys-color-on-surface, #1d1b20));--md-ripple-pressed-opacity: var(--md-list-item-pressed-state-layer-opacity, 0.12)}:host(:is([type=button]:not([disabled]),[type=link])){cursor:pointer}md-focus-ring{z-index:1;--md-focus-ring-shape: 8px}a,button,li{background:none;border:none;cursor:inherit;padding:0;margin:0;text-align:unset;text-decoration:none}.list-item{border-radius:inherit;display:flex;flex:1;max-width:inherit;min-width:inherit;outline:none;-webkit-tap-highlight-color:rgba(0,0,0,0);width:100%}.list-item.interactive{cursor:pointer}.list-item.disabled{opacity:var(--md-list-item-disabled-opacity, 0.3);pointer-events:none}[slot=container]{pointer-events:none}md-ripple{border-radius:inherit}md-item{border-radius:inherit;flex:1;height:100%;color:var(--md-list-item-label-text-color, var(--md-sys-color-on-surface, #1d1b20));font-family:var(--md-list-item-label-text-font, var(--md-sys-typescale-body-large-font, var(--md-ref-typeface-plain, Roboto)));font-size:var(--md-list-item-label-text-size, var(--md-sys-typescale-body-large-size, 1rem));line-height:var(--md-list-item-label-text-line-height, var(--md-sys-typescale-body-large-line-height, 1.5rem));font-weight:var(--md-list-item-label-text-weight, var(--md-sys-typescale-body-large-weight, var(--md-ref-typeface-weight-regular, 400)));min-height:var(--md-list-item-one-line-container-height, 56px);padding-top:var(--md-list-item-top-space, 12px);padding-bottom:var(--md-list-item-bottom-space, 12px);padding-inline-start:var(--md-list-item-leading-space, 16px);padding-inline-end:var(--md-list-item-trailing-space, 16px)}md-item[multiline]{min-height:var(--md-list-item-two-line-container-height, 72px)}[slot=supporting-text]{color:var(--md-list-item-supporting-text-color, var(--md-sys-color-on-surface-variant, #49454f));font-family:var(--md-list-item-supporting-text-font, var(--md-sys-typescale-body-medium-font, var(--md-ref-typeface-plain, Roboto)));font-size:var(--md-list-item-supporting-text-size, var(--md-sys-typescale-body-medium-size, 0.875rem));line-height:var(--md-list-item-supporting-text-line-height, var(--md-sys-typescale-body-medium-line-height, 1.25rem));font-weight:var(--md-list-item-supporting-text-weight, var(--md-sys-typescale-body-medium-weight, var(--md-ref-typeface-weight-regular, 400)))}[slot=trailing-supporting-text]{color:var(--md-list-item-trailing-supporting-text-color, var(--md-sys-color-on-surface-variant, #49454f));font-family:var(--md-list-item-trailing-supporting-text-font, var(--md-sys-typescale-label-small-font, var(--md-ref-typeface-plain, Roboto)));font-size:var(--md-list-item-trailing-supporting-text-size, var(--md-sys-typescale-label-small-size, 0.6875rem));line-height:var(--md-list-item-trailing-supporting-text-line-height, var(--md-sys-typescale-label-small-line-height, 1rem));font-weight:var(--md-list-item-trailing-supporting-text-weight, var(--md-sys-typescale-label-small-weight, var(--md-ref-typeface-weight-medium, 500)))}:is([slot=start],[slot=end])::slotted(*){fill:currentColor}[slot=start]{color:var(--md-list-item-leading-icon-color, var(--md-sys-color-on-surface-variant, #49454f))}[slot=end]{color:var(--md-list-item-trailing-icon-color, var(--md-sys-color-on-surface-variant, #49454f))}@media(forced-colors: active){.disabled slot{color:GrayText}.list-item.disabled{color:GrayText;opacity:1}} +`; + +/** + * @license + * Copyright 2022 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @summary + * Lists are continuous, vertical indexes of text or images. Items are placed + * inside the list. + * + * @description + * Lists consist of one or more list items, and can contain actions represented + * by icons and text. List items come in three sizes: one-line, two-line, and + * three-line. + * + * __Takeaways:__ + * + * - Lists should be sorted in logical ways that make content easy to scan, such + * as alphabetical, numerical, chronological, or by user preference. + * - Lists present content in a way that makes it easy to identify a specific + * item in a collection and act on it. + * - Lists should present icons, text, and actions in a consistent format. + * + * Acceptable slot child variants are: + * + * - `img[slot=end]` + * - `img[slot=start]` + * + * @example + * ```html + * + * account_circle + * check + * + * ``` + * + * @example + * + * @final + * @suppress {visibility} + */ +let MdListItem = class MdListItem extends ListItemEl { +}; +MdListItem.styles = [styles]; +MdListItem = __decorate([ + e('md-list-item') +], MdListItem); + +export { MdListItem }; diff --git a/md-web/list.js b/md-web/list.js new file mode 100644 index 0000000..7ca5f8c --- /dev/null +++ b/md-web/list.js @@ -0,0 +1,112 @@ +export const __dummy_loader = () => {}; + +import { F as NavigableKeys, _ as __decorate, l, s, L as ListController, x, i, e } from './core.js'; + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const NAVIGABLE_KEY_SET = new Set(Object.values(NavigableKeys)); +// tslint:disable-next-line:enforce-comments-on-exported-symbols +class List extends s { + /** @export */ + get items() { + return this.listController.items; + } + constructor() { + super(); + this.listController = new ListController({ + isItem: (item) => item.hasAttribute('md-list-item'), + getPossibleItems: () => this.slotItems, + isRtl: () => getComputedStyle(this).direction === 'rtl', + deactivateItem: (item) => { + item.tabIndex = -1; + }, + activateItem: (item) => { + item.tabIndex = 0; + }, + isNavigableKey: (key) => NAVIGABLE_KEY_SET.has(key), + isActivatable: (item) => !item.disabled && item.type !== 'text', + }); + this.internals = + // Cast needed for closure + this.attachInternals(); + { + this.internals.role = 'list'; + this.addEventListener('keydown', this.listController.handleKeydown); + } + } + render() { + return x ` + + + `; + } + /** + * Activates the next item in the list. If at the end of the list, the first + * item will be activated. + * + * @return The activated list item or `null` if there are no items. + */ + activateNextItem() { + return this.listController.activateNextItem(); + } + /** + * Activates the previous item in the list. If at the start of the list, the + * last item will be activated. + * + * @return The activated list item or `null` if there are no items. + */ + activatePreviousItem() { + return this.listController.activatePreviousItem(); + } +} +__decorate([ + l({ flatten: true }) +], List.prototype, "slotItems", void 0); + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./list/internal/list-styles.css. +const styles = i `:host{background:var(--md-list-container-color, var(--md-sys-color-surface, #fef7ff));color:unset;display:flex;flex-direction:column;outline:none;padding:8px 0;position:relative} +`; + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @summary Lists are continuous, vertical indexes of text or images. + * + * @description + * Lists consist of one or more list items, and can contain actions represented + * by icons and text. List items come in three sizes: one-line, two-line, and + * three-line. + * + * __Takeaways:__ + * + * - Lists should be sorted in logical ways that make content easy to scan, such + * as alphabetical, numerical, chronological, or by user preference. + * - Lists present content in a way that makes it easy to identify a specific + * item in a collection and act on it. + * - Lists should present icons, text, and actions in a consistent format. + * + * @final + * @suppress {visibility} + */ +let MdList = class MdList extends List { +}; +MdList.styles = [styles]; +MdList = __decorate([ + e('md-list') +], MdList); + +export { MdList }; diff --git a/md-web/menu-item.js b/md-web/menu-item.js new file mode 100644 index 0000000..a5feb3f --- /dev/null +++ b/md-web/menu-item.js @@ -0,0 +1,379 @@ +export const __dummy_loader = () => {}; + +import { U as createDefaultCloseMenuEvent, B as CloseReason, V as isClosableKey, m as mixinDelegatesAria, s, _ as __decorate, n, c as i, l, R as o, x, G as i$1, A, H as n$1, o as o$1, i as i$2, e } from './core.js'; + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A controller that provides most functionality of an element that implements + * the MenuItem interface. + */ +class MenuItemController { + /** + * @param host The MenuItem in which to attach this controller to. + * @param config The object that configures this controller's behavior. + */ + constructor(host, config) { + this.host = host; + this.internalTypeaheadText = null; + /** + * Bind this click listener to the interactive element. Handles closing the + * menu. + */ + this.onClick = () => { + if (this.host.keepOpen) + return; + this.host.dispatchEvent(createDefaultCloseMenuEvent(this.host, { + kind: CloseReason.CLICK_SELECTION, + })); + }; + /** + * Bind this click listener to the interactive element. Handles closing the + * menu. + */ + this.onKeydown = (event) => { + // Check if the interactive element is an anchor tag. If so, click it. + if (this.host.href && event.code === 'Enter') { + const interactiveElement = this.getInteractiveElement(); + if (interactiveElement instanceof HTMLAnchorElement) { + interactiveElement.click(); + } + } + if (event.defaultPrevented) + return; + // If the host has keepOpen = true we should ignore clicks & Space/Enter, + // however we always maintain the ability to close a menu with a explicit + // `escape` keypress. + const keyCode = event.code; + if (this.host.keepOpen && keyCode !== 'Escape') + return; + if (isClosableKey(keyCode)) { + event.preventDefault(); + this.host.dispatchEvent(createDefaultCloseMenuEvent(this.host, { + kind: CloseReason.KEYDOWN, + key: keyCode, + })); + } + }; + this.getHeadlineElements = config.getHeadlineElements; + this.getSupportingTextElements = config.getSupportingTextElements; + this.getDefaultElements = config.getDefaultElements; + this.getInteractiveElement = config.getInteractiveElement; + this.host.addController(this); + } + /** + * The text that is selectable via typeahead. If not set, defaults to the + * innerText of the item slotted into the `"headline"` slot, and if there are + * no slotted elements into headline, then it checks the _default_ slot, and + * then the `"supporting-text"` slot if nothing is in _default_. + */ + get typeaheadText() { + if (this.internalTypeaheadText !== null) { + return this.internalTypeaheadText; + } + const headlineElements = this.getHeadlineElements(); + const textParts = []; + headlineElements.forEach((headlineElement) => { + if (headlineElement.textContent && headlineElement.textContent.trim()) { + textParts.push(headlineElement.textContent.trim()); + } + }); + // If there are no headline elements, check the default slot's text content + if (textParts.length === 0) { + this.getDefaultElements().forEach((defaultElement) => { + if (defaultElement.textContent && defaultElement.textContent.trim()) { + textParts.push(defaultElement.textContent.trim()); + } + }); + } + // If there are no headline nor default slot elements, check the + //supporting-text slot's text content + if (textParts.length === 0) { + this.getSupportingTextElements().forEach((supportingTextElement) => { + if (supportingTextElement.textContent && + supportingTextElement.textContent.trim()) { + textParts.push(supportingTextElement.textContent.trim()); + } + }); + } + return textParts.join(' '); + } + /** + * The recommended tag name to render as the list item. + */ + get tagName() { + const type = this.host.type; + switch (type) { + case 'link': + return 'a'; + case 'button': + return 'button'; + default: + case 'menuitem': + case 'option': + return 'li'; + } + } + /** + * The recommended role of the menu item. + */ + get role() { + return this.host.type === 'option' ? 'option' : 'menuitem'; + } + hostConnected() { + this.host.toggleAttribute('md-menu-item', true); + } + hostUpdate() { + if (this.host.href) { + this.host.type = 'link'; + } + } + /** + * Use to set the typeaheadText when it changes. + */ + setTypeaheadText(text) { + this.internalTypeaheadText = text; + } +} + +/** + * @license + * Copyright 2022 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Separate variable needed for closure. +const menuItemBaseClass = mixinDelegatesAria(s); +/** + * @fires close-menu {CustomEvent<{initiator: SelectOption, reason: Reason, itemPath: SelectOption[]}>} + * Closes the encapsulating menu on closable interaction. --bubbles --composed + */ +class MenuItemEl extends menuItemBaseClass { + constructor() { + super(...arguments); + /** + * Disables the item and makes it non-selectable and non-interactive. + */ + this.disabled = false; + /** + * Sets the behavior and role of the menu item, defaults to "menuitem". + */ + this.type = 'menuitem'; + /** + * Sets the underlying `HTMLAnchorElement`'s `href` resource attribute. + */ + this.href = ''; + /** + * Sets the underlying `HTMLAnchorElement`'s `target` attribute when `href` is + * set. + */ + this.target = ''; + /** + * Keeps the menu open if clicked or keyboard selected. + */ + this.keepOpen = false; + /** + * Sets the item in the selected visual state when a submenu is opened. + */ + this.selected = false; + this.menuItemController = new MenuItemController(this, { + getHeadlineElements: () => { + return this.headlineElements; + }, + getSupportingTextElements: () => { + return this.supportingTextElements; + }, + getDefaultElements: () => { + return this.defaultElements; + }, + getInteractiveElement: () => this.listItemRoot, + }); + } + /** + * The text that is selectable via typeahead. If not set, defaults to the + * innerText of the item slotted into the `"headline"` slot. + */ + get typeaheadText() { + return this.menuItemController.typeaheadText; + } + set typeaheadText(text) { + this.menuItemController.setTypeaheadText(text); + } + render() { + return this.renderListItem(x ` + +
+ ${this.renderRipple()} ${this.renderFocusRing()} +
+ + + ${this.renderBody()} +
+ `); + } + /** + * Renders the root list item. + * + * @param content the child content of the list item. + */ + renderListItem(content) { + const isAnchor = this.type === 'link'; + let tag; + switch (this.menuItemController.tagName) { + case 'a': + tag = i$1 `a`; + break; + case 'button': + tag = i$1 `button`; + break; + default: + case 'li': + tag = i$1 `li`; + break; + } + // TODO(b/265339866): announce "button"/"link" inside of a list item. Until + // then all are "menuitem" roles for correct announcement. + const target = isAnchor && !!this.target ? this.target : A; + return n$1 ` + <${tag} + id="item" + tabindex=${this.disabled && !isAnchor ? -1 : 0} + role=${this.menuItemController.role} + aria-label=${this.ariaLabel || A} + aria-selected=${this.ariaSelected || A} + aria-checked=${this.ariaChecked || A} + aria-expanded=${this.ariaExpanded || A} + aria-haspopup=${this.ariaHasPopup || A} + class="list-item ${o$1(this.getRenderClasses())}" + href=${this.href || A} + target=${target} + @click=${this.menuItemController.onClick} + @keydown=${this.menuItemController.onKeydown} + >${content} + `; + } + /** + * Handles rendering of the ripple element. + */ + renderRipple() { + return x ` `; + } + /** + * Handles rendering of the focus ring. + */ + renderFocusRing() { + return x ` `; + } + /** + * Classes applied to the list item root. + */ + getRenderClasses() { + return { + 'disabled': this.disabled, + 'selected': this.selected, + }; + } + /** + * Handles rendering the headline and supporting text. + */ + renderBody() { + return x ` + + + + + + `; + } + focus() { + // TODO(b/300334509): needed for some cases where delegatesFocus doesn't + // work programmatically like in FF and select-option + this.listItemRoot?.focus(); + } +} +/** @nocollapse */ +MenuItemEl.shadowRootOptions = { + ...s.shadowRootOptions, + delegatesFocus: true, +}; +__decorate([ + n({ type: Boolean, reflect: true }) +], MenuItemEl.prototype, "disabled", void 0); +__decorate([ + n() +], MenuItemEl.prototype, "type", void 0); +__decorate([ + n() +], MenuItemEl.prototype, "href", void 0); +__decorate([ + n() +], MenuItemEl.prototype, "target", void 0); +__decorate([ + n({ type: Boolean, attribute: 'keep-open' }) +], MenuItemEl.prototype, "keepOpen", void 0); +__decorate([ + n({ type: Boolean }) +], MenuItemEl.prototype, "selected", void 0); +__decorate([ + i('.list-item') +], MenuItemEl.prototype, "listItemRoot", void 0); +__decorate([ + l({ slot: 'headline' }) +], MenuItemEl.prototype, "headlineElements", void 0); +__decorate([ + l({ slot: 'supporting-text' }) +], MenuItemEl.prototype, "supportingTextElements", void 0); +__decorate([ + o({ slot: '' }) +], MenuItemEl.prototype, "defaultElements", void 0); +__decorate([ + n({ attribute: 'typeahead-text' }) +], MenuItemEl.prototype, "typeaheadText", null); + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./menu/internal/menuitem/menu-item-styles.css. +const styles = i$2 `:host{display:flex;--md-ripple-hover-color: var(--md-menu-item-hover-state-layer-color, var(--md-sys-color-on-surface, #1d1b20));--md-ripple-hover-opacity: var(--md-menu-item-hover-state-layer-opacity, 0.08);--md-ripple-pressed-color: var(--md-menu-item-pressed-state-layer-color, var(--md-sys-color-on-surface, #1d1b20));--md-ripple-pressed-opacity: var(--md-menu-item-pressed-state-layer-opacity, 0.12)}:host([disabled]){opacity:var(--md-menu-item-disabled-opacity, 0.3);pointer-events:none}md-focus-ring{z-index:1;--md-focus-ring-shape: 8px}a,button,li{background:none;border:none;padding:0;margin:0;text-align:unset;text-decoration:none}.list-item{border-radius:inherit;display:flex;flex:1;max-width:inherit;min-width:inherit;outline:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}.list-item:not(.disabled){cursor:pointer}[slot=container]{pointer-events:none}md-ripple{border-radius:inherit}md-item{border-radius:inherit;flex:1;color:var(--md-menu-item-label-text-color, var(--md-sys-color-on-surface, #1d1b20));font-family:var(--md-menu-item-label-text-font, var(--md-sys-typescale-body-large-font, var(--md-ref-typeface-plain, Roboto)));font-size:var(--md-menu-item-label-text-size, var(--md-sys-typescale-body-large-size, 1rem));line-height:var(--md-menu-item-label-text-line-height, var(--md-sys-typescale-body-large-line-height, 1.5rem));font-weight:var(--md-menu-item-label-text-weight, var(--md-sys-typescale-body-large-weight, var(--md-ref-typeface-weight-regular, 400)));min-height:var(--md-menu-item-one-line-container-height, 56px);padding-top:var(--md-menu-item-top-space, 12px);padding-bottom:var(--md-menu-item-bottom-space, 12px);padding-inline-start:var(--md-menu-item-leading-space, 16px);padding-inline-end:var(--md-menu-item-trailing-space, 16px)}md-item[multiline]{min-height:var(--md-menu-item-two-line-container-height, 72px)}[slot=supporting-text]{color:var(--md-menu-item-supporting-text-color, var(--md-sys-color-on-surface-variant, #49454f));font-family:var(--md-menu-item-supporting-text-font, var(--md-sys-typescale-body-medium-font, var(--md-ref-typeface-plain, Roboto)));font-size:var(--md-menu-item-supporting-text-size, var(--md-sys-typescale-body-medium-size, 0.875rem));line-height:var(--md-menu-item-supporting-text-line-height, var(--md-sys-typescale-body-medium-line-height, 1.25rem));font-weight:var(--md-menu-item-supporting-text-weight, var(--md-sys-typescale-body-medium-weight, var(--md-ref-typeface-weight-regular, 400)))}[slot=trailing-supporting-text]{color:var(--md-menu-item-trailing-supporting-text-color, var(--md-sys-color-on-surface-variant, #49454f));font-family:var(--md-menu-item-trailing-supporting-text-font, var(--md-sys-typescale-label-small-font, var(--md-ref-typeface-plain, Roboto)));font-size:var(--md-menu-item-trailing-supporting-text-size, var(--md-sys-typescale-label-small-size, 0.6875rem));line-height:var(--md-menu-item-trailing-supporting-text-line-height, var(--md-sys-typescale-label-small-line-height, 1rem));font-weight:var(--md-menu-item-trailing-supporting-text-weight, var(--md-sys-typescale-label-small-weight, var(--md-ref-typeface-weight-medium, 500)))}:is([slot=start],[slot=end])::slotted(*){fill:currentColor}[slot=start]{color:var(--md-menu-item-leading-icon-color, var(--md-sys-color-on-surface-variant, #49454f))}[slot=end]{color:var(--md-menu-item-trailing-icon-color, var(--md-sys-color-on-surface-variant, #49454f))}.list-item{background-color:var(--md-menu-item-container-color, transparent)}.list-item.selected{background-color:var(--md-menu-item-selected-container-color, var(--md-sys-color-secondary-container, #e8def8))}.selected:not(.disabled) ::slotted(*){color:var(--md-menu-item-selected-label-text-color, var(--md-sys-color-on-secondary-container, #1d192b))}@media(forced-colors: active){:host([disabled]),:host([disabled]) slot{color:GrayText;opacity:1}.list-item{position:relative}.list-item.selected::before{content:"";position:absolute;inset:0;box-sizing:border-box;border-radius:inherit;pointer-events:none;border:3px double CanvasText}} +`; + +/** + * @license + * Copyright 2022 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @summary Menus display a list of choices on a temporary surface. + * + * @description + * Menu items are the selectable choices within the menu. Menu items must + * implement the `MenuItem` interface and also have the `md-menu-item` + * attribute. Additionally menu items are list items so they must also have the + * `md-list-item` attribute. + * + * Menu items can control a menu by selectively firing the `close-menu` and + * `deselect-items` events. + * + * @final + * @suppress {visibility} + */ +let MdMenuItem = class MdMenuItem extends MenuItemEl { +}; +MdMenuItem.styles = [styles]; +MdMenuItem = __decorate([ + e('md-menu-item') +], MdMenuItem); + +export { MdMenuItem }; diff --git a/md-web/menu.js b/md-web/menu.js new file mode 100644 index 0000000..b137675 --- /dev/null +++ b/md-web/menu.js @@ -0,0 +1,3 @@ +export const __dummy_loader = () => {}; + +export { B as CloseReason, u as Corner, ag as FocusState, af as MdMenu } from './core.js'; diff --git a/md-web/radio.js b/md-web/radio.js new file mode 100644 index 0000000..21f2506 --- /dev/null +++ b/md-web/radio.js @@ -0,0 +1,470 @@ +export const __dummy_loader = () => {}; + +import { W as Validator, a as mixinConstraintValidation, b as mixinFormAssociated, q as mixinElementInternals, Q as mixinFocusable, _ as __decorate, n, c as i, s, X as internals, x, o, d as isActivationClick, g as getFormValue, h as getFormState, j as createValidator, p as getValidityAnchor, i as i$1, e } from './core.js'; + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A validator that provides constraint validation that emulates + * `` validation. + */ +class RadioValidator extends Validator { + computeValidity(states) { + if (!this.radioElement) { + // Lazily create the radio element + this.radioElement = document.createElement('input'); + this.radioElement.type = 'radio'; + // A name is required for validation to run + this.radioElement.name = 'group'; + } + let isRequired = false; + let isChecked = false; + for (const { checked, required } of states) { + if (required) { + isRequired = true; + } + if (checked) { + isChecked = true; + } + } + // Firefox v119 doesn't compute grouped radio validation correctly while + // they are detached from the DOM, which is why we don't render multiple + // virtual s. Instead, we can check the required/checked states and + // grab the i18n'd validation message if the value is missing. + this.radioElement.checked = isChecked; + this.radioElement.required = isRequired; + return { + validity: { + valueMissing: isRequired && !isChecked, + }, + validationMessage: this.radioElement.validationMessage, + }; + } + equals(prevGroup, nextGroup) { + if (prevGroup.length !== nextGroup.length) { + return false; + } + for (let i = 0; i < prevGroup.length; i++) { + const prev = prevGroup[i]; + const next = nextGroup[i]; + if (prev.checked !== next.checked || prev.required !== next.required) { + return false; + } + } + return true; + } + copy(states) { + // Cast as unknown since typescript does not have enough information to + // infer that the array always has at least one element. + return states.map(({ checked, required }) => ({ + checked, + required, + })); + } +} + +/** + * @license + * Copyright 2022 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A `ReactiveController` that provides root node-scoped single selection for + * elements, similar to native `` selection. + * + * To use, elements should add the controller and call + * `selectionController.handleCheckedChange()` in a getter/setter. This must + * be synchronous to match native behavior. + * + * @example + * const CHECKED = Symbol('checked'); + * + * class MyToggle extends LitElement { + * get checked() { return this[CHECKED]; } + * set checked(checked: boolean) { + * const oldValue = this.checked; + * if (oldValue === checked) { + * return; + * } + * + * this[CHECKED] = checked; + * this.selectionController.handleCheckedChange(); + * this.requestUpdate('checked', oldValue); + * } + * + * [CHECKED] = false; + * + * private selectionController = new SingleSelectionController(this); + * + * constructor() { + * super(); + * this.addController(this.selectionController); + * } + * } + */ +class SingleSelectionController { + /** + * All single selection elements in the host element's root with the same + * `name` attribute, including the host element. + */ + get controls() { + const name = this.host.getAttribute('name'); + if (!name || !this.root || !this.host.isConnected) { + return [this.host]; + } + // Cast as unknown since there is not enough information for typescript to + // know that there is always at least one element (the host). + return Array.from(this.root.querySelectorAll(`[name="${name}"]`)); + } + constructor(host) { + this.host = host; + this.focused = false; + this.root = null; + this.handleFocusIn = () => { + this.focused = true; + this.updateTabIndices(); + }; + this.handleFocusOut = () => { + this.focused = false; + this.updateTabIndices(); + }; + /** + * Handles arrow key events from the host. Using the arrow keys will + * select and check the next or previous sibling with the host's + * `name` attribute. + */ + this.handleKeyDown = (event) => { + const isDown = event.key === 'ArrowDown'; + const isUp = event.key === 'ArrowUp'; + const isLeft = event.key === 'ArrowLeft'; + const isRight = event.key === 'ArrowRight'; + // Ignore non-arrow keys + if (!isLeft && !isRight && !isDown && !isUp) { + return; + } + // Don't try to select another sibling if there aren't any. + const siblings = this.controls; + if (!siblings.length) { + return; + } + // Prevent default interactions on the element for arrow keys, + // since this controller will introduce new behavior. + event.preventDefault(); + // Check if moving forwards or backwards + const isRtl = getComputedStyle(this.host).direction === 'rtl'; + const forwards = isRtl ? isLeft || isDown : isRight || isDown; + const hostIndex = siblings.indexOf(this.host); + let nextIndex = forwards ? hostIndex + 1 : hostIndex - 1; + // Search for the next sibling that is not disabled to select. + // If we return to the host index, there is nothing to select. + while (nextIndex !== hostIndex) { + if (nextIndex >= siblings.length) { + // Return to start if moving past the last item. + nextIndex = 0; + } + else if (nextIndex < 0) { + // Go to end if moving before the first item. + nextIndex = siblings.length - 1; + } + // Check if the next sibling is disabled. If so, + // move the index and continue searching. + const nextSibling = siblings[nextIndex]; + if (nextSibling.hasAttribute('disabled')) { + if (forwards) { + nextIndex++; + } + else { + nextIndex--; + } + continue; + } + // Uncheck and remove focusability from other siblings. + for (const sibling of siblings) { + if (sibling !== nextSibling) { + sibling.checked = false; + sibling.tabIndex = -1; + sibling.blur(); + } + } + // The next sibling should be checked, focused and dispatch a change event + nextSibling.checked = true; + nextSibling.tabIndex = 0; + nextSibling.focus(); + // Fire a change event since the change is triggered by a user action. + // This matches native behavior. + nextSibling.dispatchEvent(new Event('change', { bubbles: true })); + break; + } + }; + } + hostConnected() { + this.root = this.host.getRootNode(); + this.host.addEventListener('keydown', this.handleKeyDown); + this.host.addEventListener('focusin', this.handleFocusIn); + this.host.addEventListener('focusout', this.handleFocusOut); + if (this.host.checked) { + // Uncheck other siblings when attached if already checked. This mimics + // native behavior. + this.uncheckSiblings(); + } + // Update siblings after a microtask to allow other synchronous connected + // callbacks to settle before triggering additional Lit updates. This avoids + // stack overflow issues when too many elements are being rendered and + // connected at the same time. + queueMicrotask(() => { + // Update for the newly added host. + this.updateTabIndices(); + }); + } + hostDisconnected() { + this.host.removeEventListener('keydown', this.handleKeyDown); + this.host.removeEventListener('focusin', this.handleFocusIn); + this.host.removeEventListener('focusout', this.handleFocusOut); + // Update siblings after a microtask to allow other synchronous disconnected + // callbacks to settle before triggering additional Lit updates. This avoids + // stack overflow issues when too many elements are being rendered and + // connected at the same time. + queueMicrotask(() => { + // Update for siblings that are still connected. + this.updateTabIndices(); + this.root = null; + }); + } + /** + * Should be called whenever the host's `checked` property changes + * synchronously. + */ + handleCheckedChange() { + if (!this.host.checked) { + return; + } + this.uncheckSiblings(); + this.updateTabIndices(); + } + uncheckSiblings() { + for (const sibling of this.controls) { + if (sibling !== this.host) { + sibling.checked = false; + } + } + } + /** + * Updates the `tabindex` of the host and its siblings. + */ + updateTabIndices() { + // There are three tabindex states for a group of elements: + // 1. If any are checked, that element is focusable. + const siblings = this.controls; + const checkedSibling = siblings.find((sibling) => sibling.checked); + // 2. If an element is focused, the others are no longer focusable. + if (checkedSibling || this.focused) { + const focusable = checkedSibling || this.host; + focusable.tabIndex = 0; + for (const sibling of siblings) { + if (sibling !== focusable) { + sibling.tabIndex = -1; + } + } + return; + } + // 3. If none are checked or focused, all are focusable. + for (const sibling of siblings) { + sibling.tabIndex = 0; + } + } +} + +/** + * @license + * Copyright 2018 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +var _a; +const CHECKED = Symbol('checked'); +let maskId = 0; +// Separate variable needed for closure. +const radioBaseClass = mixinConstraintValidation(mixinFormAssociated(mixinElementInternals(mixinFocusable(s)))); +/** + * A radio component. + * + * @fires input {InputEvent} Dispatched when the value changes from user + * interaction. --bubbles + * @fires change {Event} Dispatched when the value changes from user + * interaction. --bubbles --composed + */ +class Radio extends radioBaseClass { + /** + * Whether or not the radio is selected. + */ + get checked() { + return this[CHECKED]; + } + set checked(checked) { + const wasChecked = this.checked; + if (wasChecked === checked) { + return; + } + this[CHECKED] = checked; + this.requestUpdate('checked', wasChecked); + this.selectionController.handleCheckedChange(); + } + constructor() { + super(); + // Unique maskId is required because of a Safari bug that fail to persist + // reference to the mask. This should be removed once the bug is fixed. + this.maskId = `cutout${++maskId}`; + this[_a] = false; + /** + * Whether or not the radio is required. If any radio is required in a group, + * all radios are implicitly required. + */ + this.required = false; + /** + * The element value to use in form submission when checked. + */ + this.value = 'on'; + this.selectionController = new SingleSelectionController(this); + this.addController(this.selectionController); + { + this[internals].role = 'radio'; + this.addEventListener('click', this.handleClick.bind(this)); + this.addEventListener('keydown', this.handleKeydown.bind(this)); + } + } + render() { + const classes = { 'checked': this.checked }; + return x ` + + `; + } + updated() { + this[internals].ariaChecked = String(this.checked); + } + async handleClick(event) { + if (this.disabled) { + return; + } + // allow event to propagate to user code after a microtask. + await 0; + if (event.defaultPrevented) { + return; + } + if (isActivationClick(event)) { + this.focus(); + } + // Per spec, clicking on a radio input always selects it. + this.checked = true; + this.dispatchEvent(new Event('change', { bubbles: true })); + this.dispatchEvent(new InputEvent('input', { bubbles: true, composed: true })); + } + async handleKeydown(event) { + // allow event to propagate to user code after a microtask. + await 0; + if (event.key !== ' ' || event.defaultPrevented) { + return; + } + this.click(); + } + [(_a = CHECKED, getFormValue)]() { + return this.checked ? this.value : null; + } + [getFormState]() { + return String(this.checked); + } + formResetCallback() { + // The checked property does not reflect, so the original attribute set by + // the user is used to determine the default value. + this.checked = this.hasAttribute('checked'); + } + formStateRestoreCallback(state) { + this.checked = state === 'true'; + } + [createValidator]() { + return new RadioValidator(() => { + if (!this.selectionController) { + // Validation runs on superclass construction, so selection controller + // might not actually be ready until this class constructs. + return [this]; + } + return this.selectionController.controls; + }); + } + [getValidityAnchor]() { + return this.container; + } +} +__decorate([ + n({ type: Boolean }) +], Radio.prototype, "checked", null); +__decorate([ + n({ type: Boolean }) +], Radio.prototype, "required", void 0); +__decorate([ + n() +], Radio.prototype, "value", void 0); +__decorate([ + i('.container') +], Radio.prototype, "container", void 0); + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./radio/internal/radio-styles.css. +const styles = i$1 `@layer{:host{display:inline-flex;height:var(--md-radio-icon-size, 20px);outline:none;position:relative;vertical-align:top;width:var(--md-radio-icon-size, 20px);-webkit-tap-highlight-color:rgba(0,0,0,0);cursor:pointer;--md-ripple-hover-color: var(--md-radio-hover-state-layer-color, var(--md-sys-color-on-surface, #1d1b20));--md-ripple-hover-opacity: var(--md-radio-hover-state-layer-opacity, 0.08);--md-ripple-pressed-color: var(--md-radio-pressed-state-layer-color, var(--md-sys-color-primary, #6750a4));--md-ripple-pressed-opacity: var(--md-radio-pressed-state-layer-opacity, 0.12)}:host([disabled]){cursor:default}:host([touch-target=wrapper]){margin:max(0px,(48px - var(--md-radio-icon-size, 20px))/2)}.container{display:flex;height:100%;place-content:center;place-items:center;width:100%}md-focus-ring{height:44px;inset:unset;width:44px}.checked{--md-ripple-hover-color: var(--md-radio-selected-hover-state-layer-color, var(--md-sys-color-primary, #6750a4));--md-ripple-hover-opacity: var(--md-radio-selected-hover-state-layer-opacity, 0.08);--md-ripple-pressed-color: var(--md-radio-selected-pressed-state-layer-color, var(--md-sys-color-on-surface, #1d1b20));--md-ripple-pressed-opacity: var(--md-radio-selected-pressed-state-layer-opacity, 0.12)}.touch-target{height:48px;position:absolute;width:48px}:host([touch-target=none]) .touch-target{display:none}md-ripple{border-radius:50%;height:var(--md-radio-state-layer-size, 40px);inset:unset;width:var(--md-radio-state-layer-size, 40px)}.icon{fill:var(--md-radio-icon-color, var(--md-sys-color-on-surface-variant, #49454f));inset:0;position:absolute}.outer.circle{transition:fill 50ms linear}.inner.circle{opacity:0;transform-origin:center;transition:opacity 50ms linear}.checked .icon{fill:var(--md-radio-selected-icon-color, var(--md-sys-color-primary, #6750a4))}.checked .inner.circle{animation:inner-circle-grow 300ms cubic-bezier(0.05, 0.7, 0.1, 1);opacity:1}@keyframes inner-circle-grow{from{transform:scale(0)}to{transform:scale(1)}}:host([disabled]) .circle{animation-duration:0s;transition-duration:0s}:host(:hover) .icon{fill:var(--md-radio-hover-icon-color, var(--md-sys-color-on-surface, #1d1b20))}:host(:focus-within) .icon{fill:var(--md-radio-focus-icon-color, var(--md-sys-color-on-surface, #1d1b20))}:host(:active) .icon{fill:var(--md-radio-pressed-icon-color, var(--md-sys-color-on-surface, #1d1b20))}:host([disabled]) .icon{fill:var(--md-radio-disabled-unselected-icon-color, var(--md-sys-color-on-surface, #1d1b20));opacity:var(--md-radio-disabled-unselected-icon-opacity, 0.38)}:host(:hover) .checked .icon{fill:var(--md-radio-selected-hover-icon-color, var(--md-sys-color-primary, #6750a4))}:host(:focus-within) .checked .icon{fill:var(--md-radio-selected-focus-icon-color, var(--md-sys-color-primary, #6750a4))}:host(:active) .checked .icon{fill:var(--md-radio-selected-pressed-icon-color, var(--md-sys-color-primary, #6750a4))}:host([disabled]) .checked .icon{fill:var(--md-radio-disabled-selected-icon-color, var(--md-sys-color-on-surface, #1d1b20));opacity:var(--md-radio-disabled-selected-icon-opacity, 0.38)}}@layer hcm{@media(forced-colors: active){.icon{fill:CanvasText}:host([disabled]) .icon{fill:GrayText;opacity:1}}} +`; + +/** + * @license + * Copyright 2022 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @summary Radio buttons allow users to select one option from a set. + * + * @description + * Radio buttons are the recommended way to allow users to make a single + * selection from a list of options. + * + * Only one radio button can be selected at a time. + * + * Use radio buttons to: + * - Select a single option from a set + * - Expose all available options + * + * @final + * @suppress {visibility} + */ +let MdRadio = class MdRadio extends Radio { +}; +MdRadio.styles = [styles]; +MdRadio = __decorate([ + e('md-radio') +], MdRadio); + +export { MdRadio }; diff --git a/md-web/ripple.js b/md-web/ripple.js new file mode 100644 index 0000000..b9f2970 --- /dev/null +++ b/md-web/ripple.js @@ -0,0 +1,3 @@ +export const __dummy_loader = () => {}; + +export { ae as MdRipple } from './core.js'; diff --git a/md-web/select.js b/md-web/select.js new file mode 100644 index 0000000..56bf62c --- /dev/null +++ b/md-web/select.js @@ -0,0 +1,125 @@ +export const __dummy_loader = () => {}; + +import { Z as Select, G as i, i as i$1, $ as styles$2, _ as __decorate, e } from './core.js'; + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// tslint:disable-next-line:enforce-comments-on-exported-symbols +class FilledSelect extends Select { + constructor() { + super(...arguments); + this.fieldTag = i `md-filled-field`; + } +} + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./select/internal/filled-select-styles.css. +const styles$1 = i$1 `:host{--_text-field-active-indicator-color: var(--md-filled-select-text-field-active-indicator-color, var(--md-sys-color-on-surface-variant, #49454f));--_text-field-active-indicator-height: var(--md-filled-select-text-field-active-indicator-height, 1px);--_text-field-container-color: var(--md-filled-select-text-field-container-color, var(--md-sys-color-surface-container-highest, #e6e0e9));--_text-field-disabled-active-indicator-color: var(--md-filled-select-text-field-disabled-active-indicator-color, var(--md-sys-color-on-surface, #1d1b20));--_text-field-disabled-active-indicator-height: var(--md-filled-select-text-field-disabled-active-indicator-height, 1px);--_text-field-disabled-active-indicator-opacity: var(--md-filled-select-text-field-disabled-active-indicator-opacity, 0.38);--_text-field-disabled-container-color: var(--md-filled-select-text-field-disabled-container-color, var(--md-sys-color-on-surface, #1d1b20));--_text-field-disabled-container-opacity: var(--md-filled-select-text-field-disabled-container-opacity, 0.04);--_text-field-disabled-input-text-color: var(--md-filled-select-text-field-disabled-input-text-color, var(--md-sys-color-on-surface, #1d1b20));--_text-field-disabled-input-text-opacity: var(--md-filled-select-text-field-disabled-input-text-opacity, 0.38);--_text-field-disabled-label-text-color: var(--md-filled-select-text-field-disabled-label-text-color, var(--md-sys-color-on-surface, #1d1b20));--_text-field-disabled-label-text-opacity: var(--md-filled-select-text-field-disabled-label-text-opacity, 0.38);--_text-field-disabled-leading-icon-color: var(--md-filled-select-text-field-disabled-leading-icon-color, var(--md-sys-color-on-surface, #1d1b20));--_text-field-disabled-leading-icon-opacity: var(--md-filled-select-text-field-disabled-leading-icon-opacity, 0.38);--_text-field-disabled-supporting-text-color: var(--md-filled-select-text-field-disabled-supporting-text-color, var(--md-sys-color-on-surface, #1d1b20));--_text-field-disabled-supporting-text-opacity: var(--md-filled-select-text-field-disabled-supporting-text-opacity, 0.38);--_text-field-disabled-trailing-icon-color: var(--md-filled-select-text-field-disabled-trailing-icon-color, var(--md-sys-color-on-surface, #1d1b20));--_text-field-disabled-trailing-icon-opacity: var(--md-filled-select-text-field-disabled-trailing-icon-opacity, 0.38);--_text-field-error-active-indicator-color: var(--md-filled-select-text-field-error-active-indicator-color, var(--md-sys-color-error, #b3261e));--_text-field-error-focus-active-indicator-color: var(--md-filled-select-text-field-error-focus-active-indicator-color, var(--md-sys-color-error, #b3261e));--_text-field-error-focus-input-text-color: var(--md-filled-select-text-field-error-focus-input-text-color, var(--md-sys-color-on-surface, #1d1b20));--_text-field-error-focus-label-text-color: var(--md-filled-select-text-field-error-focus-label-text-color, var(--md-sys-color-error, #b3261e));--_text-field-error-focus-leading-icon-color: var(--md-filled-select-text-field-error-focus-leading-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_text-field-error-focus-supporting-text-color: var(--md-filled-select-text-field-error-focus-supporting-text-color, var(--md-sys-color-error, #b3261e));--_text-field-error-focus-trailing-icon-color: var(--md-filled-select-text-field-error-focus-trailing-icon-color, var(--md-sys-color-error, #b3261e));--_text-field-error-hover-active-indicator-color: var(--md-filled-select-text-field-error-hover-active-indicator-color, var(--md-sys-color-on-error-container, #410e0b));--_text-field-error-hover-input-text-color: var(--md-filled-select-text-field-error-hover-input-text-color, var(--md-sys-color-on-surface, #1d1b20));--_text-field-error-hover-label-text-color: var(--md-filled-select-text-field-error-hover-label-text-color, var(--md-sys-color-on-error-container, #410e0b));--_text-field-error-hover-leading-icon-color: var(--md-filled-select-text-field-error-hover-leading-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_text-field-error-hover-state-layer-color: var(--md-filled-select-text-field-error-hover-state-layer-color, var(--md-sys-color-on-surface, #1d1b20));--_text-field-error-hover-state-layer-opacity: var(--md-filled-select-text-field-error-hover-state-layer-opacity, 0.08);--_text-field-error-hover-supporting-text-color: var(--md-filled-select-text-field-error-hover-supporting-text-color, var(--md-sys-color-error, #b3261e));--_text-field-error-hover-trailing-icon-color: var(--md-filled-select-text-field-error-hover-trailing-icon-color, var(--md-sys-color-on-error-container, #410e0b));--_text-field-error-input-text-color: var(--md-filled-select-text-field-error-input-text-color, var(--md-sys-color-on-surface, #1d1b20));--_text-field-error-label-text-color: var(--md-filled-select-text-field-error-label-text-color, var(--md-sys-color-error, #b3261e));--_text-field-error-leading-icon-color: var(--md-filled-select-text-field-error-leading-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_text-field-error-supporting-text-color: var(--md-filled-select-text-field-error-supporting-text-color, var(--md-sys-color-error, #b3261e));--_text-field-error-trailing-icon-color: var(--md-filled-select-text-field-error-trailing-icon-color, var(--md-sys-color-error, #b3261e));--_text-field-focus-active-indicator-color: var(--md-filled-select-text-field-focus-active-indicator-color, var(--md-sys-color-primary, #6750a4));--_text-field-focus-active-indicator-height: var(--md-filled-select-text-field-focus-active-indicator-height, 3px);--_text-field-focus-input-text-color: var(--md-filled-select-text-field-focus-input-text-color, var(--md-sys-color-on-surface, #1d1b20));--_text-field-focus-label-text-color: var(--md-filled-select-text-field-focus-label-text-color, var(--md-sys-color-primary, #6750a4));--_text-field-focus-leading-icon-color: var(--md-filled-select-text-field-focus-leading-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_text-field-focus-supporting-text-color: var(--md-filled-select-text-field-focus-supporting-text-color, var(--md-sys-color-on-surface-variant, #49454f));--_text-field-focus-trailing-icon-color: var(--md-filled-select-text-field-focus-trailing-icon-color, var(--md-sys-color-primary, #6750a4));--_text-field-hover-active-indicator-color: var(--md-filled-select-text-field-hover-active-indicator-color, var(--md-sys-color-on-surface, #1d1b20));--_text-field-hover-active-indicator-height: var(--md-filled-select-text-field-hover-active-indicator-height, 1px);--_text-field-hover-input-text-color: var(--md-filled-select-text-field-hover-input-text-color, var(--md-sys-color-on-surface, #1d1b20));--_text-field-hover-label-text-color: var(--md-filled-select-text-field-hover-label-text-color, var(--md-sys-color-on-surface, #1d1b20));--_text-field-hover-leading-icon-color: var(--md-filled-select-text-field-hover-leading-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_text-field-hover-state-layer-color: var(--md-filled-select-text-field-hover-state-layer-color, var(--md-sys-color-on-surface, #1d1b20));--_text-field-hover-state-layer-opacity: var(--md-filled-select-text-field-hover-state-layer-opacity, 0.08);--_text-field-hover-supporting-text-color: var(--md-filled-select-text-field-hover-supporting-text-color, var(--md-sys-color-on-surface-variant, #49454f));--_text-field-hover-trailing-icon-color: var(--md-filled-select-text-field-hover-trailing-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_text-field-input-text-color: var(--md-filled-select-text-field-input-text-color, var(--md-sys-color-on-surface, #1d1b20));--_text-field-input-text-font: var(--md-filled-select-text-field-input-text-font, var(--md-sys-typescale-body-large-font, var(--md-ref-typeface-plain, Roboto)));--_text-field-input-text-line-height: var(--md-filled-select-text-field-input-text-line-height, var(--md-sys-typescale-body-large-line-height, 1.5rem));--_text-field-input-text-size: var(--md-filled-select-text-field-input-text-size, var(--md-sys-typescale-body-large-size, 1rem));--_text-field-input-text-weight: var(--md-filled-select-text-field-input-text-weight, var(--md-sys-typescale-body-large-weight, var(--md-ref-typeface-weight-regular, 400)));--_text-field-label-text-color: var(--md-filled-select-text-field-label-text-color, var(--md-sys-color-on-surface-variant, #49454f));--_text-field-label-text-font: var(--md-filled-select-text-field-label-text-font, var(--md-sys-typescale-body-large-font, var(--md-ref-typeface-plain, Roboto)));--_text-field-label-text-line-height: var(--md-filled-select-text-field-label-text-line-height, var(--md-sys-typescale-body-large-line-height, 1.5rem));--_text-field-label-text-populated-line-height: var(--md-filled-select-text-field-label-text-populated-line-height, var(--md-sys-typescale-body-small-line-height, 1rem));--_text-field-label-text-populated-size: var(--md-filled-select-text-field-label-text-populated-size, var(--md-sys-typescale-body-small-size, 0.75rem));--_text-field-label-text-size: var(--md-filled-select-text-field-label-text-size, var(--md-sys-typescale-body-large-size, 1rem));--_text-field-label-text-weight: var(--md-filled-select-text-field-label-text-weight, var(--md-sys-typescale-body-large-weight, var(--md-ref-typeface-weight-regular, 400)));--_text-field-leading-icon-color: var(--md-filled-select-text-field-leading-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_text-field-leading-icon-size: var(--md-filled-select-text-field-leading-icon-size, 24px);--_text-field-supporting-text-color: var(--md-filled-select-text-field-supporting-text-color, var(--md-sys-color-on-surface-variant, #49454f));--_text-field-supporting-text-font: var(--md-filled-select-text-field-supporting-text-font, var(--md-sys-typescale-body-small-font, var(--md-ref-typeface-plain, Roboto)));--_text-field-supporting-text-line-height: var(--md-filled-select-text-field-supporting-text-line-height, var(--md-sys-typescale-body-small-line-height, 1rem));--_text-field-supporting-text-size: var(--md-filled-select-text-field-supporting-text-size, var(--md-sys-typescale-body-small-size, 0.75rem));--_text-field-supporting-text-weight: var(--md-filled-select-text-field-supporting-text-weight, var(--md-sys-typescale-body-small-weight, var(--md-ref-typeface-weight-regular, 400)));--_text-field-trailing-icon-color: var(--md-filled-select-text-field-trailing-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_text-field-trailing-icon-size: var(--md-filled-select-text-field-trailing-icon-size, 24px);--_text-field-container-shape-start-start: var(--md-filled-select-text-field-container-shape-start-start, var(--md-filled-select-text-field-container-shape, var(--md-sys-shape-corner-extra-small, 4px)));--_text-field-container-shape-start-end: var(--md-filled-select-text-field-container-shape-start-end, var(--md-filled-select-text-field-container-shape, var(--md-sys-shape-corner-extra-small, 4px)));--_text-field-container-shape-end-end: var(--md-filled-select-text-field-container-shape-end-end, var(--md-filled-select-text-field-container-shape, var(--md-sys-shape-corner-none, 0px)));--_text-field-container-shape-end-start: var(--md-filled-select-text-field-container-shape-end-start, var(--md-filled-select-text-field-container-shape, var(--md-sys-shape-corner-none, 0px)));--md-filled-field-active-indicator-color: var(--_text-field-active-indicator-color);--md-filled-field-active-indicator-height: var(--_text-field-active-indicator-height);--md-filled-field-container-color: var(--_text-field-container-color);--md-filled-field-container-shape-end-end: var(--_text-field-container-shape-end-end);--md-filled-field-container-shape-end-start: var(--_text-field-container-shape-end-start);--md-filled-field-container-shape-start-end: var(--_text-field-container-shape-start-end);--md-filled-field-container-shape-start-start: var(--_text-field-container-shape-start-start);--md-filled-field-content-color: var(--_text-field-input-text-color);--md-filled-field-content-font: var(--_text-field-input-text-font);--md-filled-field-content-line-height: var(--_text-field-input-text-line-height);--md-filled-field-content-size: var(--_text-field-input-text-size);--md-filled-field-content-weight: var(--_text-field-input-text-weight);--md-filled-field-disabled-active-indicator-color: var(--_text-field-disabled-active-indicator-color);--md-filled-field-disabled-active-indicator-height: var(--_text-field-disabled-active-indicator-height);--md-filled-field-disabled-active-indicator-opacity: var(--_text-field-disabled-active-indicator-opacity);--md-filled-field-disabled-container-color: var(--_text-field-disabled-container-color);--md-filled-field-disabled-container-opacity: var(--_text-field-disabled-container-opacity);--md-filled-field-disabled-content-color: var(--_text-field-disabled-input-text-color);--md-filled-field-disabled-content-opacity: var(--_text-field-disabled-input-text-opacity);--md-filled-field-disabled-label-text-color: var(--_text-field-disabled-label-text-color);--md-filled-field-disabled-label-text-opacity: var(--_text-field-disabled-label-text-opacity);--md-filled-field-disabled-leading-content-color: var(--_text-field-disabled-leading-icon-color);--md-filled-field-disabled-leading-content-opacity: var(--_text-field-disabled-leading-icon-opacity);--md-filled-field-disabled-supporting-text-color: var(--_text-field-disabled-supporting-text-color);--md-filled-field-disabled-supporting-text-opacity: var(--_text-field-disabled-supporting-text-opacity);--md-filled-field-disabled-trailing-content-color: var(--_text-field-disabled-trailing-icon-color);--md-filled-field-disabled-trailing-content-opacity: var(--_text-field-disabled-trailing-icon-opacity);--md-filled-field-error-active-indicator-color: var(--_text-field-error-active-indicator-color);--md-filled-field-error-content-color: var(--_text-field-error-input-text-color);--md-filled-field-error-focus-active-indicator-color: var(--_text-field-error-focus-active-indicator-color);--md-filled-field-error-focus-content-color: var(--_text-field-error-focus-input-text-color);--md-filled-field-error-focus-label-text-color: var(--_text-field-error-focus-label-text-color);--md-filled-field-error-focus-leading-content-color: var(--_text-field-error-focus-leading-icon-color);--md-filled-field-error-focus-supporting-text-color: var(--_text-field-error-focus-supporting-text-color);--md-filled-field-error-focus-trailing-content-color: var(--_text-field-error-focus-trailing-icon-color);--md-filled-field-error-hover-active-indicator-color: var(--_text-field-error-hover-active-indicator-color);--md-filled-field-error-hover-content-color: var(--_text-field-error-hover-input-text-color);--md-filled-field-error-hover-label-text-color: var(--_text-field-error-hover-label-text-color);--md-filled-field-error-hover-leading-content-color: var(--_text-field-error-hover-leading-icon-color);--md-filled-field-error-hover-state-layer-color: var(--_text-field-error-hover-state-layer-color);--md-filled-field-error-hover-state-layer-opacity: var(--_text-field-error-hover-state-layer-opacity);--md-filled-field-error-hover-supporting-text-color: var(--_text-field-error-hover-supporting-text-color);--md-filled-field-error-hover-trailing-content-color: var(--_text-field-error-hover-trailing-icon-color);--md-filled-field-error-label-text-color: var(--_text-field-error-label-text-color);--md-filled-field-error-leading-content-color: var(--_text-field-error-leading-icon-color);--md-filled-field-error-supporting-text-color: var(--_text-field-error-supporting-text-color);--md-filled-field-error-trailing-content-color: var(--_text-field-error-trailing-icon-color);--md-filled-field-focus-active-indicator-color: var(--_text-field-focus-active-indicator-color);--md-filled-field-focus-active-indicator-height: var(--_text-field-focus-active-indicator-height);--md-filled-field-focus-content-color: var(--_text-field-focus-input-text-color);--md-filled-field-focus-label-text-color: var(--_text-field-focus-label-text-color);--md-filled-field-focus-leading-content-color: var(--_text-field-focus-leading-icon-color);--md-filled-field-focus-supporting-text-color: var(--_text-field-focus-supporting-text-color);--md-filled-field-focus-trailing-content-color: var(--_text-field-focus-trailing-icon-color);--md-filled-field-hover-active-indicator-color: var(--_text-field-hover-active-indicator-color);--md-filled-field-hover-active-indicator-height: var(--_text-field-hover-active-indicator-height);--md-filled-field-hover-content-color: var(--_text-field-hover-input-text-color);--md-filled-field-hover-label-text-color: var(--_text-field-hover-label-text-color);--md-filled-field-hover-leading-content-color: var(--_text-field-hover-leading-icon-color);--md-filled-field-hover-state-layer-color: var(--_text-field-hover-state-layer-color);--md-filled-field-hover-state-layer-opacity: var(--_text-field-hover-state-layer-opacity);--md-filled-field-hover-supporting-text-color: var(--_text-field-hover-supporting-text-color);--md-filled-field-hover-trailing-content-color: var(--_text-field-hover-trailing-icon-color);--md-filled-field-label-text-color: var(--_text-field-label-text-color);--md-filled-field-label-text-font: var(--_text-field-label-text-font);--md-filled-field-label-text-line-height: var(--_text-field-label-text-line-height);--md-filled-field-label-text-populated-line-height: var(--_text-field-label-text-populated-line-height);--md-filled-field-label-text-populated-size: var(--_text-field-label-text-populated-size);--md-filled-field-label-text-size: var(--_text-field-label-text-size);--md-filled-field-label-text-weight: var(--_text-field-label-text-weight);--md-filled-field-leading-content-color: var(--_text-field-leading-icon-color);--md-filled-field-supporting-text-color: var(--_text-field-supporting-text-color);--md-filled-field-supporting-text-font: var(--_text-field-supporting-text-font);--md-filled-field-supporting-text-line-height: var(--_text-field-supporting-text-line-height);--md-filled-field-supporting-text-size: var(--_text-field-supporting-text-size);--md-filled-field-supporting-text-weight: var(--_text-field-supporting-text-weight);--md-filled-field-trailing-content-color: var(--_text-field-trailing-icon-color)}[has-start] .icon.leading{font-size:var(--_text-field-leading-icon-size);height:var(--_text-field-leading-icon-size);width:var(--_text-field-leading-icon-size)}.icon.trailing{font-size:var(--_text-field-trailing-icon-size);height:var(--_text-field-trailing-icon-size);width:var(--_text-field-trailing-icon-size)} +`; + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @summary + * Select menus display a list of choices on temporary surfaces and display the + * currently selected menu item above the menu. + * + * @description + * The select component allows users to choose a value from a fixed list of + * available options. Composed of an interactive anchor button and a menu, it is + * analogous to the native HTML `` element. This is the "outlined" + * variant. + * + * @example + * ```html + * + * + * + * + * + * + * + * + * + * ``` + * + * @final + * @suppress {visibility} + */ +let MdOutlinedSelect = class MdOutlinedSelect extends OutlinedSelect { +}; +MdOutlinedSelect.styles = [styles$2, styles]; +MdOutlinedSelect = __decorate([ + e('md-outlined-select') +], MdOutlinedSelect); diff --git a/md-web/slider.js b/md-web/slider.js new file mode 100644 index 0000000..0da79ac --- /dev/null +++ b/md-web/slider.js @@ -0,0 +1,759 @@ +export const __dummy_loader = () => {}; + +import { i, m as mixinDelegatesAria, b as mixinFormAssociated, s, _ as __decorate, n as n$1, c as i$1, Y as e, t, d as isActivationClick, f as dispatchActivationClick, x, o, I as o$1, A, r as redispatchEvent, g as getFormValue, q as mixinElementInternals, e as e$1 } from './core.js'; + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./slider/internal/forced-colors-styles.css. +const styles$1 = i `@media(forced-colors: active){:host{--md-slider-active-track-color: CanvasText;--md-slider-disabled-active-track-color: GrayText;--md-slider-disabled-active-track-opacity: 1;--md-slider-disabled-handle-color: GrayText;--md-slider-disabled-inactive-track-color: GrayText;--md-slider-disabled-inactive-track-opacity: 1;--md-slider-focus-handle-color: CanvasText;--md-slider-handle-color: CanvasText;--md-slider-handle-shadow-color: Canvas;--md-slider-hover-handle-color: CanvasText;--md-slider-hover-state-layer-color: Canvas;--md-slider-hover-state-layer-opacity: 1;--md-slider-inactive-track-color: Canvas;--md-slider-label-container-color: Canvas;--md-slider-label-text-color: CanvasText;--md-slider-pressed-handle-color: CanvasText;--md-slider-pressed-state-layer-color: Canvas;--md-slider-pressed-state-layer-opacity: 1;--md-slider-with-overlap-handle-outline-color: CanvasText}.label,.label::before{border:var(--_with-overlap-handle-outline-color) solid var(--_with-overlap-handle-outline-width)}:host(:not([disabled])) .track::before{border:1px solid var(--_active-track-color)}.tickmarks::before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='CanvasText'%3E%3Ccircle cx='2' cy='2' r='1'/%3E%3C/svg%3E")}.tickmarks::after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='Canvas'%3E%3Ccircle cx='2' cy='2' r='1'/%3E%3C/svg%3E")}:host([disabled]) .tickmarks::before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='Canvas'%3E%3Ccircle cx='2' cy='2' r='1'/%3E%3C/svg%3E")}} +`; + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +function n(n,o,r){return n?o():null==r?void 0:r()} + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Disable warning for classMap with destructuring +// tslint:disable:no-implicit-dictionary-conversion +// Separate variable needed for closure. +const sliderBaseClass = mixinDelegatesAria(mixinFormAssociated(mixinElementInternals(s))); +/** + * Slider component. + * + * + * @fires change {Event} The native `change` event on + * [``](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) + * --bubbles + * @fires input {InputEvent} The native `input` event on + * [``](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event) + * --bubbles --composed + */ +class Slider extends sliderBaseClass { + /** + * The HTML name to use in form submission for a range slider's starting + * value. Use `name` instead if both the start and end values should use the + * same name. + */ + get nameStart() { + return this.getAttribute('name-start') ?? this.name; + } + set nameStart(name) { + this.setAttribute('name-start', name); + } + /** + * The HTML name to use in form submission for a range slider's ending value. + * Use `name` instead if both the start and end values should use the same + * name. + */ + get nameEnd() { + return this.getAttribute('name-end') ?? this.nameStart; + } + set nameEnd(name) { + this.setAttribute('name-end', name); + } + // Note: start aria-* properties are only applied when range=true, which is + // why they do not need to handle both cases. + get renderAriaLabelStart() { + // Needed for closure conformance + const { ariaLabel } = this; + return (this.ariaLabelStart || + (ariaLabel && `${ariaLabel} start`) || + this.valueLabelStart || + String(this.valueStart)); + } + get renderAriaValueTextStart() { + return (this.ariaValueTextStart || this.valueLabelStart || String(this.valueStart)); + } + // Note: end aria-* properties are applied for single and range sliders, which + // is why it needs to handle `this.range` (while start aria-* properties do + // not). + get renderAriaLabelEnd() { + // Needed for closure conformance + const { ariaLabel } = this; + if (this.range) { + return (this.ariaLabelEnd || + (ariaLabel && `${ariaLabel} end`) || + this.valueLabelEnd || + String(this.valueEnd)); + } + return ariaLabel || this.valueLabel || String(this.value); + } + get renderAriaValueTextEnd() { + if (this.range) { + return (this.ariaValueTextEnd || this.valueLabelEnd || String(this.valueEnd)); + } + // Needed for conformance + const { ariaValueText } = this; + return ariaValueText || this.valueLabel || String(this.value); + } + constructor() { + super(); + /** + * The slider minimum value + */ + this.min = 0; + /** + * The slider maximum value + */ + this.max = 100; + /** + * An optional label for the slider's value displayed when range is + * false; if not set, the label is the value itself. + */ + this.valueLabel = ''; + /** + * An optional label for the slider's start value displayed when + * range is true; if not set, the label is the valueStart itself. + */ + this.valueLabelStart = ''; + /** + * An optional label for the slider's end value displayed when + * range is true; if not set, the label is the valueEnd itself. + */ + this.valueLabelEnd = ''; + /** + * Aria label for the slider's start handle displayed when + * range is true. + */ + this.ariaLabelStart = ''; + /** + * Aria value text for the slider's start value displayed when + * range is true. + */ + this.ariaValueTextStart = ''; + /** + * Aria label for the slider's end handle displayed when + * range is true. + */ + this.ariaLabelEnd = ''; + /** + * Aria value text for the slider's end value displayed when + * range is true. + */ + this.ariaValueTextEnd = ''; + /** + * The step between values. + */ + this.step = 1; + /** + * Whether or not to show tick marks. + */ + this.ticks = false; + /** + * Whether or not to show a value label when activated. + */ + this.labeled = false; + /** + * Whether or not to show a value range. When false, the slider displays + * a slideable handle for the value property; when true, it displays + * slideable handles for the valueStart and valueEnd properties. + */ + this.range = false; + // handle hover/pressed states are set manually since the handle + // does not receive pointer events so that the native inputs are + // interaction targets. + this.handleStartHover = false; + this.handleEndHover = false; + this.startOnTop = false; + this.handlesOverlapping = false; + // used in synthetic events generated to control ripple hover state. + this.ripplePointerId = 1; + // flag to prevent processing of re-dispatched input event. + this.isRedispatchingEvent = false; + { + this.addEventListener('click', (event) => { + if (!isActivationClick(event) || !this.inputEnd) { + return; + } + this.focus(); + dispatchActivationClick(this.inputEnd); + }); + } + } + focus() { + this.inputEnd?.focus(); + } + willUpdate(changed) { + this.renderValueStart = changed.has('valueStart') + ? this.valueStart + : this.inputStart?.valueAsNumber; + const endValueChanged = (changed.has('valueEnd') && this.range) || changed.has('value'); + this.renderValueEnd = endValueChanged + ? this.range + ? this.valueEnd + : this.value + : this.inputEnd?.valueAsNumber; + // manually handle ripple hover state since the handle is pointer events + // none. + if (changed.get('handleStartHover') !== undefined) { + this.toggleRippleHover(this.rippleStart, this.handleStartHover); + } + else if (changed.get('handleEndHover') !== undefined) { + this.toggleRippleHover(this.rippleEnd, this.handleEndHover); + } + } + updated(changed) { + // Validate input rendered value and re-render if necessary. This ensures + // the rendred handle stays in sync with the input thumb which is used for + // interaction. These can get out of sync if a supplied value does not + // map to an exactly stepped value between min and max. + if (this.range) { + this.renderValueStart = this.inputStart.valueAsNumber; + } + this.renderValueEnd = this.inputEnd.valueAsNumber; + // update values if they are unset + // when using a range, default to equi-distant between + // min - valueStart - valueEnd - max + if (this.range) { + const segment = (this.max - this.min) / 3; + if (this.valueStart === undefined) { + this.inputStart.valueAsNumber = this.min + segment; + // read actual value from input + const v = this.inputStart.valueAsNumber; + this.valueStart = this.renderValueStart = v; + } + if (this.valueEnd === undefined) { + this.inputEnd.valueAsNumber = this.min + 2 * segment; + // read actual value from input + const v = this.inputEnd.valueAsNumber; + this.valueEnd = this.renderValueEnd = v; + } + } + else { + this.value ??= this.renderValueEnd; + } + if (changed.has('range') || + changed.has('renderValueStart') || + changed.has('renderValueEnd') || + this.isUpdatePending) { + // Only check if the handle nubs are overlapping, as the ripple touch + // target extends subtantially beyond the boundary of the handle nub. + const startNub = this.handleStart?.querySelector('.handleNub'); + const endNub = this.handleEnd?.querySelector('.handleNub'); + this.handlesOverlapping = isOverlapping(startNub, endNub); + } + // called to finish the update imediately; + // note, this is a no-op unless an update is scheduled + this.performUpdate(); + } + render() { + const step = this.step === 0 ? 1 : this.step; + const range = Math.max(this.max - this.min, step); + const startFraction = this.range + ? ((this.renderValueStart ?? this.min) - this.min) / range + : 0; + const endFraction = ((this.renderValueEnd ?? this.min) - this.min) / range; + const containerStyles = { + // for clipping inputs and active track. + '--_start-fraction': String(startFraction), + '--_end-fraction': String(endFraction), + // for generating tick marks + '--_tick-count': String(range / step), + }; + const containerClasses = { ranged: this.range }; + // optional label values to show in place of the value. + const labelStart = this.valueLabelStart || String(this.renderValueStart); + const labelEnd = (this.range ? this.valueLabelEnd : this.valueLabel) || + String(this.renderValueEnd); + const inputStartProps = { + start: true, + value: this.renderValueStart, + ariaLabel: this.renderAriaLabelStart, + ariaValueText: this.renderAriaValueTextStart, + ariaMin: this.min, + ariaMax: this.valueEnd ?? this.max, + }; + const inputEndProps = { + start: false, + value: this.renderValueEnd, + ariaLabel: this.renderAriaLabelEnd, + ariaValueText: this.renderAriaValueTextEnd, + ariaMin: this.range ? this.valueStart ?? this.min : this.min, + ariaMax: this.max, + }; + const handleStartProps = { + start: true, + hover: this.handleStartHover, + label: labelStart, + }; + const handleEndProps = { + start: false, + hover: this.handleEndHover, + label: labelEnd, + }; + const handleContainerClasses = { + hover: this.handleStartHover || this.handleEndHover, + }; + return x `
+ ${n(this.range, () => this.renderInput(inputStartProps))} + ${this.renderInput(inputEndProps)} ${this.renderTrack()} +
+
+
+ ${n(this.range, () => this.renderHandle(handleStartProps))} + ${this.renderHandle(handleEndProps)} +
+
+
+
`; + } + renderTrack() { + return x ` +
+ ${this.ticks ? x `
` : A} + `; + } + renderLabel(value) { + return x ``; + } + renderHandle({ start, hover, label, }) { + const onTop = !this.disabled && start === this.startOnTop; + const isOverlapping = !this.disabled && this.handlesOverlapping; + const name = start ? 'start' : 'end'; + return x `
+ + +
+ +
+ ${n(this.labeled, () => this.renderLabel(label))} +
`; + } + renderInput({ start, value, ariaLabel, ariaValueText, ariaMin, ariaMax, }) { + // Slider requires min/max set to the overall min/max for both inputs. + // This is reported to screen readers, which is why we need aria-valuemin + // and aria-valuemax. + const name = start ? `start` : `end`; + return x ``; + } + async toggleRippleHover(ripple, hovering) { + const rippleEl = await ripple; + if (!rippleEl) { + return; + } + // TODO(b/269799771): improve slider ripple connection + if (hovering) { + rippleEl.handlePointerenter(new PointerEvent('pointerenter', { + isPrimary: true, + pointerId: this.ripplePointerId, + })); + } + else { + rippleEl.handlePointerleave(new PointerEvent('pointerleave', { + isPrimary: true, + pointerId: this.ripplePointerId, + })); + } + } + handleFocus(event) { + this.updateOnTop(event.target); + } + startAction(event) { + const target = event.target; + const fixed = target === this.inputStart ? this.inputEnd : this.inputStart; + this.action = { + canFlip: event.type === 'pointerdown', + flipped: false, + target, + fixed, + values: new Map([ + [target, target.valueAsNumber], + [fixed, fixed?.valueAsNumber], + ]), + }; + } + finishAction(event) { + this.action = undefined; + } + handleKeydown(event) { + this.startAction(event); + } + handleKeyup(event) { + this.finishAction(event); + } + handleDown(event) { + this.startAction(event); + this.ripplePointerId = event.pointerId; + const isStart = event.target === this.inputStart; + // Since handle moves to pointer on down and there may not be a move, + // it needs to be considered hovered.. + this.handleStartHover = + !this.disabled && isStart && Boolean(this.handleStart); + this.handleEndHover = !this.disabled && !isStart && Boolean(this.handleEnd); + } + async handleUp(event) { + if (!this.action) { + return; + } + const { target, values, flipped } = this.action; + // Async here for Firefox because input can be after pointerup + // when value is calmped. + await new Promise(requestAnimationFrame); + if (target !== undefined) { + // Ensure Safari focuses input so label renders. + // Ensure any flipped input is focused so the tab order is right. + target.focus(); + // When action is flipped, change must be fired manually since the + // real event target did not change. + if (flipped && target.valueAsNumber !== values.get(target)) { + target.dispatchEvent(new Event('change', { bubbles: true })); + } + } + this.finishAction(event); + } + /** + * The move handler tracks handle hovering to facilitate proper ripple + * behavior on the slider handle. This is needed because user interaction with + * the native input is leveraged to position the handle. Because the separate + * displayed handle element has pointer events disabled (to allow interaction + * with the input) and the input's handle is a pseudo-element, neither can be + * the ripple's interactive element. Therefore the input is the ripple's + * interactive element and has a `ripple` directive; however the ripple + * is gated on the handle being hovered. In addition, because the ripple + * hover state is being specially handled, it must be triggered independent + * of the directive. This is done based on the hover state when the + * slider is updated. + */ + handleMove(event) { + this.handleStartHover = !this.disabled && inBounds(event, this.handleStart); + this.handleEndHover = !this.disabled && inBounds(event, this.handleEnd); + } + handleEnter(event) { + this.handleMove(event); + } + handleLeave() { + this.handleStartHover = false; + this.handleEndHover = false; + } + updateOnTop(input) { + this.startOnTop = input.classList.contains('start'); + } + needsClamping() { + if (!this.action) { + return false; + } + const { target, fixed } = this.action; + const isStart = target === this.inputStart; + return isStart + ? target.valueAsNumber > fixed.valueAsNumber + : target.valueAsNumber < fixed.valueAsNumber; + } + // if start/end start coincident and the first drag input would e.g. move + // start > end, avoid clamping and "flip" to use the other input + // as the action target. + isActionFlipped() { + const { action } = this; + if (!action) { + return false; + } + const { target, fixed, values } = action; + if (action.canFlip) { + const coincident = values.get(target) === values.get(fixed); + if (coincident && this.needsClamping()) { + action.canFlip = false; + action.flipped = true; + action.target = fixed; + action.fixed = target; + } + } + return action.flipped; + } + // when flipped, apply the drag input to the flipped target and reset + // the actual target. + flipAction() { + if (!this.action) { + return false; + } + const { target, fixed, values } = this.action; + const changed = target.valueAsNumber !== fixed.valueAsNumber; + target.valueAsNumber = fixed.valueAsNumber; + fixed.valueAsNumber = values.get(fixed); + return changed; + } + // clamp such that start does not move beyond end and visa versa. + clampAction() { + if (!this.needsClamping() || !this.action) { + return false; + } + const { target, fixed } = this.action; + target.valueAsNumber = fixed.valueAsNumber; + return true; + } + handleInput(event) { + // avoid processing a re-dispatched event + if (this.isRedispatchingEvent) { + return; + } + let stopPropagation = false; + let redispatch = false; + if (this.range) { + if (this.isActionFlipped()) { + stopPropagation = true; + redispatch = this.flipAction(); + } + if (this.clampAction()) { + stopPropagation = true; + redispatch = false; + } + } + const target = event.target; + this.updateOnTop(target); + // update value only on interaction + if (this.range) { + this.valueStart = this.inputStart.valueAsNumber; + this.valueEnd = this.inputEnd.valueAsNumber; + } + else { + this.value = this.inputEnd.valueAsNumber; + } + // control external visibility of input event + if (stopPropagation) { + event.stopPropagation(); + } + // ensure event path is correct when flipped. + if (redispatch) { + this.isRedispatchingEvent = true; + redispatchEvent(target, event); + this.isRedispatchingEvent = false; + } + } + handleChange(event) { + // prevent keyboard triggered changes from dispatching for + // clamped values; note, this only occurs for keyboard + const changeTarget = event.target; + const { target, values } = this.action ?? {}; + const squelch = target && target.valueAsNumber === values.get(changeTarget); + if (!squelch) { + redispatchEvent(this, event); + } + // ensure keyboard triggered change clears action. + this.finishAction(event); + } + [getFormValue]() { + if (this.range) { + const data = new FormData(); + data.append(this.nameStart, String(this.valueStart)); + data.append(this.nameEnd, String(this.valueEnd)); + return data; + } + return String(this.value); + } + formResetCallback() { + if (this.range) { + const valueStart = this.getAttribute('value-start'); + this.valueStart = valueStart !== null ? Number(valueStart) : undefined; + const valueEnd = this.getAttribute('value-end'); + this.valueEnd = valueEnd !== null ? Number(valueEnd) : undefined; + return; + } + const value = this.getAttribute('value'); + this.value = value !== null ? Number(value) : undefined; + } + formStateRestoreCallback(state) { + if (Array.isArray(state)) { + const [[, valueStart], [, valueEnd]] = state; + this.valueStart = Number(valueStart); + this.valueEnd = Number(valueEnd); + this.range = true; + return; + } + this.value = Number(state); + this.range = false; + } +} +/** @nocollapse */ +Slider.shadowRootOptions = { + ...s.shadowRootOptions, + delegatesFocus: true, +}; +__decorate([ + n$1({ type: Number }) +], Slider.prototype, "min", void 0); +__decorate([ + n$1({ type: Number }) +], Slider.prototype, "max", void 0); +__decorate([ + n$1({ type: Number }) +], Slider.prototype, "value", void 0); +__decorate([ + n$1({ type: Number, attribute: 'value-start' }) +], Slider.prototype, "valueStart", void 0); +__decorate([ + n$1({ type: Number, attribute: 'value-end' }) +], Slider.prototype, "valueEnd", void 0); +__decorate([ + n$1({ attribute: 'value-label' }) +], Slider.prototype, "valueLabel", void 0); +__decorate([ + n$1({ attribute: 'value-label-start' }) +], Slider.prototype, "valueLabelStart", void 0); +__decorate([ + n$1({ attribute: 'value-label-end' }) +], Slider.prototype, "valueLabelEnd", void 0); +__decorate([ + n$1({ attribute: 'aria-label-start' }) +], Slider.prototype, "ariaLabelStart", void 0); +__decorate([ + n$1({ attribute: 'aria-valuetext-start' }) +], Slider.prototype, "ariaValueTextStart", void 0); +__decorate([ + n$1({ attribute: 'aria-label-end' }) +], Slider.prototype, "ariaLabelEnd", void 0); +__decorate([ + n$1({ attribute: 'aria-valuetext-end' }) +], Slider.prototype, "ariaValueTextEnd", void 0); +__decorate([ + n$1({ type: Number }) +], Slider.prototype, "step", void 0); +__decorate([ + n$1({ type: Boolean }) +], Slider.prototype, "ticks", void 0); +__decorate([ + n$1({ type: Boolean }) +], Slider.prototype, "labeled", void 0); +__decorate([ + n$1({ type: Boolean }) +], Slider.prototype, "range", void 0); +__decorate([ + i$1('input.start') +], Slider.prototype, "inputStart", void 0); +__decorate([ + i$1('.handle.start') +], Slider.prototype, "handleStart", void 0); +__decorate([ + e('md-ripple.start') +], Slider.prototype, "rippleStart", void 0); +__decorate([ + i$1('input.end') +], Slider.prototype, "inputEnd", void 0); +__decorate([ + i$1('.handle.end') +], Slider.prototype, "handleEnd", void 0); +__decorate([ + e('md-ripple.end') +], Slider.prototype, "rippleEnd", void 0); +__decorate([ + t() +], Slider.prototype, "handleStartHover", void 0); +__decorate([ + t() +], Slider.prototype, "handleEndHover", void 0); +__decorate([ + t() +], Slider.prototype, "startOnTop", void 0); +__decorate([ + t() +], Slider.prototype, "handlesOverlapping", void 0); +__decorate([ + t() +], Slider.prototype, "renderValueStart", void 0); +__decorate([ + t() +], Slider.prototype, "renderValueEnd", void 0); +function inBounds({ x, y }, element) { + if (!element) { + return false; + } + const { top, left, bottom, right } = element.getBoundingClientRect(); + return x >= left && x <= right && y >= top && y <= bottom; +} +function isOverlapping(elA, elB) { + if (!(elA && elB)) { + return false; + } + const a = elA.getBoundingClientRect(); + const b = elB.getBoundingClientRect(); + return !(a.top > b.bottom || + a.right < b.left || + a.bottom < b.top || + a.left > b.right); +} + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./slider/internal/slider-styles.css. +const styles = i `:host{--_active-track-color: var(--md-slider-active-track-color, var(--md-sys-color-primary, #6750a4));--_active-track-height: var(--md-slider-active-track-height, 4px);--_active-track-shape: var(--md-slider-active-track-shape, var(--md-sys-shape-corner-full, 9999px));--_disabled-active-track-color: var(--md-slider-disabled-active-track-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-active-track-opacity: var(--md-slider-disabled-active-track-opacity, 0.38);--_disabled-handle-color: var(--md-slider-disabled-handle-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-handle-elevation: var(--md-slider-disabled-handle-elevation, 0);--_disabled-inactive-track-color: var(--md-slider-disabled-inactive-track-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-inactive-track-opacity: var(--md-slider-disabled-inactive-track-opacity, 0.12);--_focus-handle-color: var(--md-slider-focus-handle-color, var(--md-sys-color-primary, #6750a4));--_handle-color: var(--md-slider-handle-color, var(--md-sys-color-primary, #6750a4));--_handle-elevation: var(--md-slider-handle-elevation, 1);--_handle-height: var(--md-slider-handle-height, 20px);--_handle-shadow-color: var(--md-slider-handle-shadow-color, var(--md-sys-color-shadow, #000));--_handle-shape: var(--md-slider-handle-shape, var(--md-sys-shape-corner-full, 9999px));--_handle-width: var(--md-slider-handle-width, 20px);--_hover-handle-color: var(--md-slider-hover-handle-color, var(--md-sys-color-primary, #6750a4));--_hover-state-layer-color: var(--md-slider-hover-state-layer-color, var(--md-sys-color-primary, #6750a4));--_hover-state-layer-opacity: var(--md-slider-hover-state-layer-opacity, 0.08);--_inactive-track-color: var(--md-slider-inactive-track-color, var(--md-sys-color-surface-container-highest, #e6e0e9));--_inactive-track-height: var(--md-slider-inactive-track-height, 4px);--_inactive-track-shape: var(--md-slider-inactive-track-shape, var(--md-sys-shape-corner-full, 9999px));--_label-container-color: var(--md-slider-label-container-color, var(--md-sys-color-primary, #6750a4));--_label-container-height: var(--md-slider-label-container-height, 28px);--_pressed-handle-color: var(--md-slider-pressed-handle-color, var(--md-sys-color-primary, #6750a4));--_pressed-state-layer-color: var(--md-slider-pressed-state-layer-color, var(--md-sys-color-primary, #6750a4));--_pressed-state-layer-opacity: var(--md-slider-pressed-state-layer-opacity, 0.12);--_state-layer-size: var(--md-slider-state-layer-size, 40px);--_with-overlap-handle-outline-color: var(--md-slider-with-overlap-handle-outline-color, var(--md-sys-color-on-primary, #fff));--_with-overlap-handle-outline-width: var(--md-slider-with-overlap-handle-outline-width, 1px);--_with-tick-marks-active-container-color: var(--md-slider-with-tick-marks-active-container-color, var(--md-sys-color-on-primary, #fff));--_with-tick-marks-container-size: var(--md-slider-with-tick-marks-container-size, 2px);--_with-tick-marks-disabled-container-color: var(--md-slider-with-tick-marks-disabled-container-color, var(--md-sys-color-on-surface, #1d1b20));--_with-tick-marks-inactive-container-color: var(--md-slider-with-tick-marks-inactive-container-color, var(--md-sys-color-on-surface-variant, #49454f));--_label-text-color: var(--md-slider-label-text-color, var(--md-sys-color-on-primary, #fff));--_label-text-font: var(--md-slider-label-text-font, var(--md-sys-typescale-label-medium-font, var(--md-ref-typeface-plain, Roboto)));--_label-text-line-height: var(--md-slider-label-text-line-height, var(--md-sys-typescale-label-medium-line-height, 1rem));--_label-text-size: var(--md-slider-label-text-size, var(--md-sys-typescale-label-medium-size, 0.75rem));--_label-text-weight: var(--md-slider-label-text-weight, var(--md-sys-typescale-label-medium-weight, var(--md-ref-typeface-weight-medium, 500)));--_start-fraction: 0;--_end-fraction: 0;--_tick-count: 0;display:inline-flex;vertical-align:middle;min-inline-size:200px;--md-elevation-level: var(--_handle-elevation);--md-elevation-shadow-color: var(--_handle-shadow-color)}md-focus-ring{height:48px;inset:unset;width:48px}md-elevation{transition-duration:250ms}@media(prefers-reduced-motion){.label{transition-duration:0}}:host([disabled]){opacity:var(--_disabled-active-track-opacity);--md-elevation-level: var(--_disabled-handle-elevation)}.container{flex:1;display:flex;align-items:center;position:relative;block-size:var(--_state-layer-size);pointer-events:none;touch-action:none}.track,.tickmarks{position:absolute;inset:0;display:flex;align-items:center}.track::before,.tickmarks::before,.track::after,.tickmarks::after{position:absolute;content:"";inset-inline-start:calc(var(--_state-layer-size)/2 - var(--_with-tick-marks-container-size));inset-inline-end:calc(var(--_state-layer-size)/2 - var(--_with-tick-marks-container-size));background-size:calc((100% - var(--_with-tick-marks-container-size)*2)/var(--_tick-count)) 100%}.track::before,.tickmarks::before{block-size:var(--_inactive-track-height);border-radius:var(--_inactive-track-shape)}.track::before{background:var(--_inactive-track-color)}.tickmarks::before{background-image:radial-gradient(circle at var(--_with-tick-marks-container-size) center, var(--_with-tick-marks-inactive-container-color) 0, var(--_with-tick-marks-inactive-container-color) calc(var(--_with-tick-marks-container-size) / 2), transparent calc(var(--_with-tick-marks-container-size) / 2))}:host([disabled]) .track::before{opacity:calc(1/var(--_disabled-active-track-opacity)*var(--_disabled-inactive-track-opacity));background:var(--_disabled-inactive-track-color)}.track::after,.tickmarks::after{block-size:var(--_active-track-height);border-radius:var(--_active-track-shape);clip-path:inset(0 calc(var(--_with-tick-marks-container-size) * min((1 - var(--_end-fraction)) * 1000000000, 1) + (100% - var(--_with-tick-marks-container-size) * 2) * (1 - var(--_end-fraction))) 0 calc(var(--_with-tick-marks-container-size) * min(var(--_start-fraction) * 1000000000, 1) + (100% - var(--_with-tick-marks-container-size) * 2) * var(--_start-fraction)))}.track::after{background:var(--_active-track-color)}.tickmarks::after{background-image:radial-gradient(circle at var(--_with-tick-marks-container-size) center, var(--_with-tick-marks-active-container-color) 0, var(--_with-tick-marks-active-container-color) calc(var(--_with-tick-marks-container-size) / 2), transparent calc(var(--_with-tick-marks-container-size) / 2))}.track:dir(rtl)::after{clip-path:inset(0 calc(var(--_with-tick-marks-container-size) * min(var(--_start-fraction) * 1000000000, 1) + (100% - var(--_with-tick-marks-container-size) * 2) * var(--_start-fraction)) 0 calc(var(--_with-tick-marks-container-size) * min((1 - var(--_end-fraction)) * 1000000000, 1) + (100% - var(--_with-tick-marks-container-size) * 2) * (1 - var(--_end-fraction))))}.tickmarks:dir(rtl)::after{clip-path:inset(0 calc(var(--_with-tick-marks-container-size) * min(var(--_start-fraction) * 1000000000, 1) + (100% - var(--_with-tick-marks-container-size) * 2) * var(--_start-fraction)) 0 calc(var(--_with-tick-marks-container-size) * min((1 - var(--_end-fraction)) * 1000000000, 1) + (100% - var(--_with-tick-marks-container-size) * 2) * (1 - var(--_end-fraction))))}:host([disabled]) .track::after{background:var(--_disabled-active-track-color)}:host([disabled]) .tickmarks::before{background-image:radial-gradient(circle at var(--_with-tick-marks-container-size) center, var(--_with-tick-marks-disabled-container-color) 0, var(--_with-tick-marks-disabled-container-color) calc(var(--_with-tick-marks-container-size) / 2), transparent calc(var(--_with-tick-marks-container-size) / 2))}.handleContainerPadded{position:relative;block-size:100%;inline-size:100%;padding-inline:calc(var(--_state-layer-size)/2)}.handleContainerBlock{position:relative;block-size:100%;inline-size:100%}.handleContainer{position:absolute;inset-block-start:0;inset-block-end:0;inset-inline-start:calc(100%*var(--_start-fraction));inline-size:calc(100%*(var(--_end-fraction) - var(--_start-fraction)))}.handle{position:absolute;block-size:var(--_state-layer-size);inline-size:var(--_state-layer-size);border-radius:var(--_handle-shape);display:flex;place-content:center;place-items:center}.handleNub{position:absolute;height:var(--_handle-height);width:var(--_handle-width);border-radius:var(--_handle-shape);background:var(--_handle-color)}:host([disabled]) .handleNub{background:var(--_disabled-handle-color)}input.end:focus~.handleContainerPadded .handle.end>.handleNub,input.start:focus~.handleContainerPadded .handle.start>.handleNub{background:var(--_focus-handle-color)}.container>.handleContainerPadded .handle.hover>.handleNub{background:var(--_hover-handle-color)}:host(:not([disabled])) input.end:active~.handleContainerPadded .handle.end>.handleNub,:host(:not([disabled])) input.start:active~.handleContainerPadded .handle.start>.handleNub{background:var(--_pressed-handle-color)}.onTop.isOverlapping .label,.onTop.isOverlapping .label::before{outline:var(--_with-overlap-handle-outline-color) solid var(--_with-overlap-handle-outline-width)}.onTop.isOverlapping .handleNub{border:var(--_with-overlap-handle-outline-color) solid var(--_with-overlap-handle-outline-width)}.handle.start{inset-inline-start:calc(0px - var(--_state-layer-size)/2)}.handle.end{inset-inline-end:calc(0px - var(--_state-layer-size)/2)}.label{position:absolute;box-sizing:border-box;display:flex;padding:4px;place-content:center;place-items:center;border-radius:var(--md-sys-shape-corner-full, 9999px);color:var(--_label-text-color);font-family:var(--_label-text-font);font-size:var(--_label-text-size);line-height:var(--_label-text-line-height);font-weight:var(--_label-text-weight);inset-block-end:100%;min-inline-size:var(--_label-container-height);min-block-size:var(--_label-container-height);background:var(--_label-container-color);transition:transform 100ms cubic-bezier(0.2, 0, 0, 1);transform-origin:center bottom;transform:scale(0)}:host(:focus-within) .label,.handleContainer.hover .label,:where(:has(input:active)) .label{transform:scale(1)}.label::before,.label::after{position:absolute;display:block;content:"";background:inherit}.label::before{inline-size:calc(var(--_label-container-height)/2);block-size:calc(var(--_label-container-height)/2);bottom:calc(var(--_label-container-height)/-10);transform:rotate(45deg)}.label::after{inset:0px;border-radius:inherit}.labelContent{z-index:1}input[type=range]{opacity:0;-webkit-tap-highlight-color:rgba(0,0,0,0);position:absolute;box-sizing:border-box;height:100%;width:100%;margin:0;background:rgba(0,0,0,0);cursor:pointer;pointer-events:auto;appearance:none}input[type=range]:focus{outline:none}::-webkit-slider-runnable-track{-webkit-appearance:none}::-moz-range-track{appearance:none}::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;block-size:var(--_handle-height);inline-size:var(--_handle-width);opacity:0;z-index:2}input.end::-webkit-slider-thumb{--_track-and-knob-padding: calc( (var(--_state-layer-size) - var(--_handle-width)) / 2 );--_x-translate: calc( var(--_track-and-knob-padding) - 2 * var(--_end-fraction) * var(--_track-and-knob-padding) );transform:translateX(var(--_x-translate))}input.end:dir(rtl)::-webkit-slider-thumb{transform:translateX(calc(-1 * var(--_x-translate)))}input.start::-webkit-slider-thumb{--_track-and-knob-padding: calc( (var(--_state-layer-size) - var(--_handle-width)) / 2 );--_x-translate: calc( var(--_track-and-knob-padding) - 2 * var(--_start-fraction) * var(--_track-and-knob-padding) );transform:translateX(var(--_x-translate))}input.start:dir(rtl)::-webkit-slider-thumb{transform:translateX(calc(-1 * var(--_x-translate)))}::-moz-range-thumb{appearance:none;block-size:var(--_state-layer-size);inline-size:var(--_state-layer-size);transform:scaleX(0);opacity:0;z-index:2}.ranged input.start{clip-path:inset(0 calc(100% - (var(--_state-layer-size) / 2 + (100% - var(--_state-layer-size)) * (var(--_start-fraction) + (var(--_end-fraction) - var(--_start-fraction)) / 2))) 0 0)}.ranged input.start:dir(rtl){clip-path:inset(0 0 0 calc(100% - (var(--_state-layer-size) / 2 + (100% - var(--_state-layer-size)) * (var(--_start-fraction) + (var(--_end-fraction) - var(--_start-fraction)) / 2))))}.ranged input.end{clip-path:inset(0 0 0 calc(var(--_state-layer-size) / 2 + (100% - var(--_state-layer-size)) * (var(--_start-fraction) + (var(--_end-fraction) - var(--_start-fraction)) / 2)))}.ranged input.end:dir(rtl){clip-path:inset(0 calc(var(--_state-layer-size) / 2 + (100% - var(--_state-layer-size)) * (var(--_start-fraction) + (var(--_end-fraction) - var(--_start-fraction)) / 2)) 0 0)}.onTop{z-index:1}.handle{--md-ripple-hover-color: var(--_hover-state-layer-color);--md-ripple-hover-opacity: var(--_hover-state-layer-opacity);--md-ripple-pressed-color: var(--_pressed-state-layer-color);--md-ripple-pressed-opacity: var(--_pressed-state-layer-opacity)}md-ripple{border-radius:50%;height:var(--_state-layer-size);width:var(--_state-layer-size)} +`; + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @summary Sliders allow users to view and select a value (or range) along + * a track. + * + * @description + * Changes made with sliders are immediate, allowing the user to make slider + * adjustments while determining a selection. Sliders shouldn’t be used to + * adjust settings with any delay in providing user feedback. Sliders reflect + * the current state of the settings they control. + * + * __Example usages:__ + * - Sliders are ideal for adjusting settings such as volume and brightness, or + * for applying image filters. + * + * @final + * @suppress {visibility} + */ +let MdSlider = class MdSlider extends Slider { +}; +MdSlider.styles = [styles, styles$1]; +MdSlider = __decorate([ + e$1('md-slider') +], MdSlider); + +export { MdSlider }; diff --git a/md-web/sub-menu.js b/md-web/sub-menu.js new file mode 100644 index 0000000..1c46169 --- /dev/null +++ b/md-web/sub-menu.js @@ -0,0 +1,432 @@ +export const __dummy_loader = () => {}; + +import { _ as __decorate, n, l, s, u as Corner, x, v as createActivateTypeaheadEvent, w as createDeactivateItemsEvent, y as createDeactivateTypeaheadEvent, N as NavigableKey, S as SelectionKey, z as getFirstActivatableItem, B as CloseReason, K as KeydownCloseKey, D as createRequestActivationEvent, E as deactivateActiveItem, i, e } from './core.js'; + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @fires deactivate-items {Event} Requests the parent menu to deselect other + * items when a submenu opens. --bubbles --composed + * @fires request-activation {Event} Requests the parent to make the slotted item + * focusable and focus the item. --bubbles --composed + * @fires deactivate-typeahead {Event} Requests the parent menu to deactivate + * the typeahead functionality when a submenu opens. --bubbles --composed + * @fires activate-typeahead {Event} Requests the parent menu to activate the + * typeahead functionality when a submenu closes. --bubbles --composed + */ +class SubMenu extends s { + get item() { + return this.items[0] ?? null; + } + get menu() { + return this.menus[0] ?? null; + } + constructor() { + super(); + /** + * The anchorCorner to set on the submenu. + */ + this.anchorCorner = Corner.START_END; + /** + * The menuCorner to set on the submenu. + */ + this.menuCorner = Corner.START_START; + /** + * The delay between mouseenter and submenu opening. + */ + this.hoverOpenDelay = 400; + /** + * The delay between ponterleave and the submenu closing. + */ + this.hoverCloseDelay = 400; + /** + * READONLY: self-identifies as a menu item and sets its identifying attribute + */ + this.isSubMenu = true; + this.previousOpenTimeout = 0; + this.previousCloseTimeout = 0; + /** + * Starts the default 400ms countdown to open the submenu. + * + * NOTE: We explicitly use mouse events and not pointer events because + * pointer events apply to touch events. And if a user were to tap a + * sub-menu, it would fire the "pointerenter", "pointerleave", "click" events + * which would open the menu on click, and then set the timeout to close the + * menu due to pointerleave. + */ + this.onMouseenter = () => { + clearTimeout(this.previousOpenTimeout); + clearTimeout(this.previousCloseTimeout); + if (this.menu?.open) + return; + // Open synchronously if delay is 0. (screenshot tests infra + // would never resolve otherwise) + if (!this.hoverOpenDelay) { + this.show(); + } + else { + this.previousOpenTimeout = setTimeout(() => { + this.show(); + }, this.hoverOpenDelay); + } + }; + /** + * Starts the default 400ms countdown to close the submenu. + * + * NOTE: We explicitly use mouse events and not pointer events because + * pointer events apply to touch events. And if a user were to tap a + * sub-menu, it would fire the "pointerenter", "pointerleave", "click" events + * which would open the menu on click, and then set the timeout to close the + * menu due to pointerleave. + */ + this.onMouseleave = () => { + clearTimeout(this.previousCloseTimeout); + clearTimeout(this.previousOpenTimeout); + // Close synchronously if delay is 0. (screenshot tests infra + // would never resolve otherwise) + if (!this.hoverCloseDelay) { + this.close(); + } + else { + this.previousCloseTimeout = setTimeout(() => { + this.close(); + }, this.hoverCloseDelay); + } + }; + { + this.addEventListener('mouseenter', this.onMouseenter); + this.addEventListener('mouseleave', this.onMouseleave); + } + } + render() { + return x ` + + + + + `; + } + firstUpdated() { + // slotchange is not fired if the contents have been SSRd + this.onSlotchange(); + } + /** + * Shows the submenu. + */ + async show() { + const menu = this.menu; + if (!menu || menu.open) + return; + // Ensures that we deselect items when the menu closes and reactivate + // typeahead when the menu closes, so that we do not have dirty state of + // `sub-menu > menu-item[selected]` when we reopen. + // + // This cannot happen in `close()` because the menu may close via other + // means Additionally, this cannot happen in onCloseSubmenu because + // `close-menu` may not be called via focusout of outside click and not + // triggered by an item + menu.addEventListener('closed', () => { + this.item.ariaExpanded = 'false'; + this.dispatchEvent(createActivateTypeaheadEvent()); + this.dispatchEvent(createDeactivateItemsEvent()); + // aria-hidden required so ChromeVox doesn't announce the closed menu + menu.ariaHidden = 'true'; + }, { once: true }); + // Parent menu is `position: absolute` – this creates a new CSS relative + // positioning context (similar to doing `position: relative`), so the + // submenu's `` would be + // wrong even if we change `md-sub-menu` from `position: relative` to + // `position: static` because the submenu it would still be positioning + // itself relative to the parent menu. + if (menu.positioning === 'document') { + menu.positioning = 'absolute'; + } + menu.quick = true; + // Submenus are in overflow when not fixed. Can remove once we have native + // popup support + menu.hasOverflow = true; + menu.anchorCorner = this.anchorCorner; + menu.menuCorner = this.menuCorner; + menu.anchorElement = this.item; + menu.defaultFocus = 'first-item'; + // aria-hidden management required so ChromeVox doesn't announce the closed + // menu. Remove it here since we are about to show and focus it. + menu.removeAttribute('aria-hidden'); + // This is required in the case where we have a leaf menu open and and the + // user hovers a parent menu's item which is not an md-sub-menu item. + // If this were set to true, then the menu would close and focus would be + // lost. That means the focusout event would have a `relatedTarget` of + // `null` since nothing in the menu would be focused anymore due to the + // leaf menu closing. restoring focus ensures that we keep focus in the + // submenu tree. + menu.skipRestoreFocus = false; + // Menu could already be opened because of mouse interaction + const menuAlreadyOpen = menu.open; + menu.show(); + this.item.ariaExpanded = 'true'; + this.item.ariaHasPopup = 'menu'; + if (menu.id) { + this.item.setAttribute('aria-controls', menu.id); + } + // Deactivate other items. This can be the case if the user has tabbed + // around the menu and then mouses over an md-sub-menu. + this.dispatchEvent(createDeactivateItemsEvent()); + this.dispatchEvent(createDeactivateTypeaheadEvent()); + this.item.selected = true; + // This is the case of mouse hovering when already opened via keyboard or + // vice versa + if (!menuAlreadyOpen) { + let open = (value) => { }; + const opened = new Promise((resolve) => { + open = resolve; + }); + menu.addEventListener('opened', open, { once: true }); + await opened; + } + } + /** + * Closes the submenu. + */ + async close() { + const menu = this.menu; + if (!menu || !menu.open) + return; + this.dispatchEvent(createActivateTypeaheadEvent()); + menu.quick = true; + menu.close(); + this.dispatchEvent(createDeactivateItemsEvent()); + let close = (value) => { }; + const closed = new Promise((resolve) => { + close = resolve; + }); + menu.addEventListener('closed', close, { once: true }); + await closed; + } + onSlotchange() { + if (!this.item) { + return; + } + // TODO(b/301296618): clean up old aria values on change + this.item.ariaExpanded = 'false'; + this.item.ariaHasPopup = 'menu'; + if (this.menu?.id) { + this.item.setAttribute('aria-controls', this.menu.id); + } + this.item.keepOpen = true; + const menu = this.menu; + if (!menu) + return; + menu.isSubmenu = true; + // Required for ChromeVox to not linearly navigate to the menu while closed + menu.ariaHidden = 'true'; + } + onClick() { + this.show(); + } + /** + * On item keydown handles opening the submenu. + */ + async onKeydown(event) { + const shouldOpenSubmenu = this.isSubmenuOpenKey(event.code); + if (event.defaultPrevented) + return; + const openedWithLR = shouldOpenSubmenu && + (NavigableKey.LEFT === event.code || NavigableKey.RIGHT === event.code); + if (event.code === SelectionKey.SPACE || openedWithLR) { + // prevent space from scrolling and Left + Right from selecting previous / + // next items or opening / closing parent menus. Only open the submenu. + event.preventDefault(); + if (openedWithLR) { + event.stopPropagation(); + } + } + if (!shouldOpenSubmenu) { + return; + } + const submenu = this.menu; + if (!submenu) + return; + const submenuItems = submenu.items; + const firstActivatableItem = getFirstActivatableItem(submenuItems); + if (firstActivatableItem) { + await this.show(); + firstActivatableItem.tabIndex = 0; + firstActivatableItem.focus(); + return; + } + } + onCloseSubmenu(event) { + const { itemPath, reason } = event.detail; + itemPath.push(this.item); + this.dispatchEvent(createActivateTypeaheadEvent()); + // Escape should only close one menu not all of the menus unlike space or + // click selection which should close all menus. + if (reason.kind === CloseReason.KEYDOWN && + reason.key === KeydownCloseKey.ESCAPE) { + event.stopPropagation(); + this.item.dispatchEvent(createRequestActivationEvent()); + return; + } + this.dispatchEvent(createDeactivateItemsEvent()); + } + async onSubMenuKeydown(event) { + if (event.defaultPrevented) + return; + const { close: shouldClose, keyCode } = this.isSubmenuCloseKey(event.code); + if (!shouldClose) + return; + // Communicate that it's handled so that we don't accidentally close every + // parent menu. Additionally, we want to isolate things like the typeahead + // keydowns from bubbling up to the parent menu and confounding things. + event.preventDefault(); + if (keyCode === NavigableKey.LEFT || keyCode === NavigableKey.RIGHT) { + // Prevent this from bubbling to parents + event.stopPropagation(); + } + await this.close(); + deactivateActiveItem(this.menu.items); + this.item?.focus(); + this.item.tabIndex = 0; + this.item.focus(); + } + /** + * Determines whether the given KeyboardEvent code is one that should open + * the submenu. This is RTL-aware. By default, left, right, space, or enter. + * + * @param code The native KeyboardEvent code. + * @return Whether or not the key code should open the submenu. + */ + isSubmenuOpenKey(code) { + const isRtl = getComputedStyle(this).direction === 'rtl'; + const arrowEnterKey = isRtl ? NavigableKey.LEFT : NavigableKey.RIGHT; + switch (code) { + case arrowEnterKey: + case SelectionKey.SPACE: + case SelectionKey.ENTER: + return true; + default: + return false; + } + } + /** + * Determines whether the given KeyboardEvent code is one that should close + * the submenu. This is RTL-aware. By default right, left, or escape. + * + * @param code The native KeyboardEvent code. + * @return Whether or not the key code should close the submenu. + */ + isSubmenuCloseKey(code) { + const isRtl = getComputedStyle(this).direction === 'rtl'; + const arrowEnterKey = isRtl ? NavigableKey.RIGHT : NavigableKey.LEFT; + switch (code) { + case arrowEnterKey: + case KeydownCloseKey.ESCAPE: + return { close: true, keyCode: code }; + default: + return { close: false }; + } + } +} +__decorate([ + n({ attribute: 'anchor-corner' }) +], SubMenu.prototype, "anchorCorner", void 0); +__decorate([ + n({ attribute: 'menu-corner' }) +], SubMenu.prototype, "menuCorner", void 0); +__decorate([ + n({ type: Number, attribute: 'hover-open-delay' }) +], SubMenu.prototype, "hoverOpenDelay", void 0); +__decorate([ + n({ type: Number, attribute: 'hover-close-delay' }) +], SubMenu.prototype, "hoverCloseDelay", void 0); +__decorate([ + n({ type: Boolean, reflect: true, attribute: 'md-sub-menu' }) +], SubMenu.prototype, "isSubMenu", void 0); +__decorate([ + l({ slot: 'item', flatten: true }) +], SubMenu.prototype, "items", void 0); +__decorate([ + l({ slot: 'menu', flatten: true }) +], SubMenu.prototype, "menus", void 0); + +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Generated stylesheet for ./menu/internal/submenu/sub-menu-styles.css. +const styles = i `:host{position:relative;display:flex;flex-direction:column} +`; + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @summary Menus display a list of choices on a temporary surface. + * + * @description + * Menu items are the selectable choices within the menu. Menu items must + * implement the `Menu` interface and also have the `md-menu` + * attribute. Additionally menu items are list items so they must also have the + * `md-list-item` attribute. + * + * Menu items can control a menu by selectively firing the `close-menu` and + * `deselect-items` events. + * + * This menu item will open a sub-menu that is slotted in the `submenu` slot. + * Additionally, the containing menu must either have `has-overflow` or + * `positioning=fixed` set to `true` in order to display the containing menu + * properly. + * + * @example + * ```html + *
+ * + * + * + * + * + * + * + * + * + * + * + * + * + *
+ * ``` + * + * @final + * @suppress {visibility} + */ +let MdSubMenu = class MdSubMenu extends SubMenu { +}; +MdSubMenu.styles = [styles]; +MdSubMenu = __decorate([ + e('md-sub-menu') +], MdSubMenu); + +export { MdSubMenu }; diff --git a/md-web/switch.js b/md-web/switch.js new file mode 100644 index 0000000..af69219 --- /dev/null +++ b/md-web/switch.js @@ -0,0 +1,389 @@ +export const __dummy_loader = () => {}; + +import { m as mixinDelegatesAria, a as mixinConstraintValidation, b as mixinFormAssociated, _ as __decorate, n, c as i, d as isActivationClick, f as dispatchActivationClick, x, o, A, r as redispatchEvent, g as getFormValue, h as getFormState, j as createValidator, k as CheckboxValidator, p as getValidityAnchor, q as mixinElementInternals, s, i as i$1, e } from './core.js'; + +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A symbol used to access dispatch hooks on an event. + */ +const dispatchHooks = Symbol('dispatchHooks'); +/** + * Add a hook for an event that is called after the event is dispatched and + * propagates to other event listeners. + * + * This is useful for behaviors that need to check if an event is canceled. + * + * The callback is invoked synchronously, which allows for better integration + * with synchronous platform APIs (like `` or `