@redvars/peacock 3.6.1 → 3.6.3

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 (120) hide show
  1. package/dist/assets/components.css.map +1 -1
  2. package/dist/assets/styles.css +1 -1
  3. package/dist/assets/styles.css.map +1 -1
  4. package/dist/assets/tokens.css +1 -1
  5. package/dist/assets/tokens.css.map +1 -1
  6. package/dist/{button-colors-Ccys3hvS.js → button-colors-Cg6oxiz-.js} +126 -116
  7. package/dist/{button-colors-Ccys3hvS.js.map → button-colors-Cg6oxiz-.js.map} +1 -1
  8. package/dist/button-group.js +2 -2
  9. package/dist/button.js +18 -16
  10. package/dist/button.js.map +1 -1
  11. package/dist/canvas.js +126 -107
  12. package/dist/canvas.js.map +1 -1
  13. package/dist/card.js +1 -1
  14. package/dist/card.js.map +1 -1
  15. package/dist/code-highlighter.js +34 -9
  16. package/dist/code-highlighter.js.map +1 -1
  17. package/dist/custom-elements-jsdocs.json +4306 -3215
  18. package/dist/custom-elements.json +8344 -7173
  19. package/dist/{flow-designer-node-BWrPuxAR.js → flow-designer-node-9Bqyn6qx.js} +2 -1
  20. package/dist/flow-designer-node-9Bqyn6qx.js.map +1 -0
  21. package/dist/flow-designer-node.js +1 -1
  22. package/dist/flow-designer.js +1402 -8
  23. package/dist/flow-designer.js.map +1 -1
  24. package/dist/icon-CueRR7wx.js +260 -0
  25. package/dist/icon-CueRR7wx.js.map +1 -0
  26. package/dist/{icon-button-CK1ZuE-2.js → icon-button-AdJBEoNy.js} +34 -30
  27. package/dist/icon-button-AdJBEoNy.js.map +1 -0
  28. package/dist/index.js +10 -9
  29. package/dist/index.js.map +1 -1
  30. package/dist/modal.js +11 -11
  31. package/dist/modal.js.map +1 -1
  32. package/dist/{navigation-rail-DTTkqohi.js → navigation-rail-DAUuJ_Yp.js} +975 -486
  33. package/dist/navigation-rail-DAUuJ_Yp.js.map +1 -0
  34. package/dist/peacock-loader.js +33 -30
  35. package/dist/peacock-loader.js.map +1 -1
  36. package/dist/{popover-NC7b1lTq.js → popover-DUPmMVWS.js} +9 -4
  37. package/dist/{popover-NC7b1lTq.js.map → popover-DUPmMVWS.js.map} +1 -1
  38. package/dist/popover-content.js +1 -1
  39. package/dist/popover-content.js.map +1 -1
  40. package/dist/popover.js +1 -1
  41. package/dist/search.js +11 -14
  42. package/dist/search.js.map +1 -1
  43. package/dist/src/__controllers/floating-controller.d.ts +1 -0
  44. package/dist/src/avatar/avatar.d.ts +1 -1
  45. package/dist/src/breadcrumb/breadcrumb/breadcrumb.d.ts +0 -1
  46. package/dist/src/canvas/canvas.d.ts +3 -3
  47. package/dist/src/chip/chip/chip.d.ts +14 -11
  48. package/dist/src/chip/chip-set/chip-set.d.ts +20 -0
  49. package/dist/src/chip/chip-set/index.d.ts +1 -0
  50. package/dist/src/code-highlighter/code-highlighter.d.ts +4 -0
  51. package/dist/src/field/field.d.ts +1 -0
  52. package/dist/src/flow-designer/flow-designer-node.d.ts +1 -0
  53. package/dist/src/image/image.d.ts +2 -2
  54. package/dist/src/index.d.ts +2 -0
  55. package/dist/src/input/input.d.ts +1 -3
  56. package/dist/src/item/index.d.ts +1 -0
  57. package/dist/src/item/item.d.ts +48 -0
  58. package/dist/src/menu/menu/menu.d.ts +1 -0
  59. package/dist/src/menu/menu-item/menu-item.d.ts +8 -9
  60. package/dist/src/menu/sub-menu/sub-menu.d.ts +1 -0
  61. package/dist/src/modal/modal.d.ts +1 -1
  62. package/dist/src/navigation-rail/navigation-rail.d.ts +2 -6
  63. package/dist/src/popover/popover-content.d.ts +1 -1
  64. package/dist/src/search/search.d.ts +2 -6
  65. package/dist/test/chip.test.d.ts +1 -0
  66. package/dist/test/item.test.d.ts +1 -0
  67. package/dist/tsconfig.tsbuildinfo +1 -1
  68. package/package.json +1 -1
  69. package/readme.md +2 -2
  70. package/scss/mixin.scss +23 -0
  71. package/scss/styles.scss +3 -3
  72. package/scss/tokens.css +1 -1
  73. package/src/__controllers/floating-controller.ts +9 -3
  74. package/src/avatar/avatar.scss +4 -4
  75. package/src/avatar/avatar.ts +1 -1
  76. package/src/breadcrumb/breadcrumb/breadcrumb.ts +0 -1
  77. package/src/button/button/button-sizes.scss +11 -11
  78. package/src/button/button/button.scss +96 -122
  79. package/src/button/button/button.ts +38 -36
  80. package/src/button/icon-button/icon-button-sizes.scss +8 -8
  81. package/src/button/icon-button/icon-button.ts +23 -20
  82. package/src/canvas/canvas.scss +18 -6
  83. package/src/canvas/canvas.ts +125 -103
  84. package/src/card/card.ts +1 -1
  85. package/src/chip/chip/chip.scss +120 -46
  86. package/src/chip/chip/chip.ts +97 -38
  87. package/src/chip/chip-set/chip-set.scss +13 -0
  88. package/src/chip/chip-set/chip-set.ts +25 -0
  89. package/src/chip/chip-set/index.ts +1 -0
  90. package/src/code-highlighter/code-highlighter.ts +33 -6
  91. package/src/empty-state/empty-state.scss +1 -0
  92. package/src/field/field.scss +1 -1
  93. package/src/field/field.ts +6 -0
  94. package/src/flow-designer/flow-designer-node.ts +1 -0
  95. package/src/image/image.scss +21 -16
  96. package/src/image/image.ts +13 -14
  97. package/src/index.ts +2 -0
  98. package/src/input/input.ts +16 -25
  99. package/src/item/index.ts +1 -0
  100. package/src/item/item.scss +184 -0
  101. package/src/item/item.ts +340 -0
  102. package/src/menu/menu/menu.ts +16 -9
  103. package/src/menu/menu-item/menu-item.scss +30 -108
  104. package/src/menu/menu-item/menu-item.ts +89 -129
  105. package/src/menu/sub-menu/sub-menu.ts +6 -2
  106. package/src/modal/modal.scss +10 -10
  107. package/src/modal/modal.ts +1 -1
  108. package/src/navigation-rail/navigation-rail.ts +2 -6
  109. package/src/peacock-loader.ts +28 -22
  110. package/src/popover/popover-content.ts +1 -1
  111. package/src/search/search.ts +11 -16
  112. package/src/select/option.ts +1 -1
  113. package/src/select/select.scss +1 -10
  114. package/src/select/select.ts +2 -0
  115. package/dist/flow-designer-DvTUrDp5.js +0 -1656
  116. package/dist/flow-designer-DvTUrDp5.js.map +0 -1
  117. package/dist/flow-designer-node-BWrPuxAR.js.map +0 -1
  118. package/dist/icon-button-CK1ZuE-2.js.map +0 -1
  119. package/dist/navigation-rail-DTTkqohi.js.map +0 -1
  120. package/src/chip/chip/chip-colors.scss +0 -31
