@patternfly/pfe-core 2.3.1 → 2.4.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.
- package/controllers/cascade-controller.js +1 -1
- package/controllers/cascade-controller.js.map +1 -1
- package/controllers/floating-dom-controller.d.ts +1 -1
- package/controllers/floating-dom-controller.js +81 -83
- package/controllers/floating-dom-controller.js.map +1 -1
- package/controllers/internals-controller.js +17 -20
- package/controllers/internals-controller.js.map +1 -1
- package/controllers/logger.js +1 -1
- package/controllers/logger.js.map +1 -1
- package/controllers/overflow-controller.js +42 -40
- package/controllers/overflow-controller.js.map +1 -1
- package/controllers/property-observer-controller.js +1 -1
- package/controllers/property-observer-controller.js.map +1 -1
- package/controllers/roving-tabindex-controller.js +114 -106
- package/controllers/roving-tabindex-controller.js.map +1 -1
- package/controllers/scroll-spy-controller.js +93 -91
- package/controllers/scroll-spy-controller.js.map +1 -1
- package/controllers/slot-controller.d.ts +2 -15
- package/controllers/slot-controller.js +47 -63
- package/controllers/slot-controller.js.map +1 -1
- package/controllers/timestamp-controller.d.ts +23 -0
- package/controllers/timestamp-controller.js +108 -0
- package/controllers/timestamp-controller.js.map +1 -0
- package/custom-elements.json +728 -627
- package/package.json +2 -1
|
@@ -1,120 +1,122 @@
|
|
|
1
|
-
var _ScrollSpyController_instances, _ScrollSpyController_tagNames, _ScrollSpyController_activeAttribute, _ScrollSpyController_io, _ScrollSpyController_passedLinks, _ScrollSpyController_force, _ScrollSpyController_intersected, _ScrollSpyController_root, _ScrollSpyController_rootMargin, _ScrollSpyController_threshold, _ScrollSpyController_rootNode, _ScrollSpyController_getHash, _ScrollSpyController_linkChildren_get, _ScrollSpyController_initIo, _ScrollSpyController_markPassed, _ScrollSpyController_setActive, _ScrollSpyController_nextIntersection, _ScrollSpyController_onIo;
|
|
2
|
-
import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
|
|
3
1
|
export class ScrollSpyController {
|
|
2
|
+
#tagNames;
|
|
3
|
+
#activeAttribute;
|
|
4
|
+
#io;
|
|
5
|
+
/** Which link's targets have already scrolled past? */
|
|
6
|
+
#passedLinks = new Set();
|
|
7
|
+
/** Ignore intersections? */
|
|
8
|
+
#force = false;
|
|
9
|
+
/** Has the intersection observer found an element? */
|
|
10
|
+
#intersected = false;
|
|
11
|
+
#root;
|
|
12
|
+
#rootMargin;
|
|
13
|
+
#threshold;
|
|
14
|
+
#rootNode;
|
|
15
|
+
#getHash;
|
|
16
|
+
get #linkChildren() {
|
|
17
|
+
return Array.from(this.host.querySelectorAll(this.#tagNames.join(',')))
|
|
18
|
+
.filter(this.#getHash);
|
|
19
|
+
}
|
|
4
20
|
get root() {
|
|
5
|
-
return
|
|
21
|
+
return this.#root;
|
|
6
22
|
}
|
|
7
23
|
set root(v) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
24
|
+
this.#root = v;
|
|
25
|
+
this.#io?.disconnect();
|
|
26
|
+
this.#initIo();
|
|
11
27
|
}
|
|
12
28
|
get rootMargin() {
|
|
13
|
-
return
|
|
29
|
+
return this.#rootMargin;
|
|
14
30
|
}
|
|
15
31
|
set rootMargin(v) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
32
|
+
this.#rootMargin = v;
|
|
33
|
+
this.#io?.disconnect();
|
|
34
|
+
this.#initIo();
|
|
19
35
|
}
|
|
20
36
|
get threshold() {
|
|
21
|
-
return
|
|
37
|
+
return this.#threshold;
|
|
22
38
|
}
|
|
23
39
|
set threshold(v) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
40
|
+
this.#threshold = v;
|
|
41
|
+
this.#io?.disconnect();
|
|
42
|
+
this.#initIo();
|
|
27
43
|
}
|
|
28
44
|
constructor(host, options) {
|
|
29
|
-
_ScrollSpyController_instances.add(this);
|
|
30
45
|
this.host = host;
|
|
31
|
-
_ScrollSpyController_tagNames.set(this, void 0);
|
|
32
|
-
_ScrollSpyController_activeAttribute.set(this, void 0);
|
|
33
|
-
_ScrollSpyController_io.set(this, void 0);
|
|
34
|
-
/** Which link's targets have already scrolled past? */
|
|
35
|
-
_ScrollSpyController_passedLinks.set(this, new Set());
|
|
36
|
-
/** Ignore intersections? */
|
|
37
|
-
_ScrollSpyController_force.set(this, false);
|
|
38
|
-
/** Has the intersection observer found an element? */
|
|
39
|
-
_ScrollSpyController_intersected.set(this, false);
|
|
40
|
-
_ScrollSpyController_root.set(this, void 0);
|
|
41
|
-
_ScrollSpyController_rootMargin.set(this, void 0);
|
|
42
|
-
_ScrollSpyController_threshold.set(this, void 0);
|
|
43
|
-
_ScrollSpyController_rootNode.set(this, void 0);
|
|
44
|
-
_ScrollSpyController_getHash.set(this, void 0);
|
|
45
46
|
host.addController(this);
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
47
|
+
this.#tagNames = options.tagNames;
|
|
48
|
+
this.#root = options.root;
|
|
49
|
+
this.#rootMargin = options.rootMargin;
|
|
50
|
+
this.#activeAttribute = options.activeAttribute ?? 'active';
|
|
51
|
+
this.#threshold = options.threshold ?? 0.85;
|
|
52
|
+
this.#rootNode = options.rootNode ?? host.getRootNode();
|
|
53
|
+
this.#getHash = options?.getHash ?? ((el) => el.getAttribute('href'));
|
|
53
54
|
}
|
|
54
55
|
hostConnected() {
|
|
55
|
-
|
|
56
|
+
this.#initIo();
|
|
56
57
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
58
|
+
#initIo() {
|
|
59
|
+
const rootNode = this.#rootNode;
|
|
60
|
+
if (rootNode instanceof Document || rootNode instanceof ShadowRoot) {
|
|
61
|
+
const { rootMargin, threshold, root } = this;
|
|
62
|
+
this.#io = new IntersectionObserver(r => this.#onIo(r), { root, rootMargin, threshold });
|
|
63
|
+
this.#linkChildren
|
|
64
|
+
.map(x => this.#getHash(x))
|
|
65
|
+
.filter((x) => !!x)
|
|
66
|
+
.map(x => rootNode.getElementById(x.replace('#', '')))
|
|
67
|
+
.filter((x) => !!x)
|
|
68
|
+
.forEach(target => this.#io?.observe(target));
|
|
67
69
|
}
|
|
68
|
-
await __classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_nextIntersection).call(this);
|
|
69
|
-
__classPrivateFieldSet(this, _ScrollSpyController_force, false, "f");
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
_ScrollSpyController_tagNames = new WeakMap(), _ScrollSpyController_activeAttribute = new WeakMap(), _ScrollSpyController_io = new WeakMap(), _ScrollSpyController_passedLinks = new WeakMap(), _ScrollSpyController_force = new WeakMap(), _ScrollSpyController_intersected = new WeakMap(), _ScrollSpyController_root = new WeakMap(), _ScrollSpyController_rootMargin = new WeakMap(), _ScrollSpyController_threshold = new WeakMap(), _ScrollSpyController_rootNode = new WeakMap(), _ScrollSpyController_getHash = new WeakMap(), _ScrollSpyController_instances = new WeakSet(), _ScrollSpyController_linkChildren_get = function _ScrollSpyController_linkChildren_get() {
|
|
73
|
-
return Array.from(this.host.querySelectorAll(__classPrivateFieldGet(this, _ScrollSpyController_tagNames, "f").join(',')))
|
|
74
|
-
.filter(__classPrivateFieldGet(this, _ScrollSpyController_getHash, "f"));
|
|
75
|
-
}, _ScrollSpyController_initIo = function _ScrollSpyController_initIo() {
|
|
76
|
-
const rootNode = __classPrivateFieldGet(this, _ScrollSpyController_rootNode, "f");
|
|
77
|
-
if (rootNode instanceof Document || rootNode instanceof ShadowRoot) {
|
|
78
|
-
const { rootMargin, threshold, root } = this;
|
|
79
|
-
__classPrivateFieldSet(this, _ScrollSpyController_io, new IntersectionObserver(r => __classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_onIo).call(this, r), { root, rootMargin, threshold }), "f");
|
|
80
|
-
__classPrivateFieldGet(this, _ScrollSpyController_instances, "a", _ScrollSpyController_linkChildren_get)
|
|
81
|
-
.map(x => __classPrivateFieldGet(this, _ScrollSpyController_getHash, "f").call(this, x))
|
|
82
|
-
.filter((x) => !!x)
|
|
83
|
-
.map(x => rootNode.getElementById(x.replace('#', '')))
|
|
84
|
-
.filter((x) => !!x)
|
|
85
|
-
.forEach(target => __classPrivateFieldGet(this, _ScrollSpyController_io, "f")?.observe(target));
|
|
86
70
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
71
|
+
#markPassed(link, force) {
|
|
72
|
+
if (force) {
|
|
73
|
+
this.#passedLinks.add(link);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
this.#passedLinks.delete(link);
|
|
77
|
+
}
|
|
90
78
|
}
|
|
91
|
-
|
|
92
|
-
|
|
79
|
+
#setActive(link) {
|
|
80
|
+
for (const child of this.#linkChildren) {
|
|
81
|
+
child.toggleAttribute(this.#activeAttribute, child === link);
|
|
82
|
+
}
|
|
93
83
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
84
|
+
async #nextIntersection() {
|
|
85
|
+
this.#intersected = false;
|
|
86
|
+
// safeguard the loop
|
|
87
|
+
setTimeout(() => this.#intersected = false, 3000);
|
|
88
|
+
while (!this.#intersected) {
|
|
89
|
+
await new Promise(requestAnimationFrame);
|
|
90
|
+
}
|
|
97
91
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
92
|
+
async #onIo(entries) {
|
|
93
|
+
if (!this.#force) {
|
|
94
|
+
for (const { target, boundingClientRect, intersectionRect } of entries) {
|
|
95
|
+
const selector = `:is(${this.#tagNames.join(',')})[href="#${target.id}"]`;
|
|
96
|
+
const link = this.host.querySelector(selector);
|
|
97
|
+
if (link) {
|
|
98
|
+
this.#markPassed(link, boundingClientRect.top < intersectionRect.top);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const link = [...this.#passedLinks];
|
|
102
|
+
const last = link.at(-1);
|
|
103
|
+
this.#setActive(last ?? this.#linkChildren.at(0));
|
|
104
|
+
}
|
|
105
|
+
this.#intersected = true;
|
|
104
106
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
107
|
+
/** Explicitly set the active item */
|
|
108
|
+
async setActive(link) {
|
|
109
|
+
this.#force = true;
|
|
110
|
+
this.#setActive(link);
|
|
111
|
+
let sawActive = false;
|
|
112
|
+
for (const child of this.#linkChildren) {
|
|
113
|
+
this.#markPassed(child, !sawActive);
|
|
114
|
+
if (child === link) {
|
|
115
|
+
sawActive = true;
|
|
112
116
|
}
|
|
113
117
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
__classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_setActive).call(this, last ?? __classPrivateFieldGet(this, _ScrollSpyController_instances, "a", _ScrollSpyController_linkChildren_get).at(0));
|
|
118
|
+
await this.#nextIntersection();
|
|
119
|
+
this.#force = false;
|
|
117
120
|
}
|
|
118
|
-
|
|
119
|
-
};
|
|
121
|
+
}
|
|
120
122
|
//# sourceMappingURL=scroll-spy-controller.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scroll-spy-controller.js","sourceRoot":"","sources":["scroll-spy-controller.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"scroll-spy-controller.js","sourceRoot":"","sources":["scroll-spy-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController, ReactiveControllerHost } from 'lit';\n\nexport interface ScrollSpyControllerOptions extends IntersectionObserverInit {\n /**\n * Tag names of legal link children.\n * Legal children must have an `href` property/attribute pair, like `<a>`.\n */\n tagNames: string[];\n\n /**\n * Attribute to set on the active link element.\n * @default 'active'\n */\n activeAttribute?: string;\n\n /**\n * The root node to query content for\n * @default the host's root node\n */\n rootNode?: Node;\n /**\n * function to call on link children to get their URL hash (i.e. id to scroll to)\n * @default el => el.getAttribute('href');\n */\n getHash?: (el: Element) => string | null;\n}\n\nexport class ScrollSpyController implements ReactiveController {\n #tagNames: string[];\n #activeAttribute: string;\n\n #io?: IntersectionObserver;\n\n /** Which link's targets have already scrolled past? */\n #passedLinks = new Set<Element>();\n\n /** Ignore intersections? */\n #force = false;\n\n /** Has the intersection observer found an element? */\n #intersected = false;\n\n #root: ScrollSpyControllerOptions['root'];\n #rootMargin?: string;\n #threshold: number | number[];\n\n #rootNode: Node;\n #getHash: (el: Element) => string | null;\n\n get #linkChildren(): Element[] {\n return Array.from(this.host.querySelectorAll(this.#tagNames.join(',')))\n .filter(this.#getHash);\n }\n\n get root() {\n return this.#root;\n }\n\n set root(v) {\n this.#root = v;\n this.#io?.disconnect();\n this.#initIo();\n }\n\n get rootMargin() {\n return this.#rootMargin;\n }\n\n set rootMargin(v) {\n this.#rootMargin = v;\n this.#io?.disconnect();\n this.#initIo();\n }\n\n get threshold() {\n return this.#threshold;\n }\n\n set threshold(v) {\n this.#threshold = v;\n this.#io?.disconnect();\n this.#initIo();\n }\n\n constructor(\n private host: ReactiveControllerHost & HTMLElement,\n options: ScrollSpyControllerOptions,\n ) {\n host.addController(this);\n this.#tagNames = options.tagNames;\n this.#root = options.root;\n this.#rootMargin = options.rootMargin;\n this.#activeAttribute = options.activeAttribute ?? 'active';\n this.#threshold = options.threshold ?? 0.85;\n this.#rootNode = options.rootNode ?? host.getRootNode();\n this.#getHash = options?.getHash ?? ((el: Element) => el.getAttribute('href'));\n }\n\n hostConnected() {\n this.#initIo();\n }\n\n #initIo() {\n const rootNode = this.#rootNode;\n if (rootNode instanceof Document || rootNode instanceof ShadowRoot) {\n const { rootMargin, threshold, root } = this;\n this.#io = new IntersectionObserver(r => this.#onIo(r), { root, rootMargin, threshold });\n this.#linkChildren\n .map(x => this.#getHash(x))\n .filter((x): x is string => !!x)\n .map(x => rootNode.getElementById(x.replace('#', '')))\n .filter((x): x is HTMLElement => !!x)\n .forEach(target => this.#io?.observe(target));\n }\n }\n\n #markPassed(link: Element, force: boolean) {\n if (force) {\n this.#passedLinks.add(link);\n } else {\n this.#passedLinks.delete(link);\n }\n }\n\n #setActive(link?: EventTarget | null) {\n for (const child of this.#linkChildren) {\n child.toggleAttribute(this.#activeAttribute, child === link);\n }\n }\n\n async #nextIntersection() {\n this.#intersected = false;\n // safeguard the loop\n setTimeout(() => this.#intersected = false, 3000);\n while (!this.#intersected) {\n await new Promise(requestAnimationFrame);\n }\n }\n\n async #onIo(entries: IntersectionObserverEntry[]) {\n if (!this.#force) {\n for (const { target, boundingClientRect, intersectionRect } of entries) {\n const selector = `:is(${this.#tagNames.join(',')})[href=\"#${target.id}\"]`;\n const link = this.host.querySelector(selector);\n if (link) {\n this.#markPassed(link, boundingClientRect.top < intersectionRect.top);\n }\n }\n const link = [...this.#passedLinks];\n const last = link.at(-1);\n this.#setActive(last ?? this.#linkChildren.at(0));\n }\n this.#intersected = true;\n }\n\n /** Explicitly set the active item */\n public async setActive(link: EventTarget | null) {\n this.#force = true;\n this.#setActive(link);\n let sawActive = false;\n for (const child of this.#linkChildren) {\n this.#markPassed(child, !sawActive);\n if (child === link) {\n sawActive = true;\n }\n }\n await this.#nextIntersection();\n this.#force = false;\n }\n}\n"]}
|
|
@@ -26,16 +26,11 @@ export interface SlotsConfig {
|
|
|
26
26
|
deprecations?: Record<string, string>;
|
|
27
27
|
}
|
|
28
28
|
export declare class SlotController implements ReactiveController {
|
|
29
|
+
#private;
|
|
29
30
|
host: ReactiveElement;
|
|
30
31
|
static anonymous: symbol;
|
|
31
|
-
private nodes;
|
|
32
|
-
private logger;
|
|
33
|
-
private firstUpdated;
|
|
34
|
-
private mo;
|
|
35
|
-
private slotNames;
|
|
36
|
-
private deprecations;
|
|
37
32
|
constructor(host: ReactiveElement, ...config: ([SlotsConfig] | (string | null)[]));
|
|
38
|
-
hostConnected(): void
|
|
33
|
+
hostConnected(): Promise<void>;
|
|
39
34
|
hostUpdated(): void;
|
|
40
35
|
hostDisconnected(): void;
|
|
41
36
|
/**
|
|
@@ -65,13 +60,5 @@ export declare class SlotController implements ReactiveController {
|
|
|
65
60
|
* ```
|
|
66
61
|
*/
|
|
67
62
|
getSlotted<T extends Element = Element>(...slotNames: string[]): T[];
|
|
68
|
-
private onSlotChange;
|
|
69
|
-
private onMutation;
|
|
70
|
-
private getChildrenForSlot;
|
|
71
|
-
private initSlot;
|
|
72
|
-
/**
|
|
73
|
-
* Maps the defined slots into an object that is easier to query
|
|
74
|
-
*/
|
|
75
|
-
private init;
|
|
76
63
|
}
|
|
77
64
|
export {};
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { __decorate } from "tslib";
|
|
2
|
-
import { bound } from '../decorators/bound.js';
|
|
3
1
|
import { Logger } from './logger.js';
|
|
4
2
|
function isObjectConfigSpread(config) {
|
|
5
3
|
return config.length === 1 && typeof config[0] === 'object' && config[0] !== null;
|
|
@@ -11,41 +9,52 @@ function isObjectConfigSpread(config) {
|
|
|
11
9
|
const isSlot = (n) => (child) => n === SlotController.anonymous ? !child.hasAttribute('slot')
|
|
12
10
|
: child.getAttribute('slot') === n;
|
|
13
11
|
class SlotController {
|
|
12
|
+
static { this.anonymous = Symbol('anonymous slot'); }
|
|
13
|
+
#nodes = new Map();
|
|
14
|
+
#logger;
|
|
15
|
+
#firstUpdated = false;
|
|
16
|
+
#mo = new MutationObserver(records => this.#onMutation(records));
|
|
17
|
+
#slotNames;
|
|
18
|
+
#deprecations = {};
|
|
14
19
|
constructor(host, ...config) {
|
|
15
20
|
this.host = host;
|
|
16
|
-
this
|
|
17
|
-
this.firstUpdated = false;
|
|
18
|
-
this.mo = new MutationObserver(this.onMutation);
|
|
19
|
-
this.deprecations = {};
|
|
20
|
-
this.logger = new Logger(this.host);
|
|
21
|
+
this.#logger = new Logger(this.host);
|
|
21
22
|
if (isObjectConfigSpread(config)) {
|
|
22
23
|
const [{ slots, deprecations }] = config;
|
|
23
|
-
this
|
|
24
|
-
this
|
|
24
|
+
this.#slotNames = slots;
|
|
25
|
+
this.#deprecations = deprecations ?? {};
|
|
25
26
|
}
|
|
26
27
|
else if (config.length >= 1) {
|
|
27
|
-
this
|
|
28
|
-
this
|
|
28
|
+
this.#slotNames = config;
|
|
29
|
+
this.#deprecations = {};
|
|
29
30
|
}
|
|
30
31
|
else {
|
|
31
|
-
this
|
|
32
|
+
this.#slotNames = [null];
|
|
32
33
|
}
|
|
33
34
|
host.addController(this);
|
|
34
35
|
}
|
|
35
|
-
hostConnected() {
|
|
36
|
-
this.host.addEventListener('slotchange', this
|
|
37
|
-
this
|
|
38
|
-
this
|
|
39
|
-
|
|
36
|
+
async hostConnected() {
|
|
37
|
+
this.host.addEventListener('slotchange', this.#onSlotChange);
|
|
38
|
+
this.#firstUpdated = false;
|
|
39
|
+
this.#mo.observe(this.host, { childList: true });
|
|
40
|
+
// Map the defined slots into an object that is easier to query
|
|
41
|
+
this.#nodes.clear();
|
|
42
|
+
// Loop over the properties provided by the schema
|
|
43
|
+
this.#slotNames.forEach(this.#initSlot);
|
|
44
|
+
Object.values(this.#deprecations).forEach(this.#initSlot);
|
|
45
|
+
this.host.requestUpdate();
|
|
46
|
+
// insurance for framework integrations
|
|
47
|
+
await this.host.updateComplete;
|
|
48
|
+
this.host.requestUpdate();
|
|
40
49
|
}
|
|
41
50
|
hostUpdated() {
|
|
42
|
-
if (!this
|
|
43
|
-
this
|
|
44
|
-
this
|
|
51
|
+
if (!this.#firstUpdated) {
|
|
52
|
+
this.#slotNames.forEach(this.#initSlot);
|
|
53
|
+
this.#firstUpdated = true;
|
|
45
54
|
}
|
|
46
55
|
}
|
|
47
56
|
hostDisconnected() {
|
|
48
|
-
this
|
|
57
|
+
this.#mo.disconnect();
|
|
49
58
|
}
|
|
50
59
|
/**
|
|
51
60
|
* Returns a boolean statement of whether or not any of those slots exists in the light DOM.
|
|
@@ -55,11 +64,11 @@ class SlotController {
|
|
|
55
64
|
*/
|
|
56
65
|
hasSlotted(...names) {
|
|
57
66
|
if (!names.length) {
|
|
58
|
-
this
|
|
67
|
+
this.#logger.warn(`Please provide at least one slot name for which to search.`);
|
|
59
68
|
return false;
|
|
60
69
|
}
|
|
61
70
|
else {
|
|
62
|
-
return names.some(x => this
|
|
71
|
+
return names.some(x => this.#nodes.get(x)?.hasContent ?? false);
|
|
63
72
|
}
|
|
64
73
|
}
|
|
65
74
|
/**
|
|
@@ -83,67 +92,42 @@ class SlotController {
|
|
|
83
92
|
*/
|
|
84
93
|
getSlotted(...slotNames) {
|
|
85
94
|
if (!slotNames.length) {
|
|
86
|
-
return (this
|
|
95
|
+
return (this.#nodes.get(SlotController.anonymous)?.elements ?? []);
|
|
87
96
|
}
|
|
88
97
|
else {
|
|
89
|
-
return slotNames.flatMap(slotName => this
|
|
98
|
+
return slotNames.flatMap(slotName => this.#nodes.get(slotName)?.elements ?? []);
|
|
90
99
|
}
|
|
91
100
|
}
|
|
92
|
-
onSlotChange(event) {
|
|
101
|
+
#onSlotChange = (event) => {
|
|
93
102
|
const slotName = event.target.name;
|
|
94
|
-
this
|
|
103
|
+
this.#initSlot(slotName);
|
|
95
104
|
this.host.requestUpdate();
|
|
96
|
-
}
|
|
97
|
-
async
|
|
105
|
+
};
|
|
106
|
+
#onMutation = async (records) => {
|
|
98
107
|
const changed = [];
|
|
99
108
|
for (const { addedNodes, removedNodes } of records) {
|
|
100
109
|
for (const node of [...addedNodes, ...removedNodes]) {
|
|
101
110
|
if (node instanceof HTMLElement && node.slot) {
|
|
102
|
-
this
|
|
111
|
+
this.#initSlot(node.slot);
|
|
103
112
|
changed.push(node.slot);
|
|
104
113
|
}
|
|
105
114
|
}
|
|
106
115
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
getChildrenForSlot(name) {
|
|
116
|
+
this.host.requestUpdate();
|
|
117
|
+
};
|
|
118
|
+
#getChildrenForSlot(name) {
|
|
112
119
|
const children = Array.from(this.host.children);
|
|
113
120
|
return children.filter(isSlot(name));
|
|
114
121
|
}
|
|
115
|
-
initSlot(slotName) {
|
|
122
|
+
#initSlot = (slotName) => {
|
|
116
123
|
const name = slotName || SlotController.anonymous;
|
|
117
|
-
const elements = this
|
|
124
|
+
const elements = this.#nodes.get(name)?.slot?.assignedElements?.() ?? this.#getChildrenForSlot(name);
|
|
118
125
|
const selector = slotName ? `slot[name="${slotName}"]` : 'slot:not([name])';
|
|
119
126
|
const slot = this.host.shadowRoot?.querySelector?.(selector) ?? null;
|
|
120
127
|
const hasContent = !!elements.length;
|
|
121
|
-
this
|
|
122
|
-
this
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Maps the defined slots into an object that is easier to query
|
|
126
|
-
*/
|
|
127
|
-
init() {
|
|
128
|
-
this.nodes.clear();
|
|
129
|
-
// Loop over the properties provided by the schema
|
|
130
|
-
this.slotNames.forEach(this.initSlot);
|
|
131
|
-
Object.values(this.deprecations).forEach(this.initSlot);
|
|
132
|
-
this.host.requestUpdate();
|
|
133
|
-
}
|
|
128
|
+
this.#nodes.set(name, { elements, name: slotName ?? '', hasContent, slot });
|
|
129
|
+
this.#logger.log(slotName, hasContent);
|
|
130
|
+
};
|
|
134
131
|
}
|
|
135
|
-
SlotController.anonymous = Symbol('anonymous slot');
|
|
136
|
-
__decorate([
|
|
137
|
-
bound
|
|
138
|
-
], SlotController.prototype, "onSlotChange", null);
|
|
139
|
-
__decorate([
|
|
140
|
-
bound
|
|
141
|
-
], SlotController.prototype, "onMutation", null);
|
|
142
|
-
__decorate([
|
|
143
|
-
bound
|
|
144
|
-
], SlotController.prototype, "initSlot", null);
|
|
145
|
-
__decorate([
|
|
146
|
-
bound
|
|
147
|
-
], SlotController.prototype, "init", null);
|
|
148
132
|
export { SlotController };
|
|
149
133
|
//# sourceMappingURL=slot-controller.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slot-controller.js","sourceRoot":"","sources":["slot-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController, ReactiveElement } from 'lit';\n\nimport { bound } from '../decorators/bound.js';\nimport { Logger } from './logger.js';\n\ninterface AnonymousSlot {\n hasContent: boolean;\n elements: Element[];\n slot: HTMLSlotElement | null;\n}\n\ninterface NamedSlot extends AnonymousSlot {\n name: string;\n initialized: true;\n}\n\nexport type Slot = NamedSlot | AnonymousSlot;\n\nexport interface SlotsConfig {\n slots: (string | null)[];\n /**\n * Object mapping new slot name keys to deprecated slot name values\n * @example `pf-modal--header` is deprecated in favour of `header`\n * ```js\n * new SlotController(this, {\n * slots: ['header'],\n * deprecations: {\n * 'header': 'pf-modal--header'\n * }\n * })\n * ```\n */\n deprecations?: Record<string, string>;\n}\n\nfunction isObjectConfigSpread(config: ([SlotsConfig] | (string | null)[])): config is [SlotsConfig] {\n return config.length === 1 && typeof config[0] === 'object' && config[0] !== null;\n}\n\n/**\n * If it's a named slot, return its children,\n * for the default slot, look for direct children not assigned to a slot\n */\nconst isSlot =\n <T extends Element = Element>(n: string | typeof SlotController.anonymous) =>\n (child: Element): child is T =>\n n === SlotController.anonymous ? !child.hasAttribute('slot')\n : child.getAttribute('slot') === n;\n\nexport class SlotController implements ReactiveController {\n public static anonymous = Symbol('anonymous slot');\n\n private nodes = new Map<string | typeof SlotController.anonymous, Slot>();\n\n private logger: Logger;\n\n private firstUpdated = false;\n\n private mo = new MutationObserver(this.onMutation);\n\n private slotNames: (string | null)[];\n\n private deprecations: Record<string, string> = {};\n\n constructor(public host: ReactiveElement, ...config: ([SlotsConfig] | (string | null)[])) {\n this.logger = new Logger(this.host);\n\n if (isObjectConfigSpread(config)) {\n const [{ slots, deprecations }] = config;\n this.slotNames = slots;\n this.deprecations = deprecations ?? {};\n } else if (config.length >= 1) {\n this.slotNames = config;\n this.deprecations = {};\n } else {\n this.slotNames = [null];\n }\n\n\n host.addController(this);\n }\n\n hostConnected() {\n this.host.addEventListener('slotchange', this.onSlotChange as EventListener);\n this.firstUpdated = false;\n this.mo.observe(this.host, { childList: true });\n this.init();\n }\n\n hostUpdated() {\n if (!this.firstUpdated) {\n this.slotNames.forEach(this.initSlot);\n this.firstUpdated = true;\n }\n }\n\n hostDisconnected() {\n this.mo.disconnect();\n }\n\n /**\n * Returns a boolean statement of whether or not any of those slots exists in the light DOM.\n *\n * @param {String|Array} name The slot name.\n * @example this.hasSlotted(\"header\");\n */\n hasSlotted(...names: string[]): boolean {\n if (!names.length) {\n this.logger.warn(`Please provide at least one slot name for which to search.`);\n return false;\n } else {\n return names.some(x =>\n this.nodes.get(x)?.hasContent ?? false);\n }\n }\n\n /**\n * Given a slot name or slot names, returns elements assigned to the requested slots as an array.\n * If no value is provided, it returns all children not assigned to a slot (without a slot attribute).\n *\n * @example Get header-slotted elements\n * ```js\n * this.getSlotted('header')\n * ```\n *\n * @example Get header- and footer-slotted elements\n * ```js\n * this.getSlotted('header', 'footer')\n * ```\n *\n * @example Get default-slotted elements\n * ```js\n * this.getSlotted();\n * ```\n */\n getSlotted<T extends Element = Element>(...slotNames: string[]): T[] {\n if (!slotNames.length) {\n return (this.nodes.get(SlotController.anonymous)?.elements ?? []) as T[];\n } else {\n return slotNames.flatMap(slotName =>\n this.nodes.get(slotName)?.elements ?? []) as T[];\n }\n }\n\n @bound private onSlotChange(event: Event & { target: HTMLSlotElement }) {\n const slotName = event.target.name;\n this.initSlot(slotName);\n this.host.requestUpdate();\n }\n\n @bound private async onMutation(records: MutationRecord[]) {\n const changed = [];\n for (const { addedNodes, removedNodes } of records) {\n for (const node of [...addedNodes, ...removedNodes]) {\n if (node instanceof HTMLElement && node.slot) {\n this.initSlot(node.slot);\n changed.push(node.slot);\n }\n }\n }\n if (changed.length) {\n this.host.requestUpdate();\n }\n }\n\n private getChildrenForSlot<T extends Element = Element>(name: string | typeof SlotController.anonymous): T[] {\n const children = Array.from(this.host.children) as T[];\n return children.filter(isSlot(name));\n }\n\n @bound private initSlot(slotName: string | null) {\n const name = slotName || SlotController.anonymous;\n const elements = this.nodes.get(name)?.slot?.assignedElements?.() ?? this.getChildrenForSlot(name);\n const selector = slotName ? `slot[name=\"${slotName}\"]` : 'slot:not([name])';\n const slot = this.host.shadowRoot?.querySelector?.<HTMLSlotElement>(selector) ?? null;\n const hasContent = !!elements.length;\n this.nodes.set(name, { elements, name: slotName ?? '', hasContent, slot });\n this.logger.log(slotName, hasContent);\n }\n\n /**\n * Maps the defined slots into an object that is easier to query\n */\n @bound private init() {\n this.nodes.clear();\n // Loop over the properties provided by the schema\n this.slotNames.forEach(this.initSlot);\n Object.values(this.deprecations).forEach(this.initSlot);\n this.host.requestUpdate();\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"slot-controller.js","sourceRoot":"","sources":["slot-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController, ReactiveElement } from 'lit';\n\nimport { Logger } from './logger.js';\n\ninterface AnonymousSlot {\n hasContent: boolean;\n elements: Element[];\n slot: HTMLSlotElement | null;\n}\n\ninterface NamedSlot extends AnonymousSlot {\n name: string;\n initialized: true;\n}\n\nexport type Slot = NamedSlot | AnonymousSlot;\n\nexport interface SlotsConfig {\n slots: (string | null)[];\n /**\n * Object mapping new slot name keys to deprecated slot name values\n * @example `pf-modal--header` is deprecated in favour of `header`\n * ```js\n * new SlotController(this, {\n * slots: ['header'],\n * deprecations: {\n * 'header': 'pf-modal--header'\n * }\n * })\n * ```\n */\n deprecations?: Record<string, string>;\n}\n\nfunction isObjectConfigSpread(config: ([SlotsConfig] | (string | null)[])): config is [SlotsConfig] {\n return config.length === 1 && typeof config[0] === 'object' && config[0] !== null;\n}\n\n/**\n * If it's a named slot, return its children,\n * for the default slot, look for direct children not assigned to a slot\n */\nconst isSlot =\n <T extends Element = Element>(n: string | typeof SlotController.anonymous) =>\n (child: Element): child is T =>\n n === SlotController.anonymous ? !child.hasAttribute('slot')\n : child.getAttribute('slot') === n;\n\nexport class SlotController implements ReactiveController {\n public static anonymous = Symbol('anonymous slot');\n\n #nodes = new Map<string | typeof SlotController.anonymous, Slot>();\n\n #logger: Logger;\n\n #firstUpdated = false;\n\n #mo = new MutationObserver(records => this.#onMutation(records));\n\n #slotNames: (string | null)[];\n\n #deprecations: Record<string, string> = {};\n\n constructor(public host: ReactiveElement, ...config: ([SlotsConfig] | (string | null)[])) {\n this.#logger = new Logger(this.host);\n\n if (isObjectConfigSpread(config)) {\n const [{ slots, deprecations }] = config;\n this.#slotNames = slots;\n this.#deprecations = deprecations ?? {};\n } else if (config.length >= 1) {\n this.#slotNames = config;\n this.#deprecations = {};\n } else {\n this.#slotNames = [null];\n }\n\n\n host.addController(this);\n }\n\n async hostConnected() {\n this.host.addEventListener('slotchange', this.#onSlotChange as EventListener);\n this.#firstUpdated = false;\n this.#mo.observe(this.host, { childList: true });\n // Map the defined slots into an object that is easier to query\n this.#nodes.clear();\n // Loop over the properties provided by the schema\n this.#slotNames.forEach(this.#initSlot);\n Object.values(this.#deprecations).forEach(this.#initSlot);\n this.host.requestUpdate();\n // insurance for framework integrations\n await this.host.updateComplete;\n this.host.requestUpdate();\n }\n\n hostUpdated() {\n if (!this.#firstUpdated) {\n this.#slotNames.forEach(this.#initSlot);\n this.#firstUpdated = true;\n }\n }\n\n hostDisconnected() {\n this.#mo.disconnect();\n }\n\n /**\n * Returns a boolean statement of whether or not any of those slots exists in the light DOM.\n *\n * @param {String|Array} name The slot name.\n * @example this.hasSlotted(\"header\");\n */\n hasSlotted(...names: string[]): boolean {\n if (!names.length) {\n this.#logger.warn(`Please provide at least one slot name for which to search.`);\n return false;\n } else {\n return names.some(x =>\n this.#nodes.get(x)?.hasContent ?? false);\n }\n }\n\n /**\n * Given a slot name or slot names, returns elements assigned to the requested slots as an array.\n * If no value is provided, it returns all children not assigned to a slot (without a slot attribute).\n *\n * @example Get header-slotted elements\n * ```js\n * this.getSlotted('header')\n * ```\n *\n * @example Get header- and footer-slotted elements\n * ```js\n * this.getSlotted('header', 'footer')\n * ```\n *\n * @example Get default-slotted elements\n * ```js\n * this.getSlotted();\n * ```\n */\n getSlotted<T extends Element = Element>(...slotNames: string[]): T[] {\n if (!slotNames.length) {\n return (this.#nodes.get(SlotController.anonymous)?.elements ?? []) as T[];\n } else {\n return slotNames.flatMap(slotName =>\n this.#nodes.get(slotName)?.elements ?? []) as T[];\n }\n }\n\n #onSlotChange = (event: Event & { target: HTMLSlotElement }) => {\n const slotName = event.target.name;\n this.#initSlot(slotName);\n this.host.requestUpdate();\n };\n\n #onMutation = async (records: MutationRecord[]) => {\n const changed = [];\n for (const { addedNodes, removedNodes } of records) {\n for (const node of [...addedNodes, ...removedNodes]) {\n if (node instanceof HTMLElement && node.slot) {\n this.#initSlot(node.slot);\n changed.push(node.slot);\n }\n }\n }\n this.host.requestUpdate();\n };\n\n #getChildrenForSlot<T extends Element = Element>(name: string | typeof SlotController.anonymous): T[] {\n const children = Array.from(this.host.children) as T[];\n return children.filter(isSlot(name));\n }\n\n #initSlot = (slotName: string | null) => {\n const name = slotName || SlotController.anonymous;\n const elements = this.#nodes.get(name)?.slot?.assignedElements?.() ?? this.#getChildrenForSlot(name);\n const selector = slotName ? `slot[name=\"${slotName}\"]` : 'slot:not([name])';\n const slot = this.host.shadowRoot?.querySelector?.<HTMLSlotElement>(selector) ?? null;\n const hasContent = !!elements.length;\n this.#nodes.set(name, { elements, name: slotName ?? '', hasContent, slot });\n this.#logger.log(slotName, hasContent);\n };\n}\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
2
|
+
export type DateTimeFormat = 'full' | 'long' | 'medium' | 'short';
|
|
3
|
+
export interface TimestampOptions {
|
|
4
|
+
dateFormat?: DateTimeFormat;
|
|
5
|
+
timeFormat?: DateTimeFormat;
|
|
6
|
+
customFormat?: Intl.DateTimeFormatOptions;
|
|
7
|
+
displaySuffix: string;
|
|
8
|
+
locale: Intl.LocalesArgument;
|
|
9
|
+
relative: boolean;
|
|
10
|
+
utc: boolean;
|
|
11
|
+
hour12: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare class TimestampController implements ReactiveController {
|
|
14
|
+
#private;
|
|
15
|
+
get localeString(): string;
|
|
16
|
+
get date(): Date;
|
|
17
|
+
set date(string: Date);
|
|
18
|
+
get isoString(): string;
|
|
19
|
+
get time(): string;
|
|
20
|
+
constructor(host: ReactiveControllerHost, options?: Partial<TimestampOptions>);
|
|
21
|
+
hostConnected?(): void;
|
|
22
|
+
set(prop: PropertyKey, value: unknown): void;
|
|
23
|
+
}
|