@patternfly/pfe-core 2.0.0-next.8 → 2.0.0-rc.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/README.md +2 -2
- package/controllers/cascade-controller.js +136 -2
- package/controllers/cascade-controller.js.map +1 -7
- package/controllers/css-variable-controller.js +13 -2
- package/controllers/css-variable-controller.js.map +1 -7
- package/controllers/floating-dom-controller.d.ts +35 -14
- package/controllers/floating-dom-controller.js +115 -2
- package/controllers/floating-dom-controller.js.map +1 -7
- package/controllers/internals-controller.d.ts +52 -0
- package/controllers/internals-controller.js +52 -0
- package/controllers/internals-controller.js.map +1 -0
- package/controllers/light-dom-controller.js +38 -2
- package/controllers/light-dom-controller.js.map +1 -7
- package/controllers/logger.js +90 -2
- package/controllers/logger.js.map +1 -7
- package/controllers/perf-controller.js +36 -2
- package/controllers/perf-controller.js.map +1 -7
- package/controllers/property-observer-controller.d.ts +3 -3
- package/controllers/property-observer-controller.js +33 -2
- package/controllers/property-observer-controller.js.map +1 -7
- package/controllers/roving-tabindex-controller.d.ts +48 -0
- package/controllers/roving-tabindex-controller.js +166 -0
- package/controllers/roving-tabindex-controller.js.map +1 -0
- package/controllers/scroll-spy-controller.d.ts +37 -0
- package/controllers/scroll-spy-controller.js +120 -0
- package/controllers/scroll-spy-controller.js.map +1 -0
- package/controllers/slot-controller.d.ts +3 -3
- package/controllers/slot-controller.js +148 -2
- package/controllers/slot-controller.js.map +1 -7
- package/controllers/style-controller.js +42 -2
- package/controllers/style-controller.js.map +1 -7
- package/core.d.ts +1 -1
- package/core.js +68 -2
- package/core.js.map +1 -7
- package/custom-elements.json +6315 -1
- package/decorators/bound.js +27 -2
- package/decorators/bound.js.map +1 -7
- package/decorators/cascades.js +18 -2
- package/decorators/cascades.js.map +1 -7
- package/decorators/deprecation.d.ts +1 -1
- package/decorators/deprecation.js +44 -2
- package/decorators/deprecation.js.map +1 -7
- package/decorators/initializer.js +21 -2
- package/decorators/initializer.js.map +1 -7
- package/decorators/observed.d.ts +1 -1
- package/decorators/observed.js +52 -2
- package/decorators/observed.js.map +1 -7
- package/decorators/time.js +36 -2
- package/decorators/time.js.map +1 -7
- package/decorators/trace.js +21 -2
- package/decorators/trace.js.map +1 -7
- package/decorators.d.ts +0 -2
- package/decorators.js +8 -2
- package/decorators.js.map +1 -7
- package/functions/debounce.js +28 -2
- package/functions/debounce.js.map +1 -7
- package/functions/deprecatedCustomEvent.js +12 -2
- package/functions/deprecatedCustomEvent.js.map +1 -7
- package/functions/isElementInView.d.ts +12 -0
- package/functions/isElementInView.js +31 -0
- package/functions/isElementInView.js.map +1 -0
- package/functions/random.js +9 -2
- package/functions/random.js.map +1 -7
- package/package.json +13 -24
- package/context.d.ts +0 -53
- package/context.js +0 -2
- package/context.js.map +0 -7
- package/controllers/color-context.d.ts +0 -114
- package/controllers/color-context.js +0 -2
- package/controllers/color-context.js.map +0 -7
- package/controllers/color-context.scss +0 -84
- package/decorators/color-context.d.ts +0 -4
- package/decorators/color-context.js +0 -2
- package/decorators/color-context.js.map +0 -7
- package/decorators/pfelement.d.ts +0 -10
- package/decorators/pfelement.js +0 -2
- package/decorators/pfelement.js.map +0 -7
|
@@ -1,7 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["light-dom-controller.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ReactiveController, ReactiveElement } from 'lit';\n\nimport { Logger } from './logger.js';\n\nexport interface Options {\n observe?: boolean|MutationObserverInit;\n emptyWarning?: string;\n}\n\nexport class LightDOMController implements ReactiveController {\n private mo: MutationObserver;\n private logger: Logger;\n private initializer: () => void;\n\n constructor(private host: ReactiveElement, initializer: () => void, private options?: Options) {\n this.initializer = initializer.bind(host);\n this.mo = new MutationObserver(this.initializer);\n this.logger = new Logger(this.host);\n host.addController(this);\n }\n\n hostConnected() {\n if (this.hasLightDOM()) {\n this.initializer();\n } else if (this.options?.emptyWarning) {\n this.logger.warn(this.options?.emptyWarning);\n }\n\n this.initObserver();\n }\n\n hostDisconnected() {\n this.mo.disconnect();\n }\n\n private initObserver() {\n if (this.options?.observe ?? true) {\n // Use the provided options, or their defaults\n this.mo.observe(\n this.host,\n typeof this.options?.observe !== 'object' ? { childList: true }\n : this.options?.observe as MutationObserverInit\n );\n }\n }\n\n /**\n * Returns a boolean statement of whether or not this component contains any light DOM.\n */\n hasLightDOM(): boolean {\n return !!(\n this.host.children.length > 0 ||\n (this.host.textContent ?? '').trim().length > 0\n );\n }\n}\n"],
|
|
5
|
-
"mappings": "AAEA,OAAS,UAAAA,MAAc,cAOhB,IAAMC,EAAN,KAAuD,CAK5D,YAAoBC,EAAuBC,EAAiCC,EAAmB,CAA3E,UAAAF,EAAwD,aAAAE,EAC1E,KAAK,YAAcD,EAAY,KAAKD,CAAI,EACxC,KAAK,GAAK,IAAI,iBAAiB,KAAK,WAAW,EAC/C,KAAK,OAAS,IAAIF,EAAO,KAAK,IAAI,EAClCE,EAAK,cAAc,IAAI,CACzB,CAEA,eAAgB,CACV,KAAK,YAAY,EACnB,KAAK,YAAY,EACR,KAAK,SAAS,cACvB,KAAK,OAAO,KAAK,KAAK,SAAS,YAAY,EAG7C,KAAK,aAAa,CACpB,CAEA,kBAAmB,CACjB,KAAK,GAAG,WAAW,CACrB,CAEQ,cAAe,EACjB,KAAK,SAAS,SAAW,KAE3B,KAAK,GAAG,QACN,KAAK,KACH,OAAO,KAAK,SAAS,SAAY,SAAW,CAAE,UAAW,EAAK,EAC9D,KAAK,SAAS,OAClB,CAEJ,CAKA,aAAuB,CACrB,OACE,KAAK,KAAK,SAAS,OAAS,IAC3B,KAAK,KAAK,aAAe,IAAI,KAAK,EAAE,OAAS,CAElD,CACF",
|
|
6
|
-
"names": ["Logger", "LightDOMController", "host", "initializer", "options"]
|
|
7
|
-
}
|
|
1
|
+
{"version":3,"file":"light-dom-controller.js","sourceRoot":"","sources":["light-dom-controller.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAOrC,MAAM,OAAO,kBAAkB;IAK7B,YAAoB,IAAqB,EAAE,WAAuB,EAAU,OAAiB;QAAzE,SAAI,GAAJ,IAAI,CAAiB;QAAmC,YAAO,GAAP,OAAO,CAAU;QAC3F,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,CAAC,EAAE,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACjD,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAED,aAAa;QACX,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE;YACtB,IAAI,CAAC,WAAW,EAAE,CAAC;SACpB;aAAM,IAAI,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE;YACrC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;SAC9C;QAED,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAED,gBAAgB;QACd,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC;IACvB,CAAC;IAEO,YAAY;QAClB,IAAI,IAAI,CAAC,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE;YACjC,8CAA8C;YAC9C,IAAI,CAAC,EAAE,CAAC,OAAO,CACb,IAAI,CAAC,IAAI,EACP,OAAO,IAAI,CAAC,OAAO,EAAE,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE;gBACjE,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,OAA+B,CAChD,CAAC;SACH;IACH,CAAC;IAED;;OAEG;IACH,WAAW;QACT,OAAO,CAAC,CAAC,CACP,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;YAC7B,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAChD,CAAC;IACJ,CAAC;CACF","sourcesContent":["import type { ReactiveController, ReactiveElement } from 'lit';\n\nimport { Logger } from './logger.js';\n\nexport interface Options {\n observe?: boolean|MutationObserverInit;\n emptyWarning?: string;\n}\n\nexport class LightDOMController implements ReactiveController {\n private mo: MutationObserver;\n private logger: Logger;\n private initializer: () => void;\n\n constructor(private host: ReactiveElement, initializer: () => void, private options?: Options) {\n this.initializer = initializer.bind(host);\n this.mo = new MutationObserver(this.initializer);\n this.logger = new Logger(this.host);\n host.addController(this);\n }\n\n hostConnected() {\n if (this.hasLightDOM()) {\n this.initializer();\n } else if (this.options?.emptyWarning) {\n this.logger.warn(this.options?.emptyWarning);\n }\n\n this.initObserver();\n }\n\n hostDisconnected() {\n this.mo.disconnect();\n }\n\n private initObserver() {\n if (this.options?.observe ?? true) {\n // Use the provided options, or their defaults\n this.mo.observe(\n this.host,\n typeof this.options?.observe !== 'object' ? { childList: true }\n : this.options?.observe as MutationObserverInit\n );\n }\n }\n\n /**\n * Returns a boolean statement of whether or not this component contains any light DOM.\n */\n hasLightDOM(): boolean {\n return !!(\n this.host.children.length > 0 ||\n (this.host.textContent ?? '').trim().length > 0\n );\n }\n}\n"]}
|
package/controllers/logger.js
CHANGED
|
@@ -1,2 +1,90 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
export class Logger {
|
|
2
|
+
get prefix() {
|
|
3
|
+
return `[${this.host.localName}${this.host.id ? `#${this.host.id}` : ''}]`;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* A boolean value that indicates if the logging should be printed to the console; used for debugging.
|
|
7
|
+
* For use in a JS file or script tag; can also be added in the constructor of a component during development.
|
|
8
|
+
* @example Logger.debugLog(true);
|
|
9
|
+
* @tags debug
|
|
10
|
+
*/
|
|
11
|
+
static debugLog(preference = null) {
|
|
12
|
+
// wrap localStorage references in a try/catch; merely referencing it can
|
|
13
|
+
// throw errors in some locked down environments
|
|
14
|
+
try {
|
|
15
|
+
if (preference !== null) {
|
|
16
|
+
Logger.logDebug = !!preference;
|
|
17
|
+
localStorage.pfeLog = !!preference;
|
|
18
|
+
}
|
|
19
|
+
return localStorage.pfeLog === 'true';
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
return Logger.logDebug;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* A logging wrapper which checks the debugLog boolean and prints to the console if true.
|
|
27
|
+
*
|
|
28
|
+
* @example Logger.log("Hello");
|
|
29
|
+
*/
|
|
30
|
+
static log(...msgs) {
|
|
31
|
+
if (Logger.debugLog()) {
|
|
32
|
+
// eslint-disable-next-line no-console
|
|
33
|
+
console.log(...msgs);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* A console warning wrapper which formats your output with useful debugging information.
|
|
38
|
+
*
|
|
39
|
+
* @example Logger.warn("Hello");
|
|
40
|
+
*/
|
|
41
|
+
static warn(...msgs) {
|
|
42
|
+
console.warn(...msgs); // eslint-disable-line no-console
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* A console error wrapper which formats your output with useful debugging information.
|
|
46
|
+
* For use inside a component's function.
|
|
47
|
+
* @example Logger.error("Hello");
|
|
48
|
+
*/
|
|
49
|
+
static error(...msgs) {
|
|
50
|
+
console.error([...msgs].join(' ')); // eslint-disable-line no-console
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Local logging that outputs the tag name as a prefix automatically
|
|
54
|
+
*
|
|
55
|
+
* @example this.logger.log("Hello");
|
|
56
|
+
*/
|
|
57
|
+
log(...msgs) {
|
|
58
|
+
Logger.log(this.prefix, ...msgs);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Local warning wrapper that outputs the tag name as a prefix automatically.
|
|
62
|
+
* For use inside a component's function.
|
|
63
|
+
* @example this.logger.warn("Hello");
|
|
64
|
+
*/
|
|
65
|
+
warn(...msgs) {
|
|
66
|
+
Logger.warn(this.prefix, ...msgs);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Local error wrapper that outputs the tag name as a prefix automatically.
|
|
70
|
+
* For use inside a component's function.
|
|
71
|
+
* @example this.logger.error("Hello");
|
|
72
|
+
*/
|
|
73
|
+
error(...msgs) {
|
|
74
|
+
Logger.error(this.prefix, ...msgs);
|
|
75
|
+
}
|
|
76
|
+
constructor(host) {
|
|
77
|
+
this.host = host;
|
|
78
|
+
// We only need one logger instance per host
|
|
79
|
+
if (Logger.instances.get(host)) {
|
|
80
|
+
return Logger.instances.get(host);
|
|
81
|
+
}
|
|
82
|
+
host.addController(this);
|
|
83
|
+
Logger.instances.set(host, this);
|
|
84
|
+
}
|
|
85
|
+
hostConnected() {
|
|
86
|
+
this.log('connected');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
Logger.instances = new WeakMap();
|
|
90
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -1,7 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["logger.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ReactiveController, ReactiveElement } from 'lit';\n\nexport class Logger implements ReactiveController {\n private static logDebug: boolean;\n\n private static instances: WeakMap<HTMLElement, Logger> = new WeakMap();\n\n private get prefix() {\n return `[${this.host.localName}${this.host.id ? `#${this.host.id}` : ''}]`;\n }\n\n /**\n * A boolean value that indicates if the logging should be printed to the console; used for debugging.\n * For use in a JS file or script tag; can also be added in the constructor of a component during development.\n * @example Logger.debugLog(true);\n * @tags debug\n */\n static debugLog(preference = null) {\n // wrap localStorage references in a try/catch; merely referencing it can\n // throw errors in some locked down environments\n try {\n if (preference !== null) {\n Logger.logDebug = !!preference;\n localStorage.pfeLog = !!preference;\n }\n return localStorage.pfeLog === 'true';\n } catch (e) {\n return Logger.logDebug;\n }\n }\n\n /**\n * A logging wrapper which checks the debugLog boolean and prints to the console if true.\n *\n * @example Logger.log(\"Hello\");\n */\n static log(...msgs: unknown[]) {\n if (Logger.debugLog()) {\n // eslint-disable-next-line no-console\n console.log(...msgs);\n }\n }\n\n /**\n * A console warning wrapper which formats your output with useful debugging information.\n *\n * @example Logger.warn(\"Hello\");\n */\n static warn(...msgs: unknown[]) {\n console.warn(...msgs); // eslint-disable-line no-console\n }\n\n /**\n * A console error wrapper which formats your output with useful debugging information.\n * For use inside a component's function.\n * @example Logger.error(\"Hello\");\n */\n static error(...msgs: unknown[]) {\n console.error([...msgs].join(' ')); // eslint-disable-line no-console\n }\n\n /**\n * Local logging that outputs the tag name as a prefix automatically\n *\n * @example this.logger.log(\"Hello\");\n */\n log(...msgs: unknown[]) {\n Logger.log(this.prefix, ...msgs);\n }\n\n /**\n * Local warning wrapper that outputs the tag name as a prefix automatically.\n * For use inside a component's function.\n * @example this.logger.warn(\"Hello\");\n */\n warn(...msgs: unknown[]) {\n Logger.warn(this.prefix, ...msgs);\n }\n\n /**\n * Local error wrapper that outputs the tag name as a prefix automatically.\n * For use inside a component's function.\n * @example this.logger.error(\"Hello\");\n */\n error(...msgs: unknown[]) {\n Logger.error(this.prefix, ...msgs);\n }\n\n constructor(private host: ReactiveElement) {\n // We only need one logger instance per host\n if (Logger.instances.get(host)) {\n return Logger.instances.get(host) as Logger;\n }\n host.addController(this);\n Logger.instances.set(host, this);\n }\n\n hostConnected() {\n this.log('connected');\n }\n}\n"],
|
|
5
|
-
"mappings": "AAEO,IAAMA,EAAN,KAA2C,CAsFhD,YAAoBC,EAAuB,CAAvB,UAAAA,EAElB,GAAID,EAAO,UAAU,IAAIC,CAAI,EAC3B,OAAOD,EAAO,UAAU,IAAIC,CAAI,EAElCA,EAAK,cAAc,IAAI,EACvBD,EAAO,UAAU,IAAIC,EAAM,IAAI,CACjC,CAxFA,IAAY,QAAS,CACnB,MAAO,IAAI,KAAK,KAAK,YAAY,KAAK,KAAK,GAAK,IAAI,KAAK,KAAK,KAAO,KACvE,CAQA,OAAO,SAASC,EAAa,KAAM,CAGjC,GAAI,CACF,OAAIA,IAAe,OACjBF,EAAO,SAAW,CAAC,CAACE,EACpB,aAAa,OAAS,CAAC,CAACA,GAEnB,aAAa,SAAW,MACjC,MAAE,CACA,OAAOF,EAAO,QAChB,CACF,CAOA,OAAO,OAAOG,EAAiB,CACzBH,EAAO,SAAS,GAElB,QAAQ,IAAI,GAAGG,CAAI,CAEvB,CAOA,OAAO,QAAQA,EAAiB,CAC9B,QAAQ,KAAK,GAAGA,CAAI,CACtB,CAOA,OAAO,SAASA,EAAiB,CAC/B,QAAQ,MAAM,CAAC,GAAGA,CAAI,EAAE,KAAK,GAAG,CAAC,CACnC,CAOA,OAAOA,EAAiB,CACtBH,EAAO,IAAI,KAAK,OAAQ,GAAGG,CAAI,CACjC,CAOA,QAAQA,EAAiB,CACvBH,EAAO,KAAK,KAAK,OAAQ,GAAGG,CAAI,CAClC,CAOA,SAASA,EAAiB,CACxBH,EAAO,MAAM,KAAK,OAAQ,GAAGG,CAAI,CACnC,CAWA,eAAgB,CACd,KAAK,IAAI,WAAW,CACtB,CACF,EAlGaC,EAANJ,EAAMI,EAGI,UAA0C,IAAI",
|
|
6
|
-
"names": ["_Logger", "host", "preference", "msgs", "Logger"]
|
|
7
|
-
}
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["logger.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,MAAM;IAKjB,IAAY,MAAM;QAChB,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC;IAC7E,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,CAAC,UAAU,GAAG,IAAI;QAC/B,yEAAyE;QACzE,gDAAgD;QAChD,IAAI;YACF,IAAI,UAAU,KAAK,IAAI,EAAE;gBACvB,MAAM,CAAC,QAAQ,GAAG,CAAC,CAAC,UAAU,CAAC;gBAC/B,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,UAAU,CAAC;aACpC;YACD,OAAO,YAAY,CAAC,MAAM,KAAK,MAAM,CAAC;SACvC;QAAC,OAAO,CAAC,EAAE;YACV,OAAO,MAAM,CAAC,QAAQ,CAAC;SACxB;IACH,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,GAAG,CAAC,GAAG,IAAe;QAC3B,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE;YACrB,sCAAsC;YACtC,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;SACtB;IACH,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,IAAI,CAAC,GAAG,IAAe;QAC5B,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,iCAAiC;IAC1D,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,KAAK,CAAC,GAAG,IAAe;QAC7B,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,iCAAiC;IACvE,CAAC;IAED;;;;OAIG;IACH,GAAG,CAAC,GAAG,IAAe;QACpB,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;IACnC,CAAC;IAED;;;;OAIG;IACH,IAAI,CAAC,GAAG,IAAe;QACrB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;IACpC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,GAAG,IAAe;QACtB,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;IACrC,CAAC;IAED,YAAoB,IAAqB;QAArB,SAAI,GAAJ,IAAI,CAAiB;QACvC,4CAA4C;QAC5C,IAAI,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YAC9B,OAAO,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAW,CAAC;SAC7C;QACD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,aAAa;QACX,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACxB,CAAC;;AA9Fc,gBAAS,GAAiC,IAAI,OAAO,EAAE,CAAC","sourcesContent":["import type { ReactiveController, ReactiveElement } from 'lit';\n\nexport class Logger implements ReactiveController {\n private static logDebug: boolean;\n\n private static instances: WeakMap<HTMLElement, Logger> = new WeakMap();\n\n private get prefix() {\n return `[${this.host.localName}${this.host.id ? `#${this.host.id}` : ''}]`;\n }\n\n /**\n * A boolean value that indicates if the logging should be printed to the console; used for debugging.\n * For use in a JS file or script tag; can also be added in the constructor of a component during development.\n * @example Logger.debugLog(true);\n * @tags debug\n */\n static debugLog(preference = null) {\n // wrap localStorage references in a try/catch; merely referencing it can\n // throw errors in some locked down environments\n try {\n if (preference !== null) {\n Logger.logDebug = !!preference;\n localStorage.pfeLog = !!preference;\n }\n return localStorage.pfeLog === 'true';\n } catch (e) {\n return Logger.logDebug;\n }\n }\n\n /**\n * A logging wrapper which checks the debugLog boolean and prints to the console if true.\n *\n * @example Logger.log(\"Hello\");\n */\n static log(...msgs: unknown[]) {\n if (Logger.debugLog()) {\n // eslint-disable-next-line no-console\n console.log(...msgs);\n }\n }\n\n /**\n * A console warning wrapper which formats your output with useful debugging information.\n *\n * @example Logger.warn(\"Hello\");\n */\n static warn(...msgs: unknown[]) {\n console.warn(...msgs); // eslint-disable-line no-console\n }\n\n /**\n * A console error wrapper which formats your output with useful debugging information.\n * For use inside a component's function.\n * @example Logger.error(\"Hello\");\n */\n static error(...msgs: unknown[]) {\n console.error([...msgs].join(' ')); // eslint-disable-line no-console\n }\n\n /**\n * Local logging that outputs the tag name as a prefix automatically\n *\n * @example this.logger.log(\"Hello\");\n */\n log(...msgs: unknown[]) {\n Logger.log(this.prefix, ...msgs);\n }\n\n /**\n * Local warning wrapper that outputs the tag name as a prefix automatically.\n * For use inside a component's function.\n * @example this.logger.warn(\"Hello\");\n */\n warn(...msgs: unknown[]) {\n Logger.warn(this.prefix, ...msgs);\n }\n\n /**\n * Local error wrapper that outputs the tag name as a prefix automatically.\n * For use inside a component's function.\n * @example this.logger.error(\"Hello\");\n */\n error(...msgs: unknown[]) {\n Logger.error(this.prefix, ...msgs);\n }\n\n constructor(private host: ReactiveElement) {\n // We only need one logger instance per host\n if (Logger.instances.get(host)) {\n return Logger.instances.get(host) as Logger;\n }\n host.addController(this);\n Logger.instances.set(host, this);\n }\n\n hostConnected() {\n this.log('connected');\n }\n}\n"]}
|
|
@@ -1,2 +1,36 @@
|
|
|
1
|
-
import{getRandomId
|
|
2
|
-
|
|
1
|
+
import { getRandomId } from '../functions/random.js';
|
|
2
|
+
export class PerfController {
|
|
3
|
+
constructor(host) {
|
|
4
|
+
this.host = host;
|
|
5
|
+
this.hasMeasured = false;
|
|
6
|
+
host.addController(this);
|
|
7
|
+
// Set up the mark ID based on existing ID on component if it exists
|
|
8
|
+
if (!host.id) {
|
|
9
|
+
this.markId = getRandomId(host.localName);
|
|
10
|
+
}
|
|
11
|
+
else if (host.id.startsWith('pf-') && !host.id.startsWith(host.localName)) {
|
|
12
|
+
this.markId = host.id.replace('pf', host.localName);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
this.markId = `${host.localName}-${host.id}`;
|
|
16
|
+
}
|
|
17
|
+
performance.mark(`${this.markId}-defined`);
|
|
18
|
+
}
|
|
19
|
+
hostUpdate() {
|
|
20
|
+
if (!this.hasMeasured) {
|
|
21
|
+
this.measure();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
measure() {
|
|
25
|
+
this.hasMeasured = true;
|
|
26
|
+
performance.mark(`${this.markId}-rendered`);
|
|
27
|
+
// Navigation start, i.e., the browser first sees that the user has navigated to the page
|
|
28
|
+
performance.measure(`${this.markId}-from-navigation-to-first-render`, undefined, `${this.markId}-rendered`);
|
|
29
|
+
// Render is run before connection unless delayRender is used
|
|
30
|
+
performance.measure(`${this.markId}-from-defined-to-first-render`, `${this.markId}-defined`, `${this.markId}-rendered`);
|
|
31
|
+
// Once we've measured time to render, we no longer need the controller,
|
|
32
|
+
// so we allow it to be garbage-collected
|
|
33
|
+
this.host.removeController(this);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=perf-controller.js.map
|
|
@@ -1,7 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["perf-controller.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ReactiveController, ReactiveElement } from 'lit';\n\nimport { getRandomId } from '../functions/random.js';\n\nexport class PerfController implements ReactiveController {\n hasMeasured = false;\n\n markId: string;\n\n constructor(private host: ReactiveElement) {\n host.addController(this);\n\n // Set up the mark ID based on existing ID on component if it exists\n if (!host.id) {\n this.markId = getRandomId(host.localName);\n } else if (host.id.startsWith('pfe-') && !host.id.startsWith(host.localName)) {\n this.markId = host.id.replace('pfe', host.localName);\n } else {\n this.markId = `${host.localName}-${host.id}`;\n }\n\n performance.mark(`${this.markId}-defined`);\n }\n\n hostUpdate() {\n if (!this.hasMeasured) {\n this.measure();\n }\n }\n\n measure() {\n this.hasMeasured = true;\n\n performance.mark(`${this.markId}-rendered`);\n\n // Navigation start, i.e., the browser first sees that the user has navigated to the page\n performance.measure(`${this.markId}-from-navigation-to-first-render`, undefined, `${this.markId}-rendered`);\n\n // Render is run before connection unless delayRender is used\n performance.measure(\n `${this.markId}-from-defined-to-first-render`,\n `${this.markId}-defined`,\n `${this.markId}-rendered`\n );\n\n // Once we've measured time to render, we no longer need the controller,\n // so we allow it to be garbage-collected\n this.host.removeController(this);\n }\n}\n"],
|
|
5
|
-
"mappings": "AAEA,OAAS,eAAAA,MAAmB,yBAErB,IAAMC,EAAN,KAAmD,CAKxD,YAAoBC,EAAuB,CAAvB,UAAAA,EAJpB,iBAAc,GAKZA,EAAK,cAAc,IAAI,EAGlBA,EAAK,GAECA,EAAK,GAAG,WAAW,MAAM,GAAK,CAACA,EAAK,GAAG,WAAWA,EAAK,SAAS,EACzE,KAAK,OAASA,EAAK,GAAG,QAAQ,MAAOA,EAAK,SAAS,EAEnD,KAAK,OAAS,GAAGA,EAAK,aAAaA,EAAK,KAJxC,KAAK,OAASF,EAAYE,EAAK,SAAS,EAO1C,YAAY,KAAK,GAAG,KAAK,gBAAgB,CAC3C,CAEA,YAAa,CACN,KAAK,aACR,KAAK,QAAQ,CAEjB,CAEA,SAAU,CACR,KAAK,YAAc,GAEnB,YAAY,KAAK,GAAG,KAAK,iBAAiB,EAG1C,YAAY,QAAQ,GAAG,KAAK,yCAA0C,OAAW,GAAG,KAAK,iBAAiB,EAG1G,YAAY,QACV,GAAG,KAAK,sCACR,GAAG,KAAK,iBACR,GAAG,KAAK,iBACV,EAIA,KAAK,KAAK,iBAAiB,IAAI,CACjC,CACF",
|
|
6
|
-
"names": ["getRandomId", "PerfController", "host"]
|
|
7
|
-
}
|
|
1
|
+
{"version":3,"file":"perf-controller.js","sourceRoot":"","sources":["perf-controller.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD,MAAM,OAAO,cAAc;IAKzB,YAAoB,IAAqB;QAArB,SAAI,GAAJ,IAAI,CAAiB;QAJzC,gBAAW,GAAG,KAAK,CAAC;QAKlB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAEzB,oEAAoE;QACpE,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE;YACZ,IAAI,CAAC,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;SAC3C;aAAM,IAAI,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE;YAC3E,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;SACrD;aAAM;YACL,IAAI,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;SAC9C;QAED,WAAW,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,UAAU,CAAC,CAAC;IAC7C,CAAC;IAED,UAAU;QACR,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;YACrB,IAAI,CAAC,OAAO,EAAE,CAAC;SAChB;IACH,CAAC;IAED,OAAO;QACL,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QAExB,WAAW,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,WAAW,CAAC,CAAC;QAE5C,yFAAyF;QACzF,WAAW,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,kCAAkC,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,MAAM,WAAW,CAAC,CAAC;QAE5G,6DAA6D;QAC7D,WAAW,CAAC,OAAO,CACjB,GAAG,IAAI,CAAC,MAAM,+BAA+B,EAC7C,GAAG,IAAI,CAAC,MAAM,UAAU,EACxB,GAAG,IAAI,CAAC,MAAM,WAAW,CAC1B,CAAC;QAEF,wEAAwE;QACxE,yCAAyC;QACzC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;CACF","sourcesContent":["import type { ReactiveController, ReactiveElement } from 'lit';\n\nimport { getRandomId } from '../functions/random.js';\n\nexport class PerfController implements ReactiveController {\n hasMeasured = false;\n\n markId: string;\n\n constructor(private host: ReactiveElement) {\n host.addController(this);\n\n // Set up the mark ID based on existing ID on component if it exists\n if (!host.id) {\n this.markId = getRandomId(host.localName);\n } else if (host.id.startsWith('pf-') && !host.id.startsWith(host.localName)) {\n this.markId = host.id.replace('pf', host.localName);\n } else {\n this.markId = `${host.localName}-${host.id}`;\n }\n\n performance.mark(`${this.markId}-defined`);\n }\n\n hostUpdate() {\n if (!this.hasMeasured) {\n this.measure();\n }\n }\n\n measure() {\n this.hasMeasured = true;\n\n performance.mark(`${this.markId}-rendered`);\n\n // Navigation start, i.e., the browser first sees that the user has navigated to the page\n performance.measure(`${this.markId}-from-navigation-to-first-render`, undefined, `${this.markId}-rendered`);\n\n // Render is run before connection unless delayRender is used\n performance.measure(\n `${this.markId}-from-defined-to-first-render`,\n `${this.markId}-defined`,\n `${this.markId}-rendered`\n );\n\n // Once we've measured time to render, we no longer need the controller,\n // so we allow it to be garbage-collected\n this.host.removeController(this);\n }\n}\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { ReactiveController, ReactiveElement } from 'lit';
|
|
2
2
|
export declare const observedController: unique symbol;
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
3
|
+
export type ChangeCallback<T = ReactiveElement> = (this: T, old?: T[keyof T], newV?: T[keyof T]) => void;
|
|
4
|
+
export type ChangeCallbackName = `_${string}Changed`;
|
|
5
|
+
export type PropertyObserverHost<T> = T & Record<ChangeCallbackName, ChangeCallback<T>> & {
|
|
6
6
|
[observedController]: PropertyObserverController;
|
|
7
7
|
};
|
|
8
8
|
/** This controller holds a cache of observed property values which were set before the element updated */
|
|
@@ -1,2 +1,33 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
export const observedController = Symbol('observed properties controller');
|
|
2
|
+
/** This controller holds a cache of observed property values which were set before the element updated */
|
|
3
|
+
export class PropertyObserverController {
|
|
4
|
+
delete(key) {
|
|
5
|
+
this.values.delete(key);
|
|
6
|
+
}
|
|
7
|
+
constructor(host) {
|
|
8
|
+
this.host = host;
|
|
9
|
+
this.values = new Map();
|
|
10
|
+
if (PropertyObserverController.hosts.get(host)) {
|
|
11
|
+
return PropertyObserverController.hosts.get(host);
|
|
12
|
+
}
|
|
13
|
+
host.addController(this);
|
|
14
|
+
host[observedController] = this;
|
|
15
|
+
}
|
|
16
|
+
/** Set any cached valued accumulated between constructor and connectedCallback */
|
|
17
|
+
hostUpdate() {
|
|
18
|
+
for (const [key, [methodName, [oldVal, newVal]]] of this.values) {
|
|
19
|
+
// @ts-expect-error: be cool, typescript
|
|
20
|
+
this.host[methodName]?.(oldVal, newVal);
|
|
21
|
+
this.delete(key);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/** Once the element has updated, we no longer need this controller, so we remove it */
|
|
25
|
+
hostUpdated() {
|
|
26
|
+
this.host.removeController(this);
|
|
27
|
+
}
|
|
28
|
+
cache(key, methodName, ...vals) {
|
|
29
|
+
this.values.set(key, [methodName, vals]);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
PropertyObserverController.hosts = new WeakMap();
|
|
33
|
+
//# sourceMappingURL=property-observer-controller.js.map
|
|
@@ -1,7 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["property-observer-controller.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ReactiveController, ReactiveElement } from 'lit';\n\nexport const observedController = Symbol('observed properties controller');\n\nexport type ChangeCallback<T = ReactiveElement> = (\n this: T,\n old?: T[keyof T],\n newV?: T[keyof T],\n) => void;\n\nexport type ChangeCallbackName = `_${string}Changed`;\n\nexport type PropertyObserverHost<T> = T & Record<ChangeCallbackName, ChangeCallback<T>> & {\n [observedController]: PropertyObserverController;\n}\n\n/** This controller holds a cache of observed property values which were set before the element updated */\nexport class PropertyObserverController implements ReactiveController {\n private static hosts: WeakMap<HTMLElement, PropertyObserverController> = new WeakMap();\n\n private values = new Map<string, [methodName: string, values: [unknown, unknown]]>();\n\n private delete(key: string) {\n this.values.delete(key);\n }\n\n constructor(private host: ReactiveElement) {\n if (PropertyObserverController.hosts.get(host)) {\n return PropertyObserverController.hosts.get(host) as PropertyObserverController;\n }\n host.addController(this);\n (host as PropertyObserverHost<ReactiveElement>)[observedController] = this;\n }\n\n /** Set any cached valued accumulated between constructor and connectedCallback */\n hostUpdate() {\n for (const [key, [methodName, [oldVal, newVal]]] of this.values) {\n // @ts-expect-error: be cool, typescript\n this.host[methodName as keyof ReactiveElement]?.(oldVal, newVal);\n this.delete(key);\n }\n }\n\n /** Once the element has updated, we no longer need this controller, so we remove it */\n hostUpdated() {\n this.host.removeController(this);\n }\n\n cache(key: string, methodName: string, ...vals: [unknown, unknown]) {\n this.values.set(key, [methodName, vals]);\n }\n}\n"],
|
|
5
|
-
"mappings": "AAEO,IAAMA,EAAqB,OAAO,gCAAgC,EAe5DC,EAAN,KAA+D,CASpE,YAAoBC,EAAuB,CAAvB,UAAAA,EANpB,KAAQ,OAAS,IAAI,IAOnB,GAAID,EAA2B,MAAM,IAAIC,CAAI,EAC3C,OAAOD,EAA2B,MAAM,IAAIC,CAAI,EAElDA,EAAK,cAAc,IAAI,EACtBA,EAA+CF,GAAsB,IACxE,CAVQ,OAAOG,EAAa,CAC1B,KAAK,OAAO,OAAOA,CAAG,CACxB,CAWA,YAAa,CACX,OAAW,CAACA,EAAK,CAACC,EAAY,CAACC,EAAQC,CAAM,CAAC,CAAC,IAAK,KAAK,OAEvD,KAAK,KAAKF,KAAuCC,EAAQC,CAAM,EAC/D,KAAK,OAAOH,CAAG,CAEnB,CAGA,aAAc,CACZ,KAAK,KAAK,iBAAiB,IAAI,CACjC,CAEA,MAAMA,EAAaC,KAAuBG,EAA0B,CAClE,KAAK,OAAO,IAAIJ,EAAK,CAACC,EAAYG,CAAI,CAAC,CACzC,CACF,EAlCaC,EAANP,EAAMO,EACI,MAA0D,IAAI",
|
|
6
|
-
"names": ["observedController", "_PropertyObserverController", "host", "key", "methodName", "oldVal", "newVal", "vals", "PropertyObserverController"]
|
|
7
|
-
}
|
|
1
|
+
{"version":3,"file":"property-observer-controller.js","sourceRoot":"","sources":["property-observer-controller.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,gCAAgC,CAAC,CAAC;AAc3E,0GAA0G;AAC1G,MAAM,OAAO,0BAA0B;IAK7B,MAAM,CAAC,GAAW;QACxB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED,YAAoB,IAAqB;QAArB,SAAI,GAAJ,IAAI,CAAiB;QANjC,WAAM,GAAG,IAAI,GAAG,EAA4D,CAAC;QAOnF,IAAI,0BAA0B,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YAC9C,OAAO,0BAA0B,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAA+B,CAAC;SACjF;QACD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QACxB,IAA8C,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAAC;IAC7E,CAAC;IAED,kFAAkF;IAClF,UAAU;QACR,KAAK,MAAM,CAAC,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE;YAC/D,wCAAwC;YACxC,IAAI,CAAC,IAAI,CAAC,UAAmC,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACjE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;SAClB;IACH,CAAC;IAED,uFAAuF;IACvF,WAAW;QACT,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,GAAW,EAAE,UAAkB,EAAE,GAAG,IAAwB;QAChE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC;IAC3C,CAAC;;AAhCc,gCAAK,GAAqD,IAAI,OAAO,EAAE,CAAC","sourcesContent":["import type { ReactiveController, ReactiveElement } from 'lit';\n\nexport const observedController = Symbol('observed properties controller');\n\nexport type ChangeCallback<T = ReactiveElement> = (\n this: T,\n old?: T[keyof T],\n newV?: T[keyof T],\n) => void;\n\nexport type ChangeCallbackName = `_${string}Changed`;\n\nexport type PropertyObserverHost<T> = T & Record<ChangeCallbackName, ChangeCallback<T>> & {\n [observedController]: PropertyObserverController;\n}\n\n/** This controller holds a cache of observed property values which were set before the element updated */\nexport class PropertyObserverController implements ReactiveController {\n private static hosts: WeakMap<HTMLElement, PropertyObserverController> = new WeakMap();\n\n private values = new Map<string, [methodName: string, values: [unknown, unknown]]>();\n\n private delete(key: string) {\n this.values.delete(key);\n }\n\n constructor(private host: ReactiveElement) {\n if (PropertyObserverController.hosts.get(host)) {\n return PropertyObserverController.hosts.get(host) as PropertyObserverController;\n }\n host.addController(this);\n (host as PropertyObserverHost<ReactiveElement>)[observedController] = this;\n }\n\n /** Set any cached valued accumulated between constructor and connectedCallback */\n hostUpdate() {\n for (const [key, [methodName, [oldVal, newVal]]] of this.values) {\n // @ts-expect-error: be cool, typescript\n this.host[methodName as keyof ReactiveElement]?.(oldVal, newVal);\n this.delete(key);\n }\n }\n\n /** Once the element has updated, we no longer need this controller, so we remove it */\n hostUpdated() {\n this.host.removeController(this);\n }\n\n cache(key: string, methodName: string, ...vals: [unknown, unknown]) {\n this.values.set(key, [methodName, vals]);\n }\n}\n"]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
2
|
+
/**
|
|
3
|
+
* Implements roving tabindex, as described in WAI-ARIA practices, [Managing Focus Within
|
|
4
|
+
* Components Using a Roving
|
|
5
|
+
* tabindex](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex)
|
|
6
|
+
*/
|
|
7
|
+
export declare class RovingTabindexController implements ReactiveController {
|
|
8
|
+
#private;
|
|
9
|
+
host: ReactiveControllerHost & HTMLElement;
|
|
10
|
+
/**
|
|
11
|
+
* active item of array of items
|
|
12
|
+
*/
|
|
13
|
+
get activeItem(): HTMLElement | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* first item in array of focusable items
|
|
16
|
+
*/
|
|
17
|
+
get firstItem(): HTMLElement | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* last item in array of focusable items
|
|
20
|
+
*/
|
|
21
|
+
get lastItem(): HTMLElement | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* next item after active item in array of focusable items
|
|
24
|
+
*/
|
|
25
|
+
get nextItem(): HTMLElement | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* previous item after active item in array of focusable items
|
|
28
|
+
*/
|
|
29
|
+
get prevItem(): HTMLElement | undefined;
|
|
30
|
+
constructor(host: ReactiveControllerHost & HTMLElement);
|
|
31
|
+
/**
|
|
32
|
+
* sets tabindex of item based on whether or not it is active
|
|
33
|
+
*/
|
|
34
|
+
updateActiveItem(item?: HTMLElement): void;
|
|
35
|
+
/**
|
|
36
|
+
* focuses on an item and sets it as active
|
|
37
|
+
*/
|
|
38
|
+
focusOnItem(item?: HTMLElement): void;
|
|
39
|
+
/**
|
|
40
|
+
* Focuses next focusable item
|
|
41
|
+
*/
|
|
42
|
+
updateItems(items: HTMLElement[]): void;
|
|
43
|
+
/**
|
|
44
|
+
* from array of HTML items, and sets active items
|
|
45
|
+
*/
|
|
46
|
+
initItems(items: HTMLElement[]): void;
|
|
47
|
+
hostConnected(): void;
|
|
48
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
var _RovingTabindexController_instances, _RovingTabindexController_activeItem, _RovingTabindexController_items, _RovingTabindexController_focusableItems_get, _RovingTabindexController_activeIndex_get, _RovingTabindexController_itemIndex_get, _RovingTabindexController_onKeydown;
|
|
2
|
+
import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
|
|
3
|
+
const isFocusableElement = (el) => !!el &&
|
|
4
|
+
!el.hasAttribute('disabled') &&
|
|
5
|
+
!el.ariaHidden &&
|
|
6
|
+
!el.hasAttribute('hidden');
|
|
7
|
+
/**
|
|
8
|
+
* Implements roving tabindex, as described in WAI-ARIA practices, [Managing Focus Within
|
|
9
|
+
* Components Using a Roving
|
|
10
|
+
* tabindex](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex)
|
|
11
|
+
*/
|
|
12
|
+
export class RovingTabindexController {
|
|
13
|
+
/**
|
|
14
|
+
* active item of array of items
|
|
15
|
+
*/
|
|
16
|
+
get activeItem() {
|
|
17
|
+
return __classPrivateFieldGet(this, _RovingTabindexController_activeItem, "f");
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* first item in array of focusable items
|
|
21
|
+
*/
|
|
22
|
+
get firstItem() {
|
|
23
|
+
return __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get)[0];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* last item in array of focusable items
|
|
27
|
+
*/
|
|
28
|
+
get lastItem() {
|
|
29
|
+
return __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get).at(-1);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* next item after active item in array of focusable items
|
|
33
|
+
*/
|
|
34
|
+
get nextItem() {
|
|
35
|
+
return (__classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_activeIndex_get) < __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get).length - 1 ? __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get)[__classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_activeIndex_get) + 1]
|
|
36
|
+
: this.firstItem);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* previous item after active item in array of focusable items
|
|
40
|
+
*/
|
|
41
|
+
get prevItem() {
|
|
42
|
+
return (__classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_activeIndex_get) > 0 ? __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get)[__classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_activeIndex_get) - 1]
|
|
43
|
+
: this.lastItem);
|
|
44
|
+
}
|
|
45
|
+
constructor(host) {
|
|
46
|
+
this.host = host;
|
|
47
|
+
_RovingTabindexController_instances.add(this);
|
|
48
|
+
/** active focusable element */
|
|
49
|
+
_RovingTabindexController_activeItem.set(this, void 0);
|
|
50
|
+
/** array of all focusable elements */
|
|
51
|
+
_RovingTabindexController_items.set(this, []);
|
|
52
|
+
this.host.addController(this);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* sets tabindex of item based on whether or not it is active
|
|
56
|
+
*/
|
|
57
|
+
updateActiveItem(item) {
|
|
58
|
+
if (item) {
|
|
59
|
+
if (!!__classPrivateFieldGet(this, _RovingTabindexController_activeItem, "f") && item !== __classPrivateFieldGet(this, _RovingTabindexController_activeItem, "f")) {
|
|
60
|
+
__classPrivateFieldGet(this, _RovingTabindexController_activeItem, "f").tabIndex = -1;
|
|
61
|
+
}
|
|
62
|
+
item.tabIndex = 0;
|
|
63
|
+
__classPrivateFieldSet(this, _RovingTabindexController_activeItem, item, "f");
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* focuses on an item and sets it as active
|
|
68
|
+
*/
|
|
69
|
+
focusOnItem(item) {
|
|
70
|
+
this.updateActiveItem(item || this.firstItem);
|
|
71
|
+
__classPrivateFieldGet(this, _RovingTabindexController_activeItem, "f")?.focus();
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Focuses next focusable item
|
|
75
|
+
*/
|
|
76
|
+
updateItems(items) {
|
|
77
|
+
const sequence = [...items.slice(__classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_itemIndex_get)), ...items.slice(0, __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_itemIndex_get))];
|
|
78
|
+
const first = sequence.find(item => __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get).includes(item));
|
|
79
|
+
this.focusOnItem(first || this.firstItem);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* from array of HTML items, and sets active items
|
|
83
|
+
*/
|
|
84
|
+
initItems(items) {
|
|
85
|
+
__classPrivateFieldSet(this, _RovingTabindexController_items, items ?? [], "f");
|
|
86
|
+
const focusableItems = __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get);
|
|
87
|
+
const [focusableItem] = focusableItems;
|
|
88
|
+
__classPrivateFieldSet(this, _RovingTabindexController_activeItem, focusableItem, "f");
|
|
89
|
+
for (const item of focusableItems) {
|
|
90
|
+
item.tabIndex = __classPrivateFieldGet(this, _RovingTabindexController_activeItem, "f") === item ? 0 : -1;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
hostConnected() {
|
|
94
|
+
this.host.addEventListener('keydown', __classPrivateFieldGet(this, _RovingTabindexController_instances, "m", _RovingTabindexController_onKeydown).bind(this));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
_RovingTabindexController_activeItem = new WeakMap(), _RovingTabindexController_items = new WeakMap(), _RovingTabindexController_instances = new WeakSet(), _RovingTabindexController_focusableItems_get = function _RovingTabindexController_focusableItems_get() {
|
|
98
|
+
return __classPrivateFieldGet(this, _RovingTabindexController_items, "f").filter(isFocusableElement);
|
|
99
|
+
}, _RovingTabindexController_activeIndex_get = function _RovingTabindexController_activeIndex_get() {
|
|
100
|
+
return !!__classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get) && !!this.activeItem ? __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get).indexOf(this.activeItem) : -1;
|
|
101
|
+
}, _RovingTabindexController_itemIndex_get = function _RovingTabindexController_itemIndex_get() {
|
|
102
|
+
return this.activeItem ? __classPrivateFieldGet(this, _RovingTabindexController_items, "f").indexOf(this.activeItem) : -1;
|
|
103
|
+
}, _RovingTabindexController_onKeydown = function _RovingTabindexController_onKeydown(event) {
|
|
104
|
+
if (event.ctrlKey || event.altKey || event.metaKey || __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get).length < 1) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const item = this.activeItem;
|
|
108
|
+
let shouldPreventDefault = false;
|
|
109
|
+
const horizontalOnly = !item ? false
|
|
110
|
+
: item.tagName === 'SELECT' ||
|
|
111
|
+
item.getAttribute('aria-expanded') === 'true' ||
|
|
112
|
+
item.getAttribute('role') === 'spinbutton';
|
|
113
|
+
switch (event.key) {
|
|
114
|
+
case 'ArrowLeft':
|
|
115
|
+
this.focusOnItem(this.prevItem);
|
|
116
|
+
shouldPreventDefault = true;
|
|
117
|
+
break;
|
|
118
|
+
case 'ArrowRight':
|
|
119
|
+
this.focusOnItem(this.nextItem);
|
|
120
|
+
shouldPreventDefault = true;
|
|
121
|
+
break;
|
|
122
|
+
case 'ArrowUp':
|
|
123
|
+
if (horizontalOnly) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
this.focusOnItem(this.prevItem);
|
|
127
|
+
shouldPreventDefault = true;
|
|
128
|
+
break;
|
|
129
|
+
case 'ArrowDown':
|
|
130
|
+
if (horizontalOnly) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
this.focusOnItem(this.nextItem);
|
|
134
|
+
shouldPreventDefault = true;
|
|
135
|
+
break;
|
|
136
|
+
case 'Home':
|
|
137
|
+
this.focusOnItem(this.firstItem);
|
|
138
|
+
shouldPreventDefault = true;
|
|
139
|
+
break;
|
|
140
|
+
case 'PageUp':
|
|
141
|
+
if (horizontalOnly) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
this.focusOnItem(this.firstItem);
|
|
145
|
+
shouldPreventDefault = true;
|
|
146
|
+
break;
|
|
147
|
+
case 'End':
|
|
148
|
+
this.focusOnItem(this.lastItem);
|
|
149
|
+
shouldPreventDefault = true;
|
|
150
|
+
break;
|
|
151
|
+
case 'PageDown':
|
|
152
|
+
if (horizontalOnly) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
this.focusOnItem(this.lastItem);
|
|
156
|
+
shouldPreventDefault = true;
|
|
157
|
+
break;
|
|
158
|
+
default:
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
if (shouldPreventDefault) {
|
|
162
|
+
event.stopPropagation();
|
|
163
|
+
event.preventDefault();
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
//# sourceMappingURL=roving-tabindex-controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roving-tabindex-controller.js","sourceRoot":"","sources":["roving-tabindex-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController, ReactiveControllerHost } from 'lit';\n\nconst isFocusableElement = (el: Element): el is HTMLElement =>\n !!el &&\n !el.hasAttribute('disabled') &&\n !el.ariaHidden &&\n !el.hasAttribute('hidden');\n\n/**\n * Implements roving tabindex, as described in WAI-ARIA practices, [Managing Focus Within\n * Components Using a Roving\n * tabindex](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex)\n */\nexport class RovingTabindexController implements ReactiveController {\n /** active focusable element */\n #activeItem?: HTMLElement;\n\n /** array of all focusable elements */\n #items: HTMLElement[] = [];\n\n /**\n * finds focusable items from a group of items\n */\n get #focusableItems(): HTMLElement[] {\n return this.#items.filter(isFocusableElement);\n }\n\n /**\n * index of active item in array of focusable items\n */\n get #activeIndex(): number {\n return !!this.#focusableItems && !!this.activeItem ? this.#focusableItems.indexOf(this.activeItem) : -1;\n }\n\n /**\n * index of active item in array of items\n */\n get #itemIndex(): number {\n return this.activeItem ? this.#items.indexOf(this.activeItem) : -1;\n }\n\n /**\n * active item of array of items\n */\n get activeItem(): HTMLElement | undefined {\n return this.#activeItem;\n }\n\n /**\n * first item in array of focusable items\n */\n get firstItem(): HTMLElement | undefined {\n return this.#focusableItems[0];\n }\n\n /**\n * last item in array of focusable items\n */\n get lastItem(): HTMLElement | undefined {\n return this.#focusableItems.at(-1);\n }\n\n /**\n * next item after active item in array of focusable items\n */\n get nextItem(): HTMLElement | undefined {\n return (\n this.#activeIndex < this.#focusableItems.length - 1 ? this.#focusableItems[this.#activeIndex + 1]\n : this.firstItem\n );\n }\n\n /**\n * previous item after active item in array of focusable items\n */\n get prevItem(): HTMLElement | undefined {\n return (\n this.#activeIndex > 0 ? this.#focusableItems[this.#activeIndex - 1]\n : this.lastItem\n );\n }\n\n constructor(public host: ReactiveControllerHost & HTMLElement) {\n this.host.addController(this);\n }\n\n /**\n * handles keyboard navigation\n */\n #onKeydown(event: KeyboardEvent):void {\n if (event.ctrlKey || event.altKey || event.metaKey || this.#focusableItems.length < 1) {\n return;\n }\n\n const item = this.activeItem;\n let shouldPreventDefault = false;\n const horizontalOnly =\n !item ? false\n : item.tagName === 'SELECT' ||\n item.getAttribute('aria-expanded') === 'true' ||\n item.getAttribute('role') === 'spinbutton';\n\n switch (event.key) {\n case 'ArrowLeft':\n this.focusOnItem(this.prevItem);\n shouldPreventDefault = true;\n break;\n case 'ArrowRight':\n this.focusOnItem(this.nextItem);\n shouldPreventDefault = true;\n break;\n case 'ArrowUp':\n if (horizontalOnly) {\n return;\n }\n this.focusOnItem(this.prevItem);\n shouldPreventDefault = true;\n break;\n case 'ArrowDown':\n if (horizontalOnly) {\n return;\n }\n this.focusOnItem(this.nextItem);\n shouldPreventDefault = true;\n break;\n case 'Home':\n this.focusOnItem(this.firstItem);\n shouldPreventDefault = true;\n break;\n case 'PageUp':\n if (horizontalOnly) {\n return;\n }\n this.focusOnItem(this.firstItem);\n shouldPreventDefault = true;\n break;\n case 'End':\n this.focusOnItem(this.lastItem);\n shouldPreventDefault = true;\n break;\n case 'PageDown':\n if (horizontalOnly) {\n return;\n }\n this.focusOnItem(this.lastItem);\n shouldPreventDefault = true;\n break;\n default:\n break;\n }\n\n if (shouldPreventDefault) {\n event.stopPropagation();\n event.preventDefault();\n }\n }\n\n /**\n * sets tabindex of item based on whether or not it is active\n */\n updateActiveItem(item?: HTMLElement):void {\n if (item) {\n if (!!this.#activeItem && item !== this.#activeItem) {\n this.#activeItem.tabIndex = -1;\n }\n item.tabIndex = 0;\n this.#activeItem = item;\n }\n }\n\n /**\n * focuses on an item and sets it as active\n */\n focusOnItem(item?: HTMLElement):void {\n this.updateActiveItem(item || this.firstItem);\n this.#activeItem?.focus();\n }\n\n /**\n * Focuses next focusable item\n */\n updateItems(items: HTMLElement[]) {\n const sequence = [...items.slice(this.#itemIndex), ...items.slice(0, this.#itemIndex)];\n const first = sequence.find(item => this.#focusableItems.includes(item));\n this.focusOnItem(first || this.firstItem);\n }\n\n /**\n * from array of HTML items, and sets active items\n */\n initItems(items: HTMLElement[]) {\n this.#items = items ?? [];\n const focusableItems = this.#focusableItems;\n const [focusableItem] = focusableItems;\n this.#activeItem = focusableItem;\n for (const item of focusableItems) {\n item.tabIndex = this.#activeItem === item ? 0 : -1;\n }\n }\n\n hostConnected() {\n this.host.addEventListener('keydown', this.#onKeydown.bind(this));\n }\n}\n"]}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
2
|
+
export interface ScrollSpyControllerOptions extends IntersectionObserverInit {
|
|
3
|
+
/**
|
|
4
|
+
* Tag names of legal link children.
|
|
5
|
+
* Legal children must have an `href` property/attribute pair, like `<a>`.
|
|
6
|
+
*/
|
|
7
|
+
tagNames: string[];
|
|
8
|
+
/**
|
|
9
|
+
* Attribute to set on the active link element.
|
|
10
|
+
* @default 'active'
|
|
11
|
+
*/
|
|
12
|
+
activeAttribute?: string;
|
|
13
|
+
/**
|
|
14
|
+
* The root node to query content for
|
|
15
|
+
* @default the host's root node
|
|
16
|
+
*/
|
|
17
|
+
rootNode?: Node;
|
|
18
|
+
/**
|
|
19
|
+
* function to call on link children to get their URL hash (i.e. id to scroll to)
|
|
20
|
+
* @default el => el.getAttribute('href');
|
|
21
|
+
*/
|
|
22
|
+
getHash?: (el: Element) => string | null;
|
|
23
|
+
}
|
|
24
|
+
export declare class ScrollSpyController implements ReactiveController {
|
|
25
|
+
#private;
|
|
26
|
+
private host;
|
|
27
|
+
get root(): Element | Document | null | undefined;
|
|
28
|
+
set root(v: Element | Document | null | undefined);
|
|
29
|
+
get rootMargin(): string | undefined;
|
|
30
|
+
set rootMargin(v: string | undefined);
|
|
31
|
+
get threshold(): number | number[];
|
|
32
|
+
set threshold(v: number | number[]);
|
|
33
|
+
constructor(host: ReactiveControllerHost & HTMLElement, options: ScrollSpyControllerOptions);
|
|
34
|
+
hostConnected(): void;
|
|
35
|
+
/** Explicitly set the active item */
|
|
36
|
+
setActive(link: EventTarget | null): Promise<void>;
|
|
37
|
+
}
|