@vollowx/seele 0.13.7 → 0.13.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/README.md +33 -15
  2. package/package.json +2 -2
  3. package/src/all.d.ts +5 -0
  4. package/src/all.js +5 -0
  5. package/src/base/autocomplete.js +13 -13
  6. package/src/base/button.d.ts +4 -2
  7. package/src/base/button.js +15 -11
  8. package/src/base/checkbox.js +3 -8
  9. package/src/base/controllers/popover-controller.js +1 -1
  10. package/src/base/experimental/popup-styles.css.js +2 -0
  11. package/src/base/experimental/popup.d.ts +40 -0
  12. package/src/base/experimental/popup.js +278 -0
  13. package/src/base/mixins/attachable.d.ts +5 -2
  14. package/src/base/mixins/attachable.js +63 -23
  15. package/src/base/mixins/button-toggle-mixin.d.ts +7 -0
  16. package/src/base/mixins/button-toggle-mixin.js +101 -0
  17. package/src/base/mixins/internals-attached.d.ts +4 -0
  18. package/src/base/mixins/internals-attached.js +6 -0
  19. package/src/base/radio.d.ts +3 -0
  20. package/src/base/radio.js +28 -16
  21. package/src/base/tab-panel.d.ts +3 -3
  22. package/src/base/tab-panel.js +9 -11
  23. package/src/base/tab.d.ts +2 -8
  24. package/src/base/tab.js +16 -35
  25. package/src/base/tabs.d.ts +6 -6
  26. package/src/base/tabs.js +101 -99
  27. package/src/base/toggle-button.d.ts +6 -45
  28. package/src/base/toggle-button.js +6 -135
  29. package/src/base/tooltip.d.ts +2 -1
  30. package/src/base/tooltip.js +2 -2
  31. package/src/core/ensure-ready.d.ts +2 -1
  32. package/src/core/ensure-ready.js +12 -7
  33. package/src/m3/button/common-button-toggle.d.ts +4 -10
  34. package/src/m3/button/common-button-toggle.js +6 -40
  35. package/src/m3/button/icon-button-toggle.d.ts +4 -6
  36. package/src/m3/button/icon-button-toggle.js +6 -33
  37. package/src/m3/button/shared-button-styles.css.js +1 -1
  38. package/src/m3/button/shared-button-toggle-styles.css.js +1 -1
  39. package/src/m3/button-group/standard-button-group-styles.css.js +1 -1
  40. package/src/m3/button-group/standard-button-group.d.ts +2 -0
  41. package/src/m3/button-group/standard-button-group.js +44 -38
  42. package/src/m3/checkbox/checkbox-styles.css.js +1 -1
  43. package/src/m3/checkbox/checkbox.d.ts +1 -1
  44. package/src/m3/checkbox/checkbox.js +2 -5
  45. package/src/m3/dialog/dialog-styles.css.js +1 -1
  46. package/src/m3/dialog/dialog.d.ts +3 -1
  47. package/src/m3/dialog/dialog.js +6 -4
  48. package/src/m3/experimental/popup-styles.css.js +2 -0
  49. package/src/m3/experimental/popup.d.ts +9 -0
  50. package/src/m3/experimental/popup.js +11 -0
  51. package/src/m3/fab/fab-styles.css.js +1 -1
  52. package/src/m3/field/field-styles.css.js +1 -1
  53. package/src/m3/field/filled-field-styles.css.js +1 -1
  54. package/src/m3/focus-ring/focus-ring-styles.css.js +1 -1
  55. package/src/m3/focus-ring/focus-ring.d.ts +2 -1
  56. package/src/m3/focus-ring/focus-ring.js +4 -7
  57. package/src/m3/list/list-item-styles.css.js +1 -1
  58. package/src/m3/menu/menu-styles.css.js +1 -1
  59. package/src/m3/nagivation/navigation-rail-item-styles.css.js +2 -0
  60. package/src/m3/nagivation/navigation-rail-item.d.ts +21 -0
  61. package/src/m3/nagivation/navigation-rail-item.js +44 -0
  62. package/src/m3/nagivation/navigation-rail-styles.css.js +2 -0
  63. package/src/m3/nagivation/navigation-rail.d.ts +12 -0
  64. package/src/m3/nagivation/navigation-rail.js +17 -0
  65. package/src/m3/radio/radio-styles.css.js +1 -1
  66. package/src/m3/radio/radio.d.ts +3 -0
  67. package/src/m3/radio/radio.js +12 -4
  68. package/src/m3/ripple/ripple-styles.css.js +1 -1
  69. package/src/m3/ripple/ripple.d.ts +3 -13
  70. package/src/m3/ripple/ripple.js +28 -31
  71. package/src/m3/{system → styles}/defaults.css +1 -1
  72. package/src/m3/styles/motion-expressive.css +15 -0
  73. package/src/m3/styles/motion-standard.css +15 -0
  74. package/src/m3/styles/typography.css +24 -0
  75. package/src/m3/switch/switch-styles.css.js +1 -1
  76. package/src/m3/switch/switch.d.ts +4 -2
  77. package/src/m3/switch/switch.js +14 -12
  78. package/src/m3/tab/secondary-tab-styles.css.js +2 -0
  79. package/src/m3/tab/secondary-tab.d.ts +5 -0
  80. package/src/m3/tab/secondary-tab.js +15 -0
  81. package/src/m3/tab/tab-panel-styles.css.js +1 -1
  82. package/src/m3/tab/tab-styles.css.js +1 -1
  83. package/src/m3/tab/tab.d.ts +3 -0
  84. package/src/m3/tab/tab.js +68 -3
  85. package/src/m3/tab/tabs-styles.css.js +1 -1
  86. package/src/m3/tab/tabs.d.ts +1 -7
  87. package/src/m3/tab/tabs.js +6 -39
  88. package/src/m3/toolbar/toolbar-styles.css.js +1 -1
  89. package/src/win98/button/button-styles.css.js +1 -1
  90. package/src/m3/system/typography.css +0 -34
  91. /package/src/m3/{system → styles}/base.css +0 -0
  92. /package/src/m3/{system → styles}/elevation.css +0 -0
  93. /package/src/m3/{system → styles}/motion.d.ts +0 -0
  94. /package/src/m3/{system → styles}/motion.js +0 -0
@@ -1,2 +1,2 @@
1
1
  import { css } from 'lit';