@@ -1,5 +1,5 @@
1
1
  import { LitElement, html } from 'lit';
2
- import { property, state } from 'lit/decorators.js';
2
+ import { property, query, state } from 'lit/decorators.js';
3
3
 
4
4
  import { isDarkMode } from '@/__utils/is-dark-mode.js';
5
5
  import { observeThemeChange } from '@/__utils/observe-theme-change.js';
@@ -37,7 +37,7 @@ export class Image extends LitElement {
37
37
 
38
38
  @state() private _loaded = false;
39
39
 
40
- @state() private _previewOpen = false;
40
+ @query('.preview-dialog') private _dialog?: HTMLDialogElement;
41
41
 
42
42
  private _intersectionObserver: IntersectionObserver | null = null;
43
43
 
@@ -90,13 +90,15 @@ export class Image extends LitElement {
90
90
 
91
91
  private _handleClick() {
92
92
  if (this.preview) {
93
- this._previewOpen = true;
93
+ this._dialog?.showModal();
94
94
  }
95
95
  }
96
96
 
97
- private _closePreview(e: Event) {
98
- e.stopPropagation();
99
- this._previewOpen = false;
97
+ private _handleDialogClick(e: MouseEvent) {
98
+ // Close when clicking the backdrop (target is the dialog itself, not the image)
99
+ if (e.target === e.currentTarget) {
100
+ (e.currentTarget as HTMLDialogElement).close();
101
+ }
100
102
  }
101
103
 
102
104
  render() {
@@ -112,17 +114,14 @@ export class Image extends LitElement {
112
114
  : html`<span class="placeholder" aria-hidden="true"></span>`}
113
115
  </div>
114
116
 
115
- <!-- Lightbox preview overlay (inside shadow root) -->
116
- <div
117
- class="preview-overlay ${this._previewOpen ? 'open' : ''}"
118
- role="dialog"
119
- aria-modal="true"
117
+ <!-- Lightbox preview dialog uses native top-layer to avoid stacking context issues -->
118
+ <dialog
119
+ class="preview-dialog"
120
120
  aria-label="Image preview"
121
- @click=${this._closePreview}
122
- @keydown=${(e: KeyboardEvent) => e.key === 'Escape' && this._closePreview(e)}
121
+ @click=${this._handleDialogClick}
123
122
  >
124
123
  <img src=${this._activeSrc} alt=${this.imageTitle} @click=${(e: Event) => e.stopPropagation()} />
125
- </div>
124
+ </dialog>
126
125
  `;
127
126
  }
128
127
  }
package/src/index.ts CHANGED
@@ -16,6 +16,7 @@ export { Accordion } from './accordion/index.js';
16
16
  export { Link } from './link/index.js';
17
17
  export { Tag } from './chip/tag/index.js';
18
18
  export { Chip } from './chip/chip/index.js';
19
+ export { ChipSet } from './chip/chip-set/index.js';
19
20
  export { LinearProgress } from './progress/linear-progress/index.js';
20
21
  export { CircularProgress } from './progress/circular-progress/index.js';
21
22
  export { Skeleton } from './skeleton/index.js';
@@ -38,6 +39,7 @@ export { Popover, PopoverContent } from './popover/index.js';
38
39
  export { Breadcrumb, BreadcrumbItem } from './breadcrumb/index.js';
39
40
  export { Menu, MenuItem, SubMenu } from './menu/index.js';
40
41
  export { List, ListItem } from './list/index.js';
42
+ export { Item } from './item/index.js';
41
43
 
42
44
  export { CodeHighlighter } from './code-highlighter/index.js';
43
45
  export { CodeEditor } from './code-editor/index.js';
@@ -79,7 +79,14 @@ export class Input extends BaseInput {
79
79
  @query('.input-element')
80
80
  private inputElement?: HTMLInputElement;
81
81
 
82
- private tabindex?: string;
82
+ override async focus() {
83
+ await Promise.all([
84
+ customElements.whenDefined('wc-input'),
85
+ customElements.whenDefined('wc-field'),
86
+ ]);
87
+ await this.updateComplete;
88
+ this.inputElement?.focus();
89
+ }
83
90
 
84
91
  connectedCallback() {
85
92
  super.connectedCallback();
@@ -87,11 +94,6 @@ export class Input extends BaseInput {
87
94
  }
88
95
 
89
96
  private handleInitialAttributes() {
90
- if (this.hasAttribute('tabindex')) {
91
- this.tabindex = this.getAttribute('tabindex') || undefined;
92
- this.removeAttribute('tabindex');
93
- }
94
-
95
97
  Array.from(this.attributes).forEach(attr => {
96
98
  if (attr.name.startsWith('aria-')) {
97
99
  this.configAria[attr.name] = attr.value;
@@ -105,21 +107,9 @@ export class Input extends BaseInput {
105
107
  this.value = (event.target as HTMLInputElement).value;
106
108
  }
107
109
 
108
- override focus() {
109
- this.inputElement?.focus();
110
- }
111
-
112
- override blur() {
113
- this.inputElement?.blur();
114
- }
115
-
116
- private __handleFocusChange() {
117
- // When calling focus() or reportValidity() during change, it's possible
118
- // for blur to be called after the new focus event. Rather than set
119
- // `this.focused` to true/false on focus/blur, we always set it to whether
120
- // or not the input itself is focused.
121
- this.focused = this.inputElement?.matches(':focus') ?? false;
122
- }
110
+ private __handleFocusChange = (event: FocusEvent) => {
111
+ this.focused = event.type === 'focus';
112
+ };
123
113
 
124
114
  private __redispatchEvent(event: Event) {
125
115
  redispatchEvent(this, event);
@@ -156,7 +146,6 @@ export class Input extends BaseInput {
156
146
  placeholder=${this.placeholder}
157
147
  autocomplete=${this.autocomplete}
158
148
  .value=${this.value}
159
- ?tabindex=${this.tabindex}
160
149
  ?readonly=${this.readonly}
161
150
  ?required=${this.required}
162
151
  ?disabled=${this.disabled}
@@ -169,7 +158,7 @@ export class Input extends BaseInput {
169
158
 
170
159
  ${this.type === 'password'
171
160
  ? html`
172
- <pc-tooltip
161
+ <wc-tooltip
173
162
  slot="field-end"
174
163
  content=${this.passwordVisible
175
164
  ? 'Hide password'
@@ -183,10 +172,12 @@ export class Input extends BaseInput {
183
172
  }}
184
173
  >
185
174
  <wc-icon
186
- name=${this.passwordVisible ? 'visibility_off' : 'visibility'}
175
+ name=${this.passwordVisible
176
+ ? 'visibility_off'
177
+ : 'visibility'}
187
178
  ></wc-icon>
188
179
  </wc-icon-button>
189
- </pc-tooltip>
180
+ </wc-tooltip>
190
181
  `
191
182
  : nothing}
192
183
 
@@ -0,0 +1 @@
1
+ export { Item } from './item.js';
@@ -0,0 +1,184 @@
1
+ @use "../../scss/mixin";
2
+
3
+ @include mixin.base-styles;
4
+
5
+ :host {
6
+ display: block;
7
+ padding-inline: var(--spacing-050);
8
+ --item-height: 3.5rem;
9
+ }
10
+
11
+ /**
12
+ * Reset native button/link styles
13
+ */
14
+ .native-button {
15
+ @include mixin.reset-button-styles;
16
+ }
17
+ .native-link {
18
+ @include mixin.reset-link-styles;
19
+ }
20
+
21
+ .item {
22
+ position: relative;
23
+ min-height: var(--item-height);
24
+ width: 100%;
25
+ background: transparent;
26
+ text-align: initial;
27
+ cursor: pointer;
28
+
29
+ --private-item-container-shape-start-start: var(--item-container-shape-start-start, var(--shape-corner-extra-small));
30
+ --private-item-container-shape-start-end: var(--item-container-shape-start-end, var(--shape-corner-extra-small));
31
+ --private-item-container-shape-end-start: var(--item-container-shape-end-start, var(--shape-corner-extra-small));
32
+ --private-item-container-shape-end-end: var(--item-container-shape-end-end, var(--shape-corner-extra-small));
33
+ --private-item-container-shape-variant: var(--item-container-shape-variant, none);
34
+
35
+ font-family: var(--item-label-font-family, var(--typography-body-large-font-family)) !important;
36
+ font-size: var(--item-label-font-size, var(--typography-body-large-font-size)) !important;
37
+ font-weight: var(--item-label-font-weight, var(--typography-body-large-font-weight)) !important;
38
+ line-height: var(--item-label-line-height, var(--typography-body-large-line-height)) !important;
39
+ letter-spacing: var(--item-label-letter-spacing, var(--typography-body-large-letter-spacing)) !important;
40
+
41
+ .item-content {
42
+ position: relative;
43
+ z-index: 1;
44
+ display: flex;
45
+ align-items: center;
46
+ gap: var(--spacing-200);
47
+ min-height: var(--item-height);
48
+
49
+ padding-inline: var(--spacing-200);
50
+ color: var(--private-item-label-text-color);
51
+ opacity: var(--private-item-label-text-opacity, 1);
52
+ --icon-size: var(--item-icon-size, 1.5rem);
53
+ --icon-color: var(--private-item-leading-trailing-color);
54
+ }
55
+
56
+ .start,
57
+ .end {
58
+ display: inline-flex;
59
+ align-items: center;
60
+ justify-content: center;
61
+ color: var(--private-item-leading-trailing-color);
62
+ }
63
+
64
+ .end {
65
+ margin-inline-start: auto;
66
+ }
67
+
68
+ .content {
69
+ display: flex;
70
+ flex: 1;
71
+ flex-direction: column;
72
+ justify-content: center;
73
+ gap: 0.125rem;
74
+ min-inline-size: 0;
75
+ }
76
+
77
+ .headline-row {
78
+ display: flex;
79
+ min-inline-size: 0;
80
+ }
81
+
82
+ .headline,
83
+ .overline,
84
+ .supporting-text,
85
+ .trailing-supporting-text {
86
+ min-inline-size: 0;
87
+ }
88
+
89
+ .headline {
90
+ flex: 1;
91
+ color: var(--private-item-label-text-color);
92
+ }
93
+
94
+ .overline,
95
+ .supporting-text,
96
+ .trailing-supporting-text {
97
+ color: var(--private-item-supporting-text-color);
98
+ }
99
+
100
+ .overline {
101
+ @include mixin.get-typography(label-small);
102
+ }
103
+
104
+ .supporting-text,
105
+ .trailing-supporting-text {
106
+ @include mixin.get-typography(body-medium);
107
+ }
108
+
109
+ .trailing-supporting-text {
110
+ display: inline-flex;
111
+ align-items: center;
112
+ white-space: nowrap;
113
+ color: var(--private-item-supporting-text-color);
114
+ }
115
+
116
+ .background {
117
+ position: absolute;
118
+ inset: 0;
119
+ background-color: var(--private-item-container-color);
120
+ opacity: var(--private-item-container-opacity, 1);
121
+ pointer-events: none;
122
+
123
+ @include mixin.apply-container-shape(private-item);
124
+ }
125
+
126
+ .focus-ring {
127
+ z-index: 2;
128
+ @include mixin.copy-container-shape(private-item, focus-ring);
129
+
130
+ }
131
+
132
+ .ripple {
133
+ @include mixin.apply-container-shape(private-item);
134
+ --ripple-state-opacity: var(--private-item-container-state-opacity, 0);
135
+ --ripple-pressed-color: var(--private-item-container-state-color);
136
+ }
137
+ }
138
+
139
+ .item {
140
+ --private-item-container-color: var(--item-container-color);
141
+ --private-item-label-text-color: var(--item-label-text-color);
142
+ --private-item-leading-trailing-color: var(--item-leading-trailing-color);
143
+ --private-item-supporting-text-color: var(--item-supporting-text-color);
144
+
145
+ --private-item-container-state-color: var(--private-item-label-text-color);
146
+
147
+ &:hover:not(:where(.disabled, .selected)) {
148
+ --private-item-container-state-opacity: 0.08;
149
+ }
150
+
151
+ &.pressed:not(:where(.disabled)) {
152
+ --private-item-container-state-opacity: 0.12;
153
+ }
154
+
155
+ &.selected {
156
+ --private-item-container-color: var(--item-container-selected-color);
157
+ --private-item-label-text-color: var(--item-label-text-selected-color);
158
+ --private-item-leading-trailing-color: var(--item-label-text-selected-color);
159
+ --private-item-supporting-text-color: var(--item-label-text-selected-color);
160
+ }
161
+
162
+ &.disabled {
163
+ cursor: not-allowed;
164
+ --private-item-label-text-color: var(--color-on-surface);
165
+ --private-item-label-text-opacity: 0.38;
166
+ --private-item-leading-trailing-color: var(--color-on-surface);
167
+ --private-item-supporting-text-color: var(--color-on-surface);
168
+ --private-item-container-opacity: 0.12;
169
+
170
+ .ripple {
171
+ display: none;
172
+ }
173
+ }
174
+ }
175
+
176
+ :host {
177
+ --item-container-color: transparent;
178
+ --item-label-text-color: var(--color-on-surface);
179
+ --item-leading-trailing-color: var(--color-on-surface-variant);
180
+ --item-supporting-text-color: var(--color-on-surface-variant);
181
+
182
+ --item-container-selected-color: var(--color-tertiary-container);
183
+ --item-label-text-selected-color: var(--color-on-tertiary-container);
184
+ }
@@ -0,0 +1,340 @@
1
+ import { html, LitElement, nothing } from 'lit';
2
+ import { property, query, state } from 'lit/decorators.js';
3
+ import { classMap } from 'lit/directives/class-map.js';
4
+ import { ifDefined } from 'lit/directives/if-defined.js';
5
+ import styles from './item.scss';
6
+ import BaseButtonMixin from '@/__mixins/BaseButtonMixin.js';
7
+ import BaseHyperlinkMixin from '@/__mixins/BaseHyperlinkMixin.js';
8
+ import {
9
+ dispatchActivationClick,
10
+ isActivationClick,
11
+ } from '@/__utils/dispatch-event-utils.js';
12
+
13
+ /**
14
+ * @label Item
15
+ * @tag wc-item
16
+ * @rawTag item
17
+ *
18
+ * @summary A Material 3 item with start, text and end slots.
19
+ *
20
+ * @example
21
+ * ```html
22
+ * <wc-item selected>
23
+ * <wc-icon slot="start" name="home"></wc-icon>
24
+ * <div slot="overline">Overline</div>
25
+ * <div slot="headline">Headline</div>
26
+ * <div slot="supporting-text">Supporting text</div>
27
+ * <div slot="trailing-supporting-text">Trailing</div>
28
+ * <wc-icon slot="end" name="chevron_right"></wc-icon>
29
+ * </wc-item>
30
+ * ```
31
+ * @tags display
32
+ */
33
+ export class Item extends BaseButtonMixin(BaseHyperlinkMixin(LitElement)) {
34
+ static styles = [styles];
35
+
36
+ static override get observedAttributes() {
37
+ return [...super.observedAttributes, 'tabindex'];
38
+ }
39
+
40
+ private readonly __contentObserver = new MutationObserver(() => {
41
+ this.requestUpdate();
42
+ });
43
+
44
+ private __capturedTabIndex?: string;
45
+
46
+ private __isCapturingTabIndex = false;
47
+
48
+ @property({ type: Boolean, reflect: true }) selected = false;
49
+
50
+ @query('#item') readonly itemElement!: HTMLElement | null;
51
+
52
+ @state() isPressed = false;
53
+
54
+ private __handleSlotChange = () => {
55
+ this.requestUpdate();
56
+ };
57
+
58
+ private __hasNamedSlot(...names: string[]) {
59
+ return names.some(name =>
60
+ Array.from(this.children).some(child => child.getAttribute('slot') === name),
61
+ );
62
+ }
63
+
64
+ private __hasDefaultSlot() {
65
+ return Array.from(this.childNodes).some(node => {
66
+ if (node.nodeType === Node.TEXT_NODE) {
67
+ return Boolean(node.textContent?.trim());
68
+ }
69
+
70
+ return (
71
+ node.nodeType === Node.ELEMENT_NODE &&
72
+ !(node as Element).hasAttribute('slot')
73
+ );
74
+ });
75
+ }
76
+
77
+ connectedCallback() {
78
+ // eslint-disable-next-line wc/guard-super-call
79
+ super.connectedCallback();
80
+ this.__captureHostTabIndex();
81
+
82
+ this.__contentObserver.observe(this, {
83
+ subtree: true,
84
+ childList: true,
85
+ characterData: true,
86
+ attributes: true,
87
+ attributeFilter: ['slot'],
88
+ });
89
+ }
90
+
91
+ disconnectedCallback() {
92
+ this.__contentObserver.disconnect();
93
+ super.disconnectedCallback();
94
+ }
95
+
96
+ override attributeChangedCallback(
97
+ name: string,
98
+ oldValue: string | null,
99
+ newValue: string | null,
100
+ ) {
101
+ if (name === 'tabindex') {
102
+ if (!this.__isCapturingTabIndex && newValue != null) {
103
+ this.__capturedTabIndex = newValue;
104
+ this.__isCapturingTabIndex = true;
105
+ this.removeAttribute('tabindex');
106
+ this.__isCapturingTabIndex = false;
107
+ this.requestUpdate();
108
+ }
109
+
110
+ return;
111
+ }
112
+
113
+ super.attributeChangedCallback(name, oldValue, newValue);
114
+ }
115
+
116
+ override focus() {
117
+ this.itemElement?.focus();
118
+ }
119
+
120
+ override blur() {
121
+ this.itemElement?.blur();
122
+ }
123
+
124
+ __dispatchClick = (event: MouseEvent | KeyboardEvent) => {
125
+ if (this.softDisabled || (this.disabled && this.href)) {
126
+ event.stopImmediatePropagation();
127
+ event.preventDefault();
128
+ return;
129
+ }
130
+
131
+ if (!isActivationClick(event) || !this.itemElement) {
132
+ return;
133
+ }
134
+
135
+ this.focus();
136
+ dispatchActivationClick(this.itemElement);
137
+ };
138
+
139
+ __handleKeyDown = (event: KeyboardEvent) => {
140
+ this.__handlePress(event);
141
+
142
+ if (this.disabled || this.softDisabled || !this.itemElement) {
143
+ return;
144
+ }
145
+
146
+ if (event.key === ' ') {
147
+ event.preventDefault();
148
+ this.itemElement.click();
149
+ return;
150
+ }
151
+
152
+ if (event.key === 'Enter' && !this.__isLink()) {
153
+ event.preventDefault();
154
+ this.itemElement.click();
155
+ }
156
+ };
157
+
158
+ __handlePress = (event: KeyboardEvent | MouseEvent) => {
159
+ if (this.disabled || this.softDisabled) return;
160
+
161
+ if (
162
+ event instanceof KeyboardEvent &&
163
+ event.type === 'keydown' &&
164
+ (event.key === 'Enter' || event.key === ' ')
165
+ ) {
166
+ this.isPressed = true;
167
+ } else if (event.type === 'mousedown') {
168
+ this.isPressed = true;
169
+ } else {
170
+ this.isPressed = false;
171
+ }
172
+ };
173
+
174
+ private __getForwardedAttribute(name: string) {
175
+ return this.getAttribute(name) ?? undefined;
176
+ }
177
+
178
+ private __captureHostTabIndex() {
179
+ const tabIndex = this.getAttribute('tabindex');
180
+
181
+ if (tabIndex == null) {
182
+ return;
183
+ }
184
+
185
+ this.__capturedTabIndex = tabIndex;
186
+ this.__isCapturingTabIndex = true;
187
+ this.removeAttribute('tabindex');
188
+ this.__isCapturingTabIndex = false;
189
+ }
190
+
191
+ render() {
192
+ const isLink = this.__isLink();
193
+ const role = this.__getForwardedAttribute('role');
194
+ const tabIndex = this.__capturedTabIndex;
195
+ const ariaHasPopup = this.__getForwardedAttribute('aria-haspopup');
196
+ const ariaControls = this.__getForwardedAttribute('aria-controls');
197
+ const ariaExpanded = this.__getForwardedAttribute('aria-expanded');
198
+
199
+ const cssClasses: any = {
200
+ item: true,
201
+ selected: this.selected,
202
+ disabled: this.disabled || this.softDisabled,
203
+ pressed: this.isPressed,
204
+ };
205
+
206
+ if (!isLink) {
207
+ cssClasses['native-button'] = true;
208
+
209
+ return html`
210
+ <button
211
+ id="item"
212
+ class=${classMap(cssClasses)}
213
+ type=${this.htmlType}
214
+ role=${ifDefined(role)}
215
+ tabindex=${ifDefined(tabIndex)}
216
+ ?disabled=${this.disabled}
217
+ ?aria-disabled=${this.softDisabled}
218
+ aria-haspopup=${ifDefined(ariaHasPopup)}
219
+ aria-controls=${ifDefined(ariaControls)}
220
+ aria-expanded=${ifDefined(ariaExpanded)}
221
+ @click=${this.__dispatchClick}
222
+ @mousedown=${this.__handlePress}
223
+ @keydown=${this.__handleKeyDown}
224
+ @keyup=${this.__handlePress}
225
+ >
226
+ ${this.renderContent()}
227
+ </button>
228
+ `;
229
+ } else {
230
+ cssClasses['native-link'] = true;
231
+ return html`
232
+ <a
233
+ id="item"
234
+ class=${classMap(cssClasses)}
235
+ href=${this.href}
236
+ target=${this.target}
237
+ rel=${ifDefined(this.rel)}
238
+ download=${ifDefined(this.download)}
239
+ role=${ifDefined(role)}
240
+ tabindex=${ifDefined(tabIndex ?? (this.disabled ? '-1' : '0'))}
241
+ aria-disabled=${String(this.disabled || this.softDisabled)}
242
+ aria-haspopup=${ifDefined(ariaHasPopup)}
243
+ aria-controls=${ifDefined(ariaControls)}
244
+ aria-expanded=${ifDefined(ariaExpanded)}
245
+ @click=${this.__dispatchClick}
246
+ @mousedown=${this.__handlePress}
247
+ @keydown=${this.__handleKeyDown}
248
+ @keyup=${this.__handlePress}
249
+ >
250
+ ${this.renderContent()}
251
+ </a>
252
+ `;
253
+ }
254
+
255
+
256
+ }
257
+
258
+ renderContent() {
259
+ const hasStart = this.__hasNamedSlot('start');
260
+ const hasEnd = this.__hasNamedSlot('end');
261
+ const hasOverline = this.__hasNamedSlot('overline');
262
+ const hasHeadline = this.__hasNamedSlot('headline');
263
+ const hasDefault = this.__hasDefaultSlot();
264
+ const hasSupportingText = this.__hasNamedSlot('supporting-text');
265
+ const hasTrailingSupportingText = this.__hasNamedSlot(
266
+ 'trailing-supporting-text',
267
+ );
268
+
269
+ return html`
270
+ <wc-focus-ring class="focus-ring" for="item"></wc-focus-ring>
271
+ <div class="background"></div>
272
+ <wc-ripple class="ripple"></wc-ripple>
273
+
274
+ <div class="item-content">
275
+ ${hasStart
276
+ ? html`
277
+ <div class="start">
278
+ <slot name="start" @slotchange=${this.__handleSlotChange}></slot>
279
+ </div>
280
+ `
281
+ : nothing}
282
+ <div class="content">
283
+
284
+ ${hasOverline
285
+ ? html`
286
+ <div class="overline">
287
+ <slot name="overline" @slotchange=${this.__handleSlotChange}></slot>
288
+ </div>
289
+ `
290
+ : nothing}
291
+ ${hasHeadline || hasDefault
292
+ ? html`
293
+ <div class="headline-row">
294
+ ${hasHeadline || hasDefault
295
+ ? html`
296
+ <div class="headline">
297
+ ${hasHeadline
298
+ ? html`<slot name="headline" @slotchange=${this.__handleSlotChange}></slot>`
299
+ : nothing}
300
+ ${hasDefault
301
+ ? html`<slot @slotchange=${this.__handleSlotChange}></slot>`
302
+ : nothing}
303
+ </div>
304
+ `
305
+ : nothing}
306
+ </div>
307
+ `
308
+ : nothing}
309
+ ${hasSupportingText
310
+ ? html`
311
+ <div class="supporting-text">
312
+ <slot
313
+ name="supporting-text"
314
+ @slotchange=${this.__handleSlotChange}
315
+ ></slot>
316
+ </div>
317
+ `
318
+ : nothing}
319
+ </div>
320
+ ${hasTrailingSupportingText
321
+ ? html`
322
+ <div class="trailing-supporting-text">
323
+ <slot
324
+ name="trailing-supporting-text"
325
+ @slotchange=${this.__handleSlotChange}
326
+ ></slot>
327
+ </div>
328
+ `
329
+ : nothing}
330
+ ${hasEnd
331
+ ? html`
332
+ <div class="end">
333
+ <slot name="end" @slotchange=${this.__handleSlotChange}></slot>
334
+ </div>
335
+ `
336
+ : nothing}
337
+ </div>
338
+ `;
339
+ }
340
+ }