UNPKG

@sandlada/mdc

Version:

@sandlada/mdc is an open source component library that follows the Material Design 3 design specifications.

335 lines (315 loc) 15 kB
import{css as e,unsafeCSS as t}from"../../node_modules/@lit/reactive-element/css-tag.js";import"../../node_modules/lit/index.js";import{defineVars as n}from"../../node_modules/@sandlada/jss/dist/define-vars.js";import{defineTokenRefsRecord as r}from"../../node_modules/@sandlada/jss/dist/define-token-refs.js";import{Easing as i}from"../../node_modules/@sandlada/mdk/build/domain/easing.js";import"../../node_modules/@sandlada/mdk/build/index.js";import{overrideComponentTokens as a}from"../../utils/tokens/override-component-tokens.js";import{stringTokens as o}from"../../utils/tokens/string-tokens.js";import"../../utils/tokens/index.js";import{CheckboxDefinition as s}from"../../component-definitions/checkbox.definition.js"; /** * @license * Copyright 2026 Kai-Orion & Sandlada * SPDX-License-Identifier: MIT */ const c=r(s,{expandShapes:!1,useBaseFallback:!0,prefix:`--mdc-checkbox`}),l=t(n(c,!0).join(``)),u=t(i.EmphasizedAccelerate.ToCSSValue()),d=t(i.EmphasizedDecelerate.ToCSSValue()),f=e=>o(a(`--mdc-ripple`,{"enabled-hovered-color":`var(--_hovered-state-layer-color-${e})`,"enabled-hovered-opacity":`var(--_hovered-state-layer-opacity-${e})`,"enabled-focused-color":`var(--_focused-state-layer-color-${e})`,"enabled-focused-opacity":`var(--_focused-state-layer-opacity-${e})`,"enabled-pressed-color":`var(--_pressed-state-layer-color-${e})`,"enabled-pressed-opacity":`var(--_pressed-state-layer-opacity-${e})`})),p=()=>o(a(`--mdc-ripple`,{"enabled-hovered-color":`var(--_hovered-error-state-layer-color)`,"enabled-hovered-opacity":`var(--_hovered-error-state-layer-opacity)`,"enabled-focused-color":`var(--_focused-error-state-layer-color)`,"enabled-focused-opacity":`var(--_focused-error-state-layer-opacity)`,"enabled-pressed-color":`var(--_pressed-error-state-layer-color)`,"enabled-pressed-opacity":`var(--_pressed-error-state-layer-opacity)`})),m=o(a(`--mdc-focus-ring`,{"enabled-color":`var(--_focused-indicator-color)`,"outward-offset":`calc((44px - var(--_enabled-container-size)) / 2)`,"shape-end-end":`var(--_focus-ring-shape-end-end)`,"shape-end-start":`var(--_focus-ring-shape-end-start)`,"shape-start-end":`var(--_focus-ring-shape-start-end)`,"shape-start-start":`var(--_focus-ring-shape-start-start)`})),h=e` @layer mdc.checkbox { @layer variable { :host { ${l} } } @layer base { :host { display: inline-flex; vertical-align: top; cursor: pointer; box-sizing: border-box; -webkit-tap-highlight-color: transparent; outline: none; position: relative; height: var(--_enabled-container-size); width: var(--_enabled-container-size); border-start-start-radius: var(--_container-shape-start-start); border-start-end-radius: var(--_container-shape-start-end); border-end-end-radius: var(--_container-shape-end-end); border-end-start-radius: var(--_container-shape-end-start); /* Reserve space for the 48px touch target around the 18px box. */ margin: max(0px, ((48px - var(--_enabled-container-size)) / 2)); } :host([disabled]) { cursor: default; } :host([touch-target='none']) { margin: 0px; } .container { display: flex; height: 100%; place-content: center; place-items: center; position: relative; width: 100%; z-index: 0; /* The host carries the container-shape-* corner tokens; the outline / background / focus ring all derive their radius from this node. */ border-radius: inherit; } .outline, .background, .icon { inset: 0; position: absolute; } .outline, .background { border-radius: inherit; } .outline { border-color: var(--_enabled-outline-color-unselected); border-style: solid; border-width: var(--_enabled-outline-width-unselected); box-sizing: border-box; } .selected .outline { border-color: transparent; border-width: var(--_enabled-outline-width-selected); } .background { background-color: var(--_enabled-container-color-selected); } /* 48px touch target. Covers the box plus its margin so hover, pointer and keyboard activation work over the whole target. */ .touch { appearance: none; height: 48px; margin: 0; opacity: 0; outline: none; position: absolute; width: 48px; z-index: 1; cursor: inherit; top: 50%; left: 50%; transform: translate(-50%, -50%); } :host([touch-target='none']) .touch { height: 100%; width: 100%; } /* Background and icon fade in/out with a vertical 45° flip. */ .background, .icon { opacity: 0; /* Fade in */ transition-duration: 150ms, 50ms; /* Exit duration for scale and opacity. */ transition-property: transform, opacity; /* Exit easing for scale, linear for opacity. */ transition-timing-function: ${u}, linear; transform: scale(0.6); /* Scale from 60% to 100%. */ } .selected :is(.background, .icon) { opacity: 1; transition-duration: 350ms, 50ms; /* Enter duration for scale and opacity. */ transition-timing-function: ${d}, linear; transform: scale(1); } .icon { fill: var(--_enabled-icon-color-selected); height: var(--_enabled-icon-size); width: var(--_enabled-icon-size); } /* The checkmark is two <rect> marks: a short 2×2 leading segment and a long 10×2 trailing segment (the indeterminate dash). */ .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: ${u}; transition-duration: 150ms; transition-timing-function: ${u}; } .selected .mark { animation-duration: 350ms; animation-timing-function: ${d}; transition-duration: 350ms; transition-timing-function: ${d}; } /* Creates the checkmark icon. The rects' bottom-left corner becomes the bottom-most point of the checkmark (scaleY(-1) flips them around the top-left origin, a Safari-compatible workaround). */ .checked .mark, .prev-checked.unselected .mark { transform: scaleY(-1) translate(7px, -14px) rotate(45deg); } .checked .mark.short, .prev-checked.unselected .mark.short { /* Right triangle with X,Y legs of 4dp: √(4² + 4²) */ height: 5.656854249492381px; } .checked .mark.long, .prev-checked.unselected .mark.long { /* Right triangle with X,Y legs of 8dp: √(8² + 8²) */ width: 11.313708498984761px; } /* Creates the indeterminate icon (a horizontal dash). */ .indeterminate .mark, .prev-indeterminate.unselected .mark { transform: scaleY(-1) translate(4px, -10px) rotate(0deg); } /* When selecting an unselected box, fade the icon in from its final position rather than animating the mark shape. */ .prev-unselected .mark { transition-property: none; } .prev-unselected.checked .mark.long { /* Grow the long end of the checkmark from zero width. */ animation-name: prev-unselected-to-checked; } @keyframes prev-unselected-to-checked { from { width: 0; } } /* Unselected outline colors across interaction states. */ :host(:hover) .unselected .outline { border-color: var(--_hovered-outline-color-unselected); border-width: var(--_hovered-outline-width-unselected); } :host(:focus-within) .unselected .outline { border-color: var(--_focused-outline-color-unselected); border-width: var(--_focused-outline-width-unselected); } :host(:active) .unselected .outline { border-color: var(--_pressed-outline-color-unselected); border-width: var(--_pressed-outline-width-unselected); } /* Container and icon colors across interaction states. */ :host(:hover) .background { background: var(--_hovered-container-color-selected); } :host(:focus-within) .background { background: var(--_focused-container-color-selected); } :host(:active) .background { background: var(--_pressed-container-color-selected); } :host(:hover) .icon { fill: var(--_hovered-icon-color-selected); } :host(:focus-within) .icon { fill: var(--_focused-icon-color-selected); } :host(:active) .icon { fill: var(--_pressed-icon-color-selected); } /* Error states — mixinDelegatesAria shifts the host's aria-invalid to data-aria-invalid, which is what these selectors match. */ :host([data-aria-invalid='true']) .outline { border-color: var(--_enabled-error-outline-color-unselected); } :host([data-aria-invalid='true']:hover) .outline { border-color: var(--_hovered-error-outline-color-unselected); } :host([data-aria-invalid='true']:focus-within) .outline { border-color: var(--_focused-error-outline-color-unselected); } :host([data-aria-invalid='true']:active) .outline { border-color: var(--_pressed-error-outline-color-unselected); } :host([data-aria-invalid='true']) .background { background: var(--_enabled-error-container-color-selected); } :host([data-aria-invalid='true']:hover) .background { background: var(--_hovered-error-container-color-selected); } :host([data-aria-invalid='true']:active) .background { background: var(--_pressed-error-container-color-unselected); } :host([data-aria-invalid='true']) .icon { fill: var(--_enabled-error-icon-color-selected); } :host([data-aria-invalid='true']:hover) .icon { fill: var(--_hovered-error-icon-color-selected); } :host([data-aria-invalid='true']:focus-within) .icon { fill: var(--_focused-error-icon-color-selected); } :host([data-aria-invalid='true']:active) .icon { fill: var(--_pressed-error-icon-color-selected); } /* Disabled: don't animate to/from disabled states because the outline is hidden when selected — otherwise there'd be a flash when the state changes programmatically while disabled. */ .disabled :is(.background, .icon, .mark), .prev-disabled :is(.background, .icon, .mark) { animation-duration: 0s; transition-duration: 0s; } .disabled .outline { border-color: var(--_disabled-outline-color-unselected); border-width: var(--_disabled-outline-width-unselected); opacity: var(--_disabled-container-opacity-unselected); } .selected.disabled .outline { border-color: transparent; } .selected.disabled .background { background: var(--_disabled-container-color-selected); opacity: var(--_disabled-container-opacity-selected); } .disabled .icon { fill: var(--_disabled-icon-color-selected); } } @layer composite.ripple { .container mdc-ripple { border-end-end-radius: var(--_state-layer-shape-end-end); border-end-start-radius: var(--_state-layer-shape-end-start); border-start-end-radius: var(--_state-layer-shape-start-end); border-start-start-radius: var(--_state-layer-shape-start-start); height: var(--_state-layer-size); inset: unset; width: var(--_state-layer-size); } .container.selected mdc-ripple { ${f(`selected`)} } .container:not(.selected) mdc-ripple { ${f(`unselected`)} } :host([data-aria-invalid='true']) .container mdc-ripple { ${p()} } } @layer composite.focus-ring { .container { ${m}; } } @layer hcm { @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; } } } } `;export{h as CheckboxStyles}; //# sourceMappingURL=checkbox.style.js.map