2
- export const radioStyles = css`:host{--_d:var(--md-sys-motion-effects-default-duration);--_default:var(--_d) var(--md-sys-motion-effects-default);--_slow:var(--md-sys-motion-effects-slow-duration) var(--md-sys-motion-effects-slow);cursor:pointer;-webkit-tap-highlight-color:transparent;-webkit-user-select:none;user-select:none;border-radius:20px;outline:0;justify-content:center;align-items:center;width:40px;height:40px;display:inline-flex;position:relative}:host:before,.middle,:host:after{content:"";box-sizing:border-box;border-radius:50%;position:absolute;animation-fill-mode:forwards!important}:host:before{z-index:1;background-color:var(--md-sys-color-on-surface-variant);width:20px;height:20px;transition:background var(--_default)}.middle{z-index:2;background-color:var(--md-sys-color-surface);width:16px;height:16px}:host:after{z-index:3;background-color:var(--md-sys-color-primary);width:10px;height:10px;transform:scale(0)}:host(:state(unchecking)) .middle{animation:uncheck-mid-2 var(--_slow) var(--_d)}:host(:state(unchecking)):after{animation:uncheck-inner-1 var(--_default), uncheck-inner-2 var(--_slow) var(--_d)}:host([checked]):before{background-color:var(--md-sys-color-primary)}:host([checked]):after{transform:scale(1)}:host(:state(checking)) .middle{animation:check-mid-1 var(--_default), check-mid-2 var(--_slow) var(--_d)}:host(:state(checking)):after{animation:check-inner-1 var(--_default), check-inner-2 var(--_slow) var(--_d)}@keyframes uncheck-mid-2{0%,to{z-index:4}0%{transform:scale(0)}to{transform:scale(1)}}@keyframes uncheck-inner-1{0%{background-color:var(--md-sys-color-primary);transform:scale(1)}to{background-color:var(--md-sys-color-on-surface-variant);transform:scale(1.6)}}@keyframes uncheck-inner-2{0%{transform:scale(1.6)}to{transform:scale(1.6)}}@keyframes check-mid-1{0%{transform:scale(1)}to{transform:scale(0)}}@keyframes check-mid-2{0%{transform:scale(.625)}to{transform:scale(1)}}@keyframes check-inner-1{0%,to{transform:scale(0)}}@keyframes check-inner-2{0%,to{transform:scale(1)}}:host([disabled]){pointer-events:none}:host([disabled]):before,:host([disabled]):after{background:color-mix(in srgb, var(--md-sys-color-on-surface) 38%, transparent)}`;
2
+ export const radioStyles = css`:host{--_d:var(--md-sys-motion-effects-default-duration);--_default:var(--_d) var(--md-sys-motion-effects-default);--_slow:var(--md-sys-motion-effects-slow-duration) var(--md-sys-motion-effects-slow);cursor:pointer;-webkit-tap-highlight-color:transparent;-webkit-user-select:none;user-select:none;border-radius:20px;outline:0;justify-content:center;align-items:center;width:40px;height:40px;display:inline-flex;position:relative}.icon{z-index:1;width:20px;height:20px}.ring{fill:none;r:9px;stroke:var(--md-sys-color-on-surface-variant);stroke-width:2px;transition:stroke var(--_default);will-change:r, stroke-width}:host(:state(checked)) .ring{stroke:var(--md-sys-color-primary)}.dot{fill:var(--md-sys-color-primary);r:0px;will-change:r}:host(:state(checked)) .dot{r:5px}:host(:state(checking)) .ring{animation:check-ring-1 var(--_default), check-ring-2 var(--_slow) var(--_d)}:host(:state(checking)) .dot{animation:check-dot-1 var(--_default), check-dot-2 var(--_slow) var(--_d)}@keyframes check-ring-1{0%{r:9px;stroke-width:2px}to{r:4.5px;stroke-width:9px}}@keyframes check-ring-2{0%{r:8px;stroke-width:2px}to{r:9px;stroke-width:2px}}@keyframes check-dot-1{0%,to{r:0px}}@keyframes check-dot-2{0%{r:7px}to{r:5px}}:host(:state(unchecking)) .ring{animation:uncheck-ring-1 var(--_default), uncheck-ring-2 var(--_slow) var(--_d)}:host(:state(unchecking)) .dot{animation:uncheck-dot-1 var(--_default)}@keyframes uncheck-ring-1{0%{r:9px;stroke:var(--md-sys-color-primary);stroke-width:2px}to{r:8px;stroke:var(--md-sys-color-on-surface-variant);stroke-width:2px}}@keyframes uncheck-ring-2{0%{r:4.5px;stroke-width:9px}to{r:9px;stroke-width:2px}}@keyframes uncheck-dot-1{0%{fill:var(--md-sys-color-primary);r:5px}to{fill:var(--md-sys-color-on-surface-variant);r:7.5px}}:host([disabled]){pointer-events:none}:host([disabled]) .ring{stroke:color-mix(in srgb, var(--md-sys-color-on-surface) 38%, transparent)}:host([disabled]) .dot{fill:color-mix(in srgb, var(--md-sys-color-on-surface) 38%, transparent)}@media (forced-colors:active){:host{--md-sys-color-primary:SelectedItem;--md-sys-color-on-surface-variant:CanvasText}:host(:disabled) .ring{stroke:graytext}:host(:disabled) .dot{fill:graytext}}`;
@@ -2,12 +2,15 @@ import { PropertyValues } from 'lit';
2
2
  import { Radio } from '../../base/radio.js';
3
3
  import '../focus-ring/focus-ring.js';
4
4
  import '../ripple/ripple.js';
5
+ import type { M3Ripple } from '../ripple/ripple.js';
5
6
  /**
6
7
  * @tag md-radio
7
8
  */
8
9
  export declare class M3Radio extends Radio {
10
+ $ripple: M3Ripple;
9
11
  static styles: any[];
10
12
  render(): import("lit-html").TemplateResult<1>;
13
+ firstUpdated(): void;
11
14
  updated(changedProperties: PropertyValues<this>): void;
12
15
  }
