@redvars/peacock 3.6.3 → 3.7.0
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.
- package/dist/ButtonConstants-D06bY4uy.js +114 -0
- package/dist/ButtonConstants-D06bY4uy.js.map +1 -0
- package/dist/{BaseHyperlinkMixin-BNuwbiEf.js → NativeHyperlinkMixin-DrYXyfMQ.js} +8 -10
- package/dist/NativeHyperlinkMixin-DrYXyfMQ.js.map +1 -0
- package/dist/assets/components.css +1 -1
- package/dist/assets/components.css.map +1 -1
- package/dist/assets/styles.css +1 -1
- package/dist/assets/styles.css.map +1 -1
- package/dist/{button-colors-Cg6oxiz-.js → button-colors-Dwnez1tR.js} +201 -186
- package/dist/button-colors-Dwnez1tR.js.map +1 -0
- package/dist/button-group.js +8 -8
- package/dist/button-group.js.map +1 -1
- package/dist/button.js +224 -124
- package/dist/button.js.map +1 -1
- package/dist/calendar-column-view.js +0 -1
- package/dist/calendar-column-view.js.map +1 -1
- package/dist/calendar-month-view.js +0 -1
- package/dist/calendar-month-view.js.map +1 -1
- package/dist/card-content.js +0 -1
- package/dist/card-content.js.map +1 -1
- package/dist/card.js +96 -90
- package/dist/card.js.map +1 -1
- package/dist/cb-compound-expression.js +4 -1
- package/dist/cb-compound-expression.js.map +1 -1
- package/dist/cb-divider.js +0 -1
- package/dist/cb-divider.js.map +1 -1
- package/dist/cb-expression.js +0 -2
- package/dist/cb-expression.js.map +1 -1
- package/dist/cb-predicate.js +0 -1
- package/dist/cb-predicate.js.map +1 -1
- package/dist/code-highlighter.js +23 -6
- package/dist/code-highlighter.js.map +1 -1
- package/dist/custom-elements-jsdocs.json +5102 -18408
- package/dist/custom-elements.json +19630 -20205
- package/dist/fab.js +181 -117
- package/dist/fab.js.map +1 -1
- package/dist/{flow-designer-node-9Bqyn6qx.js → flow-designer-node-BWrPuxAR.js} +1 -2
- package/dist/flow-designer-node-BWrPuxAR.js.map +1 -0
- package/dist/flow-designer-node.js +1 -1
- package/dist/flow-designer.js +5 -5
- package/dist/icon-button-DJ0kZXYr.js +318 -0
- package/dist/icon-button-DJ0kZXYr.js.map +1 -0
- package/dist/index.js +8 -8
- package/dist/{navigation-rail-DAUuJ_Yp.js → navigation-rail-CM_svs5_.js} +511 -295
- package/dist/navigation-rail-CM_svs5_.js.map +1 -0
- package/dist/observe-slot-change-D8Xg-kSS.js +60 -0
- package/dist/observe-slot-change-D8Xg-kSS.js.map +1 -0
- package/dist/peacock-loader.js +7 -7
- package/dist/peacock-loader.js.map +1 -1
- package/dist/popover-content.js +0 -1
- package/dist/popover-content.js.map +1 -1
- package/dist/search.js +4 -1
- package/dist/search.js.map +1 -1
- package/dist/src/__controllers/attachable-controller.d.ts +109 -0
- package/dist/src/__mixins/{BaseButtonMixin.d.ts → NativeButtonMixin.d.ts} +3 -3
- package/dist/src/__mixins/{BaseHyperlinkMixin.d.ts → NativeHyperlinkMixin.d.ts} +3 -4
- package/dist/src/__utils/is-link.d.ts +1 -0
- package/dist/src/__utils/observe-slot-change.d.ts +1 -1
- package/dist/src/accordion/accordion-item.d.ts +0 -1
- package/dist/src/breadcrumb/breadcrumb-item/breadcrumb-item.d.ts +0 -1
- package/dist/src/button/ButtonConstants.d.ts +1 -0
- package/dist/src/button/GroupButtonInterface.d.ts +4 -0
- package/dist/src/button/button/button.d.ts +32 -7
- package/dist/src/button/button-group/button-group.d.ts +2 -1
- package/dist/src/button/icon-button/icon-button.d.ts +26 -5
- package/dist/src/button/index.d.ts +1 -1
- package/dist/src/calendar/calendar-column-view.d.ts +0 -1
- package/dist/src/calendar/calendar-month-view.d.ts +0 -1
- package/dist/src/card/card-content.d.ts +0 -1
- package/dist/src/card/card.d.ts +9 -6
- package/dist/src/chip/chip/chip.d.ts +22 -3
- package/dist/src/condition-builder/cb-compound-expression.d.ts +0 -1
- package/dist/src/condition-builder/cb-divider.d.ts +0 -1
- package/dist/src/condition-builder/cb-expression.d.ts +0 -1
- package/dist/src/condition-builder/cb-predicate.d.ts +0 -1
- package/dist/src/fab/fab.d.ts +20 -6
- package/dist/src/flow-designer/flow-designer-node.d.ts +0 -1
- package/dist/src/focus-ring/focus-ring.d.ts +26 -20
- package/dist/src/item/item.d.ts +2 -1
- package/dist/src/link/link.d.ts +1 -1
- package/dist/src/list/list-item.d.ts +1 -2
- package/dist/src/menu/menu-item/menu-item.d.ts +1 -2
- package/dist/src/menu/sub-menu/sub-menu.d.ts +0 -1
- package/dist/src/navigation-rail/navigation-rail-item.d.ts +0 -2
- package/dist/src/popover/popover-content.d.ts +0 -1
- package/dist/src/ripple/ripple.d.ts +9 -1
- package/dist/src/segmented-button/segmented-button.d.ts +0 -1
- package/dist/src/select/option.d.ts +0 -1
- package/dist/src/sidebar-menu/sidebar-menu-item.d.ts +0 -1
- package/dist/src/sidebar-menu/sidebar-sub-menu.d.ts +0 -1
- package/dist/src/tabs/tab-panel.d.ts +0 -1
- package/dist/src/tabs/tab.d.ts +4 -6
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -2
- package/readme.md +2 -2
- package/scss/components.scss +0 -1
- package/scss/mixin.scss +10 -13
- package/scss/styles.scss +1 -3
- package/src/__controllers/attachable-controller.ts +198 -0
- package/src/__mixins/NativeButtonMixin.ts +87 -0
- package/src/__mixins/{BaseHyperlinkMixin.ts → NativeHyperlinkMixin.ts} +15 -15
- package/src/__utils/is-link.ts +3 -0
- package/src/__utils/observe-slot-change.ts +46 -14
- package/src/accordion/accordion-item.scss +1 -1
- package/src/accordion/accordion-item.ts +0 -1
- package/src/breadcrumb/breadcrumb-item/breadcrumb-item.ts +0 -1
- package/src/button/ButtonConstants.ts +1 -0
- package/src/button/GroupButtonInterface.ts +4 -0
- package/src/button/button/button-colors.scss +2 -2
- package/src/button/button/button-layers.scss +124 -0
- package/src/button/button/button-sizes.scss +20 -42
- package/src/button/button/button.scss +72 -169
- package/src/button/button/button.ts +229 -78
- package/src/button/button/only-button.scss +13 -0
- package/src/button/button-group/button-group.ts +59 -17
- package/src/button/icon-button/icon-button-sizes.scss +6 -21
- package/src/button/icon-button/icon-button.ts +198 -93
- package/src/button/index.ts +1 -1
- package/src/calendar/calendar-column-view.ts +0 -1
- package/src/calendar/calendar-month-view.ts +0 -1
- package/src/card/card-content.ts +2 -3
- package/src/card/card.scss +87 -95
- package/src/card/card.ts +62 -60
- package/src/chip/chip/chip.scss +65 -70
- package/src/chip/chip/chip.ts +155 -56
- package/src/code-highlighter/code-highlighter.scss +1 -1
- package/src/code-highlighter/code-highlighter.ts +20 -5
- package/src/condition-builder/cb-compound-expression.scss +4 -0
- package/src/condition-builder/cb-compound-expression.ts +0 -1
- package/src/condition-builder/cb-divider.ts +0 -1
- package/src/condition-builder/cb-expression.scss +0 -1
- package/src/condition-builder/cb-expression.ts +0 -1
- package/src/condition-builder/cb-predicate.ts +0 -1
- package/src/elevation/elevation.scss +5 -1
- package/src/fab/fab-colors.scss +2 -2
- package/src/fab/fab-sizes.scss +24 -34
- package/src/fab/fab.scss +77 -71
- package/src/fab/fab.ts +141 -65
- package/src/flow-designer/flow-designer-node.ts +0 -1
- package/src/focus-ring/focus-ring.ts +81 -72
- package/src/item/item.scss +77 -66
- package/src/item/item.ts +61 -39
- package/src/link/link.scss +1 -10
- package/src/link/link.ts +4 -2
- package/src/list/list-item.ts +8 -8
- package/src/menu/menu-item/menu-item.ts +17 -8
- package/src/menu/sub-menu/sub-menu.ts +0 -1
- package/src/navigation-rail/navigation-rail-item.scss +5 -0
- package/src/navigation-rail/navigation-rail-item.ts +10 -15
- package/src/peacock-loader.ts +1 -1
- package/src/popover/popover-content.ts +0 -1
- package/src/ripple/ripple.ts +52 -20
- package/src/search/search.scss +3 -0
- package/src/segmented-button/segmented-button.ts +0 -1
- package/src/select/option.ts +0 -1
- package/src/sidebar-menu/sidebar-menu-item.ts +0 -1
- package/src/sidebar-menu/sidebar-sub-menu.ts +0 -1
- package/src/skeleton/skeleton.scss +5 -1
- package/src/tabs/tab-panel.ts +0 -1
- package/src/tabs/tab.ts +60 -70
- package/src/text/text.css-component.scss +3 -21
- package/src/tooltip/tooltip.scss +5 -8
- package/src/tooltip/tooltip.ts +1 -2
- package/dist/BaseButton-BNFAYn-S.js +0 -219
- package/dist/BaseButton-BNFAYn-S.js.map +0 -1
- package/dist/BaseHyperlinkMixin-BNuwbiEf.js.map +0 -1
- package/dist/button-colors-Cg6oxiz-.js.map +0 -1
- package/dist/flow-designer-node-9Bqyn6qx.js.map +0 -1
- package/dist/icon-button-AdJBEoNy.js +0 -251
- package/dist/icon-button-AdJBEoNy.js.map +0 -1
- package/dist/navigation-rail-DAUuJ_Yp.js.map +0 -1
- package/dist/observe-slot-change-BGJfgg2E.js +0 -31
- package/dist/observe-slot-change-BGJfgg2E.js.map +0 -1
- package/dist/src/button/BaseButton.d.ts +0 -28
- package/dist/src/focus-ring/FocusAttachableController.d.ts +0 -8
- package/src/__mixins/BaseButtonMixin.ts +0 -83
- package/src/button/BaseButton.ts +0 -113
- package/src/focus-ring/FocusAttachableController.ts +0 -28
- package/src/popover/tooltip.css-component.scss +0 -19
|
@@ -1,15 +1,26 @@
|
|
|
1
|
-
import { html } from 'lit';
|
|
2
|
-
import { property
|
|
1
|
+
import { html, LitElement, nothing } from 'lit';
|
|
2
|
+
import { property } from 'lit/decorators.js';
|
|
3
3
|
import { classMap } from 'lit/directives/class-map.js';
|
|
4
4
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
5
|
+
import { when } from 'lit/directives/when.js';
|
|
5
6
|
import IndividualComponent from '@/IndividualComponent.js';
|
|
6
7
|
import styles from './button.scss';
|
|
8
|
+
import onlyButton from './only-button.scss';
|
|
9
|
+
import buttonLayers from './button-layers.scss';
|
|
7
10
|
import colorStyles from './button-colors.scss';
|
|
8
11
|
import sizeStyles from './button-sizes.scss';
|
|
9
|
-
import { observerSlotChangesWithCallback } from '@/__utils/observe-slot-change.js';
|
|
10
12
|
import { throttle } from '@/__utils/throttle.js';
|
|
11
13
|
import { spread } from '@/__directive/spread.js';
|
|
12
|
-
import {
|
|
14
|
+
import { isLink } from '@/__utils/is-link.js';
|
|
15
|
+
import { observerSlotChangesWithCallback } from '@/__utils/observe-slot-change.js';
|
|
16
|
+
import NativeButtonMixin from '@/__mixins/NativeButtonMixin.js';
|
|
17
|
+
import NativeHyperlinkMixin from '@/__mixins/NativeHyperlinkMixin.js';
|
|
18
|
+
import { GroupButtonInterface } from '@/button/GroupButtonInterface.js';
|
|
19
|
+
import {
|
|
20
|
+
dispatchActivationClick,
|
|
21
|
+
isActivationClick,
|
|
22
|
+
} from '@/__utils/dispatch-event-utils.js';
|
|
23
|
+
import { DISABLED_REASON_ID } from '@/button/ButtonConstants.js';
|
|
13
24
|
|
|
14
25
|
/**
|
|
15
26
|
* @label Button
|
|
@@ -54,15 +65,24 @@ import { BaseButton } from '../BaseButton.js';
|
|
|
54
65
|
* @tags display
|
|
55
66
|
*/
|
|
56
67
|
@IndividualComponent
|
|
57
|
-
export class Button
|
|
58
|
-
|
|
68
|
+
export class Button
|
|
69
|
+
extends NativeButtonMixin(NativeHyperlinkMixin(LitElement))
|
|
70
|
+
implements GroupButtonInterface
|
|
71
|
+
{
|
|
72
|
+
static override styles = [
|
|
73
|
+
buttonLayers,
|
|
74
|
+
styles,
|
|
75
|
+
onlyButton,
|
|
76
|
+
sizeStyles,
|
|
77
|
+
colorStyles,
|
|
78
|
+
];
|
|
59
79
|
|
|
60
80
|
/**
|
|
61
81
|
* Icon alignment.
|
|
62
82
|
* Possible values are `"start"`, `"end"`. Defaults to `"end"`.
|
|
63
83
|
*/
|
|
64
|
-
@property({ attribute: 'icon
|
|
65
|
-
|
|
84
|
+
@property({ type: Boolean, reflect: true, attribute: 'trailing-icon' })
|
|
85
|
+
trailingIcon = false;
|
|
66
86
|
|
|
67
87
|
/**
|
|
68
88
|
* Button size.
|
|
@@ -71,9 +91,9 @@ export class Button extends BaseButton {
|
|
|
71
91
|
@property({ reflect: true }) size: 'xs' | 'sm' | 'md' | 'lg' | 'xl' = 'sm';
|
|
72
92
|
|
|
73
93
|
/**
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
94
|
+
* Type is preset of color and variant. Type will be only applied.
|
|
95
|
+
*
|
|
96
|
+
*/
|
|
77
97
|
@property({ type: String }) type?: 'primary' | 'secondary' | 'tertiary';
|
|
78
98
|
|
|
79
99
|
/**
|
|
@@ -86,7 +106,7 @@ export class Button extends BaseButton {
|
|
|
86
106
|
* `"tonal"` is a light color button.
|
|
87
107
|
* `"elevated"` is elevated button
|
|
88
108
|
*/
|
|
89
|
-
@property() variant:
|
|
109
|
+
@property({ reflect: true }) variant:
|
|
90
110
|
| 'elevated'
|
|
91
111
|
| 'filled'
|
|
92
112
|
| 'tonal'
|
|
@@ -111,15 +131,12 @@ export class Button extends BaseButton {
|
|
|
111
131
|
@property({ reflect: true })
|
|
112
132
|
configAria?: { [key: string]: any };
|
|
113
133
|
|
|
114
|
-
@state()
|
|
115
|
-
private slotHasContent = false;
|
|
116
|
-
|
|
117
134
|
override focus() {
|
|
118
|
-
this.
|
|
135
|
+
this.getControl()?.focus();
|
|
119
136
|
}
|
|
120
137
|
|
|
121
138
|
override blur() {
|
|
122
|
-
this.
|
|
139
|
+
this.getControl()?.blur();
|
|
123
140
|
}
|
|
124
141
|
|
|
125
142
|
override firstUpdated() {
|
|
@@ -127,15 +144,34 @@ export class Button extends BaseButton {
|
|
|
127
144
|
this.__dispatchClick,
|
|
128
145
|
this.throttleDelay,
|
|
129
146
|
);
|
|
130
|
-
observerSlotChangesWithCallback(
|
|
131
|
-
this.renderRoot.querySelector('slot'),
|
|
132
|
-
hasContent => {
|
|
133
|
-
this.slotHasContent = hasContent;
|
|
134
|
-
this.requestUpdate();
|
|
135
|
-
},
|
|
136
|
-
);
|
|
137
147
|
|
|
138
148
|
this.__convertTypeToVariantAndColor();
|
|
149
|
+
// Initialize slot presence tracking for smooth transitions when label/icon are added/removed
|
|
150
|
+
const iconSlot = this.renderRoot.querySelector(
|
|
151
|
+
'slot[name="icon"]',
|
|
152
|
+
) as HTMLSlotElement | null;
|
|
153
|
+
const labelSlot = this.renderRoot.querySelector(
|
|
154
|
+
'slot.label',
|
|
155
|
+
) as HTMLSlotElement | null;
|
|
156
|
+
|
|
157
|
+
// Use MutationObserver-based helper so we react to content/character changes
|
|
158
|
+
if (iconSlot) {
|
|
159
|
+
this.__iconSlotCleanup = observerSlotChangesWithCallback(
|
|
160
|
+
iconSlot,
|
|
161
|
+
has => {
|
|
162
|
+
this.toggleAttribute('has-icon', has);
|
|
163
|
+
},
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (labelSlot) {
|
|
168
|
+
this.__labelSlotCleanup = observerSlotChangesWithCallback(
|
|
169
|
+
labelSlot,
|
|
170
|
+
has => {
|
|
171
|
+
this.toggleAttribute('has-label', has);
|
|
172
|
+
},
|
|
173
|
+
);
|
|
174
|
+
}
|
|
139
175
|
}
|
|
140
176
|
|
|
141
177
|
__convertTypeToVariantAndColor() {
|
|
@@ -155,85 +191,200 @@ export class Button extends BaseButton {
|
|
|
155
191
|
}
|
|
156
192
|
|
|
157
193
|
override render() {
|
|
194
|
+
const buttonId = isLink(this) ? 'link' : 'button';
|
|
195
|
+
|
|
196
|
+
return html`
|
|
197
|
+
<wc-focus-ring class="focus-ring" for=${buttonId}></wc-focus-ring>
|
|
198
|
+
<wc-elevation class="elevation"></wc-elevation>
|
|
199
|
+
${when(
|
|
200
|
+
this.variant === 'neo',
|
|
201
|
+
() => html`<div class="neo-background"></div>`,
|
|
202
|
+
)}
|
|
203
|
+
<div class="background"></div>
|
|
204
|
+
${when(
|
|
205
|
+
this.variant === 'outlined' || this.variant === 'neo',
|
|
206
|
+
() => html`<div class="outline"></div>`,
|
|
207
|
+
)}
|
|
208
|
+
<wc-ripple class="ripple" for=${buttonId}></wc-ripple>
|
|
209
|
+
<wc-skeleton class="skeleton"></wc-skeleton>
|
|
210
|
+
|
|
211
|
+
${this.renderButtonElement()} ${this.__renderTooltip()}
|
|
212
|
+
`;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
renderButtonElement() {
|
|
216
|
+
const isElementLink = isLink(this);
|
|
158
217
|
|
|
159
218
|
const cssClasses: any = {
|
|
160
219
|
button: true,
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
disabled: this.disabled || this.softDisabled,
|
|
165
|
-
pressed: this.isPressed,
|
|
166
|
-
'has-content': this.slotHasContent,
|
|
167
|
-
'show-skeleton': this.skeleton,
|
|
168
|
-
[`icon-align-${this.iconAlign}`]: true,
|
|
220
|
+
'native-button': !isElementLink,
|
|
221
|
+
'native-link': isElementLink,
|
|
222
|
+
'trailing-icon': this.trailingIcon,
|
|
169
223
|
};
|
|
170
224
|
|
|
171
|
-
if (
|
|
172
|
-
cssClasses['native-button'] = true;
|
|
173
|
-
|
|
174
|
-
return html`<button
|
|
175
|
-
class=${classMap(cssClasses)}
|
|
176
|
-
id="button"
|
|
177
|
-
type=${this.htmlType}
|
|
178
|
-
@click=${this.__dispatchClickWithThrottle}
|
|
179
|
-
@mousedown=${this.__handlePress}
|
|
180
|
-
@keydown=${this.__handlePress}
|
|
181
|
-
@keyup=${this.__handlePress}
|
|
182
|
-
|
|
183
|
-
aria-describedby=${ifDefined(this.softDisabled ? BaseButton.DISABLED_REASON_ID : undefined)}
|
|
184
|
-
?aria-disabled=${this.softDisabled}
|
|
185
|
-
|
|
186
|
-
?disabled=${this.disabled}
|
|
187
|
-
${spread(this.configAria)}
|
|
188
|
-
>
|
|
189
|
-
${this.renderButtonContent()}
|
|
190
|
-
</button>
|
|
191
|
-
${this.__renderTooltip()}`;
|
|
192
|
-
} else {
|
|
193
|
-
cssClasses['native-link'] = true;
|
|
225
|
+
if (isElementLink) {
|
|
194
226
|
return html`<a
|
|
195
227
|
class=${classMap(cssClasses)}
|
|
196
|
-
id="
|
|
228
|
+
id="link"
|
|
197
229
|
href=${this.href}
|
|
198
230
|
target=${this.target}
|
|
199
231
|
tabindex=${this.disabled ? '-1' : '0'}
|
|
200
|
-
|
|
201
232
|
@click=${this.__dispatchClick}
|
|
202
233
|
@mousedown=${this.__handlePress}
|
|
203
234
|
@keydown=${this.__handlePress}
|
|
204
235
|
@keyup=${this.__handlePress}
|
|
205
236
|
role="button"
|
|
206
|
-
|
|
207
|
-
|
|
237
|
+
aria-describedby=${ifDefined(
|
|
238
|
+
this.softDisabled ? DISABLED_REASON_ID : undefined,
|
|
239
|
+
)}
|
|
208
240
|
?aria-disabled=${this.softDisabled}
|
|
209
|
-
|
|
210
241
|
${spread(this.configAria)}
|
|
211
242
|
>
|
|
212
243
|
${this.renderButtonContent()}
|
|
213
|
-
</a
|
|
214
|
-
${this.__renderTooltip()}`;
|
|
244
|
+
</a>`;
|
|
215
245
|
}
|
|
246
|
+
return html`<button
|
|
247
|
+
class=${classMap(cssClasses)}
|
|
248
|
+
id="button"
|
|
249
|
+
type=${this.htmlType}
|
|
250
|
+
@click=${this.__dispatchClickWithThrottle}
|
|
251
|
+
@mousedown=${this.__handlePress}
|
|
252
|
+
@keydown=${this.__handlePress}
|
|
253
|
+
@keyup=${this.__handlePress}
|
|
254
|
+
aria-describedby=${ifDefined(
|
|
255
|
+
this.softDisabled ? DISABLED_REASON_ID : undefined,
|
|
256
|
+
)}
|
|
257
|
+
?aria-disabled=${this.softDisabled}
|
|
258
|
+
?disabled=${this.disabled}
|
|
259
|
+
${spread(this.configAria)}
|
|
260
|
+
>
|
|
261
|
+
${this.renderButtonContent()}
|
|
262
|
+
</button>
|
|
263
|
+
${this.__renderTooltip()}`;
|
|
216
264
|
}
|
|
217
265
|
|
|
218
266
|
renderButtonContent() {
|
|
219
|
-
return html`
|
|
220
|
-
<
|
|
221
|
-
<
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
<wc-ripple class="ripple"></wc-ripple>
|
|
226
|
-
<wc-skeleton class="skeleton"></wc-skeleton>
|
|
267
|
+
return html` <slot class="icon-slot" name="icon"></slot>
|
|
268
|
+
<slot class="label"></slot>
|
|
269
|
+
<div class="touch"></div>
|
|
270
|
+
|
|
271
|
+
${this.__renderDisabledReason(this.softDisabled)}`;
|
|
272
|
+
}
|
|
227
273
|
|
|
228
|
-
|
|
229
|
-
<div class="slot-container">
|
|
230
|
-
<slot></slot>
|
|
231
|
-
</div>
|
|
274
|
+
@property({ type: Boolean, reflect: true }) skeleton: boolean = false;
|
|
232
275
|
|
|
233
|
-
|
|
234
|
-
</div>
|
|
276
|
+
@property({ type: Boolean, reflect: true }) toggle: boolean = false;
|
|
235
277
|
|
|
236
|
-
|
|
237
|
-
|
|
278
|
+
@property({ type: Boolean, reflect: true }) selected: boolean = false;
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Sets the delay for throttle in milliseconds. Defaults to 200 milliseconds.
|
|
282
|
+
*/
|
|
283
|
+
@property() throttleDelay = 200;
|
|
284
|
+
|
|
285
|
+
@property() tooltip?: string;
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* States
|
|
289
|
+
*/
|
|
290
|
+
@property({ type: Boolean, reflect: true })
|
|
291
|
+
pressed = false;
|
|
292
|
+
|
|
293
|
+
// Query the internal control (button or link) on demand instead of
|
|
294
|
+
// keeping a persistent query reference.
|
|
295
|
+
|
|
296
|
+
// cleanup functions returned by observerSlotChangesWithCallback
|
|
297
|
+
private __iconSlotCleanup: (() => void) | null = null;
|
|
298
|
+
|
|
299
|
+
private __labelSlotCleanup: (() => void) | null = null;
|
|
300
|
+
|
|
301
|
+
override connectedCallback() {
|
|
302
|
+
super.connectedCallback();
|
|
303
|
+
this.addEventListener('click', this.__dispatchClickWithThrottle);
|
|
304
|
+
window.addEventListener('mouseup', this.__handlePress);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
override disconnectedCallback() {
|
|
308
|
+
// disconnect slot observers first to avoid callbacks during teardown
|
|
309
|
+
try {
|
|
310
|
+
this.__iconSlotCleanup?.();
|
|
311
|
+
} catch (e) {
|
|
312
|
+
/* ignore */
|
|
313
|
+
}
|
|
314
|
+
try {
|
|
315
|
+
this.__labelSlotCleanup?.();
|
|
316
|
+
} catch (e) {
|
|
317
|
+
/* ignore */
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
window.removeEventListener('mouseup', this.__handlePress);
|
|
321
|
+
this.removeEventListener('click', this.__dispatchClickWithThrottle);
|
|
322
|
+
super.disconnectedCallback();
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
__handlePress = (event: KeyboardEvent | MouseEvent) => {
|
|
326
|
+
if (this.disabled || this.skeleton || this.softDisabled) return;
|
|
327
|
+
this.pressed =
|
|
328
|
+
(event instanceof KeyboardEvent &&
|
|
329
|
+
event.type === 'keydown' &&
|
|
330
|
+
(event.key === 'Enter' || event.key === ' ')) ||
|
|
331
|
+
event.type === 'mousedown';
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
__dispatchClickWithThrottle: (event: MouseEvent | KeyboardEvent) => void =
|
|
335
|
+
event => {
|
|
336
|
+
this.__dispatchClick(event);
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
__dispatchClick = (event: MouseEvent | KeyboardEvent) => {
|
|
340
|
+
// If the button is soft-disabled or a disabled link, we need to explicitly
|
|
341
|
+
// prevent the click from propagating to other event listeners as well as
|
|
342
|
+
// prevent the default action.
|
|
343
|
+
if (this.softDisabled || (this.disabled && this.href) || this.skeleton) {
|
|
344
|
+
event.stopImmediatePropagation();
|
|
345
|
+
event.preventDefault();
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const control = this.getControl();
|
|
350
|
+
|
|
351
|
+
if (!isActivationClick(event) || !control) {
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
if (this.toggle) {
|
|
356
|
+
this.selected = !this.selected;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
this.focus();
|
|
360
|
+
dispatchActivationClick(control);
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
private getControl(): HTMLElement | null {
|
|
364
|
+
return (
|
|
365
|
+
(this.renderRoot?.querySelector('#button') as HTMLElement | null) ??
|
|
366
|
+
(this.renderRoot?.querySelector('#link') as HTMLElement | null)
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
__renderDisabledReason(softDisabled: boolean) {
|
|
371
|
+
if (softDisabled)
|
|
372
|
+
return html`<div
|
|
373
|
+
id=${DISABLED_REASON_ID}
|
|
374
|
+
role="tooltip"
|
|
375
|
+
aria-label=${this.disabledReason}
|
|
376
|
+
class="screen-reader-only"
|
|
377
|
+
>
|
|
378
|
+
${this.disabledReason}
|
|
379
|
+
</div>`;
|
|
380
|
+
return nothing;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
__renderTooltip() {
|
|
384
|
+
if (this.tooltip) {
|
|
385
|
+
const buttonId = isLink(this) ? 'link' : 'button';
|
|
386
|
+
return html`<wc-tooltip class="tooltip" for=${buttonId}>${this.tooltip}</wc-tooltip>`;
|
|
387
|
+
}
|
|
388
|
+
return nothing;
|
|
238
389
|
}
|
|
239
390
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
|
|
2
|
+
/* When both icon and label are present, apply the configured spacing */
|
|
3
|
+
:host([has-icon][has-label]) .button {
|
|
4
|
+
gap: var(--private-button-icon-label-spacing);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
:host(:not([trailing-icon])) .button {
|
|
8
|
+
flex-direction: row;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
:host([trailing-icon]) .button {
|
|
12
|
+
flex-direction: row-reverse;
|
|
13
|
+
}
|
|
@@ -5,7 +5,7 @@ import IndividualComponent from '@/IndividualComponent.js';
|
|
|
5
5
|
import styles from './button-group.scss';
|
|
6
6
|
import { Button } from '../button/button.js';
|
|
7
7
|
import { IconButton } from '../icon-button/icon-button.js';
|
|
8
|
-
import {
|
|
8
|
+
import type { GroupButtonInterface } from '@/button/GroupButtonInterface.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* @label Button Group
|
|
@@ -25,7 +25,7 @@ import { BaseButton } from '../BaseButton.js';
|
|
|
25
25
|
* @tags controls
|
|
26
26
|
*/
|
|
27
27
|
@IndividualComponent
|
|
28
|
-
|
|
28
|
+
class ButtonGroup extends LitElement {
|
|
29
29
|
// Lit prefers CSS-in-JS for better performance and scoping.
|
|
30
30
|
// If you prefer keeping the SCSS file, you'll need a build tool (like Vite or Webpack)
|
|
31
31
|
// that can import .scss files as lit-css.
|
|
@@ -57,19 +57,29 @@ export class ButtonGroup extends LitElement {
|
|
|
57
57
|
* `"vertical"` stacks buttons in a column.
|
|
58
58
|
* Defaults to `"horizontal"`.
|
|
59
59
|
*/
|
|
60
|
-
@property({ reflect: true }) orientation: 'horizontal' | 'vertical' =
|
|
60
|
+
@property({ reflect: true }) orientation: 'horizontal' | 'vertical' =
|
|
61
|
+
'horizontal';
|
|
61
62
|
|
|
62
63
|
/**
|
|
63
64
|
* Color applied to all buttons in the group.
|
|
64
65
|
* Possible values are `"primary"`, `"success"`, `"danger"`, `"warning"`, `"surface"`, `"on-surface"`.
|
|
65
66
|
*/
|
|
66
|
-
@property({ reflect: true }) color?:
|
|
67
|
+
@property({ reflect: true }) color?:
|
|
68
|
+
| 'primary'
|
|
69
|
+
| 'success'
|
|
70
|
+
| 'danger'
|
|
71
|
+
| 'warning'
|
|
72
|
+
| 'surface'
|
|
73
|
+
| 'on-surface';
|
|
67
74
|
|
|
68
75
|
/**
|
|
69
76
|
* Visual style applied to all buttons in the group.
|
|
70
77
|
* Possible values are `"filled"`, `"tonal"`, `"outlined"`.
|
|
71
78
|
*/
|
|
72
|
-
@property({ attribute: 'button-variant', reflect: true }) buttonVariant?:
|
|
79
|
+
@property({ attribute: 'button-variant', reflect: true }) buttonVariant?:
|
|
80
|
+
| 'filled'
|
|
81
|
+
| 'tonal'
|
|
82
|
+
| 'outlined';
|
|
73
83
|
|
|
74
84
|
override updated() {
|
|
75
85
|
this._syncChildren();
|
|
@@ -90,18 +100,21 @@ export class ButtonGroup extends LitElement {
|
|
|
90
100
|
const isOnly = children.length === 1;
|
|
91
101
|
|
|
92
102
|
if (this.color && 'color' in child) {
|
|
93
|
-
(child as
|
|
103
|
+
(child as GroupButtonInterface).color = this.color;
|
|
94
104
|
}
|
|
95
105
|
|
|
96
106
|
if (this.buttonVariant && 'variant' in child) {
|
|
97
|
-
(child as
|
|
107
|
+
(child as GroupButtonInterface).variant = this.buttonVariant;
|
|
98
108
|
}
|
|
99
109
|
|
|
100
110
|
if (this.variant === 'connected') {
|
|
101
111
|
child.style.setProperty('--button-container-shape-variant', 'round');
|
|
102
112
|
|
|
103
113
|
if (isOnly) {
|
|
104
|
-
child.style.setProperty(
|
|
114
|
+
child.style.setProperty(
|
|
115
|
+
'--button-container-shape',
|
|
116
|
+
'var(--shape-corner-full)',
|
|
117
|
+
);
|
|
105
118
|
child.style.removeProperty('--button-container-shape-start-start');
|
|
106
119
|
child.style.removeProperty('--button-container-shape-end-start');
|
|
107
120
|
child.style.removeProperty('--button-container-shape-start-end');
|
|
@@ -116,10 +129,22 @@ export class ButtonGroup extends LitElement {
|
|
|
116
129
|
child.style.removeProperty('--button-container-shape-end-end');
|
|
117
130
|
} else {
|
|
118
131
|
// Left button in horizontal group: round left corners, standard right corners
|
|
119
|
-
child.style.setProperty(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
132
|
+
child.style.setProperty(
|
|
133
|
+
'--button-container-shape-start-start',
|
|
134
|
+
'calc(var(--button-height) / 2)',
|
|
135
|
+
);
|
|
136
|
+
child.style.setProperty(
|
|
137
|
+
'--button-container-shape-end-start',
|
|
138
|
+
'calc(var(--button-height) / 2)',
|
|
139
|
+
);
|
|
140
|
+
child.style.setProperty(
|
|
141
|
+
'--button-container-shape-start-end',
|
|
142
|
+
'var(--shape-corner-medium)',
|
|
143
|
+
);
|
|
144
|
+
child.style.setProperty(
|
|
145
|
+
'--button-container-shape-end-end',
|
|
146
|
+
'var(--shape-corner-medium)',
|
|
147
|
+
);
|
|
123
148
|
}
|
|
124
149
|
} else if (isLast) {
|
|
125
150
|
child.style.removeProperty('--button-container-shape');
|
|
@@ -131,14 +156,29 @@ export class ButtonGroup extends LitElement {
|
|
|
131
156
|
child.style.removeProperty('--button-container-shape-end-end');
|
|
132
157
|
} else {
|
|
133
158
|
// Right button in horizontal group: standard left corners, round right corners
|
|
134
|
-
child.style.setProperty(
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
159
|
+
child.style.setProperty(
|
|
160
|
+
'--button-container-shape-start-start',
|
|
161
|
+
'var(--shape-corner-medium)',
|
|
162
|
+
);
|
|
163
|
+
child.style.setProperty(
|
|
164
|
+
'--button-container-shape-end-start',
|
|
165
|
+
'var(--shape-corner-medium)',
|
|
166
|
+
);
|
|
167
|
+
child.style.setProperty(
|
|
168
|
+
'--button-container-shape-start-end',
|
|
169
|
+
'calc(var(--button-height) / 2)',
|
|
170
|
+
);
|
|
171
|
+
child.style.setProperty(
|
|
172
|
+
'--button-container-shape-end-end',
|
|
173
|
+
'calc(var(--button-height) / 2)',
|
|
174
|
+
);
|
|
138
175
|
}
|
|
139
176
|
} else {
|
|
140
177
|
// Middle buttons: standard rounded corners on all sides
|
|
141
|
-
child.style.setProperty(
|
|
178
|
+
child.style.setProperty(
|
|
179
|
+
'--button-container-shape',
|
|
180
|
+
'var(--shape-corner-medium)',
|
|
181
|
+
);
|
|
142
182
|
child.style.removeProperty('--button-container-shape-start-start');
|
|
143
183
|
child.style.removeProperty('--button-container-shape-end-start');
|
|
144
184
|
child.style.removeProperty('--button-container-shape-start-end');
|
|
@@ -169,3 +209,5 @@ export class ButtonGroup extends LitElement {
|
|
|
169
209
|
`;
|
|
170
210
|
}
|
|
171
211
|
}
|
|
212
|
+
|
|
213
|
+
export default ButtonGroup;
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
@use '../../../scss/mixin';
|
|
2
2
|
|
|
3
|
+
.button .icon-slot {
|
|
4
|
+
overflow: initial;
|
|
5
|
+
}
|
|
6
|
+
|
|
3
7
|
.button {
|
|
4
|
-
--private-button-container-padding: 0.75rem;
|
|
5
8
|
width: var(--button-height);
|
|
9
|
+
|
|
10
|
+
--private-button-container-padding: 0.75rem;
|
|
6
11
|
--private-button-container-padding: 0;
|
|
7
12
|
}
|
|
8
13
|
|
|
9
14
|
:host([size='xs']),
|
|
10
15
|
:host([size='extra-small']) {
|
|
11
16
|
--button-height: 2rem;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
:host([size='xs']) .button,
|
|
15
|
-
:host([size='extra-small']) .button {
|
|
16
17
|
--private-button-icon-size: 1rem;
|
|
17
18
|
}
|
|
18
19
|
|
|
@@ -20,38 +21,22 @@
|
|
|
20
21
|
:host([size='sm']),
|
|
21
22
|
:host([size='small']) {
|
|
22
23
|
--button-height: 2.5rem;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
:host([size='sm']) .button,
|
|
26
|
-
:host([size='small']) .button {
|
|
27
24
|
--private-button-icon-size: 1.25rem;
|
|
28
|
-
--private-button-icon-label-spacing: 0.5rem;
|
|
29
25
|
}
|
|
30
26
|
|
|
31
27
|
:host([size='md']),
|
|
32
28
|
:host([size='medium']) {
|
|
33
29
|
--button-height: 3.5rem;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
:host([size='md']) .button,
|
|
37
|
-
:host([size='medium']) .button {
|
|
38
30
|
--private-button-icon-size: 1.5rem;
|
|
39
31
|
}
|
|
40
32
|
|
|
41
33
|
:host([size='lg']),
|
|
42
34
|
:host([size='large']) {
|
|
43
35
|
--button-height: 6rem;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
:host([size='lg']) .button,
|
|
47
|
-
:host([size='large']) .button {
|
|
48
36
|
--private-button-icon-size: 2rem;
|
|
49
37
|
}
|
|
50
38
|
|
|
51
39
|
:host([size='xl']) {
|
|
52
40
|
--button-height: 8.5rem;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
:host([size='xl']) .button {
|
|
56
41
|
--private-button-icon-size: 2.5rem;
|
|
57
42
|
}
|