Skip to content

Commit 7410dee

Browse files
authored
refactor: Abstracted ShadowRoot options into a decorator (#1760)
1 parent 2e7c295 commit 7410dee

8 files changed

Lines changed: 37 additions & 37 deletions

File tree

src/components/button-group/toggle-button.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { property, query } from 'lit/decorators.js';
33

44
import { themes } from '../../theming/theming-decorator.js';
55
import { addKeyboardFocusRing } from '../common/controllers/focus-ring.js';
6+
import { shadowOptions } from '../common/decorators/shadow-options.js';
67
import { registerComponent } from '../common/definitions/register.js';
78
import { partMap } from '../common/part-map.js';
89
import { styles } from './themes/button.base.css.js';
@@ -20,15 +21,11 @@ import { styles as shared } from './themes/shared/button/button.common.css.js';
2021
* @csspart toggle - The native button element.
2122
*/
2223
@themes(all)
24+
@shadowOptions({ delegatesFocus: true })
2325
export default class IgcToggleButtonComponent extends LitElement {
2426
public static override styles = [styles, shared];
2527
public static readonly tagName = 'igc-toggle-button';
2628

27-
public static override shadowRootOptions = {
28-
...LitElement.shadowRootOptions,
29-
delegatesFocus: true,
30-
};
31-
3229
/* blazorSuppress */
3330
public static register(): void {
3431
registerComponent(IgcToggleButtonComponent);

src/components/button/button-base.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { ifDefined } from 'lit/directives/if-defined.js';
44
import { addKeyboardFocusRing } from '../common/controllers/focus-ring.js';
55
import { addInternalsController } from '../common/controllers/internals.js';
66
import { blazorDeepImport } from '../common/decorators/blazorDeepImport.js';
7+
import { shadowOptions } from '../common/decorators/shadow-options.js';
78
import type { Constructor } from '../common/mixins/constructor.js';
89
import { EventEmitterMixin } from '../common//mixins/event-emitter.js';
910
import { partMap } from '../common/part-map.js';
@@ -17,17 +18,13 @@ export interface IgcButtonEventMap {
1718
}
1819

1920
@blazorDeepImport
21+
@shadowOptions({ delegatesFocus: true })
2022
export abstract class IgcButtonBaseComponent extends EventEmitterMixin<
2123
IgcButtonEventMap,
2224
Constructor<LitElement>
2325
>(LitElement) {
2426
public static readonly formAssociated = true;
2527

26-
protected static shadowRootOptions = {
27-
...LitElement.shadowRootOptions,
28-
delegatesFocus: true,
29-
};
30-
3128
protected readonly _internals = addInternalsController(this);
3229
private readonly _focusRingManager = addKeyboardFocusRing(this);
3330

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { LitElement } from 'lit';
2+
3+
/**
4+
* TypeScript decorator that allows customizing the Shadow DOM options for a LitElement component.
5+
*
6+
* This decorator merges the provided `options` with LitElement's default `shadowRootOptions`,
7+
* providing a convenient way to configure the Shadow DOM, such as its `mode` (e.g., 'open' or 'closed')
8+
* or `delegatesFocus` property.
9+
*
10+
* https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow#options
11+
*/
12+
export function shadowOptions(
13+
options: Partial<ShadowRootInit>
14+
): (proto: unknown) => void {
15+
return (proto: unknown) => {
16+
(proto as typeof LitElement).shadowRootOptions = {
17+
...LitElement.shadowRootOptions,
18+
...options,
19+
};
20+
};
21+
}

src/components/date-picker/date-picker.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { html, LitElement, nothing, type TemplateResult } from 'lit';
1+
import { html, nothing, type TemplateResult } from 'lit';
22
import { property, query, queryAssignedElements } from 'lit/decorators.js';
33
import { ifDefined } from 'lit/directives/if-defined.js';
44
import { live } from 'lit/directives/live.js';
@@ -20,6 +20,7 @@ import {
2020
escapeKey,
2121
} from '../common/controllers/key-bindings.js';
2222
import { blazorAdditionalDependencies } from '../common/decorators/blazorAdditionalDependencies.js';
23+
import { shadowOptions } from '../common/decorators/shadow-options.js';
2324
import { watch } from '../common/decorators/watch.js';
2425
import { registerComponent } from '../common/definitions/register.js';
2526
import {
@@ -150,6 +151,7 @@ export interface IgcDatePickerComponentEventMap {
150151
@blazorAdditionalDependencies(
151152
'IgcCalendarComponent, IgcDateTimeInputComponent, IgcDialogComponent, IgcIconComponent'
152153
)
154+
@shadowOptions({ delegatesFocus: true })
153155
export default class IgcDatePickerComponent extends FormAssociatedRequiredMixin(
154156
EventEmitterMixin<
155157
IgcDatePickerComponentEventMap,
@@ -159,11 +161,6 @@ export default class IgcDatePickerComponent extends FormAssociatedRequiredMixin(
159161
public static readonly tagName = 'igc-date-picker';
160162
public static styles = [styles, shared];
161163

162-
protected static shadowRootOptions = {
163-
...LitElement.shadowRootOptions,
164-
delegatesFocus: true,
165-
};
166-
167164
/* blazorSuppress */
168165
public static register(): void {
169166
registerComponent(

src/components/date-range-picker/date-range-picker.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { html, LitElement, nothing, type TemplateResult } from 'lit';
1+
import { html, nothing, type TemplateResult } from 'lit';
22
import {
33
property,
44
query,
@@ -25,6 +25,7 @@ import {
2525
escapeKey,
2626
} from '../common/controllers/key-bindings.js';
2727
import { blazorAdditionalDependencies } from '../common/decorators/blazorAdditionalDependencies.js';
28+
import { shadowOptions } from '../common/decorators/shadow-options.js';
2829
import { watch } from '../common/decorators/watch.js';
2930
import { registerComponent } from '../common/definitions/register.js';
3031
import { IgcDateRangePickerResourceStringsEN } from '../common/i18n/date-range-picker.resources.js';
@@ -179,6 +180,7 @@ export interface IgcDateRangePickerComponentEventMap {
179180
@blazorAdditionalDependencies(
180181
'IgcCalendarComponent, IgcDateTimeInputComponent, IgcDialogComponent, IgcIconComponent, IgcChipComponent, IgcInputComponent'
181182
)
183+
@shadowOptions({ delegatesFocus: true })
182184
export default class IgcDateRangePickerComponent extends FormAssociatedRequiredMixin(
183185
EventEmitterMixin<
184186
IgcDateRangePickerComponentEventMap,
@@ -188,11 +190,6 @@ export default class IgcDateRangePickerComponent extends FormAssociatedRequiredM
188190
public static readonly tagName = 'igc-date-range-picker';
189191
public static styles = [styles, shared];
190192

191-
protected static shadowRootOptions = {
192-
...LitElement.shadowRootOptions,
193-
delegatesFocus: true,
194-
};
195-
196193
/* blazorSuppress */
197194
public static register(): void {
198195
registerComponent(

src/components/input/input-base.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { property, query, queryAssignedElements } from 'lit/decorators.js';
33

44
import { getThemeController, themes } from '../../theming/theming-decorator.js';
55
import { blazorDeepImport } from '../common/decorators/blazorDeepImport.js';
6+
import { shadowOptions } from '../common/decorators/shadow-options.js';
67
import type { Constructor } from '../common/mixins/constructor.js';
78
import { EventEmitterMixin } from '../common/mixins/event-emitter.js';
89
import { FormAssociatedRequiredMixin } from '../common/mixins/forms/associated-required.js';
@@ -28,16 +29,12 @@ export interface IgcInputComponentEventMap {
2829

2930
@blazorDeepImport
3031
@themes(all, { exposeController: true })
32+
@shadowOptions({ delegatesFocus: true })
3133
export abstract class IgcInputBaseComponent extends FormAssociatedRequiredMixin(
3234
EventEmitterMixin<IgcInputComponentEventMap, Constructor<LitElement>>(
3335
LitElement
3436
)
3537
) {
36-
protected static shadowRootOptions = {
37-
...LitElement.shadowRootOptions,
38-
delegatesFocus: true,
39-
};
40-
4138
public static styles = [styles, shared];
4239
private static readonly increment = createCounter();
4340

src/components/textarea/textarea.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { type StyleInfo, styleMap } from 'lit/directives/style-map.js';
1111

1212
import { getThemeController, themes } from '../../theming/theming-decorator.js';
1313
import { createResizeObserverController } from '../common/controllers/resize-observer.js';
14+
import { shadowOptions } from '../common/decorators/shadow-options.js';
1415
import { watch } from '../common/decorators/watch.js';
1516
import { registerComponent } from '../common/definitions/register.js';
1617
import type { Constructor } from '../common/mixins/constructor.js';
@@ -76,6 +77,7 @@ export interface IgcTextareaComponentEventMap {
7677
* @csspart helper-text - The helper text wrapper of the igc-textarea.
7778
*/
7879
@themes(all, { exposeController: true })
80+
@shadowOptions({ delegatesFocus: true })
7981
export default class IgcTextareaComponent extends FormAssociatedRequiredMixin(
8082
EventEmitterMixin<IgcTextareaComponentEventMap, Constructor<LitElement>>(
8183
LitElement
@@ -89,11 +91,6 @@ export default class IgcTextareaComponent extends FormAssociatedRequiredMixin(
8991
registerComponent(IgcTextareaComponent, IgcValidationContainerComponent);
9092
}
9193

92-
protected static shadowRootOptions = {
93-
...LitElement.shadowRootOptions,
94-
delegatesFocus: true,
95-
};
96-
9794
//#region Private properties and state
9895

9996
private static readonly increment = createCounter();

src/components/tile-manager/tile-manager.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
createMutationController,
1313
type MutationControllerParams,
1414
} from '../common/controllers/mutation-observer.js';
15+
import { shadowOptions } from '../common/decorators/shadow-options.js';
1516
import { registerComponent } from '../common/definitions/register.js';
1617
import { partMap } from '../common/part-map.js';
1718
import { asNumber } from '../common/util.js';
@@ -40,15 +41,11 @@ import IgcTileComponent from './tile.js';
4041
*
4142
*/
4243
@themes(all)
44+
@shadowOptions({ slotAssignment: 'manual' })
4345
export default class IgcTileManagerComponent extends LitElement {
4446
public static readonly tagName = 'igc-tile-manager';
4547
public static override styles = [styles, shared];
4648

47-
public static override shadowRootOptions: ShadowRootInit = {
48-
mode: 'open',
49-
slotAssignment: 'manual',
50-
};
51-
5249
/* blazorSuppress */
5350
public static register() {
5451
registerComponent(IgcTileManagerComponent, IgcTileComponent);

0 commit comments

Comments
 (0)