13
16
  declare global {
@@ -1,19 +1,24 @@
1
1
  import { __decorate } from "tslib";
2
2
  import { html } from 'lit';
3
- import { Radio } from '../../base/radio.js';
3
+ import { query } from 'lit/decorators.js';
4
4
  import { customElement } from '../../core/decorators.js';
5
5
  import { internals } from '../../base/mixins/internals-attached.js';
6
- import { radioStyles } from './radio-styles.css.js';
7
- import { targetStyles } from '../target-styles.css.js';
6
+ import { Radio } from '../../base/radio.js';
8
7
  import '../focus-ring/focus-ring.js';
9
8
  import '../ripple/ripple.js';
9
+ import { targetStyles } from '../target-styles.css.js';
10
+ import { radioStyles } from './radio-styles.css.js';
10
11
  /**
11
12
  * @tag md-radio
12
13
  */
13
14
  let M3Radio = class M3Radio extends Radio {
14
15
  static { this.styles = [targetStyles, radioStyles]; }
15
16
  render() {
16
- return html `<md-focus-ring></md-focus-ring><md-ripple></md-ripple><span part="target"></span> <span class="middle"></span>`;
17
+ return html `<md-focus-ring></md-focus-ring><md-ripple enterbehavior="none"></md-ripple><span part="target"></span> <svg class="icon" viewBox="0 0 20 20" aria-hidden="true"><circle class="ring" cx="10" cy="10" r="9"/><circle class="dot" cx="10" cy="10" r="0"/></svg>`;
18
+ }
19
+ firstUpdated() {
20
+ // SSR'd <md-radio> components don't have their labels set up on time
21
+ this.$ripple.attach(this, true);
17
22
  }
18
23
  updated(changedProperties) {
19
24
  super.updated(changedProperties);
@@ -27,6 +32,9 @@ let M3Radio = class M3Radio extends Radio {
27
32
  }
28
33
  }
29
34
  };
35
+ __decorate([
36
+ query('md-ripple')
37
+ ], M3Radio.prototype, "$ripple", void 0);
30
38
  M3Radio = __decorate([
31
39
  customElement('md-radio')
32
40
  ], M3Radio);
@@ -1,2 +1,2 @@
1
1
  import { css } from 'lit';
2
- export const rippleStyles = css`:host{border-radius:inherit;pointer-events:none;display:block;position:absolute;inset:0;overflow:hidden}[part~=ripple]{background-image:radial-gradient(closest-side, var(--md-ripple-color,currentColor) max(calc(100% - 70px), 65%), transparent 100%);position:absolute;top:0;left:0}:host:before{background-color:var(--md-ripple-color,currentColor);border-radius:inherit;content:"";opacity:0;transition:opacity 67ms linear;display:block;position:absolute;inset:0}:host(:state(hover)):before{opacity:.08}`;
2
+ export const rippleStyles = css`:host{--_color:var(--md-ripple-color,currentColor);border-radius:inherit;pointer-events:none;display:block;position:absolute;inset:0;overflow:hidden}[part~=ripple]{background-image:radial-gradient(closest-side, var(--_color) max(calc(100% - 70px), 65%), transparent 100%);position:absolute;top:0;left:0}:host:before{background-color:var(--_color);border-radius:inherit;content:"";opacity:0;transition:opacity 67ms linear;display:block;position:absolute;inset:0}:host(:state(hover)):before{opacity:.08}@media (forced-colors:active){:host{--_color:var(--md-ripple-color,Highlight)}}`;
@@ -1,4 +1,5 @@
1
1
  import { LitElement } from 'lit';
2
+ import { handleControlChange } from '../../base/mixins/attachable.js';
2
3
  declare const M3Ripple_base: Constructor<import("../../base/mixins/attachable.js").AttachableInterface> & Constructor<import("../../base/mixins/internals-attached.js").InternalsAttachedInterface> & typeof LitElement;
3
4
  /**
4
5
  * @tag md-ripple
@@ -19,21 +20,10 @@ export declare class M3Ripple extends M3Ripple_base {
19
20
  handlePointerLeave: () => void;
20
21
  handlePointerDown: (e: PointerEvent) => void;
21
22
  handlePointerUp: () => void;
22
- handleControlChange(prev?: HTMLElement | null, next?: HTMLElement | HTMLInputElement | null): void;
23
- calculateRipple(e?: MouseEvent | null): {
24
- startCenter: {
25
- x: number;
26
- y: number;
27
- };
28
- endCenter: {
29
- x: number;
30
- y: number;
31
- };
32
- radius: number;
33
- };
23
+ [handleControlChange](prev?: HTMLElement | null, next?: HTMLElement | null): void;
34
24
  addRipple(e?: MouseEvent | null): void;
35
25
  removeRipple(ripple: HTMLSpanElement): void;
36
- removeRippleAll(): void;
26
+ keepLastRipple(): void;
37
27
  }
38
28
  declare global {
39
29
  interface HTMLElementTagNameMap {
@@ -2,16 +2,16 @@ import { __decorate } from "tslib";
2
2
  import { LitElement } from 'lit';
3
3
  import { property } from 'lit/decorators.js';
4
4
  import { customElement } from '../../core/decorators.js';
5
- import { Attachable } from '../../base/mixins/attachable.js';
5
+ import { Attachable, handleControlChange, } from '../../base/mixins/attachable.js';
6
6
  import { InternalsAttached, internals, } from '../../base/mixins/internals-attached.js';
7
7
  import { rippleStyles } from './ripple-styles.css.js';
8
8
  const PRESS_GROW_MS = 450;
9
9
  const MINIMUM_PRESS_MS = 225;
10
10
  const OPACITY_IN_MS = 105;
11
11
  const OPACITY_OUT_MS = 375;
12
- function distance({ x: ax, y: ay }, { x: bx, y: by }) {
12
+ const distance = ({ x: ax, y: ay }, { x: bx, y: by }) => {
13
13
  return Math.sqrt((ax - bx) ** 2 + (ay - by) ** 2);
14
- }
14
+ };
15
15
  /**
16
16
  * @tag md-ripple
17
17
  *
@@ -32,7 +32,7 @@ let M3Ripple = class M3Ripple extends Attachable(InternalsAttached(LitElement))
32
32
  if ((e.key === 'Enter' && this.enterBehavior === 'always') ||
33
33
  (e.key === ' ' && this.spaceBehavior === 'always')) {
34
34
  this.addRipple();
35
- this.removeRippleAll();
35
+ this.keepLastRipple();
36
36
  }
37
37
  else if (e.key === ' ' && this.spaceBehavior === 'once') {
38
38
  if (!this.#spaceKeyDown)
@@ -43,7 +43,7 @@ let M3Ripple = class M3Ripple extends Attachable(InternalsAttached(LitElement))
43
43
  this.handleKeyUp = (e) => {
44
44
  if (e.key === ' ' && this.spaceBehavior === 'once') {
45
45
  this.#spaceKeyDown = false;
46
- this.removeRippleAll();
46
+ this.keepLastRipple();
47
47
  }
48
48
  };
49
49
  this.handlePointerEnter = (e) => {
@@ -56,7 +56,7 @@ let M3Ripple = class M3Ripple extends Attachable(InternalsAttached(LitElement))
56
56
  this.handlePointerLeave = () => {
57
57
  this[internals].states.delete('hover');
58
58
  if (this.#pointerDown && this.clickBehavior === 'always')
59
- this.removeRippleAll();
59
+ this.keepLastRipple();
60
60
  };
61
61
  this.handlePointerDown = (e) => {
62
62
  if (e.pointerType === 'mouse')
@@ -65,7 +65,7 @@ let M3Ripple = class M3Ripple extends Attachable(InternalsAttached(LitElement))
65
65
  document.addEventListener('touchcancel', this.handlePointerUp);
66
66
  document.addEventListener('touchend', this.handlePointerUp);
67
67
  document.addEventListener('touchmove', this.handlePointerUp);
68
- if (e.button === 2)
68
+ if (e.button !== 0)
69
69
  return;
70
70
  if (this.clickBehavior === 'always')
71
71
  this.addRipple(e);
@@ -76,42 +76,40 @@ let M3Ripple = class M3Ripple extends Attachable(InternalsAttached(LitElement))
76
76
  document.removeEventListener('touchcancel', this.handlePointerUp);
77
77
  document.removeEventListener('touchend', this.handlePointerUp);
78
78
  document.removeEventListener('touchmove', this.handlePointerUp);
79
- this.removeRippleAll();
79
+ this.keepLastRipple();
80
80
  };
81
81
  this[internals].ariaHidden = 'true';
82
82
  }
83
83
  #spaceKeyDown;
84
84
  #pointerDown;
85
85
  #lastTime;
86
- handleControlChange(prev = null, next = null) {
86
+ [handleControlChange](prev = null, next = null) {
87
87
  const eventHandlers = {
88
- keydown: this.handleKeyDown,
89
- keyup: this.handleKeyUp,
90
- pointerenter: this.handlePointerEnter,
91
- pointerleave: this.handlePointerLeave,
92
- pointerdown: this.handlePointerDown,
88
+ keydown: { fn: this.handleKeyDown, kbd: true },
89
+ keyup: { fn: this.handleKeyUp, kbd: true },
90
+ pointerenter: { fn: this.handlePointerEnter, kbd: false },
91
+ pointerleave: { fn: this.handlePointerLeave, kbd: false },
92
+ pointerdown: { fn: this.handlePointerDown, kbd: false },
93
93
  };
94
- Object.keys(eventHandlers).forEach((eventName) => {
95
- // @ts-ignore
96
- prev?.labels?.forEach((label) => label.removeEventListener(eventName, eventHandlers[eventName]));
97
- prev?.removeEventListener(eventName, eventHandlers[eventName]);
94
+ Object.entries(eventHandlers).forEach(([eventName, { fn, kbd }]) => {
95
+ prev?.labels?.forEach((label) => label.removeEventListener(eventName, fn));
96
+ prev?.removeEventListener(eventName, fn);
98
97
  // Check if control is nested in label, if so, only bind to label
99
98
  let isNestedInLabel = false;
100
- // @ts-ignore
101
99
  next?.labels?.forEach((label) => {
102
- if (label.contains(next))
100
+ if (label.contains(next)) {
103
101
  isNestedInLabel = true;
102
+ }
103
+ if (!kbd) {
104
+ label.addEventListener(eventName, fn);
105
+ }
104
106
  });
105
- if (isNestedInLabel) {
106
- // @ts-ignore
107
- next.labels?.forEach((label) => label.addEventListener(eventName, eventHandlers[eventName]));
108
- }
109
- else {
110
- next?.addEventListener(eventName, eventHandlers[eventName]);
107
+ if (!isNestedInLabel || kbd) {
108
+ next?.addEventListener(eventName, fn);
111
109
  }
112
110
  });
113
111
  }
114
- calculateRipple(e = null) {
112
+ #calculateRipple(e = null) {
115
113
  const containerRect = this.getBoundingClientRect();
116
114
  const containerMiddle = {
117
115
  x: containerRect.width / 2,
@@ -119,7 +117,7 @@ let M3Ripple = class M3Ripple extends Attachable(InternalsAttached(LitElement))
119
117
  };
120
118
  const centered = !e;
121
119
  const endCenter = containerMiddle;
122
- let startCenter = endCenter;
120
+ let startCenter = { ...endCenter };
123
121
  if (!centered) {
124
122
  startCenter.x = e.clientX - containerRect.left;
125
123
  startCenter.y = e.clientY - containerRect.top;
@@ -134,7 +132,7 @@ let M3Ripple = class M3Ripple extends Attachable(InternalsAttached(LitElement))
134
132
  return { startCenter, endCenter, radius };
135
133
  }
136
134
  addRipple(e = null) {
137
- const { startCenter, endCenter, radius } = this.calculateRipple(e);
135
+ const { startCenter, endCenter, radius } = this.#calculateRipple(e);
138
136
  const diameter = radius * 2 + 'px';
139
137
  const translateStart = `${startCenter.x - radius}px ${startCenter.y - radius}px`;
140
138
  const translateEnd = `${endCenter.x - radius}px ${endCenter.y - radius}px`;
@@ -156,7 +154,6 @@ let M3Ripple = class M3Ripple extends Attachable(InternalsAttached(LitElement))
156
154
  scale: [0.2, 1.35],
157
155
  }, {
158
156
  duration: PRESS_GROW_MS,
159
- // TODO: Control by global variables
160
157
  easing: 'cubic-bezier(0.2, 0, 0, 1)',
161
158
  fill: 'forwards',
162
159
  });
@@ -174,7 +171,7 @@ let M3Ripple = class M3Ripple extends Attachable(InternalsAttached(LitElement))
174
171
  animation.onfinish = animation.oncancel = () => ripple.remove();
175
172
  }, Math.max(MINIMUM_PRESS_MS - (Date.now() - this.#lastTime), 0));
176
173
  }
177
- removeRippleAll() {
174
+ keepLastRipple() {
178
175
  for (const ripple of this.$ripples.splice(0))
179
176
  this.removeRipple(ripple);
180
177
  }
@@ -2,7 +2,7 @@ body {
2
2
  accent-color: var(--md-sys-color-primary);
3
3
  background-color: var(--md-sys-color-background);
4
4
  color: var(--md-sys-color-on-background);
5
- font-family: var(--md-sys-typography-family);
5
+ font: var(--md-sys-typography-body-large);
6
6
  }
7
7
 
8
8
  ::selection {
@@ -0,0 +1,15 @@
1
+ :root {
2
+ --md-sys-motion-spatial-fast: cubic-bezier(0.42, 1.67, 0.21, 0.9);
3
+ --md-sys-motion-spatial-fast-duration: 350ms;
4
+ --md-sys-motion-spatial-default: cubic-bezier(0.38, 1.21, 0.22, 1);
5
+ --md-sys-motion-spatial-default-duration: 500ms;
6
+ --md-sys-motion-spatial-slow: cubic-bezier(0.39, 1.29, 0.35, 0.98);
7
+ --md-sys-motion-spatial-slow-duration: 650ms;
8
+
9
+ --md-sys-motion-effects-fast: cubic-bezier(0.31, 0.94, 0.34, 1);
10
+ --md-sys-motion-effects-fast-duration: 150ms;
11
+ --md-sys-motion-effects-default: cubic-bezier(0.34, 0.8, 0.34, 1);
12
+ --md-sys-motion-effects-default-duration: 200ms;
13
+ --md-sys-motion-effects-slow: cubic-bezier(0.34, 0.88, 0.34, 1);
14
+ --md-sys-motion-effects-slow-duration: 300ms;
15
+ }
@@ -0,0 +1,15 @@
1
+ :root {
2
+ --md-sys-motion-spatial-fast: cubic-bezier(0.27, 1.06, 0.18, 1);
3
+ --md-sys-motion-spatial-fast-duration: 350ms;
4
+ --md-sys-motion-spatial-default: cubic-bezier(0.27, 1.06, 0.18, 1);
5
+ --md-sys-motion-spatial-default-duration: 500ms;
6
+ --md-sys-motion-spatial-slow: cubic-bezier(0.27, 1.06, 0.18, 1);
7
+ --md-sys-motion-spatial-slow-duration: 750ms;
8
+
9
+ --md-sys-motion-effects-fast: cubic-bezier(0.31, 0.94, 0.34, 1);
10
+ --md-sys-motion-effects-fast-duration: 150ms;
11
+ --md-sys-motion-effects-default: cubic-bezier(0.34, 0.8, 0.34, 1);
12
+ --md-sys-motion-effects-default-duration: 200ms;
13
+ --md-sys-motion-effects-slow: cubic-bezier(0.34, 0.88, 0.34, 1);
14
+ --md-sys-motion-effects-slow-duration: 300ms;
15
+ }
@@ -0,0 +1,24 @@
1
+ :root {
2
+ --_brand: var(--md-ref-typeface-brand, sans-serif);
3
+ --_plain: var(--md-ref-typeface-plain, sans-serif);
4
+
5
+ --md-sys-typography-display-large: 400 3.5625rem / 4rem var(--_brand);
6
+ --md-sys-typography-display-medium: 400 2.8125rem / 3.25rem var(--_brand);
7
+ --md-sys-typography-display-small: 400 2.25rem / 2.75rem var(--_brand);
8
+
9
+ --md-sys-typography-headline-large: 400 2rem / 2.5rem var(--_brand);
10
+ --md-sys-typography-headline-medium: 400 1.75rem / 2.25rem var(--_brand);
11
+ --md-sys-typography-headline-small: 400 1.5rem / 2rem var(--_brand);
12
+
13
+ --md-sys-typography-title-large: 400 1.375rem / 1.75rem var(--_brand);
14
+ --md-sys-typography-title-medium: 500 1rem / 1.25rem var(--_plain);
15
+ --md-sys-typography-title-small: 500 0.875rem / 1.125rem var(--_plain);
16
+
17
+ --md-sys-typography-label-large: 500 0.875rem / 1.25rem var(--_plain);
18
+ --md-sys-typography-label-medium: 500 0.75rem / 1rem var(--_plain);
19
+ --md-sys-typography-label-small: 500 0.6875rem / 0.875rem var(--_plain);
20
+
21
+ --md-sys-typography-body-large: 400 1rem / 1.5rem var(--_plain);
22
+ --md-sys-typography-body-medium: 400 0.875rem / 1.25rem var(--_plain);
23
+ --md-sys-typography-body-small: 400 0.75rem / 1rem var(--_plain);
24
+ }
@@ -1,2 +1,2 @@
1
1
  import { css } from 'lit';
2
- export const switchStyles = css`:host{--_outline-color:var(--md-sys-color-outline);--_track-color:var(--md-sys-color-surface-container-highest);--_thumb-color:var(--md-sys-color-outline);--_icon-color:var(--md-sys-color-surface-container-highest);--_ripple-color:var(--md-sys-color-on-surface);background-color:color-mix(in srgb, var(--_track-color) var(--_track-opacity,100%), transparent);border-color:color-mix(in srgb, var(--_outline-color) var(--_outline-opacity,100%), transparent);box-sizing:border-box;cursor:pointer;-webkit-tap-highlight-color:transparent;touch-action:none;height:32px;transition:background-color var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast), border-color var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast);-webkit-user-select:none;user-select:none;vertical-align:top;border-style:solid;border-width:2px;border-radius:9999px;outline:0;place-content:center;place-items:center;width:52px;display:inline-grid;position:relative}:host(:state(checked)){--_outline-color:var(--md-sys-color-primary);--_track-color:var(--md-sys-color-primary);--_thumb-color:var(--md-sys-color-on-primary);--_icon-color:var(--md-sys-color-on-primary-container);--_ripple-color:var(--md-sys-color-primary)}:host(:disabled){--_outline-color:var(--md-sys-color-on-surface);--_outline-opacity:12%;--_track-color:var(--md-sys-color-surface-variant);--_track-opacity:12%;--_thumb-color:var(--md-sys-color-on-surface);--_thumb-opacity:38%;--_icon-color:var(--md-sys-color-surface-container-highest);cursor:default;pointer-events:none}:host(:disabled:state(checked)){--_outline-color:var(--md-sys-color-surface);--_track-color:var(--md-sys-color-on-surface);--_thumb-color:var(--md-sys-color-surface);--_thumb-opacity:100%;--_icon-color:var(--md-sys-color-on-surface)}:host([icons]:not(:state(checked)):not([checkedicononly])) [part~=icon-off],:host([icons]:state(checked)) [part~=icon-on]{--_icon-opacity:100%}:host([icons]:state(checked):disabled) [part~=icon-on]{--_icon-opacity:38%}@media (hover:hover) and (pointer:fine){:host(:hover){--_thumb-color:var(--md-sys-color-on-surface-variant)}:host(:state(checked):hover){--_thumb-color:var(--md-sys-color-primary-container)}}@media (forced-colors:active){:host{forced-color-adjust:none}}[part~=thumb]{--_thumb-diameter:16px;--_thumb-diff-default:20px;background-color:color-mix(in srgb, var(--_thumb-color) var(--_thumb-opacity,100%), transparent);height:var(--_thumb-diameter);transition:background-color var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast), width var(--md-sys-motion-spatial-fast-duration) var(--md-sys-motion-spatial-fast), height var(--md-sys-motion-spatial-fast-duration) var(--md-sys-motion-spatial-fast), margin var(--md-sys-motion-spatial-fast-duration) var(--md-sys-motion-spatial-fast);width:var(--_thumb-diameter);z-index:1;border-radius:50%;place-content:center;place-items:center;margin-inline-start:calc(var(--_thumb-diff-pointer,0px) - var(--_thumb-diff-default));display:grid;position:absolute}:host(:state(checked)) [part~=thumb]{--_thumb-diameter:24px;--_thumb-diff-default:-20px;background-color:var(--_thumb-color)}:host([icons]:not([checkedicononly])) [part~=thumb]{--_thumb-diameter:24px}:host(:active) [part~=thumb]{--_thumb-color:var(--md-sys-color-on-surface-variant);--_thumb-diameter:28px!important}:host(:state(checked):active) [part~=thumb]{--_thumb-color:var(--md-sys-color-primary-container)}[part~=icons]{fill:color-mix(in srgb, var(--_icon-color) var(--_icon-opacity,0%), transparent);width:16px;height:16px;transition:fill 67ms linear;position:absolute}md-focus-ring{inset:-4px}md-ripple{color:var(--_ripple-color);height:40px;inset:unset;width:40px}`;
2
+ export const switchStyles = css`:host{--_outline-color:var(--md-sys-color-outline);--_track-color:var(--md-sys-color-surface-container-highest);--_thumb-color:var(--md-sys-color-outline);--_icon-color:var(--md-sys-color-surface-container-highest);--_ripple-color:var(--md-sys-color-on-surface);background-color:color-mix(in srgb, var(--_track-color) var(--_track-opacity,100%), transparent);border-color:color-mix(in srgb, var(--_outline-color) var(--_outline-opacity,100%), transparent);box-sizing:border-box;cursor:pointer;-webkit-tap-highlight-color:transparent;touch-action:none;height:32px;transition:background-color var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast), border-color var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast);-webkit-user-select:none;user-select:none;vertical-align:top;border-style:solid;border-width:2px;border-radius:9999px;outline:0;place-content:center;place-items:center;width:52px;display:inline-grid;position:relative}:host(:state(checked)){--_outline-color:var(--md-sys-color-primary);--_track-color:var(--md-sys-color-primary);--_thumb-color:var(--md-sys-color-on-primary);--_icon-color:var(--md-sys-color-on-primary-container);--_ripple-color:var(--md-sys-color-primary)}:host(:disabled){--_outline-color:var(--md-sys-color-on-surface);--_outline-opacity:12%;--_track-color:var(--md-sys-color-surface-variant);--_track-opacity:12%;--_thumb-color:var(--md-sys-color-on-surface);--_thumb-opacity:38%;--_icon-color:var(--md-sys-color-surface-container-highest);cursor:default;pointer-events:none}:host(:disabled:state(checked)){--_outline-color:var(--md-sys-color-surface);--_track-color:var(--md-sys-color-on-surface);--_thumb-color:var(--md-sys-color-surface);--_thumb-opacity:100%;--_icon-color:var(--md-sys-color-on-surface)}:host([icons]:not(:state(checked)):not([checkedicononly])) [part~=icon-off],:host([icons]:state(checked)) [part~=icon-on]{--_icon-opacity:100%}:host([icons]:state(checked):disabled) [part~=icon-on]{--_icon-opacity:38%}@media (hover:hover) and (pointer:fine){:host(:hover){--_thumb-color:var(--md-sys-color-on-surface-variant)}:host(:state(checked):hover){--_thumb-color:var(--md-sys-color-primary-container)}}@media (forced-colors:active){:host{forced-color-adjust:none}}[part~=thumb]{--_thumb-diameter:16px;--_thumb-diff-default:20px;background-color:color-mix(in srgb, var(--_thumb-color) var(--_thumb-opacity,100%), transparent);height:var(--_thumb-diameter);transition:background-color var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast), width var(--md-sys-motion-spatial-fast-duration) var(--md-sys-motion-spatial-fast), height var(--md-sys-motion-spatial-fast-duration) var(--md-sys-motion-spatial-fast), margin var(--md-sys-motion-spatial-fast-duration) var(--md-sys-motion-spatial-fast);width:var(--_thumb-diameter);z-index:1;border-radius:50%;place-content:center;place-items:center;margin-inline-start:calc(var(--_thumb-diff-pointer,0px) - var(--_thumb-diff-default));display:grid;position:absolute}:host(:state(checked)) [part~=thumb]{--_thumb-diameter:24px;--_thumb-diff-default:-20px;background-color:var(--_thumb-color)}:host([icons]:not([checkedicononly])) [part~=thumb]{--_thumb-diameter:24px}:host(:active) [part~=thumb]{--_thumb-color:var(--md-sys-color-on-surface-variant);--_thumb-diameter:28px!important}:host(:state(checked):active) [part~=thumb]{--_thumb-color:var(--md-sys-color-primary-container)}[part~=icons]{fill:color-mix(in srgb, var(--_icon-color) var(--_icon-opacity,0%), transparent);width:16px;height:16px;transition:fill 67ms linear;position:absolute}md-focus-ring{inset:-4px}md-ripple{color:var(--_ripple-color);height:40px;inset:unset;width:40px}@media (forced-colors:active){:host{--md-sys-color-primary:SelectedItem;--md-sys-color-primary-container:SelectedItemText;--md-sys-color-on-primary:SelectedItemText}}`;
@@ -1,5 +1,6 @@
1
1
  import { ToggleButton } from '../../base/toggle-button.js';
2
2
  import '../focus-ring/focus-ring.js';
3
+ import '../ripple/ripple.js';
3
4
  import { M3Ripple } from '../ripple/ripple.js';
4
5
  /**
5
6
  * @tag md-switch
@@ -9,6 +10,8 @@ import { M3Ripple } from '../ripple/ripple.js';
9
10
  */
10
11
  export declare class M3Switch extends ToggleButton {
11
12
  #private;
13
+ icons: boolean;
14
+ checkedIconOnly: boolean;
12
15
  $ripple: M3Ripple;
13
16
  $thumb: HTMLSpanElement;
14
17
  static styles: any[];
@@ -17,8 +20,7 @@ export declare class M3Switch extends ToggleButton {
17
20
  renderOffIcon(): import("lit-html").TemplateResult<1>;
18
21
  connectedCallback(): void;
19
22
  disconnectedCallback(): void;
20
- icons: boolean;
21
- checkedIconOnly: boolean;
23
+ firstUpdated(): void;
22
24
  }
23
25
  declare global {
24
26
  interface HTMLElementTagNameMap {
@@ -3,6 +3,7 @@ import { html } from 'lit';
3
3
  import { customElement, property, query } from 'lit/decorators.js';
4
4
  import { ToggleButton } from '../../base/toggle-button.js';
5
5
  import '../focus-ring/focus-ring.js';
6
+ import '../ripple/ripple.js';
6
7
  import { switchStyles } from './switch-styles.css.js';
7
8
  import { targetStyles } from '../target-styles.css.js';
8
9
  function isRTL() {
@@ -53,12 +54,12 @@ let M3Switch = class M3Switch extends ToggleButton {
53
54
  this.$thumb.style.setProperty('--_thumb-diameter', '');
54
55
  this.$thumb.style.transitionDuration = '';
55
56
  if (this.checked != shouldBeChecked)
56
- this.toggleChecked();
57
+ this._toggle();
57
58
  };
58
59
  }
59
60
  static { this.styles = [targetStyles, switchStyles]; }
60
61
  render() {
61
- return html `<md-focus-ring></md-focus-ring><div part="thumb"><md-ripple spacebehavior="always"></md-ripple><span part="target"></span> ${this.renderOffIcon()}${this.renderOnIcon()}</div>`;
62
+ return html `<md-focus-ring></md-focus-ring><div part="thumb"><md-ripple></md-ripple><span part="target"></span> ${this.renderOffIcon()}${this.renderOnIcon()}</div>`;
62
63
  }
63
64
  renderOnIcon() {
64
65
  return html `<svg part="icons icon-on" viewBox="0 0 24 24" aria-hidden="true"><path d="M9.55 18.2 3.65 12.3 5.275 10.675 9.55 14.95 18.725 5.775 20.35 7.4Z"/></svg>`;
@@ -68,34 +69,35 @@ let M3Switch = class M3Switch extends ToggleButton {
68
69
  }
69
70
  connectedCallback() {
70
71
  super.connectedCallback();
71
- this.updateComplete.then(() => {
72
- this.$ripple.attach(this);
73
- });
74
72
  this.addEventListener('pointerdown', this.#handlePointerDown);
75
73
  this.addEventListener('pointerup', this.#handlePointerUp);
76
74
  }
77
75
  disconnectedCallback() {
78
- super.disconnectedCallback();
79
76
  this.removeEventListener('pointerdown', this.#handlePointerDown);
80
77
  this.removeEventListener('pointerup', this.#handlePointerUp);
78
+ super.disconnectedCallback();
79
+ }
80
+ firstUpdated() {
81
+ // SSR'd <md-switch> components don't have their labels set up on time
82
+ this.$ripple.attach(this, true);
81
83
  }
82
84
  #pointerDownX;
83
85
  #handlePointerDown;
84
86
  #handlePointerMove;
85
87
  #handlePointerUp;
86
88
  };
87
- __decorate([
88
- query('md-ripple')
89
- ], M3Switch.prototype, "$ripple", void 0);
90
- __decorate([
91
- query('[part~="thumb"]')
92
- ], M3Switch.prototype, "$thumb", void 0);
93
89
  __decorate([
94
90
  property({ type: Boolean, reflect: true })
95
91
  ], M3Switch.prototype, "icons", void 0);
96
92
  __decorate([
97
93
  property({ type: Boolean, reflect: true })
98
94
  ], M3Switch.prototype, "checkedIconOnly", void 0);
95
+ __decorate([
96
+ query('md-ripple')
97
+ ], M3Switch.prototype, "$ripple", void 0);
98
+ __decorate([
99
+ query('[part~="thumb"]')
100
+ ], M3Switch.prototype, "$thumb", void 0);
99
101
  M3Switch = __decorate([
100
102
  customElement('md-switch')
101
103
  ], M3Switch);
@@ -0,0 +1,2 @@
1
+ import { css } from 'lit';
2
+ export const secondaryTabStyles = css`:host{--_tab-selected-color:var(--md-sys-color-on-surface);--_indicator-height:2px}[part=indicator]{border-radius:0;left:0;right:0}`;
@@ -0,0 +1,5 @@
1
+ import { M3Tab } from './tab.js';
2
+ export declare class M3SecondaryTab extends M3Tab {
3
+ protected _isSecondary: boolean;
4
+ static styles: any[];
5
+ }
@@ -0,0 +1,15 @@
1
+ import { __decorate } from "tslib";
2
+ import { customElement } from '../../core/decorators.js';
3
+ import { M3Tab } from './tab.js';
4
+ import { secondaryTabStyles } from './secondary-tab-styles.css.js';
5
+ let M3SecondaryTab = class M3SecondaryTab extends M3Tab {
6
+ constructor() {
7
+ super(...arguments);
8
+ this._isSecondary = true;
9
+ }
10
+ static { this.styles = [...super.styles, secondaryTabStyles]; }
11
+ };
12
+ M3SecondaryTab = __decorate([
13
+ customElement('md-secondary-tab')
14
+ ], M3SecondaryTab);
15
+ export { M3SecondaryTab };
@@ -1,2 +1,2 @@
1
1
  import { css } from 'lit';
2
- export const tabPanelStyles = css`:host{display:block}:host([hidden]){display:none}`;
2
+ export const tabPanelStyles = css`:host{display:block}:host(:not([selected])){display:none!important}`;
@@ -1,2 +1,2 @@
1
1
  import { css } from 'lit';
2
- export const tabStyles = css`:host{--md-focus-ring-shape:12px;box-sizing:border-box;color:var(--md-sys-color-on-surface-variant);cursor:pointer;font:var(--md-sys-typography-title-small);-webkit-tap-highlight-color:transparent;text-wrap-mode:nowrap;user-select:none;-webkit-user-select-:none;outline:none;flex-shrink:0;justify-content:center;padding:0 16px;display:inline-flex;position:relative}:host([selected]){color:var(--_tab-selected-color)}:host([selected]) md-focus-ring{margin-bottom:calc(var(--_tab-indicator-height) + 2px)}[part=content]{flex-direction:var(--_tab-flex-dir,row);align-items:center;gap:var(--_tab-gap,8px);height:var(--_tab-height,48px);justify-content:center;display:inline-flex}[part~=icon]{fill:currentColor;block-size:1em;inline-size:1em;font-size:24px}`;
2
+ export const tabStyles = css`:host{--md-focus-ring-shape:12px;box-sizing:border-box;color:var(--md-sys-color-on-surface-variant);cursor:pointer;font:var(--md-sys-typography-title-small);-webkit-tap-highlight-color:transparent;text-wrap-mode:nowrap;user-select:none;-webkit-user-select-:none;outline:none;flex-shrink:0;justify-content:center;padding:0 16px;display:inline-flex;position:relative}:host([selected]){color:var(--_tab-selected-color);& md-focus-ring{margin-bottom:calc(var(--_indicator-height) + 2px)}& [part=indicator]{opacity:1}}:host([disabled]){pointer-events:none;color:color-mix(in srgb, var(--md-sys-color-on-surface) 38%, transparent)}[part=content]{flex-direction:var(--_tab-flex-dir,row);align-items:center;gap:var(--_tab-gap,8px);height:var(--_tab-height,48px);justify-content:center;display:inline-flex;position:relative}[part=indicator]{height:var(--_indicator-height);background-color:var(--md-sys-color-primary);opacity:0;transform-origin:0;pointer-events:none;will-change:transform, opacity;border-radius:3px 3px 0 0;min-width:24px;position:absolute;bottom:0;left:2px;right:2px}::slotted([slot=icon]){fill:currentColor;block-size:1em;inline-size:1em;font-size:24px}`;
@@ -9,8 +9,11 @@ import '../ripple/ripple.js';
9
9
  */
10
10
  export declare class M3Tab extends Tab {
11
11
  $content: HTMLDivElement;
12
+ $indicator: HTMLElement;
13
+ protected _isSecondary: boolean;
12
14
  static styles: any[];
13
15
  render(): import("lit-html").TemplateResult<1>;
16
+ animateIndicator(previousTab: M3Tab): void;
14
17
  }
15
18
  declare global {
16
19
  interface HTMLElementTagNameMap {
package/src/m3/tab/tab.js CHANGED
@@ -1,11 +1,13 @@
1
1
  import { __decorate } from "tslib";
2
- import { html } from 'lit';
3
- import { customElement, query } from 'lit/decorators.js';
2
+ import { html, nothing } from 'lit';
3
+ import { customElement, query, state } from 'lit/decorators.js';
4
4
  import { Tab } from '../../base/tab.js';
5
+ import { getSpring } from '../styles/motion.js';
5
6
  import '../focus-ring/focus-ring.js';
6
7
  import '../ripple/ripple.js';
7
8
  import { targetStyles } from '../target-styles.css.js';
8
9
  import { tabStyles } from './tab-styles.css.js';
10
+ const KEYFRAMES = 20;
9
11
  /**
10
12
  * @tag md-tab
11
13
  *
@@ -13,14 +15,77 @@ import { tabStyles } from './tab-styles.css.js';
13
15
  * @slot - label
14
16
  */
15
17
  let M3Tab = class M3Tab extends Tab {
18
+ constructor() {
19
+ super(...arguments);
20
+ this._isSecondary = false;
21
+ }
16
22
  static { this.styles = [targetStyles, tabStyles]; }
17
23
  render() {
18
- return html `<md-focus-ring inward></md-focus-ring><md-ripple inward></md-ripple><span part="target"></span><div part="content"><slot part="icon" name="icon" aria-hidden="true"></slot><slot part="label"></slot></div>`;
24
+ return html `<md-focus-ring inward></md-focus-ring><md-ripple></md-ripple><span part="target"></span><div part="content"><slot part="icon" name="icon" aria-hidden="true"></slot><slot part="label"></slot>${!this._isSecondary ? html `<div part="indicator" role="presentation"></div>` : nothing}</div>${this._isSecondary ? html `<div part="indicator" role="presentation"></div>` : nothing}`;
25
+ }
26
+ animateIndicator(previousTab) {
27
+ const indicator = this.$indicator;
28
+ indicator.getAnimations().forEach((a) => a.cancel());
29
+ const prevIndicator = previousTab.$indicator;
30
+ if (prevIndicator &&
31
+ !window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
32
+ const from = prevIndicator.getBoundingClientRect();
33
+ const to = indicator.getBoundingClientRect();
34
+ let keyframes = [];
35
+ if (!this._isSecondary) {
36
+ const startLeft = from.left - to.left;
37
+ const startRight = from.right - to.left;
38
+ const endLeft = 0;
39
+ const endRight = to.width;
40
+ const movingRight = startLeft < 0;
41
+ for (let i = 0; i <= KEYFRAMES; i++) {
42
+ const t = i / KEYFRAMES;
43
+ const dec = Math.sin((t * Math.PI) / 2);
44
+ const acc = 1 - Math.cos((t * Math.PI) / 2);
45
+ const leftProgress = movingRight ? acc : dec;
46
+ const rightProgress = movingRight ? dec : acc;
47
+ const left = startLeft + (endLeft - startLeft) * leftProgress;
48
+ const right = startRight + (endRight - startRight) * rightProgress;
49
+ const width = right - left;
50
+ const translateX = left.toFixed(4);
51
+ const scaleX = (width / to.width).toFixed(4);
52
+ keyframes.push({
53
+ transform: `translateX(${translateX}px) scaleX(${scaleX})`,
54
+ });
55
+ }
56
+ }
57
+ else {
58
+ const translateX = (from.left - to.left).toFixed(4);
59
+ const scaleX = (from.width / to.width).toFixed(4);
60
+ keyframes = [
61
+ {
62
+ transform: `translateX(${translateX}px) scaleX(${scaleX})`,
63
+ },
64
+ { transform: 'none' },
65
+ ];
66
+ }
67
+ indicator.animate(keyframes, {
68
+ ...getSpring(this, 'spatial', 'default'),
69
+ fill: 'none',
70
+ });
71
+ }
72
+ else {
73
+ indicator.animate([{ opacity: '0' }, { opacity: '1' }], {
74
+ ...getSpring(this, 'effects', 'default'),
75
+ fill: 'none',
76
+ });
77
+ }
19
78
  }
20
79
  };
21
80
  __decorate([
22
81
  query('[part="content"]')
23
82
  ], M3Tab.prototype, "$content", void 0);
83
+ __decorate([
84
+ query('[part="indicator"]')
85
+ ], M3Tab.prototype, "$indicator", void 0);
86
+ __decorate([
87
+ state()
88
+ ], M3Tab.prototype, "_isSecondary", void 0);
24
89
  M3Tab = __decorate([
25
90
  customElement('md-tab')
26
91
  ], M3Tab);
@@ -1,2 +1,2 @@
1
1
  import { css } from 'lit';
2
- export const tabsStyles = css`:host{--_tab-selected-color:var(--md-sys-color-primary);--_tab-indicator-height:3px;border-bottom:1px solid var(--md-sys-color-outline-variant);box-sizing:border-box;scroll-behavior:smooth;scrollbar-width:none;display:block;position:relative;overflow:auto hidden}[part=tablist]{display:flex}[part=indicator]{height:var(--_tab-indicator-height);background-color:var(--md-sys-color-primary);transition:left var(--md-sys-motion-spatial-default-duration) var(--md-sys-motion-spatial-default), width var(--md-sys-motion-spatial-default-duration) var(--md-sys-motion-spatial-default);will-change:left, width;border-radius:3px 3px 0 0;position:absolute;bottom:0}::slotted(*){flex:1}:host([secondary]){--_tab-selected-color:var(--md-sys-color-on-surface);--_tab-indicator-height:2px}:host([secondary]) [part=indicator]{border-radius:0}:host([iconsabove]){--_tab-flex-dir:column;--_tab-height:64px;--_tab-gap:2px}`;
2
+ export const tabsStyles = css`:host{--_tab-selected-color:var(--md-sys-color-primary);--_indicator-height:3px;box-sizing:border-box;flex-direction:column;display:flex;position:relative}[part=tablist]{border-bottom:1px solid var(--md-sys-color-outline-variant);box-sizing:border-box;scroll-behavior:smooth;scrollbar-width:none;display:flex;overflow:auto hidden}::slotted(md-tab),::slotted(md-secondary-tab){flex:1}:host([iconsabove]){--_tab-flex-dir:column;--_tab-height:64px;--_tab-gap:2px}@media (forced-colors:active){[part=indicator]{background-color:highlight}}`;
@@ -5,18 +5,12 @@ import type { M3Tab } from './tab.js';
5
5
  *
6
6
  * @tag md-tabs
7
7
  *
8
- * @csspart indicator
9
- *
10
8
  * @slot - tabs
11
9
  */
12
10
  export declare class M3Tabs extends Tabs {
13
- #private;
14
- $indicator: HTMLElement;
15
- secondary: boolean;
16
11
  iconsAbove: boolean;
17
12
  static styles: any[];
18
- render(): import("lit-html").TemplateResult<1>;
19
- selectTab(selectedTab: M3Tab): void;
13
+ _selectTab(selectedTab: M3Tab): void;
20
14
  }
21
15
  declare global {
22
16
  interface HTMLElementTagNameMap {