• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

adobe / spectrum-web-components / 13322647394

14 Feb 2025 04:40AM UTC coverage: 98.189%. First build
13322647394

Pull #5082

github

web-flow
Merge 88793c34c into ff7318295
Pull Request #5082: fix(menu): make submenu scrollable

5187 of 5464 branches covered (94.93%)

Branch coverage included in aggregate %.

33099 of 33528 relevant lines covered (98.72%)

386.54 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.12
/tools/shared/src/observe-slot-presence.ts
1
/*
65✔
2
Copyright 2020 Adobe. All rights reserved.
65✔
3
This file is licensed to you under the Apache License, Version 2.0 (the "License");
65✔
4
you may not use this file except in compliance with the License. You may obtain a copy
65✔
5
of the License at http://www.apache.org/licenses/LICENSE-2.0
65✔
6
Unless required by applicable law or agreed to in writing, software distributed under
65✔
7
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
65✔
8
OF ANY KIND, either express or implied. See the License for the specific language
65✔
9
governing permissions and limitations under the License.
65✔
10
*/
65✔
11
import { ReactiveElement } from '@spectrum-web-components/base';
65✔
12
import { MutationController } from '@lit-labs/observers/mutation-controller.js';
65✔
13

65✔
14
const slotContentIsPresent = Symbol('slotContentIsPresent');
65✔
15

65✔
16
type Constructor<T = Record<string, unknown>> = {
65✔
17
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
65✔
18
    new (...args: any[]): T;
65✔
19
    prototype: T;
65✔
20
};
65✔
21

65✔
22
export interface SlotPresenceObservingInterface {
65✔
23
    slotContentIsPresent: boolean;
65✔
24
    getSlotContentPresence(selector: string): boolean;
65✔
25
    managePresenceObservedSlot(): void;
65✔
26
}
65✔
27

65✔
28
export function ObserveSlotPresence<T extends Constructor<ReactiveElement>>(
65✔
29
    constructor: T,
89✔
30
    lightDomSelector: string | string[]
89✔
31
): T & Constructor<SlotPresenceObservingInterface> {
89✔
32
    const lightDomSelectors = Array.isArray(lightDomSelector)
89✔
33
        ? lightDomSelector
24✔
34
        : [lightDomSelector];
65✔
35
    class SlotPresenceObservingElement
89✔
36
        extends constructor
89✔
37
        implements SlotPresenceObservingInterface
89✔
38
    {
89✔
39
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
89✔
40
        constructor(...args: any[]) {
89✔
41
            super(args);
5,615✔
42

5,615✔
43
            new MutationController(this, {
5,615✔
44
                config: {
5,615✔
45
                    childList: true,
5,615✔
46
                    subtree: true,
5,615✔
47
                },
5,615✔
48
                callback: () => {
5,615✔
49
                    this.managePresenceObservedSlot();
5,727✔
50
                },
5,727✔
51
            });
5,615✔
52

5,615✔
53
            this.managePresenceObservedSlot();
5,615✔
54
        }
5,615✔
55

89✔
56
        /**
89✔
57
         *  @private
89✔
58
         */
89✔
59
        public get slotContentIsPresent(): boolean {
89✔
60
            if (lightDomSelectors.length === 1) {
2,692✔
61
                return (
2,692✔
62
                    this[slotContentIsPresent].get(lightDomSelectors[0]) ||
2,692✔
63
                    false
2,648✔
64
                );
2,692✔
65
            } else {
2,692✔
66
                throw new Error(
×
67
                    'Multiple selectors provided to `ObserveSlotPresence` use `getSlotContentPresence(selector: string)` instead.'
×
68
                );
×
69
            }
×
70
        }
2,692✔
71
        private [slotContentIsPresent]: Map<string, boolean> = new Map();
89✔
72

89✔
73
        public getSlotContentPresence(selector: string): boolean {
89✔
74
            if (this[slotContentIsPresent].has(selector)) {
913✔
75
                return this[slotContentIsPresent].get(selector) || false;
913✔
76
            }
913✔
77
            throw new Error(
×
78
                `The provided selector \`${selector}\` is not being observed.`
×
79
            );
×
80
        }
913✔
81

89✔
82
        public managePresenceObservedSlot = (): void => {
89✔
83
            let changes = false;
11,359✔
84
            lightDomSelectors.forEach((selector) => {
11,359✔
85
                const nextValue = !!this.querySelector(`:scope > ${selector}`);
12,331✔
86
                const previousValue =
12,331✔
87
                    this[slotContentIsPresent].get(selector) || false;
12,331✔
88
                changes = changes || previousValue !== nextValue;
12,331✔
89
                this[slotContentIsPresent].set(
12,331✔
90
                    selector,
12,331✔
91
                    !!this.querySelector(`:scope > ${selector}`)
12,331✔
92
                );
12,331✔
93
            });
11,359✔
94
            if (changes) {
11,359✔
95
                this.updateComplete.then(() => {
306✔
96
                    this.requestUpdate();
306✔
97
                });
306✔
98
            }
306✔
99
        };
11,359✔
100
    }
89✔
101
    return SlotPresenceObservingElement;
89✔
102
}
89✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc