@ds-mo/ui 2.11.2 → 2.13.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/README.md +13 -13
- package/dist/.build-stamp +1 -1
- package/dist/components/ds-app-shell.js +1 -1
- package/dist/components/ds-banner.js +1 -1
- package/dist/components/ds-banner.js.map +1 -1
- package/dist/components/ds-bar-nav.js +1 -1
- package/dist/components/ds-bar-nav.js.map +1 -1
- package/dist/components/ds-button-filled.js +1 -1
- package/dist/components/{ds-accordion.d.ts → ds-button-unfilled.d.ts} +4 -4
- package/dist/components/ds-button-unfilled.js +2 -0
- package/dist/components/{ds-card-data-viz.d.ts → ds-card-data-viz-donut.d.ts} +4 -4
- package/dist/components/ds-card-data-viz-donut.js +2 -0
- package/dist/components/ds-card-data-viz-donut.js.map +1 -0
- package/dist/components/ds-card-setting.js +1 -1
- package/dist/components/ds-card-setting.js.map +1 -1
- package/dist/components/{ds-fade.d.ts → ds-card.d.ts} +4 -4
- package/dist/components/ds-card.js +2 -0
- package/dist/components/ds-card.js.map +1 -0
- package/dist/components/ds-chart-bar.js +1 -1
- package/dist/components/ds-chart-bar.js.map +1 -1
- package/dist/components/ds-chart-donut.js +1 -1
- package/dist/components/ds-chart-donut.js.map +1 -1
- package/dist/components/ds-chart-legend.js +1 -1
- package/dist/components/ds-chart-legend.js.map +1 -1
- package/dist/components/ds-chart-line.js +1 -1
- package/dist/components/ds-checkbox.js +1 -1
- package/dist/components/ds-checkbox.js.map +1 -1
- package/dist/components/ds-chip.js +1 -1
- package/dist/components/ds-chip.js.map +1 -1
- package/dist/components/ds-empty-state.js +1 -1
- package/dist/components/ds-empty-state.js.map +1 -1
- package/dist/components/ds-field.js +1 -1
- package/dist/components/ds-icon.js +1 -1
- package/dist/components/ds-input.js +1 -1
- package/dist/components/ds-input.js.map +1 -1
- package/dist/components/ds-loader.js +1 -1
- package/dist/components/ds-loader.js.map +1 -1
- package/dist/components/ds-menu.js +1 -1
- package/dist/components/ds-modal.js +1 -1
- package/dist/components/ds-pagination.js +1 -1
- package/dist/components/ds-pagination.js.map +1 -1
- package/dist/components/ds-panel-nav.js +1 -1
- package/dist/components/ds-panel-nav.js.map +1 -1
- package/dist/components/ds-panel-tools.js +1 -1
- package/dist/components/ds-panel-tools.js.map +1 -1
- package/dist/components/ds-radio-group.js +1 -1
- package/dist/components/ds-radio-group.js.map +1 -1
- package/dist/components/ds-select.js +1 -1
- package/dist/components/ds-select.js.map +1 -1
- package/dist/components/ds-shell-gradient-picker.js +1 -1
- package/dist/components/ds-shell-gradient-swatch.js +1 -1
- package/dist/components/ds-skeleton.js +1 -1
- package/dist/components/ds-skeleton.js.map +1 -1
- package/dist/components/ds-slider.js +1 -1
- package/dist/components/ds-slider.js.map +1 -1
- package/dist/components/ds-tab-group-nav.js +1 -1
- package/dist/components/ds-tab-group.js +1 -1
- package/dist/components/ds-tab-group.js.map +1 -1
- package/dist/components/ds-table.js +1 -1
- package/dist/components/ds-table.js.map +1 -1
- package/dist/components/ds-tag.js +1 -1
- package/dist/components/ds-tag.js.map +1 -1
- package/dist/components/ds-text.js +1 -1
- package/dist/components/ds-toggle.js +1 -1
- package/dist/components/ds-toggle.js.map +1 -1
- package/dist/components/ds-tooltip-data-viz.js +1 -1
- package/dist/components/ds-tooltip-data-viz.js.map +1 -1
- package/dist/components/ds-tooltip.js +1 -1
- package/dist/components/ds-tooltip.js.map +1 -1
- package/dist/components/p-1m8r0wFg.js +2 -0
- package/dist/components/p-1m8r0wFg.js.map +1 -0
- package/dist/components/p-3FLHei19.js +2 -0
- package/dist/components/p-3FLHei19.js.map +1 -0
- package/dist/components/p-B2_D4IDN.js +2 -0
- package/dist/components/p-B2_D4IDN.js.map +1 -0
- package/dist/components/p-B5NcWtpp.js +2 -0
- package/dist/components/p-B5NcWtpp.js.map +1 -0
- package/dist/components/{p-8Nt92j1-.js → p-B82KZX9D.js} +2 -2
- package/dist/components/p-BQq26pt9.js.map +1 -1
- package/dist/components/p-B_g8X0eh.js +2 -0
- package/dist/components/p-B_g8X0eh.js.map +1 -0
- package/dist/components/{p-DdFUTZ3y.js → p-Be3PHv34.js} +2 -2
- package/dist/components/p-CQmf2CeW.js +2 -0
- package/dist/components/p-CQmf2CeW.js.map +1 -0
- package/dist/components/{p-DOU4cbpc.js → p-CtwNUCnp.js} +2 -2
- package/dist/components/p-CuRjYmBk.js +2 -0
- package/dist/components/p-CuRjYmBk.js.map +1 -0
- package/dist/components/p-CwARVsZQ.js +2 -0
- package/dist/components/p-CwARVsZQ.js.map +1 -0
- package/dist/components/p-DohXlNCJ.js +2 -0
- package/dist/components/p-DohXlNCJ.js.map +1 -0
- package/dist/components/p-DuFm-ieS.js +2 -0
- package/dist/components/p-DuFm-ieS.js.map +1 -0
- package/dist/components/p-EK1hOP19.js.map +1 -1
- package/dist/lib/nav/index.js +3 -0
- package/dist/lib/nav/index.js.map +2 -2
- package/dist/lib/utils/control-width.d.ts +4 -0
- package/dist/lib/utils/index.d.ts +2 -0
- package/dist/lib/utils/index.js +20 -1
- package/dist/lib/utils/index.js.map +3 -3
- package/dist/lib/utils/token-defaults.d.ts +7 -0
- package/dist/types/components/ButtonFilled/ButtonFilled.d.ts +21 -3
- package/dist/types/components/ButtonFilled/index.d.ts +1 -1
- package/dist/types/components/ButtonUnfilled/ButtonUnfilled.d.ts +70 -0
- package/dist/types/components/ButtonUnfilled/index.d.ts +2 -0
- package/dist/types/components/Card/Card.d.ts +20 -0
- package/dist/types/components/Card/index.d.ts +2 -0
- package/dist/types/components/CardDataVizDonut/CardDataVizDonut.d.ts +26 -0
- package/dist/types/components/CardDataVizDonut/index.d.ts +2 -0
- package/dist/types/components/CardSetting/CardSetting.d.ts +7 -2
- package/dist/types/components/ChartDonut/ChartDonut.d.ts +31 -1
- package/dist/types/components/Checkbox/Checkbox.d.ts +1 -1
- package/dist/types/components/Chip/Chip.d.ts +18 -14
- package/dist/types/components/Chip/index.d.ts +1 -1
- package/dist/types/components/Input/Input.d.ts +1 -1
- package/dist/types/components/Pagination/Pagination.d.ts +1 -1
- package/dist/types/components/PanelNav/PanelNav.d.ts +2 -0
- package/dist/types/components/PanelTools/panel-tools-types.d.ts +1 -1
- package/dist/types/components/RadioGroup/RadioGroup.d.ts +2 -2
- package/dist/types/components/Select/Select.d.ts +34 -2
- package/dist/types/components/Select/index.d.ts +2 -0
- package/dist/types/components/ShellGradientSwatch/ShellGradientSwatch.d.ts +1 -1
- package/dist/types/components/Slider/Slider.d.ts +1 -1
- package/dist/types/components/TabGroup/TabGroup.d.ts +1 -1
- package/dist/types/components/TabGroup/tab-item-utils.d.ts +2 -1
- package/dist/types/components/TabGroupNav/TabGroupNav.d.ts +1 -1
- package/dist/types/components/Tag/Tag.d.ts +0 -2
- package/dist/types/components/Tag/index.d.ts +1 -1
- package/dist/types/components/Toggle/Toggle.d.ts +1 -1
- package/dist/types/components/Tooltip/Tooltip.d.ts +25 -6
- package/dist/types/components/TooltipDataViz/TooltipDataViz.d.ts +18 -0
- package/dist/types/components.d.ts +474 -576
- package/dist/types/utils/control-width.d.ts +5 -0
- package/dist/types/utils/index.d.ts +2 -0
- package/dist/types/utils/token-defaults.d.ts +7 -0
- package/package.json +7 -4
- package/src/angular/index.ts +3 -9
- package/src/angular/proxies.ts +62 -215
- package/src/react/components.ts +3 -9
- package/src/react/ds-button-unfilled.ts +33 -0
- package/src/react/ds-card-data-viz-donut.ts +27 -0
- package/src/react/{ds-fade.ts → ds-card.ts} +7 -7
- package/src/react/ds-chip.ts +2 -10
- package/src/wc/components/BarNav/BarNav.tsx +3 -2
- package/src/wc/components/BarNav/bar-nav-tabs-menu-utils.ts +1 -1
- package/src/wc/components/ButtonFilled/ButtonFilled.tsx +97 -11
- package/src/wc/components/ButtonFilled/index.ts +7 -1
- package/src/wc/components/ButtonUnfilled/ButtonUnfilled.tsx +230 -0
- package/src/wc/components/ButtonUnfilled/index.ts +7 -0
- package/src/wc/components/Card/Card.tsx +79 -0
- package/src/wc/components/Card/index.ts +1 -0
- package/src/wc/components/{CardDataViz/CardDataViz.tsx → CardDataVizDonut/CardDataVizDonut.tsx} +47 -41
- package/src/wc/components/CardDataVizDonut/index.ts +1 -0
- package/src/wc/components/CardSetting/CardSetting.tsx +21 -36
- package/src/wc/components/ChartDonut/ChartDonut.tsx +159 -11
- package/src/wc/components/ChartLegend/ChartLegend.tsx +3 -0
- package/src/wc/components/Checkbox/Checkbox.tsx +5 -5
- package/src/wc/components/Chip/Chip.tsx +50 -67
- package/src/wc/components/Chip/index.ts +1 -1
- package/src/wc/components/Input/Input.tsx +4 -4
- package/src/wc/components/Menu/Menu.tsx +7 -4
- package/src/wc/components/Pagination/Pagination.tsx +6 -6
- package/src/wc/components/PanelNav/PanelNav.tsx +77 -48
- package/src/wc/components/PanelTools/PanelTools.tsx +19 -16
- package/src/wc/components/PanelTools/panel-tools-types.ts +1 -1
- package/src/wc/components/PanelTools/panel-tools-utils.ts +1 -1
- package/src/wc/components/RadioGroup/RadioGroup.tsx +7 -7
- package/src/wc/components/Select/Select.tsx +145 -64
- package/src/wc/components/Select/index.ts +1 -0
- package/src/wc/components/ShellGradientSwatch/ShellGradientSwatch.tsx +4 -3
- package/src/wc/components/Slider/Slider.tsx +7 -3
- package/src/wc/components/TabGroup/TabGroup.tsx +13 -7
- package/src/wc/components/TabGroup/tab-item-utils.ts +2 -1
- package/src/wc/components/TabGroupNav/TabGroupNav.tsx +14 -13
- package/src/wc/components/Tag/Tag.tsx +25 -24
- package/src/wc/components/Tag/index.ts +1 -1
- package/src/wc/components/Toggle/Toggle.tsx +6 -6
- package/src/wc/components/Tooltip/Tooltip.tsx +166 -64
- package/src/wc/components/TooltipDataViz/TooltipDataViz.tsx +57 -2
- package/src/wc/components.d.ts +474 -579
- package/src/wc/utils/control-density.css +42 -0
- package/src/wc/utils/control-inactive.css +20 -0
- package/src/wc/utils/control-width.css +28 -0
- package/src/wc/utils/control-width.ts +10 -0
- package/src/wc/utils/index.ts +2 -0
- package/src/wc/utils/interaction-fill.css +162 -0
- package/src/wc/utils/scroll-edge-fade.css +5 -0
- package/src/wc/utils/token-defaults.ts +10 -0
- package/dist/components/ds-accordion.js +0 -2
- package/dist/components/ds-accordion.js.map +0 -1
- package/dist/components/ds-breadcrumb.d.ts +0 -11
- package/dist/components/ds-breadcrumb.js +0 -2
- package/dist/components/ds-breadcrumb.js.map +0 -1
- package/dist/components/ds-button-unfilled-icon.d.ts +0 -11
- package/dist/components/ds-button-unfilled-icon.js +0 -2
- package/dist/components/ds-card-data-viz.js +0 -2
- package/dist/components/ds-card-data-viz.js.map +0 -1
- package/dist/components/ds-fade.js +0 -2
- package/dist/components/ds-fade.js.map +0 -1
- package/dist/components/ds-header.d.ts +0 -11
- package/dist/components/ds-header.js +0 -2
- package/dist/components/ds-header.js.map +0 -1
- package/dist/components/ds-scrollbar.d.ts +0 -11
- package/dist/components/ds-scrollbar.js +0 -2
- package/dist/components/ds-scrollbar.js.map +0 -1
- package/dist/components/ds-surface.d.ts +0 -11
- package/dist/components/ds-surface.js +0 -2
- package/dist/components/ds-surface.js.map +0 -1
- package/dist/components/ds-toast-provider.d.ts +0 -11
- package/dist/components/ds-toast-provider.js +0 -2
- package/dist/components/ds-toast-provider.js.map +0 -1
- package/dist/components/p-BMQbEIrQ.js +0 -2
- package/dist/components/p-BMQbEIrQ.js.map +0 -1
- package/dist/components/p-BSFgy5r6.js +0 -2
- package/dist/components/p-BSFgy5r6.js.map +0 -1
- package/dist/components/p-CBUIn8dk.js +0 -2
- package/dist/components/p-CBUIn8dk.js.map +0 -1
- package/dist/components/p-ChVwCVHy.js +0 -2
- package/dist/components/p-ChVwCVHy.js.map +0 -1
- package/dist/components/p-CpNIQXz6.js +0 -2
- package/dist/components/p-CpNIQXz6.js.map +0 -1
- package/dist/components/p-CvgHQfvT.js +0 -2
- package/dist/components/p-CvgHQfvT.js.map +0 -1
- package/dist/components/p-bDf6yBQd.js +0 -2
- package/dist/components/p-bDf6yBQd.js.map +0 -1
- package/dist/types/components/Accordion/Accordion.d.ts +0 -28
- package/dist/types/components/Breadcrumb/Breadcrumb.d.ts +0 -16
- package/dist/types/components/ButtonUnfilledIcon/ButtonUnfilledIcon.d.ts +0 -45
- package/dist/types/components/ButtonUnfilledIcon/index.d.ts +0 -2
- package/dist/types/components/CardDataViz/CardDataViz.d.ts +0 -22
- package/dist/types/components/CardDataViz/index.d.ts +0 -2
- package/dist/types/components/Fade/Fade.d.ts +0 -22
- package/dist/types/components/Fade/index.d.ts +0 -2
- package/dist/types/components/Header/Header.d.ts +0 -7
- package/dist/types/components/Scrollbar/Scrollbar.d.ts +0 -27
- package/dist/types/components/Surface/Surface.d.ts +0 -22
- package/dist/types/components/Toast/Toast.d.ts +0 -16
- package/dist/types/components/Toast/toast-service.d.ts +0 -24
- package/src/react/ds-accordion.ts +0 -27
- package/src/react/ds-breadcrumb.ts +0 -27
- package/src/react/ds-button-unfilled-icon.ts +0 -33
- package/src/react/ds-card-data-viz.ts +0 -26
- package/src/react/ds-header.ts +0 -26
- package/src/react/ds-scrollbar.ts +0 -26
- package/src/react/ds-surface.ts +0 -26
- package/src/react/ds-toast-provider.ts +0 -26
- package/src/wc/components/Accordion/Accordion.tsx +0 -144
- package/src/wc/components/Breadcrumb/Breadcrumb.tsx +0 -61
- package/src/wc/components/ButtonUnfilledIcon/ButtonUnfilledIcon.tsx +0 -129
- package/src/wc/components/ButtonUnfilledIcon/index.ts +0 -1
- package/src/wc/components/CardDataViz/index.ts +0 -1
- package/src/wc/components/Fade/Fade.tsx +0 -58
- package/src/wc/components/Fade/index.ts +0 -1
- package/src/wc/components/Header/Header.tsx +0 -33
- package/src/wc/components/Scrollbar/Scrollbar.tsx +0 -189
- package/src/wc/components/Surface/Surface.tsx +0 -81
- package/src/wc/components/Toast/Toast.tsx +0 -179
- package/src/wc/components/Toast/toast-service.ts +0 -67
- /package/dist/components/{ds-button-unfilled-icon.js.map → ds-button-unfilled.js.map} +0 -0
- /package/dist/components/{p-8Nt92j1-.js.map → p-B82KZX9D.js.map} +0 -0
- /package/dist/components/{p-DdFUTZ3y.js.map → p-Be3PHv34.js.map} +0 -0
- /package/dist/components/{p-DOU4cbpc.js.map → p-CtwNUCnp.js.map} +0 -0
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { Component, Prop, State, Event, EventEmitter, Element, Watch, Listen, h, Host } from '@stencil/core';
|
|
2
|
+
import { controlWidthClass, type ControlWidth } from '../../utils/control-width';
|
|
3
|
+
import { resolveCssLengthPx, TOKEN_DEFAULTS } from '../../utils';
|
|
2
4
|
import type { MenuItemData } from '../Menu/menu-types';
|
|
3
5
|
|
|
4
6
|
export interface SelectOption {
|
|
@@ -6,6 +8,28 @@ export interface SelectOption {
|
|
|
6
8
|
value: string;
|
|
7
9
|
}
|
|
8
10
|
|
|
11
|
+
export type SelectSize = 'md' | 'sm' | 'xs';
|
|
12
|
+
|
|
13
|
+
export type SelectWidth = ControlWidth;
|
|
14
|
+
|
|
15
|
+
/** Regular (non-emphasis) type per density — selects stay visually lighter than buttons. */
|
|
16
|
+
const TEXT_VARIANT: Record<SelectSize, string> = {
|
|
17
|
+
md: 'text-body-medium',
|
|
18
|
+
sm: 'text-body-small',
|
|
19
|
+
xs: 'text-caption',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/** `ds-icon` size matching control-density icon metrics. */
|
|
23
|
+
const ICON_SIZE: Record<SelectSize, 'md' | 'sm' | 'xs'> = {
|
|
24
|
+
md: 'md',
|
|
25
|
+
sm: 'sm',
|
|
26
|
+
xs: 'xs',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Dropdown select — unfilled-button chrome (label + trailing ChevronDown) in
|
|
31
|
+
* control-density sizes, with `ds-menu` for the option list.
|
|
32
|
+
*/
|
|
9
33
|
@Component({
|
|
10
34
|
tag: 'ds-select',
|
|
11
35
|
styleUrl: 'Select.css',
|
|
@@ -24,10 +48,27 @@ export class Select {
|
|
|
24
48
|
@Prop({ mutable: true }) value: string = '';
|
|
25
49
|
|
|
26
50
|
/** Placeholder shown when no value is selected. */
|
|
27
|
-
@Prop() placeholder: string = 'Select
|
|
51
|
+
@Prop() placeholder: string = 'Select';
|
|
52
|
+
|
|
53
|
+
/** Control density (height, padding, icon, type). */
|
|
54
|
+
@Prop() size: SelectSize = 'md';
|
|
28
55
|
|
|
29
|
-
/**
|
|
30
|
-
@Prop()
|
|
56
|
+
/** Width fit — fill the parent (default) or hug content. */
|
|
57
|
+
@Prop() width: SelectWidth = 'fill';
|
|
58
|
+
|
|
59
|
+
/** Disables interaction (25% opacity via ds-control-inactive). */
|
|
60
|
+
@Prop() isInactive: boolean = false;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* When a value is selected, render the selected interaction fill (same recipe
|
|
64
|
+
* as unfilled-button `activeFill`). Default `true`. Pass `false` for
|
|
65
|
+
* foreground-only selection (primary label, no fill).
|
|
66
|
+
* Selected/open promotes the label to primary; chevron stays secondary.
|
|
67
|
+
*/
|
|
68
|
+
@Prop() activeFill: boolean = true;
|
|
69
|
+
|
|
70
|
+
/** Show a 1px secondary inset border. Default on (matches unfilled button). */
|
|
71
|
+
@Prop() hasBorder: boolean = true;
|
|
31
72
|
|
|
32
73
|
@Prop({ attribute: 'aria-label' }) ariaLabel: string | undefined;
|
|
33
74
|
@Prop({ attribute: 'aria-labelledby' }) ariaLabelledby: string | undefined;
|
|
@@ -39,32 +80,28 @@ export class Select {
|
|
|
39
80
|
|
|
40
81
|
private triggerEl: HTMLButtonElement | null = null;
|
|
41
82
|
private menuEl: HTMLDsMenuElement | null = null;
|
|
83
|
+
/** True when the open was keyboard-driven — menu shows initial focus ring. */
|
|
84
|
+
private openWithFocusVisible = false;
|
|
42
85
|
|
|
43
86
|
componentDidLoad() {
|
|
44
|
-
// Wire up the menu anchor to the trigger button
|
|
45
87
|
if (this.menuEl && this.triggerEl) {
|
|
46
88
|
this.menuEl.anchor = this.triggerEl;
|
|
47
89
|
}
|
|
48
|
-
|
|
49
|
-
this.menuEl?.addEventListener('
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
});
|
|
57
|
-
// Listen for menu close event
|
|
58
|
-
this.menuEl?.addEventListener('dsClose', () => {
|
|
59
|
-
this.isOpen = false;
|
|
60
|
-
});
|
|
90
|
+
this.menuEl?.addEventListener('dsSelect', this.handleMenuSelect);
|
|
91
|
+
this.menuEl?.addEventListener('dsClose', this.handleMenuClose);
|
|
92
|
+
this.syncMenuItems();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
disconnectedCallback() {
|
|
96
|
+
this.menuEl?.removeEventListener('dsSelect', this.handleMenuSelect);
|
|
97
|
+
this.menuEl?.removeEventListener('dsClose', this.handleMenuClose);
|
|
61
98
|
}
|
|
62
99
|
|
|
63
100
|
@Watch('isOpen')
|
|
64
101
|
onIsOpenChange(open: boolean) {
|
|
65
|
-
if (this.menuEl)
|
|
66
|
-
|
|
67
|
-
|
|
102
|
+
if (!this.menuEl) return;
|
|
103
|
+
this.menuEl.initialFocusVisible = open && this.openWithFocusVisible;
|
|
104
|
+
this.menuEl.open = open;
|
|
68
105
|
}
|
|
69
106
|
|
|
70
107
|
@Watch('options')
|
|
@@ -77,6 +114,19 @@ export class Select {
|
|
|
77
114
|
this.syncMenuItems();
|
|
78
115
|
}
|
|
79
116
|
|
|
117
|
+
private handleMenuSelect = (e: Event) => {
|
|
118
|
+
const detail = (e as CustomEvent<MenuItemData>).detail;
|
|
119
|
+
if (detail?.value !== undefined) {
|
|
120
|
+
this.value = String(detail.value);
|
|
121
|
+
this.dsChange.emit(this.value);
|
|
122
|
+
}
|
|
123
|
+
this.close();
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
private handleMenuClose = () => {
|
|
127
|
+
this.close();
|
|
128
|
+
};
|
|
129
|
+
|
|
80
130
|
private syncMenuItems() {
|
|
81
131
|
if (!this.menuEl) return;
|
|
82
132
|
this.menuEl.items = this.options.map(opt => ({
|
|
@@ -86,32 +136,46 @@ export class Select {
|
|
|
86
136
|
}));
|
|
87
137
|
}
|
|
88
138
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
139
|
+
/**
|
|
140
|
+
* Size/place the menu so option labels line up with the select label.
|
|
141
|
+
* Menu section padding insets items; we expand min-width by that chrome and
|
|
142
|
+
* shift left by the same amount (`alignOffset`). Menu can grow wider than
|
|
143
|
+
* the field (left-bottom / `align="start"`) when labels need more room.
|
|
144
|
+
*/
|
|
145
|
+
private syncMenuLayout() {
|
|
146
|
+
if (!this.menuEl || !this.triggerEl) return;
|
|
147
|
+
const sectionPadPx = resolveCssLengthPx(TOKEN_DEFAULTS.space050, TOKEN_DEFAULTS.space050);
|
|
148
|
+
const triggerW = this.triggerEl.offsetWidth;
|
|
149
|
+
// Prefer min-width over fixed width so long options can grow the menu.
|
|
150
|
+
this.menuEl.menuWidth = '';
|
|
151
|
+
this.menuEl.minWidth = `${triggerW + sectionPadPx * 2}px`;
|
|
152
|
+
this.menuEl.alignOffset = -sectionPadPx;
|
|
153
|
+
this.menuEl.anchor = this.triggerEl;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
private open(opts: { focusVisible: boolean } = { focusVisible: false }) {
|
|
157
|
+
if (this.isInactive || !this.options.length) return;
|
|
158
|
+
this.openWithFocusVisible = opts.focusVisible;
|
|
159
|
+
this.syncMenuLayout();
|
|
96
160
|
this.syncMenuItems();
|
|
97
161
|
this.isOpen = true;
|
|
98
162
|
}
|
|
99
163
|
|
|
100
164
|
private close() {
|
|
101
165
|
this.isOpen = false;
|
|
166
|
+
this.openWithFocusVisible = false;
|
|
102
167
|
}
|
|
103
168
|
|
|
104
|
-
private toggle() {
|
|
169
|
+
private toggle(opts: { focusVisible: boolean }) {
|
|
105
170
|
if (this.isOpen) {
|
|
106
171
|
this.close();
|
|
107
172
|
} else {
|
|
108
|
-
this.open();
|
|
173
|
+
this.open(opts);
|
|
109
174
|
}
|
|
110
175
|
}
|
|
111
176
|
|
|
112
177
|
@Listen('keydown')
|
|
113
178
|
handleKeyDown(e: KeyboardEvent) {
|
|
114
|
-
// Only handle keydown on the trigger button
|
|
115
179
|
if (document.activeElement !== this.triggerEl) return;
|
|
116
180
|
|
|
117
181
|
if (!this.isOpen) {
|
|
@@ -121,67 +185,84 @@ export class Select {
|
|
|
121
185
|
case 'Enter':
|
|
122
186
|
case ' ':
|
|
123
187
|
e.preventDefault();
|
|
124
|
-
this.open();
|
|
188
|
+
this.open({ focusVisible: true });
|
|
125
189
|
break;
|
|
126
190
|
}
|
|
127
|
-
} else {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
this.triggerEl?.focus();
|
|
132
|
-
}
|
|
191
|
+
} else if (e.key === 'Escape') {
|
|
192
|
+
e.preventDefault();
|
|
193
|
+
this.close();
|
|
194
|
+
this.triggerEl?.focus();
|
|
133
195
|
}
|
|
134
196
|
}
|
|
135
197
|
|
|
136
198
|
private get selectedLabel(): string {
|
|
137
|
-
|
|
138
|
-
return found?.label ?? '';
|
|
199
|
+
return this.options.find(o => o.value === this.value)?.label ?? '';
|
|
139
200
|
}
|
|
140
201
|
|
|
141
202
|
private get hasSelection(): boolean {
|
|
142
|
-
return
|
|
203
|
+
return this.options.some(o => o.value === this.value);
|
|
143
204
|
}
|
|
144
205
|
|
|
145
206
|
render() {
|
|
146
|
-
const label = this.hasSelection ? this.selectedLabel : this.placeholder;
|
|
147
207
|
const showPlaceholder = !this.hasSelection;
|
|
208
|
+
const hasValue = !showPlaceholder;
|
|
209
|
+
const label = showPlaceholder ? this.placeholder : this.selectedLabel;
|
|
210
|
+
const textVariant = TEXT_VARIANT[this.size];
|
|
211
|
+
const iconSize = ICON_SIZE[this.size];
|
|
212
|
+
const density = `ds-control--${this.size}`;
|
|
213
|
+
// Selected fill when a value is set (or while open), gated by `activeFill`.
|
|
214
|
+
const showSelectedFill =
|
|
215
|
+
!this.isInactive && this.activeFill && (hasValue || this.isOpen);
|
|
148
216
|
|
|
149
217
|
return (
|
|
150
|
-
<Host
|
|
218
|
+
<Host
|
|
219
|
+
class={{
|
|
220
|
+
'select-host': true,
|
|
221
|
+
'ds-control-inactive': this.isInactive,
|
|
222
|
+
'ds-control--md': this.size === 'md',
|
|
223
|
+
'ds-control--sm': this.size === 'sm',
|
|
224
|
+
'ds-control--xs': this.size === 'xs',
|
|
225
|
+
...controlWidthClass(this.width),
|
|
226
|
+
}}
|
|
227
|
+
>
|
|
151
228
|
<button
|
|
152
229
|
ref={el => {
|
|
153
230
|
this.triggerEl = (el as HTMLButtonElement) ?? null;
|
|
154
231
|
}}
|
|
155
232
|
type="button"
|
|
156
|
-
class={{
|
|
157
|
-
|
|
233
|
+
class={{
|
|
234
|
+
trigger: true,
|
|
235
|
+
'ds-focus-ring-inset': true,
|
|
236
|
+
'ds-interaction-fill': true,
|
|
237
|
+
'ds-interaction-fill--selected': showSelectedFill,
|
|
238
|
+
'trigger--open': this.isOpen,
|
|
239
|
+
'trigger--bordered': this.hasBorder,
|
|
240
|
+
'trigger--placeholder': showPlaceholder,
|
|
241
|
+
'trigger--has-value': hasValue,
|
|
242
|
+
[density]: true,
|
|
243
|
+
}}
|
|
244
|
+
disabled={this.isInactive}
|
|
158
245
|
role="combobox"
|
|
159
|
-
aria-haspopup="
|
|
160
|
-
aria-expanded={this.isOpen}
|
|
246
|
+
aria-haspopup="menu"
|
|
247
|
+
aria-expanded={String(this.isOpen)}
|
|
161
248
|
aria-label={this.ariaLabel}
|
|
162
249
|
aria-labelledby={this.ariaLabelledby}
|
|
163
|
-
onClick={() => this.toggle()}
|
|
250
|
+
onClick={() => this.toggle({ focusVisible: false })}
|
|
164
251
|
>
|
|
165
|
-
<span
|
|
252
|
+
<span
|
|
253
|
+
class={{
|
|
254
|
+
'trigger__label': true,
|
|
255
|
+
[textVariant]: true,
|
|
256
|
+
'ds-interaction-fill__content': true,
|
|
257
|
+
}}
|
|
258
|
+
>
|
|
166
259
|
{label}
|
|
167
260
|
</span>
|
|
168
|
-
<
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
height="16"
|
|
172
|
-
viewBox="0 0 16 16"
|
|
173
|
-
fill="none"
|
|
174
|
-
aria-hidden="true"
|
|
175
|
-
>
|
|
176
|
-
<path
|
|
177
|
-
d="M4 6L8 10L12 6"
|
|
178
|
-
stroke="currentColor"
|
|
179
|
-
stroke-width="1.25"
|
|
180
|
-
stroke-linecap="round"
|
|
181
|
-
stroke-linejoin="round"
|
|
182
|
-
/>
|
|
183
|
-
</svg>
|
|
261
|
+
<span class="trigger__chevron ds-interaction-fill__content" aria-hidden="true">
|
|
262
|
+
<ds-icon name="ChevronDown" size={iconSize} color="inherit" />
|
|
263
|
+
</span>
|
|
184
264
|
</button>
|
|
265
|
+
{/* bottom + start: left-aligned under the field; wider menus grow right. */}
|
|
185
266
|
<ds-menu
|
|
186
267
|
ref={el => {
|
|
187
268
|
this.menuEl = (el as HTMLDsMenuElement) ?? null;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type { SelectOption, SelectSize, SelectWidth } from './Select';
|
|
@@ -19,14 +19,14 @@ export class ShellGradientSwatch {
|
|
|
19
19
|
/** Selected — brand stroke + halo over inner fill/border/interaction stack. */
|
|
20
20
|
@Prop({ reflect: true }) selected = false;
|
|
21
21
|
|
|
22
|
-
@Prop()
|
|
22
|
+
@Prop() isInactive = false;
|
|
23
23
|
|
|
24
24
|
@Prop({ attribute: 'aria-label' }) ariaLabel: string | undefined;
|
|
25
25
|
|
|
26
26
|
@Event() dsSelect!: EventEmitter<ShellGradientPreset>;
|
|
27
27
|
|
|
28
28
|
private handleClick = () => {
|
|
29
|
-
if (this.
|
|
29
|
+
if (this.isInactive) return;
|
|
30
30
|
this.dsSelect.emit(this.preset);
|
|
31
31
|
};
|
|
32
32
|
|
|
@@ -40,6 +40,7 @@ export class ShellGradientSwatch {
|
|
|
40
40
|
class={{
|
|
41
41
|
'shell-gradient-swatch': true,
|
|
42
42
|
'ds-focus-ring-inset': true,
|
|
43
|
+
'ds-control-inactive': this.isInactive,
|
|
43
44
|
'shell-gradient-swatch--selected': this.selected,
|
|
44
45
|
'shell-gradient-swatch--none': this.preset === 'none',
|
|
45
46
|
}}
|
|
@@ -53,7 +54,7 @@ export class ShellGradientSwatch {
|
|
|
53
54
|
}
|
|
54
55
|
aria-label={label}
|
|
55
56
|
aria-pressed={this.selected ? 'true' : 'false'}
|
|
56
|
-
disabled={this.
|
|
57
|
+
disabled={this.isInactive}
|
|
57
58
|
onClick={this.handleClick}
|
|
58
59
|
>
|
|
59
60
|
<span class="shell-gradient-swatch__fill" aria-hidden="true" />
|
|
@@ -15,7 +15,7 @@ export class Slider {
|
|
|
15
15
|
@Prop() max: number = 100;
|
|
16
16
|
@Prop() step: number = 1;
|
|
17
17
|
@Prop() label!: string;
|
|
18
|
-
@Prop()
|
|
18
|
+
@Prop() isInactive: boolean = false;
|
|
19
19
|
@Prop() valueText: string | undefined;
|
|
20
20
|
/** Associates with an external <label>. Defaults to an auto-generated ID. */
|
|
21
21
|
@Prop() inputId: string | undefined;
|
|
@@ -42,7 +42,11 @@ export class Slider {
|
|
|
42
42
|
<span class="text-body-small-emphasis">{this.value}</span>
|
|
43
43
|
</div>
|
|
44
44
|
<div
|
|
45
|
-
class={{
|
|
45
|
+
class={{
|
|
46
|
+
track: true,
|
|
47
|
+
'ds-control-inactive': this.isInactive,
|
|
48
|
+
'track--at-min': pct === 0,
|
|
49
|
+
}}
|
|
46
50
|
style={{ '--slider-pct': String(pct) } as Record<string, string>}
|
|
47
51
|
>
|
|
48
52
|
<div class="track-inner">
|
|
@@ -56,7 +60,7 @@ export class Slider {
|
|
|
56
60
|
max={this.max}
|
|
57
61
|
step={this.step}
|
|
58
62
|
value={this.value}
|
|
59
|
-
disabled={this.
|
|
63
|
+
disabled={this.isInactive}
|
|
60
64
|
class="range-input"
|
|
61
65
|
aria-valuetext={this.valueText}
|
|
62
66
|
onInput={this.handleInput}
|
|
@@ -64,7 +64,7 @@ export class TabGroup {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
/**
|
|
67
|
-
* Find the next non-
|
|
67
|
+
* Find the next non-inactive tab index relative to `from`, stepping by `step`.
|
|
68
68
|
* Returns `from` unchanged if no other enabled tab exists.
|
|
69
69
|
*/
|
|
70
70
|
private findEnabled(from: number, step: 1 | -1): number {
|
|
@@ -72,7 +72,7 @@ export class TabGroup {
|
|
|
72
72
|
const len = tabs.length;
|
|
73
73
|
for (let n = 0; n < len; n++) {
|
|
74
74
|
const i = (from + step * (n + 1) + len * (n + 1)) % len;
|
|
75
|
-
if (!tabs[i]?.
|
|
75
|
+
if (!tabs[i]?.isInactive) return i;
|
|
76
76
|
}
|
|
77
77
|
return from;
|
|
78
78
|
}
|
|
@@ -102,10 +102,10 @@ export class TabGroup {
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
if (e.key === 'Home') {
|
|
105
|
-
const first = tabs.findIndex(t => !t.
|
|
105
|
+
const first = tabs.findIndex(t => !t.isInactive);
|
|
106
106
|
nextIdx = first === -1 ? null : first;
|
|
107
107
|
} else if (e.key === 'End') {
|
|
108
|
-
const lastEnabled = [...tabs].reverse().findIndex(t => !t.
|
|
108
|
+
const lastEnabled = [...tabs].reverse().findIndex(t => !t.isInactive);
|
|
109
109
|
nextIdx = lastEnabled === -1 ? null : tabs.length - 1 - lastEnabled;
|
|
110
110
|
}
|
|
111
111
|
|
|
@@ -162,14 +162,20 @@ export class TabGroup {
|
|
|
162
162
|
tab: true,
|
|
163
163
|
'tab--selected': isSelected,
|
|
164
164
|
'ds-focus-ring-inset': true,
|
|
165
|
+
'ds-interaction-fill': !tab.isInactive,
|
|
166
|
+
'ds-interaction-fill--on-medium': bgClass === 'on-medium',
|
|
167
|
+
'ds-interaction-fill--on-bold': bgClass === 'on-bold',
|
|
168
|
+
'ds-interaction-fill--on-strong': bgClass === 'on-strong',
|
|
169
|
+
'ds-interaction-fill--on-always-dark': bgClass === 'on-always-dark',
|
|
170
|
+
'ds-control-inactive': !!tab.isInactive,
|
|
165
171
|
[bgClass]: !!bgClass,
|
|
166
172
|
}}
|
|
167
173
|
aria-selected={isSelected}
|
|
168
|
-
aria-disabled={tab.
|
|
174
|
+
aria-disabled={tab.isInactive || undefined}
|
|
169
175
|
aria-controls={tab.panelId ?? undefined}
|
|
170
|
-
disabled={tab.
|
|
176
|
+
disabled={tab.isInactive}
|
|
171
177
|
tabIndex={isSelected ? 0 : -1}
|
|
172
|
-
onClick={() => !tab.
|
|
178
|
+
onClick={() => !tab.isInactive && this.selectTab(tab.id)}
|
|
173
179
|
>
|
|
174
180
|
<span class={{
|
|
175
181
|
tab__label: true,
|
|
@@ -5,7 +5,8 @@ export interface TabItemDivider {
|
|
|
5
5
|
export interface TabItemTab {
|
|
6
6
|
id: string;
|
|
7
7
|
label: string;
|
|
8
|
-
|
|
8
|
+
/** Disables the tab (same meaning as control `isInactive`). */
|
|
9
|
+
isInactive?: boolean;
|
|
9
10
|
/** id of the tabpanel this tab controls */
|
|
10
11
|
panelId?: string;
|
|
11
12
|
/** Show a notification dot (brand) on the tab — no count, matching panel-nav. */
|
|
@@ -91,23 +91,23 @@ export class TabGroupNav {
|
|
|
91
91
|
@Method()
|
|
92
92
|
async focusLastTab() {
|
|
93
93
|
const tabs = this.selectableTabs;
|
|
94
|
-
const last = [...tabs].reverse().find(tab => !tab.
|
|
94
|
+
const last = [...tabs].reverse().find(tab => !tab.isInactive);
|
|
95
95
|
if (last) await this.focusTab(last.id);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
@Method()
|
|
99
99
|
async focusFirstTab() {
|
|
100
|
-
const first = this.selectableTabs.find(tab => !tab.
|
|
100
|
+
const first = this.selectableTabs.find(tab => !tab.isInactive);
|
|
101
101
|
if (first) await this.focusTab(first.id);
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
private syncFocusedTabId(preferred: string) {
|
|
105
105
|
const tabs = this.selectableTabs;
|
|
106
|
-
if (tabs.some(tab => tab.id === preferred && !tab.
|
|
106
|
+
if (tabs.some(tab => tab.id === preferred && !tab.isInactive)) {
|
|
107
107
|
this.focusedTabId = preferred;
|
|
108
108
|
return;
|
|
109
109
|
}
|
|
110
|
-
const first = tabs.find(tab => !tab.
|
|
110
|
+
const first = tabs.find(tab => !tab.isInactive);
|
|
111
111
|
this.focusedTabId = first?.id ?? '';
|
|
112
112
|
}
|
|
113
113
|
|
|
@@ -127,13 +127,13 @@ export class TabGroupNav {
|
|
|
127
127
|
private findEnabledLinear(from: number, step: 1 | -1): number | null {
|
|
128
128
|
const tabs = this.selectableTabs;
|
|
129
129
|
for (let i = from + step; i >= 0 && i < tabs.length; i += step) {
|
|
130
|
-
if (!tabs[i]?.
|
|
130
|
+
if (!tabs[i]?.isInactive) return i;
|
|
131
131
|
}
|
|
132
132
|
return null;
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
/**
|
|
136
|
-
* Find the next non-
|
|
136
|
+
* Find the next non-inactive tab index relative to `from`, stepping by `step`.
|
|
137
137
|
* Returns `from` unchanged if no other enabled tab exists.
|
|
138
138
|
*/
|
|
139
139
|
private findEnabled(from: number, step: 1 | -1): number {
|
|
@@ -141,7 +141,7 @@ export class TabGroupNav {
|
|
|
141
141
|
const len = tabs.length;
|
|
142
142
|
for (let n = 0; n < len; n++) {
|
|
143
143
|
const i = (from + step * (n + 1) + len * (n + 1)) % len;
|
|
144
|
-
if (!tabs[i]?.
|
|
144
|
+
if (!tabs[i]?.isInactive) return i;
|
|
145
145
|
}
|
|
146
146
|
return from;
|
|
147
147
|
}
|
|
@@ -156,7 +156,7 @@ export class TabGroupNav {
|
|
|
156
156
|
private activateFocusedTab(e: KeyboardEvent) {
|
|
157
157
|
if (e.key !== 'Enter' && e.key !== ' ') return;
|
|
158
158
|
const tab = this.selectableTabs.find(item => item.id === this.focusedTabId);
|
|
159
|
-
if (!tab || tab.
|
|
159
|
+
if (!tab || tab.isInactive) return;
|
|
160
160
|
e.preventDefault();
|
|
161
161
|
this.selectTab(tab.id, { focus: true });
|
|
162
162
|
}
|
|
@@ -221,10 +221,10 @@ export class TabGroupNav {
|
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
if (e.key === 'Home') {
|
|
224
|
-
const first = tabs.findIndex(t => !t.
|
|
224
|
+
const first = tabs.findIndex(t => !t.isInactive);
|
|
225
225
|
nextIdx = first === -1 ? null : first;
|
|
226
226
|
} else if (e.key === 'End') {
|
|
227
|
-
const lastEnabled = [...tabs].reverse().findIndex(t => !t.
|
|
227
|
+
const lastEnabled = [...tabs].reverse().findIndex(t => !t.isInactive);
|
|
228
228
|
nextIdx = lastEnabled === -1 ? null : tabs.length - 1 - lastEnabled;
|
|
229
229
|
}
|
|
230
230
|
|
|
@@ -305,14 +305,15 @@ export class TabGroupNav {
|
|
|
305
305
|
tab: true,
|
|
306
306
|
'tab--selected': isSelected,
|
|
307
307
|
'ds-focus-ring-inset': true,
|
|
308
|
+
'ds-control-inactive': !!tab.isInactive,
|
|
308
309
|
[bgClass]: !!bgClass,
|
|
309
310
|
}}
|
|
310
311
|
aria-selected={isSelected}
|
|
311
|
-
aria-disabled={tab.
|
|
312
|
+
aria-disabled={tab.isInactive || undefined}
|
|
312
313
|
aria-controls={tab.panelId ?? undefined}
|
|
313
|
-
disabled={tab.
|
|
314
|
+
disabled={tab.isInactive}
|
|
314
315
|
tabIndex={this.tabIndexForTab(tab)}
|
|
315
|
-
onClick={() => !tab.
|
|
316
|
+
onClick={() => !tab.isInactive && this.selectTab(tab.id)}
|
|
316
317
|
onFocus={() => {
|
|
317
318
|
if (!this.selectionFollowsFocus) {
|
|
318
319
|
this.focusedTabId = tab.id;
|
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
import { Component, Prop, h, Host } from '@stencil/core';
|
|
2
2
|
|
|
3
|
-
export type TagIntent
|
|
4
|
-
export type TagContrast
|
|
5
|
-
export type
|
|
6
|
-
export type TagSize = 'md' | 'sm' | 'xs';
|
|
3
|
+
export type TagIntent = 'neutral' | 'brand' | 'ai' | 'negative' | 'warning' | 'caution' | 'positive';
|
|
4
|
+
export type TagContrast = 'strong' | 'bold' | 'medium' | 'faint';
|
|
5
|
+
export type TagSize = 'md' | 'sm' | 'xs';
|
|
7
6
|
|
|
7
|
+
/** Text variant per control-density recipe (md / sm / xs). */
|
|
8
8
|
const TEXT_VARIANT: Record<TagSize, string> = {
|
|
9
9
|
md: 'text-body-medium',
|
|
10
10
|
sm: 'text-body-small',
|
|
11
11
|
xs: 'text-caption',
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* `ds-icon` size prop matching control-density icon metrics
|
|
16
|
+
* (md→20 / sm→16 / xs→12 via `--dimension-iconography-*`).
|
|
17
|
+
*/
|
|
18
|
+
const ICON_SIZE: Record<TagSize, 'md' | 'sm' | 'xs'> = {
|
|
19
|
+
md: 'md',
|
|
20
|
+
sm: 'sm',
|
|
21
|
+
xs: 'xs',
|
|
22
|
+
};
|
|
15
23
|
|
|
16
24
|
@Component({
|
|
17
25
|
tag: 'ds-tag',
|
|
@@ -22,13 +30,11 @@ export class Tag {
|
|
|
22
30
|
@Prop() label!: string;
|
|
23
31
|
@Prop() intent: TagIntent = 'neutral';
|
|
24
32
|
@Prop() contrast: TagContrast = 'faint';
|
|
25
|
-
@Prop() elevation: TagElevation = 'none';
|
|
26
33
|
@Prop() size: TagSize = 'md';
|
|
27
34
|
@Prop() rounded: boolean = false;
|
|
28
35
|
@Prop() maxWidth: string | number | undefined;
|
|
29
36
|
|
|
30
37
|
render() {
|
|
31
|
-
const sz = this.size.toUpperCase() as 'MD' | 'SM' | 'XS';
|
|
32
38
|
const textVariant = TEXT_VARIANT[this.size];
|
|
33
39
|
const iconSize = ICON_SIZE[this.size];
|
|
34
40
|
|
|
@@ -36,29 +42,24 @@ export class Tag {
|
|
|
36
42
|
? { maxWidth: typeof this.maxWidth === 'number' ? `${this.maxWidth}px` : this.maxWidth }
|
|
37
43
|
: undefined;
|
|
38
44
|
|
|
39
|
-
const hostCls: Record<string, boolean> = {
|
|
40
|
-
'tag': true,
|
|
41
|
-
[`tag--intent-${this.intent}`]: true,
|
|
42
|
-
[`tag--contrast-${this.contrast}`]: true,
|
|
43
|
-
[`tag--elevation-${this.elevation}`]: true,
|
|
44
|
-
[`tag--size-${this.size}`]: true,
|
|
45
|
-
'tag--rounded': this.rounded,
|
|
46
|
-
'tag--rounded-no-icon-left': this.rounded, // consumer overrides via slot presence hack
|
|
47
|
-
'tag--rounded-no-remove-right': this.rounded,
|
|
48
|
-
[`tag--icon-left-${sz}`]: false, // toggled by slotchange
|
|
49
|
-
[`tag--icon-right-${sz}`]: false,
|
|
50
|
-
};
|
|
51
|
-
|
|
52
45
|
return (
|
|
53
46
|
<Host
|
|
54
|
-
class={
|
|
47
|
+
class={{
|
|
48
|
+
'tag': true,
|
|
49
|
+
[`tag--intent-${this.intent}`]: true,
|
|
50
|
+
[`tag--contrast-${this.contrast}`]: true,
|
|
51
|
+
[`tag--size-${this.size}`]: true,
|
|
52
|
+
'ds-control--md': this.size === 'md',
|
|
53
|
+
'ds-control--sm': this.size === 'sm',
|
|
54
|
+
'ds-control--xs': this.size === 'xs',
|
|
55
|
+
'tag--rounded': this.rounded,
|
|
56
|
+
}}
|
|
55
57
|
style={maxWidthStyle}
|
|
56
58
|
>
|
|
57
|
-
{/* Leading icon
|
|
58
|
-
<span class="tag__icon-slot"
|
|
59
|
+
{/* Leading icon — consumer provides ds-icon (or any SVG); prefer size matching tag size. */}
|
|
60
|
+
<span class="tag__icon-slot" data-icon-size={iconSize}>
|
|
59
61
|
<slot name="icon" />
|
|
60
62
|
</span>
|
|
61
|
-
{/* Label */}
|
|
62
63
|
<span class={{ 'tag__label': true, [textVariant]: true }}>
|
|
63
64
|
{this.label}
|
|
64
65
|
</span>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export type { TagIntent, TagContrast,
|
|
1
|
+
export type { TagIntent, TagContrast, TagSize } from './Tag';
|
|
@@ -7,18 +7,18 @@ import { Component, Prop, Event, EventEmitter, h, Host } from '@stencil/core';
|
|
|
7
7
|
})
|
|
8
8
|
export class Toggle {
|
|
9
9
|
@Prop({ mutable: true }) checked: boolean = false;
|
|
10
|
-
@Prop()
|
|
10
|
+
@Prop() isInactive: boolean = false;
|
|
11
11
|
|
|
12
12
|
@Event() dsChange!: EventEmitter<boolean>;
|
|
13
13
|
|
|
14
14
|
private handleClick = () => {
|
|
15
|
-
if (this.
|
|
15
|
+
if (this.isInactive) return;
|
|
16
16
|
this.checked = !this.checked;
|
|
17
17
|
this.dsChange.emit(this.checked);
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
private handleKeyDown = (e: KeyboardEvent) => {
|
|
21
|
-
if (this.
|
|
21
|
+
if (this.isInactive) return;
|
|
22
22
|
if (e.key === ' ' || e.key === 'Enter') {
|
|
23
23
|
e.preventDefault();
|
|
24
24
|
this.handleClick();
|
|
@@ -30,9 +30,9 @@ export class Toggle {
|
|
|
30
30
|
<Host
|
|
31
31
|
role="switch"
|
|
32
32
|
aria-checked={String(this.checked)}
|
|
33
|
-
aria-disabled={this.
|
|
34
|
-
tabIndex={this.
|
|
35
|
-
class={{ toggle: true, checked: this.checked, inactive: this.
|
|
33
|
+
aria-disabled={this.isInactive || undefined}
|
|
34
|
+
tabIndex={this.isInactive ? -1 : 0}
|
|
35
|
+
class={{ toggle: true, checked: this.checked, 'ds-control-inactive': this.isInactive }}
|
|
36
36
|
onClick={this.handleClick}
|
|
37
37
|
onKeyDown={this.handleKeyDown}
|
|
38
38
|
>
|