@momentum-design/components 0.137.7 → 0.138.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/browser/index.js +394 -369
- package/dist/browser/index.js.map +4 -4
- package/dist/components/checkbox/checkbox.component.d.ts +6 -1
- package/dist/components/checkbox/checkbox.component.js +34 -4
- package/dist/components/checkboxtree/checkboxtree.component.d.ts +99 -0
- package/dist/components/checkboxtree/checkboxtree.component.js +213 -0
- package/dist/components/checkboxtree/checkboxtree.constants.d.ts +2 -0
- package/dist/components/checkboxtree/checkboxtree.constants.js +3 -0
- package/dist/components/checkboxtree/checkboxtree.styles.d.ts +2 -0
- package/dist/components/checkboxtree/checkboxtree.styles.js +25 -0
- package/dist/components/checkboxtree/index.d.ts +13 -0
- package/dist/components/checkboxtree/index.js +10 -0
- package/dist/components/listitem/listitem.component.d.ts +1 -1
- package/dist/components/tab/tab.component.d.ts +1 -1
- package/dist/custom-elements.json +759 -9
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/react/checkboxtree/index.d.ts +50 -0
- package/dist/react/checkboxtree/index.js +40 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +1 -0
- package/dist/utils/mixins/lifecycle/LifeCycleMixin.d.ts +2 -9
- package/dist/utils/mixins/lifecycle/LifeCycleMixin.js +2 -9
- package/dist/utils/mixins/lifecycle/ModifiedEventMixin.d.ts +12 -0
- package/dist/utils/mixins/lifecycle/ModifiedEventMixin.js +15 -0
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@ import { CSSResult, PropertyValueMap, PropertyValues } from 'lit';
|
|
|
2
2
|
import { AssociatedFormControl } from '../../utils/mixins/FormInternalsMixin';
|
|
3
3
|
import FormfieldWrapper from '../formfieldwrapper/formfieldwrapper.component';
|
|
4
4
|
import type { CheckboxValidationType } from './checkbox.types';
|
|
5
|
-
declare const Checkbox_base: import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/KeyDownHandledMixin").KeyDownHandledMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/KeyToActionMixin").KeyToActionInterface> & import("../../utils/mixins/index.types").Constructor<import("../../models").Component & import("../../utils/mixins/AutoFocusOnMountMixin").AutoFocusOnMountMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/FormInternalsMixin").FormInternalsMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/DataAriaLabelMixin").DataAriaLabelMixinInterface> & typeof FormfieldWrapper;
|
|
5
|
+
declare const Checkbox_base: import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/KeyDownHandledMixin").KeyDownHandledMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/KeyToActionMixin").KeyToActionInterface> & import("../../utils/mixins/index.types").Constructor<import("../../models").Component & import("../../utils/mixins/AutoFocusOnMountMixin").AutoFocusOnMountMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/FormInternalsMixin").FormInternalsMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/DataAriaLabelMixin").DataAriaLabelMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/lifecycle/ModifiedEventMixin").ModifiedEventMixinInterface> & typeof FormfieldWrapper;
|
|
6
6
|
/**
|
|
7
7
|
* The checkbox is a form control that represents a binary choice ("checked"/"unchecked") or, when used in a group, allows multiple selections from a list. It wraps a native `<input type="checkbox">` and renders a custom visual through `mdc-staticcheckbox`, while preserving full form participation (value, name, validation, reset).
|
|
8
8
|
*
|
|
@@ -47,6 +47,11 @@ declare const Checkbox_base: import("../../utils/mixins/index.types").Constructo
|
|
|
47
47
|
* @cssstate checked - Active when the checkbox is checked.
|
|
48
48
|
*/
|
|
49
49
|
declare class Checkbox extends Checkbox_base implements AssociatedFormControl {
|
|
50
|
+
/**
|
|
51
|
+
* Controls the tab order of the native checkbox input.
|
|
52
|
+
* @default 0
|
|
53
|
+
*/
|
|
54
|
+
tabIndex: number;
|
|
50
55
|
/**
|
|
51
56
|
* Determines whether the checkbox is checked (selected) or unchecked.
|
|
52
57
|
* @default false
|
|
@@ -17,6 +17,7 @@ import FormfieldWrapper from '../formfieldwrapper/formfieldwrapper.component';
|
|
|
17
17
|
import { DEFAULTS as FORMFIELD_DEFAULTS } from '../formfieldwrapper/formfieldwrapper.constants';
|
|
18
18
|
import { KeyToActionMixin, ACTIONS, NAV_MODES } from '../../utils/mixins/KeyToActionMixin';
|
|
19
19
|
import { KeyDownHandledMixin } from '../../utils/mixins/KeyDownHandledMixin';
|
|
20
|
+
import { ModifiedEventMixin } from '../../utils/mixins/lifecycle/ModifiedEventMixin';
|
|
20
21
|
import styles from './checkbox.styles';
|
|
21
22
|
import { CHECKBOX_VALIDATION } from './checkbox.constants';
|
|
22
23
|
/**
|
|
@@ -45,9 +46,14 @@ import { CHECKBOX_VALIDATION } from './checkbox.constants';
|
|
|
45
46
|
*
|
|
46
47
|
* @cssstate checked - Active when the checkbox is checked.
|
|
47
48
|
*/
|
|
48
|
-
class Checkbox extends KeyDownHandledMixin(KeyToActionMixin(AutoFocusOnMountMixin(FormInternalsMixin(DataAriaLabelMixin(FormfieldWrapper))))) {
|
|
49
|
+
class Checkbox extends KeyDownHandledMixin(KeyToActionMixin(AutoFocusOnMountMixin(FormInternalsMixin(DataAriaLabelMixin(ModifiedEventMixin(FormfieldWrapper)))))) {
|
|
49
50
|
constructor() {
|
|
50
51
|
super(...arguments);
|
|
52
|
+
/**
|
|
53
|
+
* Controls the tab order of the native checkbox input.
|
|
54
|
+
* @default 0
|
|
55
|
+
*/
|
|
56
|
+
this.tabIndex = 0;
|
|
51
57
|
/**
|
|
52
58
|
* Determines whether the checkbox is checked (selected) or unchecked.
|
|
53
59
|
* @default false
|
|
@@ -144,11 +150,17 @@ class Checkbox extends KeyDownHandledMixin(KeyToActionMixin(AutoFocusOnMountMixi
|
|
|
144
150
|
if (!this.disabled && !this.softDisabled && !this.readonly) {
|
|
145
151
|
this.checked = !this.checked;
|
|
146
152
|
this.indeterminate = false;
|
|
153
|
+
return true;
|
|
147
154
|
}
|
|
155
|
+
return false;
|
|
148
156
|
}
|
|
149
157
|
click() {
|
|
150
158
|
super.click();
|
|
151
|
-
this.toggleState();
|
|
159
|
+
const hasBeenToggled = this.toggleState();
|
|
160
|
+
if (hasBeenToggled) {
|
|
161
|
+
// Host clicks bypass the native input, so dispatch the equivalent change event.
|
|
162
|
+
this.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
|
|
163
|
+
}
|
|
152
164
|
}
|
|
153
165
|
/**
|
|
154
166
|
* Handles the keydown event on the checkbox.
|
|
@@ -171,7 +183,10 @@ class Checkbox extends KeyDownHandledMixin(KeyToActionMixin(AutoFocusOnMountMixi
|
|
|
171
183
|
}
|
|
172
184
|
if (this.getKeyboardNavMode() === NAV_MODES.SPATIAL) {
|
|
173
185
|
if (!(this.readonly || this.softDisabled) && action === ACTIONS.ENTER) {
|
|
174
|
-
this.toggleState();
|
|
186
|
+
const hasBeenToggled = this.toggleState();
|
|
187
|
+
if (hasBeenToggled) {
|
|
188
|
+
this.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
|
|
189
|
+
}
|
|
175
190
|
this.keyDownEventHandled();
|
|
176
191
|
}
|
|
177
192
|
}
|
|
@@ -197,6 +212,13 @@ class Checkbox extends KeyDownHandledMixin(KeyToActionMixin(AutoFocusOnMountMixi
|
|
|
197
212
|
this.internals.states.delete('checked');
|
|
198
213
|
}
|
|
199
214
|
}
|
|
215
|
+
if (changedProperties.has('checked') ||
|
|
216
|
+
changedProperties.has('disabled') ||
|
|
217
|
+
changedProperties.has('indeterminate') ||
|
|
218
|
+
changedProperties.has('readonly') ||
|
|
219
|
+
changedProperties.has('softDisabled')) {
|
|
220
|
+
this.dispatchModifiedEvent('state');
|
|
221
|
+
}
|
|
200
222
|
}
|
|
201
223
|
render() {
|
|
202
224
|
var _a;
|
|
@@ -223,7 +245,7 @@ class Checkbox extends KeyDownHandledMixin(KeyToActionMixin(AutoFocusOnMountMixi
|
|
|
223
245
|
.disabled="${this.disabled}"
|
|
224
246
|
?readonly="${this.readonly}"
|
|
225
247
|
aria-label="${(_a = this.dataAriaLabel) !== null && _a !== void 0 ? _a : ''}"
|
|
226
|
-
tabindex="${this.disabled ? -1 :
|
|
248
|
+
tabindex="${this.disabled ? -1 : this.tabIndex}"
|
|
227
249
|
aria-describedby="${ifDefined(this.helpText ? FORMFIELD_DEFAULTS.HELPER_TEXT_ID : '')}"
|
|
228
250
|
@change=${this.handleChange}
|
|
229
251
|
@keydown=${this.handleKeyDown}
|
|
@@ -235,6 +257,14 @@ class Checkbox extends KeyDownHandledMixin(KeyToActionMixin(AutoFocusOnMountMixi
|
|
|
235
257
|
}
|
|
236
258
|
Checkbox.styles = [...FormfieldWrapper.styles, ...styles];
|
|
237
259
|
Checkbox.shadowRootOptions = { ...FormfieldWrapper.shadowRootOptions, delegatesFocus: true };
|
|
260
|
+
__decorate([
|
|
261
|
+
property({
|
|
262
|
+
converter: {
|
|
263
|
+
fromAttribute: value => (value === null ? 0 : Number(value)),
|
|
264
|
+
},
|
|
265
|
+
}),
|
|
266
|
+
__metadata("design:type", Object)
|
|
267
|
+
], Checkbox.prototype, "tabIndex", void 0);
|
|
238
268
|
__decorate([
|
|
239
269
|
property({ type: Boolean, reflect: true }),
|
|
240
270
|
__metadata("design:type", Object)
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { CSSResult, PropertyValues } from 'lit';
|
|
2
|
+
import type Checkbox from '../checkbox/checkbox.component';
|
|
3
|
+
import FormfieldGroup from '../formfieldgroup/formfieldgroup.component';
|
|
4
|
+
declare const CheckboxTree_base: import("../../utils/mixins/index.types").Constructor<import("../../models").Component & import("../../utils/mixins/ListNavigationMixin").ListNavigationMixinInterface & import("../../utils/mixins/KeyToActionMixin").KeyToActionInterface & import("../../utils/mixins/KeyDownHandledMixin").KeyDownHandledMixinInterface> & typeof FormfieldGroup;
|
|
5
|
+
/**
|
|
6
|
+
* The checkbox tree lets people select related options at different levels while parent choices summarize and control
|
|
7
|
+
* their descendants. It supports hierarchical choice sets that would be difficult to understand as one flat group.
|
|
8
|
+
*
|
|
9
|
+
* **When to use**
|
|
10
|
+
*
|
|
11
|
+
* - Use `mdc-checkboxtree` when options belong to categories and people need to select any number of categories or
|
|
12
|
+
* individual descendants.
|
|
13
|
+
* - Use `mdc-checkboxtree` when a parent choice must select or clear every available option in its branch.
|
|
14
|
+
* - Use `mdc-checkboxtree` when mixed parent states help people understand that only part of a category is selected.
|
|
15
|
+
*
|
|
16
|
+
* **When not to use**
|
|
17
|
+
*
|
|
18
|
+
* - Do not use a checkbox tree for a flat list of unrelated options. Use `mdc-formfieldgroup` with direct `mdc-checkbox`
|
|
19
|
+
* children instead.
|
|
20
|
+
* - Do not use a checkbox tree when exactly one option can be selected. Use `mdc-radiogroup` with `mdc-radio` children
|
|
21
|
+
* instead.
|
|
22
|
+
* - Do not use a deeply nested checkbox tree when the hierarchy can be split into smaller steps or filtered lists.
|
|
23
|
+
* Shallower choices are easier to scan and use on small screens.
|
|
24
|
+
*
|
|
25
|
+
* @tagname mdc-checkboxtree
|
|
26
|
+
*
|
|
27
|
+
* @dependency mdc-button
|
|
28
|
+
* @dependency mdc-checkbox
|
|
29
|
+
* @dependency mdc-icon
|
|
30
|
+
* @dependency mdc-statusmessage
|
|
31
|
+
* @dependency mdc-text
|
|
32
|
+
* @dependency mdc-toggletip
|
|
33
|
+
*
|
|
34
|
+
* @slot default - Direct `mdc-checkbox` children and nested `mdc-checkboxtree` descendants. A nested tree belongs to the checkbox immediately before it.
|
|
35
|
+
* @slot label - Slot for the visible group label. If omitted, the `label` property is used.
|
|
36
|
+
* @slot toggletip - Slot for the label's information button and toggletip.
|
|
37
|
+
* @slot help-icon - Slot for the helper or validation icon.
|
|
38
|
+
* @slot help-text - Slot for the helper or validation text.
|
|
39
|
+
*
|
|
40
|
+
* @csspart group-header - Container for the outer tree's label and helper text.
|
|
41
|
+
* @csspart label - The outer tree's label.
|
|
42
|
+
* @csspart label-text - Container for the label, required indicator, and information button.
|
|
43
|
+
* @csspart required-indicator - Required indicator displayed next to the label.
|
|
44
|
+
* @csspart info-icon-btn - Information button displayed next to the label.
|
|
45
|
+
* @csspart label-toggletip - Toggletip associated with the information button.
|
|
46
|
+
* @csspart help-text - Helper or validation text.
|
|
47
|
+
* @csspart helper-icon - Helper or validation icon.
|
|
48
|
+
* @csspart help-text-container - Container for helper or validation content.
|
|
49
|
+
*
|
|
50
|
+
* @cssproperty --mdc-checkboxtree-indent - Inline indentation added by each nested tree.
|
|
51
|
+
*/
|
|
52
|
+
declare class CheckboxTree extends CheckboxTree_base {
|
|
53
|
+
/** @internal */
|
|
54
|
+
protected loop: 'true' | 'false';
|
|
55
|
+
/** @internal */
|
|
56
|
+
private generatedAriaLabel?;
|
|
57
|
+
private pendingSynchronization;
|
|
58
|
+
constructor();
|
|
59
|
+
connectedCallback(): void;
|
|
60
|
+
/** @internal */
|
|
61
|
+
private get parentTree();
|
|
62
|
+
/** @internal */
|
|
63
|
+
private get rootTree();
|
|
64
|
+
/** @internal */
|
|
65
|
+
private get isNested();
|
|
66
|
+
/** @internal */
|
|
67
|
+
protected get navItems(): Checkbox[];
|
|
68
|
+
/** @internal */
|
|
69
|
+
protected setInitialFocus(): void;
|
|
70
|
+
/** @internal */
|
|
71
|
+
private getCheckboxes;
|
|
72
|
+
/** @internal */
|
|
73
|
+
private handleSlotChange;
|
|
74
|
+
/** @internal */
|
|
75
|
+
private handleCheckboxModified;
|
|
76
|
+
/** Coalesces checkbox modifications into one full-tree synchronization. @internal */
|
|
77
|
+
private scheduleSynchronizeTree;
|
|
78
|
+
/** @internal */
|
|
79
|
+
private handleCheckboxChange;
|
|
80
|
+
/** @internal */
|
|
81
|
+
private getChildTree;
|
|
82
|
+
/** @internal */
|
|
83
|
+
private getParentCheckbox;
|
|
84
|
+
/** @internal */
|
|
85
|
+
private setDescendantState;
|
|
86
|
+
/** @internal */
|
|
87
|
+
private synchronizeTree;
|
|
88
|
+
/** @internal */
|
|
89
|
+
private synchronizeParentStates;
|
|
90
|
+
/** @internal */
|
|
91
|
+
private synchronizeTabIndexes;
|
|
92
|
+
/** @internal */
|
|
93
|
+
private synchronizeContext;
|
|
94
|
+
update(changedProperties: PropertyValues): void;
|
|
95
|
+
protected updated(changedProperties: PropertyValues): void;
|
|
96
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
97
|
+
static styles: Array<CSSResult>;
|
|
98
|
+
}
|
|
99
|
+
export default CheckboxTree;
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { html, nothing } from 'lit';
|
|
2
|
+
import { ListNavigationMixin } from '../../utils/mixins/ListNavigationMixin';
|
|
3
|
+
import { ROLE } from '../../utils/roles';
|
|
4
|
+
import { TAG_NAME as CHECKBOX_TAG_NAME } from '../checkbox/checkbox.constants';
|
|
5
|
+
import FormfieldGroup from '../formfieldgroup/formfieldgroup.component';
|
|
6
|
+
import { VALIDATION } from '../formfieldwrapper/formfieldwrapper.constants';
|
|
7
|
+
import { TAG_NAME } from './checkboxtree.constants';
|
|
8
|
+
import styles from './checkboxtree.styles';
|
|
9
|
+
/**
|
|
10
|
+
* @tagname mdc-checkboxtree
|
|
11
|
+
*
|
|
12
|
+
* @dependency mdc-button
|
|
13
|
+
* @dependency mdc-checkbox
|
|
14
|
+
* @dependency mdc-icon
|
|
15
|
+
* @dependency mdc-statusmessage
|
|
16
|
+
* @dependency mdc-text
|
|
17
|
+
* @dependency mdc-toggletip
|
|
18
|
+
*
|
|
19
|
+
* @slot default - Direct `mdc-checkbox` children and nested `mdc-checkboxtree` descendants. A nested tree belongs to the checkbox immediately before it.
|
|
20
|
+
* @slot label - Slot for the visible group label. If omitted, the `label` property is used.
|
|
21
|
+
* @slot toggletip - Slot for the label's information button and toggletip.
|
|
22
|
+
* @slot help-icon - Slot for the helper or validation icon.
|
|
23
|
+
* @slot help-text - Slot for the helper or validation text.
|
|
24
|
+
*
|
|
25
|
+
* @csspart group-header - Container for the outer tree's label and helper text.
|
|
26
|
+
* @csspart label - The outer tree's label.
|
|
27
|
+
* @csspart label-text - Container for the label, required indicator, and information button.
|
|
28
|
+
* @csspart required-indicator - Required indicator displayed next to the label.
|
|
29
|
+
* @csspart info-icon-btn - Information button displayed next to the label.
|
|
30
|
+
* @csspart label-toggletip - Toggletip associated with the information button.
|
|
31
|
+
* @csspart help-text - Helper or validation text.
|
|
32
|
+
* @csspart helper-icon - Helper or validation icon.
|
|
33
|
+
* @csspart help-text-container - Container for helper or validation content.
|
|
34
|
+
*
|
|
35
|
+
* @cssproperty --mdc-checkboxtree-indent - Inline indentation added by each nested tree.
|
|
36
|
+
*/
|
|
37
|
+
class CheckboxTree extends ListNavigationMixin(FormfieldGroup) {
|
|
38
|
+
constructor() {
|
|
39
|
+
super();
|
|
40
|
+
/** @internal */
|
|
41
|
+
this.loop = 'false';
|
|
42
|
+
this.pendingSynchronization = false;
|
|
43
|
+
/** @internal */
|
|
44
|
+
this.handleSlotChange = () => {
|
|
45
|
+
this.rootTree.synchronizeTree();
|
|
46
|
+
};
|
|
47
|
+
/** @internal */
|
|
48
|
+
this.handleCheckboxModified = (event) => {
|
|
49
|
+
if (this.isNested || !(event.target instanceof HTMLElement) || !event.target.matches(CHECKBOX_TAG_NAME))
|
|
50
|
+
return;
|
|
51
|
+
this.scheduleSynchronizeTree();
|
|
52
|
+
};
|
|
53
|
+
/** @internal */
|
|
54
|
+
this.handleCheckboxChange = (event) => {
|
|
55
|
+
if (this.isNested || !(event.target instanceof HTMLElement) || !event.target.matches(CHECKBOX_TAG_NAME))
|
|
56
|
+
return;
|
|
57
|
+
const checkbox = event.target;
|
|
58
|
+
const childTree = this.getChildTree(checkbox);
|
|
59
|
+
if (childTree) {
|
|
60
|
+
this.setDescendantState(childTree, checkbox.checked);
|
|
61
|
+
}
|
|
62
|
+
this.synchronizeParentStates();
|
|
63
|
+
};
|
|
64
|
+
this.addEventListener('change', this.handleCheckboxChange);
|
|
65
|
+
this.addEventListener('modified', this.handleCheckboxModified);
|
|
66
|
+
}
|
|
67
|
+
connectedCallback() {
|
|
68
|
+
var _a;
|
|
69
|
+
const ariaLabelBeforeConnection = this.getAttribute('aria-label');
|
|
70
|
+
super.connectedCallback();
|
|
71
|
+
if (this.generatedAriaLabel === undefined && ariaLabelBeforeConnection === null) {
|
|
72
|
+
this.generatedAriaLabel = (_a = this.label) !== null && _a !== void 0 ? _a : '';
|
|
73
|
+
}
|
|
74
|
+
this.synchronizeContext();
|
|
75
|
+
if (!this.isNested) {
|
|
76
|
+
this.synchronizeTree();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** @internal */
|
|
80
|
+
get parentTree() {
|
|
81
|
+
var _a, _b;
|
|
82
|
+
return (_b = (_a = this.parentElement) === null || _a === void 0 ? void 0 : _a.closest(TAG_NAME)) !== null && _b !== void 0 ? _b : null;
|
|
83
|
+
}
|
|
84
|
+
/** @internal */
|
|
85
|
+
get rootTree() {
|
|
86
|
+
var _a, _b;
|
|
87
|
+
return (_b = (_a = this.parentTree) === null || _a === void 0 ? void 0 : _a.rootTree) !== null && _b !== void 0 ? _b : this;
|
|
88
|
+
}
|
|
89
|
+
/** @internal */
|
|
90
|
+
get isNested() {
|
|
91
|
+
return this.parentTree !== null;
|
|
92
|
+
}
|
|
93
|
+
/** @internal */
|
|
94
|
+
get navItems() {
|
|
95
|
+
if (this.isNested)
|
|
96
|
+
return [];
|
|
97
|
+
return this.getCheckboxes().filter(checkbox => !checkbox.disabled);
|
|
98
|
+
}
|
|
99
|
+
/** @internal */
|
|
100
|
+
setInitialFocus() {
|
|
101
|
+
if (this.isNested)
|
|
102
|
+
return;
|
|
103
|
+
this.synchronizeTabIndexes();
|
|
104
|
+
}
|
|
105
|
+
/** @internal */
|
|
106
|
+
getCheckboxes() {
|
|
107
|
+
return Array.from(this.querySelectorAll(CHECKBOX_TAG_NAME));
|
|
108
|
+
}
|
|
109
|
+
/** Coalesces checkbox modifications into one full-tree synchronization. @internal */
|
|
110
|
+
scheduleSynchronizeTree() {
|
|
111
|
+
if (this.pendingSynchronization)
|
|
112
|
+
return;
|
|
113
|
+
this.pendingSynchronization = true;
|
|
114
|
+
queueMicrotask(() => {
|
|
115
|
+
this.pendingSynchronization = false;
|
|
116
|
+
this.synchronizeTree();
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
/** @internal */
|
|
120
|
+
getChildTree(checkbox) {
|
|
121
|
+
const sibling = checkbox.nextElementSibling;
|
|
122
|
+
return (sibling === null || sibling === void 0 ? void 0 : sibling.matches(TAG_NAME)) ? sibling : null;
|
|
123
|
+
}
|
|
124
|
+
/** @internal */
|
|
125
|
+
getParentCheckbox(tree) {
|
|
126
|
+
const sibling = tree.previousElementSibling;
|
|
127
|
+
return (sibling === null || sibling === void 0 ? void 0 : sibling.matches(CHECKBOX_TAG_NAME)) ? sibling : null;
|
|
128
|
+
}
|
|
129
|
+
/** @internal */
|
|
130
|
+
setDescendantState(tree, checked) {
|
|
131
|
+
tree.getCheckboxes().forEach(checkbox => {
|
|
132
|
+
if (checkbox.disabled || checkbox.readonly || checkbox.softDisabled)
|
|
133
|
+
return;
|
|
134
|
+
const descendant = checkbox;
|
|
135
|
+
descendant.checked = checked;
|
|
136
|
+
descendant.indeterminate = false;
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
/** @internal */
|
|
140
|
+
synchronizeTree() {
|
|
141
|
+
if (this.isNested || !this.isConnected)
|
|
142
|
+
return;
|
|
143
|
+
this.synchronizeParentStates();
|
|
144
|
+
this.synchronizeTabIndexes();
|
|
145
|
+
}
|
|
146
|
+
/** @internal */
|
|
147
|
+
synchronizeParentStates() {
|
|
148
|
+
const nestedTrees = Array.from(this.querySelectorAll(TAG_NAME)).reverse();
|
|
149
|
+
nestedTrees.forEach(tree => {
|
|
150
|
+
const parentCheckbox = this.getParentCheckbox(tree);
|
|
151
|
+
const descendants = tree.getCheckboxes();
|
|
152
|
+
if (!parentCheckbox || descendants.length === 0)
|
|
153
|
+
return;
|
|
154
|
+
const allChecked = descendants.every(checkbox => checkbox.checked && !checkbox.indeterminate);
|
|
155
|
+
const anyChecked = descendants.some(checkbox => checkbox.checked || checkbox.indeterminate);
|
|
156
|
+
parentCheckbox.checked = allChecked;
|
|
157
|
+
parentCheckbox.indeterminate = !allChecked && anyChecked;
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
/** @internal */
|
|
161
|
+
synchronizeTabIndexes() {
|
|
162
|
+
var _a;
|
|
163
|
+
const checkboxes = this.getCheckboxes();
|
|
164
|
+
const navigableCheckboxes = checkboxes.filter(checkbox => !checkbox.disabled);
|
|
165
|
+
const focusedCheckbox = navigableCheckboxes.find(checkbox => checkbox.matches(':focus-within'));
|
|
166
|
+
const currentCheckbox = navigableCheckboxes.find(checkbox => checkbox.getAttribute('tabindex') === '0');
|
|
167
|
+
const activeCheckbox = (_a = focusedCheckbox !== null && focusedCheckbox !== void 0 ? focusedCheckbox : currentCheckbox) !== null && _a !== void 0 ? _a : navigableCheckboxes[0];
|
|
168
|
+
checkboxes.forEach(checkbox => {
|
|
169
|
+
checkbox.setAttribute('tabindex', checkbox === activeCheckbox ? '0' : '-1');
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
/** @internal */
|
|
173
|
+
synchronizeContext() {
|
|
174
|
+
var _a;
|
|
175
|
+
if (this.isNested) {
|
|
176
|
+
this.removeAttribute('aria-description');
|
|
177
|
+
this.removeAttribute('aria-invalid');
|
|
178
|
+
this.removeAttribute('aria-label');
|
|
179
|
+
this.removeAttribute('role');
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
this.role = ROLE.GROUP;
|
|
183
|
+
this.ariaDescription = (_a = this.helpText) !== null && _a !== void 0 ? _a : '';
|
|
184
|
+
if (this.helpTextType === VALIDATION.ERROR) {
|
|
185
|
+
this.setAttribute('aria-invalid', 'true');
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
this.removeAttribute('aria-invalid');
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
update(changedProperties) {
|
|
192
|
+
var _a;
|
|
193
|
+
// Capture before FormfieldGroup may regenerate aria-label from label.
|
|
194
|
+
const ariaLabelBeforeUpdate = this.getAttribute('aria-label');
|
|
195
|
+
super.update(changedProperties);
|
|
196
|
+
if (!this.isNested && (ariaLabelBeforeUpdate === null || ariaLabelBeforeUpdate === this.generatedAriaLabel)) {
|
|
197
|
+
this.generatedAriaLabel = (_a = this.label) !== null && _a !== void 0 ? _a : '';
|
|
198
|
+
this.setAttribute('aria-label', this.generatedAriaLabel);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
updated(changedProperties) {
|
|
202
|
+
super.updated(changedProperties);
|
|
203
|
+
this.synchronizeContext();
|
|
204
|
+
}
|
|
205
|
+
render() {
|
|
206
|
+
return html `
|
|
207
|
+
${this.isNested ? nothing : html `<div part="group-header">${this.renderLabel()} ${this.renderHelperText()}</div>`}
|
|
208
|
+
<slot @slotchange=${this.handleSlotChange}></slot>
|
|
209
|
+
`;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
CheckboxTree.styles = [...FormfieldGroup.styles, ...styles];
|
|
213
|
+
export default CheckboxTree;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
const styles = css `
|
|
3
|
+
:host {
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
max-width: 100%;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
:host::part(label) {
|
|
9
|
+
overflow: visible;
|
|
10
|
+
text-overflow: clip;
|
|
11
|
+
white-space: normal;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
::slotted(mdc-checkbox),
|
|
15
|
+
::slotted(mdc-checkboxtree) {
|
|
16
|
+
box-sizing: border-box;
|
|
17
|
+
max-width: 100%;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
::slotted(mdc-checkboxtree) {
|
|
21
|
+
/* Keep the fallback here so consumer overrides inherit through nested trees. */
|
|
22
|
+
padding-inline-start: var(--mdc-checkboxtree-indent, 1.5rem);
|
|
23
|
+
}
|
|
24
|
+
`;
|
|
25
|
+
export default [styles];
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import '../button';
|
|
2
|
+
import '../checkbox';
|
|
3
|
+
import '../icon';
|
|
4
|
+
import '../statusmessage';
|
|
5
|
+
import '../text';
|
|
6
|
+
import '../toggletip';
|
|
7
|
+
import CheckboxTree from './checkboxtree.component';
|
|
8
|
+
declare global {
|
|
9
|
+
interface HTMLElementTagNameMap {
|
|
10
|
+
['mdc-checkboxtree']: CheckboxTree;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export default CheckboxTree;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import '../button';
|
|
2
|
+
import '../checkbox';
|
|
3
|
+
import '../icon';
|
|
4
|
+
import '../statusmessage';
|
|
5
|
+
import '../text';
|
|
6
|
+
import '../toggletip';
|
|
7
|
+
import CheckboxTree from './checkboxtree.component';
|
|
8
|
+
import { TAG_NAME } from './checkboxtree.constants';
|
|
9
|
+
CheckboxTree.register(TAG_NAME);
|
|
10
|
+
export default CheckboxTree;
|
|
@@ -2,7 +2,7 @@ import { CSSResult, PropertyValues, TemplateResult } from 'lit';
|
|
|
2
2
|
import { Component } from '../../models';
|
|
3
3
|
import type { TextType } from '../text/text.types';
|
|
4
4
|
import { ListItemVariants } from './listitem.types';
|
|
5
|
-
declare const ListItem_base: import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/KeyDownHandledMixin").KeyDownHandledMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/KeyToActionMixin").KeyToActionInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/DisabledMixin").DisabledMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/TabIndexMixin").TabIndexMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/lifecycle/
|
|
5
|
+
declare const ListItem_base: import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/KeyDownHandledMixin").KeyDownHandledMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/KeyToActionMixin").KeyToActionInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/DisabledMixin").DisabledMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/TabIndexMixin").TabIndexMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/lifecycle/ModifiedEventMixin").ModifiedEventMixinInterface> & typeof Component;
|
|
6
6
|
/**
|
|
7
7
|
* `mdc-listitem` is the row primitive for an `mdc-list` — a single focusable entry that presents one piece of repeated content and lets the user act on it. The parent `mdc-list` manages navigation between rows, so each item only has to represent its own content and behavior.
|
|
8
8
|
*
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CSSResult, PropertyValues } from 'lit';
|
|
2
2
|
import Buttonsimple from '../buttonsimple/buttonsimple.component';
|
|
3
3
|
import type { TabSize, Variant } from './tab.types';
|
|
4
|
-
declare const Tab_base: import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/IconNameMixin").IconNameMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/lifecycle/
|
|
4
|
+
declare const Tab_base: import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/IconNameMixin").IconNameMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/lifecycle/ModifiedEventMixin").ModifiedEventMixinInterface> & typeof Buttonsimple;
|
|
5
5
|
/**
|
|
6
6
|
* `mdc-tab` is a single tab control inside an `mdc-tablist`, representing one panel of related content the user can switch to. It shows which panel is currently active, while the parent `mdc-tablist` owns focus movement and selection.
|
|
7
7
|
*
|