@momentum-design/components 0.19.1 → 0.20.1

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.
@@ -0,0 +1,7 @@
1
+ import Radio from './radio.component';
2
+ declare global {
3
+ interface HTMLElementTagNameMap {
4
+ ['mdc-radio']: Radio;
5
+ }
6
+ }
7
+ export default Radio;
@@ -0,0 +1,4 @@
1
+ import Radio from './radio.component';
2
+ import { TAG_NAME } from './radio.constants';
3
+ Radio.register(TAG_NAME);
4
+ export default Radio;
@@ -0,0 +1,97 @@
1
+ import { CSSResult, PropertyValues } from 'lit';
2
+ import FormfieldWrapper from '../formfieldwrapper/formfieldwrapper.component';
3
+ declare const Radio_base: import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/NameMixin").NameMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/ValueMixin").ValueMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/DataAriaLabelMixin").DataAriaLabelMixinInterface> & typeof FormfieldWrapper;
4
+ /**
5
+ * Radio allow users to select single options from a list or turn an item/feature on or off.
6
+ * These are often used in forms, settings, and selection in lists.
7
+ *
8
+ * A radio component contains an optional label, optional info icon and an optional helper text.
9
+ * @dependency mdc-formfieldwrapper
10
+ *
11
+ * @tagname mdc-radio
12
+ *
13
+ * @cssproperty --mdc-radio-inner-circle-size - size of the inner circle
14
+ * @cssproperty --mdc-radio-text-disabled-color - color of the label when disabled
15
+ * @cssproperty --mdc-radio-disabled-border-color - color of the radio button border when disabled
16
+ * @cssproperty --mdc-radio-normal-border-color - color of the radio button border when normal
17
+ * @cssproperty --mdc-radio-inner-circle-normal-background - background color of the inner circle when normal
18
+ * @cssproperty --mdc-radio-inner-circle-disabled-background - background color of the inner circle when disabled
19
+ * @cssproperty --mdc-radio-control-inactive-color - color of the radio button when inactive
20
+ * @cssproperty --mdc-radio-control-inactive-hover - color of the radio button when inactive and hovered
21
+ * @cssproperty --mdc-radio-control-inactive-pressed-color - color of the radio button when inactive and pressed
22
+ * @cssproperty --mdc-radio-control-inactive-disabled-background - background color of the radio button when
23
+ * inactive and disabled
24
+ * @cssproperty --mdc-radio-control-active-color - color of the radio button when active
25
+ * @cssproperty --mdc-radio-control-active-hover-color - color of the radio button when active and hovered
26
+ * @cssproperty --mdc-radio-control-active-pressed-color - color of the radio button when active and pressed
27
+ * @cssproperty --mdc-radio-control-active-disabled-background - background color of the radio button
28
+ * when active and disabled
29
+ *
30
+ */
31
+ declare class Radio extends Radio_base {
32
+ /**
33
+ * Determines whether the radio is selected or unselected.
34
+ *
35
+ * @default false
36
+ */
37
+ checked: boolean;
38
+ /**
39
+ * Determines whether the radio is read-only.
40
+ *
41
+ * @default false
42
+ */
43
+ readonly: boolean;
44
+ /** @internal */
45
+ private internals;
46
+ /** @internal */
47
+ static formAssociated: boolean;
48
+ /** @internal */
49
+ get form(): HTMLFormElement | null;
50
+ constructor();
51
+ /**
52
+ * Updates the form value to reflect the current state of the radio.
53
+ * If checked, the value is set to the user-provided value.
54
+ * If unchecked, the value is set to null.
55
+ */
56
+ private setFormValue;
57
+ firstUpdated(): void;
58
+ /**
59
+ * Returns all radios within the same group (name).
60
+ */
61
+ private getAllRadiosWithinSameGroup;
62
+ /**
63
+ * The 'change' event does not bubble up through the shadow DOM as it was not composed.
64
+ * Therefore, we need to re-dispatch the same event to ensure it is propagated correctly.
65
+ * Read more: https://developer.mozilla.org/en-US/docs/Web/API/Event/composed
66
+ */
67
+ private dispatchChangeEvent;
68
+ /**
69
+ * Handles the change event on the radio element.
70
+ * This will toggle the state of the radio element.
71
+ * Dispatches the change event.
72
+ */
73
+ private handleChange;
74
+ /**
75
+ * Updates the state of the radio button at the specified index within the enabled radios.
76
+ * Focuses the radio button and triggers the change event if the radio button is not read-only.
77
+ *
78
+ * @param enabledRadios - An array of enabled radio buttons within the same group.
79
+ * @param index - The index of the radio button to be updated within the enabled radios array.
80
+ * @param event - The event that triggered the update.
81
+ */
82
+ private updateRadio;
83
+ /**
84
+ * Handles the keydown event (Arrow Up/Down/Left/Right) on the radio element.
85
+ */
86
+ private handleKeyDown;
87
+ /**
88
+ * Update tab index for all radios in the same group (name)
89
+ * If any radio group is checked, it will have a tab index of 0
90
+ * If no radio group is checked, the first enabled radio will have a tab index of 0
91
+ */
92
+ private updateTabIndex;
93
+ update(changedProperties: PropertyValues): void;
94
+ render(): import("lit-html").TemplateResult<1>;
95
+ static styles: Array<CSSResult>;
96
+ }
97
+ export default Radio;
@@ -0,0 +1,229 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { html, nothing } from 'lit';
11
+ import { property } from 'lit/decorators.js';
12
+ import { ifDefined } from 'lit/directives/if-defined.js';
13
+ import { NameMixin } from '../../utils/mixins/NameMixin';
14
+ import { ValueMixin } from '../../utils/mixins/ValueMixin';
15
+ import styles from './radio.styles';
16
+ import FormfieldWrapper from '../formfieldwrapper/formfieldwrapper.component';
17
+ import { DataAriaLabelMixin } from '../../utils/mixins/DataAriaLabelMixin';
18
+ /**
19
+ * Radio allow users to select single options from a list or turn an item/feature on or off.
20
+ * These are often used in forms, settings, and selection in lists.
21
+ *
22
+ * A radio component contains an optional label, optional info icon and an optional helper text.
23
+ * @dependency mdc-formfieldwrapper
24
+ *
25
+ * @tagname mdc-radio
26
+ *
27
+ * @cssproperty --mdc-radio-inner-circle-size - size of the inner circle
28
+ * @cssproperty --mdc-radio-text-disabled-color - color of the label when disabled
29
+ * @cssproperty --mdc-radio-disabled-border-color - color of the radio button border when disabled
30
+ * @cssproperty --mdc-radio-normal-border-color - color of the radio button border when normal
31
+ * @cssproperty --mdc-radio-inner-circle-normal-background - background color of the inner circle when normal
32
+ * @cssproperty --mdc-radio-inner-circle-disabled-background - background color of the inner circle when disabled
33
+ * @cssproperty --mdc-radio-control-inactive-color - color of the radio button when inactive
34
+ * @cssproperty --mdc-radio-control-inactive-hover - color of the radio button when inactive and hovered
35
+ * @cssproperty --mdc-radio-control-inactive-pressed-color - color of the radio button when inactive and pressed
36
+ * @cssproperty --mdc-radio-control-inactive-disabled-background - background color of the radio button when
37
+ * inactive and disabled
38
+ * @cssproperty --mdc-radio-control-active-color - color of the radio button when active
39
+ * @cssproperty --mdc-radio-control-active-hover-color - color of the radio button when active and hovered
40
+ * @cssproperty --mdc-radio-control-active-pressed-color - color of the radio button when active and pressed
41
+ * @cssproperty --mdc-radio-control-active-disabled-background - background color of the radio button
42
+ * when active and disabled
43
+ *
44
+ */
45
+ class Radio extends NameMixin(ValueMixin(DataAriaLabelMixin(FormfieldWrapper))) {
46
+ /** @internal */
47
+ get form() {
48
+ return this.internals.form;
49
+ }
50
+ constructor() {
51
+ super();
52
+ /**
53
+ * Determines whether the radio is selected or unselected.
54
+ *
55
+ * @default false
56
+ */
57
+ this.checked = false;
58
+ /**
59
+ * Determines whether the radio is read-only.
60
+ *
61
+ * @default false
62
+ */
63
+ this.readonly = false;
64
+ /** @internal */
65
+ this.internals = this.attachInternals();
66
+ }
67
+ /**
68
+ * Updates the form value to reflect the current state of the radio.
69
+ * If checked, the value is set to the user-provided value.
70
+ * If unchecked, the value is set to null.
71
+ */
72
+ setFormValue() {
73
+ if (this.checked) {
74
+ this.internals.setFormValue(this.value);
75
+ }
76
+ }
77
+ firstUpdated() {
78
+ this.updateTabIndex();
79
+ }
80
+ /**
81
+ * Returns all radios within the same group (name).
82
+ */
83
+ getAllRadiosWithinSameGroup() {
84
+ return Array.from(document.querySelectorAll(`mdc-radio[name="${this.name}"]`));
85
+ }
86
+ /**
87
+ * The 'change' event does not bubble up through the shadow DOM as it was not composed.
88
+ * Therefore, we need to re-dispatch the same event to ensure it is propagated correctly.
89
+ * Read more: https://developer.mozilla.org/en-US/docs/Web/API/Event/composed
90
+ */
91
+ dispatchChangeEvent(event) {
92
+ const EventConstructor = event.constructor;
93
+ this.dispatchEvent(new EventConstructor(event.type, event));
94
+ }
95
+ /**
96
+ * Handles the change event on the radio element.
97
+ * This will toggle the state of the radio element.
98
+ * Dispatches the change event.
99
+ */
100
+ handleChange(event) {
101
+ var _a;
102
+ if (this.disabled || this.readonly)
103
+ return;
104
+ const radios = this.getAllRadiosWithinSameGroup();
105
+ radios.forEach((radio) => {
106
+ var _a;
107
+ /**
108
+ * Uncheck all radios in the same group (name)
109
+ */
110
+ const radioElement = (_a = radio.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('input');
111
+ if (radioElement) {
112
+ // eslint-disable-next-line no-param-reassign
113
+ radio.checked = false;
114
+ radioElement.checked = false;
115
+ }
116
+ });
117
+ this.checked = true;
118
+ const inputElement = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('input');
119
+ if (inputElement) {
120
+ inputElement.checked = true;
121
+ }
122
+ this.dispatchChangeEvent(event);
123
+ }
124
+ /**
125
+ * Updates the state of the radio button at the specified index within the enabled radios.
126
+ * Focuses the radio button and triggers the change event if the radio button is not read-only.
127
+ *
128
+ * @param enabledRadios - An array of enabled radio buttons within the same group.
129
+ * @param index - The index of the radio button to be updated within the enabled radios array.
130
+ * @param event - The event that triggered the update.
131
+ */
132
+ updateRadio(enabledRadios, index, event) {
133
+ var _a, _b;
134
+ (_b = (_a = enabledRadios[index].shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('input')) === null || _b === void 0 ? void 0 : _b.focus();
135
+ enabledRadios[index].handleChange(event);
136
+ }
137
+ /**
138
+ * Handles the keydown event (Arrow Up/Down/Left/Right) on the radio element.
139
+ */
140
+ handleKeyDown(event) {
141
+ if (this.disabled)
142
+ return;
143
+ const radios = this.getAllRadiosWithinSameGroup();
144
+ const enabledRadios = radios.filter((radio) => !radio.disabled);
145
+ const currentIndex = enabledRadios.indexOf(this);
146
+ if (['ArrowDown', 'ArrowRight'].includes(event.key)) {
147
+ // Move focus to the next radio
148
+ const nextIndex = (currentIndex + 1) % enabledRadios.length;
149
+ this.updateRadio(enabledRadios, nextIndex, event);
150
+ }
151
+ else if (['ArrowUp', 'ArrowLeft'].includes(event.key)) {
152
+ // Move focus to the previous radio
153
+ const prevIndex = (currentIndex - 1 + enabledRadios.length) % enabledRadios.length;
154
+ this.updateRadio(enabledRadios, prevIndex, event);
155
+ }
156
+ this.updateTabIndex();
157
+ }
158
+ /**
159
+ * Update tab index for all radios in the same group (name)
160
+ * If any radio group is checked, it will have a tab index of 0
161
+ * If no radio group is checked, the first enabled radio will have a tab index of 0
162
+ */
163
+ updateTabIndex() {
164
+ const radios = this.getAllRadiosWithinSameGroup();
165
+ const checked = radios.find((radio) => radio.checked);
166
+ const firstEnabledRadio = radios.find((radio) => !radio.disabled);
167
+ radios.forEach((radio) => {
168
+ var _a;
169
+ const inputElement = (_a = radio.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('input');
170
+ if (inputElement) {
171
+ inputElement.tabIndex = -1;
172
+ if (radio === checked) {
173
+ inputElement.tabIndex = 0;
174
+ }
175
+ else if (!checked && radio === firstEnabledRadio) {
176
+ inputElement.tabIndex = 0;
177
+ }
178
+ }
179
+ });
180
+ }
181
+ update(changedProperties) {
182
+ super.update(changedProperties);
183
+ if (changedProperties.has('checked')) {
184
+ this.setFormValue();
185
+ }
186
+ }
187
+ render() {
188
+ var _a;
189
+ const helpTextContent = this.helpText ? this.renderHelperText() : nothing;
190
+ return html `
191
+ <div class="mdc-radio__container">
192
+ <div class="mdc-radio__icon-container mdc-focus-ring">
193
+ <input
194
+ id="${this.id}"
195
+ type="radio"
196
+ role="radio"
197
+ name="${ifDefined(this.name)}"
198
+ value="${ifDefined(this.value)}"
199
+ @change=${this.handleChange}
200
+ @keydown=${this.handleKeyDown}
201
+ ?checked=${this.checked}
202
+ ?readonly=${this.readonly}
203
+ ?disabled=${this.disabled}
204
+ class="mdc-radio__input"
205
+ aria-checked="${this.checked}"
206
+ aria-label="${(_a = this.dataAriaLabel) !== null && _a !== void 0 ? _a : ''}"
207
+ />
208
+ <span class="mdc-radio__icon"></span>
209
+ </div>
210
+ <div class="mdc-radio__label-container">
211
+ ${this.renderLabel()}
212
+ ${helpTextContent}
213
+ </div>
214
+ </div>
215
+ `;
216
+ }
217
+ }
218
+ /** @internal */
219
+ Radio.formAssociated = true;
220
+ Radio.styles = [...FormfieldWrapper.styles, ...styles];
221
+ __decorate([
222
+ property({ type: Boolean, reflect: true }),
223
+ __metadata("design:type", Object)
224
+ ], Radio.prototype, "checked", void 0);
225
+ __decorate([
226
+ property({ type: Boolean, reflect: true }),
227
+ __metadata("design:type", Object)
228
+ ], Radio.prototype, "readonly", void 0);
229
+ export default Radio;
@@ -0,0 +1,2 @@
1
+ declare const TAG_NAME: "mdc-radio";
2
+ export { TAG_NAME };
@@ -0,0 +1,3 @@
1
+ import utils from '../../utils/tag-name';
2
+ const TAG_NAME = utils.constructTagName('radio');
3
+ export { TAG_NAME };
@@ -0,0 +1,2 @@
1
+ declare const styles: import("lit").CSSResult[];
2
+ export default styles;
@@ -0,0 +1,162 @@
1
+ import { css } from 'lit';
2
+ import { hostFitContentStyles, hostFocusRingStyles } from '../../utils/styles';
3
+ const styles = [hostFitContentStyles, css `
4
+ :host{
5
+ --mdc-radio-inner-circle-size: 0.375rem;
6
+ --mdc-radio-text-disabled-color: var(--mds-color-theme-text-primary-disabled);
7
+ --mdc-radio-disabled-border-color: var(--mds-color-theme-outline-primary-disabled);
8
+ --mdc-radio-normal-border-color: var(--mds-color-theme-outline-input-normal);
9
+ --mdc-radio-inner-circle-normal-background: var(--mds-color-theme-inverted-text-primary-normal);
10
+ --mdc-radio-inner-circle-disabled-background: var(--mds-color-theme-inverted-text-primary-disabled);
11
+
12
+ --mdc-radio-control-inactive-color: var(--mds-color-theme-control-inactive-normal);
13
+ --mdc-radio-control-inactive-hover: var(--mds-color-theme-control-inactive-hover);
14
+ --mdc-radio-control-inactive-pressed-color: var(--mds-color-theme-control-inactive-pressed);
15
+ --mdc-radio-control-inactive-disabled-background: var(--mds-color-theme-control-inactive-disabled);
16
+
17
+ --mdc-radio-control-active-color: var(--mds-color-theme-control-active-normal);
18
+ --mdc-radio-control-active-hover-color: var(--mds-color-theme-control-active-hover);
19
+ --mdc-radio-control-active-pressed-color: var(--mds-color-theme-control-active-pressed);
20
+ --mdc-radio-control-active-disabled-background: var(--mds-color-theme-control-active-disabled);
21
+
22
+ }
23
+ :host([readonly]) .mdc-radio__input,
24
+ :host([disabled]) .mdc-radio__input,
25
+ :host([disabled]) .mdc-label,
26
+ :host([readonly]) .mdc-label{
27
+ cursor: default;
28
+ }
29
+
30
+ .mdc-label {
31
+ cursor: pointer;
32
+ }
33
+
34
+ :host([disabled]) .mdc-radio__label-text,
35
+ :host([disabled]) .mdc-radio__help-text {
36
+ color: var(--mdc-radio-text-disabled-color);
37
+ }
38
+
39
+ :host([disabled]) .mdc-radio__icon,
40
+ :host([disabled]) .mdc-radio__container:hover .mdc-radio__icon,
41
+ :host([disabled][readonly]) .mdc-radio__icon,
42
+ :host([disabled][readonly]) .mdc-radio__container:hover .mdc-radio__icon {
43
+ border-color: var(--mdc-radio-disabled-border-color);
44
+ background: var(--mdc-radio-control-inactive-disabled-background);
45
+ }
46
+
47
+ :host([disabled][checked]) .mdc-radio__icon,
48
+ :host([disabled][checked]) .mdc-radio__container:hover .mdc-radio__icon,
49
+ :host([disabled][readonly][checked]) .mdc-radio__icon,
50
+ :host([disabled][readonly][checked]) .mdc-radio__container:hover .mdc-radio__icon {
51
+ border: var(--mdc-radio-control-active-disabled-background);
52
+ background: var(--mdc-radio-control-active-disabled-background);
53
+ }
54
+
55
+ :host([disabled][checked]) .mdc-radio__icon:after,
56
+ :host([disabled][checked]) .mdc-radio__container:hover .mdc-radio__icon:after,
57
+ :host([disabled][readonly][checked]) .mdc-radio__icon:after,
58
+ :host([disabled][readonly][checked]) .mdc-radio__container:hover .mdc-radio__icon:after {
59
+ background: var(--mdc-radio-inner-circle-disabled-background);
60
+ }
61
+
62
+ :host .mdc-radio__icon {
63
+ position: absolute;
64
+ top: 0;
65
+ left: 0;
66
+ width: 1rem;
67
+ height: 1rem;
68
+ border: 0.0625rem solid var(--mdc-radio-normal-border-color);
69
+ background-color: var(--mdc-radio-control-inactive-color);
70
+ border-radius: 50%;
71
+ }
72
+
73
+ :host([checked]) .mdc-radio__icon {
74
+ border-color: var(--mdc-radio-control-active-color);
75
+ background-color: var(--mdc-radio-control-active-color);
76
+ }
77
+
78
+ :host([checked]) .mdc-radio__icon:after {
79
+ display: block;
80
+ top: 50%;
81
+ left: 50%;
82
+ transform: translate(-50%, -50%);
83
+ width: var(--mdc-radio-inner-circle-size);
84
+ height: var(--mdc-radio-inner-circle-size);
85
+ border-radius: 50%;
86
+ background: var(--mdc-radio-inner-circle-normal-background);
87
+ }
88
+
89
+ :host .mdc-radio__input:hover ~ .mdc-radio__icon {
90
+ border-color: var(--mdc-radio-normal-border-color);
91
+ background-color: var(--mdc-radio-control-inactive-hover);
92
+ }
93
+
94
+ :host([checked]) .mdc-radio__input:hover ~ .mdc-radio__icon {
95
+ border-color: var(--mdc-radio-control-active-hover-color);
96
+ background-color: var(--mdc-radio-control-active-hover-color);
97
+ }
98
+
99
+ :host .mdc-radio__input:active ~ .mdc-radio__icon {
100
+ border-color: var(--mdc-radio-normal-border-color);
101
+ background-color: var(--mdc-radio-control-inactive-pressed-color);
102
+ }
103
+
104
+ :host([checked]) .mdc-radio__input:active ~ .mdc-radio__icon {
105
+ border-color: var(--mdc-radio-control-active-pressed-color);
106
+ background-color: var(--mdc-radio-control-active-pressed-color);
107
+ }
108
+
109
+ :host([readonly]) .mdc-radio__icon,
110
+ :host([readonly]) .mdc-radio__container:hover .mdc-radio__icon {
111
+ border-color: var(--mdc-radio-normal-border-color);
112
+ background-color: var(--mdc-radio-control-inactive-color);
113
+ }
114
+
115
+ :host([readonly][checked]) .mdc-radio__icon {
116
+ border-color: var(--mdc-radio-normal-border-color);
117
+ }
118
+
119
+ :host([readonly][checked]) .mdc-radio__icon:after,
120
+ :host([readonly][checked]) .mdc-radio__container:hover .mdc-radio__icon:after,
121
+ :host([readonly][checked]) .mdc-radio__container:active .mdc-radio__icon:after {
122
+ background-color: var(--mdc-radio-text-disabled-color);
123
+ }
124
+
125
+ .mdc-radio__container {
126
+ display: flex;
127
+ align-items: start;
128
+ gap: 0.5rem;
129
+ }
130
+ .mdc-radio__icon-container {
131
+ display: block;
132
+ position: relative;
133
+ width: 1rem;
134
+ height: 1rem;
135
+ margin: 0.125rem 0;
136
+ border-radius: 50%;
137
+ }
138
+
139
+ .mdc-radio__icon-container input{
140
+ position: absolute;
141
+ opacity: 0;
142
+ margin: 0;
143
+ width: 100%;
144
+ height: 100%;
145
+ cursor: pointer;
146
+ z-index: 2;
147
+ }
148
+
149
+ .mdc-radio__icon-container .mdc-radio__icon:after {
150
+ content: "";
151
+ position: absolute;
152
+ display: none;
153
+ }
154
+
155
+ .mdc-radio__label-container{
156
+ display: flex;
157
+ flex-direction: column;
158
+ justify-content: center;
159
+ gap: 0.25rem;
160
+ }
161
+ `, ...hostFocusRingStyles(true)];
162
+ export default styles;