Skip to content

Commit c242deb

Browse files
authored
feat(utils): add new utilities and mixins (#222)
1 parent 6f38ca4 commit c242deb

11 files changed

+364
-40
lines changed

src/utils.ts

-40
This file was deleted.

src/utils/debounce.ts

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2+
const debounce = <T extends (...args: any[]) => any>(
3+
func: T,
4+
delay: number,
5+
): ((...args: Parameters<T>) => void) => {
6+
let timeoutId: ReturnType<typeof setTimeout>;
7+
8+
return function (this: ThisParameterType<T>, ...args: Parameters<T>) {
9+
// eslint-disable-next-line @typescript-eslint/no-this-alias
10+
const context = this;
11+
12+
clearTimeout(timeoutId);
13+
timeoutId = setTimeout(() => {
14+
func.apply(context, args);
15+
}, delay);
16+
};
17+
};
18+
19+
export default debounce;

src/utils/events/BaseEvent.ts

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
abstract class BaseEvent<T> extends Event {
2+
private _details?: T;
3+
4+
public get details(): T | undefined {
5+
return this._details;
6+
}
7+
8+
constructor(name: string, eventInit?: EventInit & { details?: T }) {
9+
const { details, ...init } = eventInit ?? {};
10+
11+
super(name, init);
12+
13+
this._details = details;
14+
}
15+
}
16+
17+
export default BaseEvent;

src/utils/events/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { default as BaseEvent } from "./BaseEvent";
2+
export { default as redispatchEvent } from "./redispatch-event";

src/utils/events/redispatch-event.ts

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* Re-dispatches an event from the provided element.
3+
*
4+
* cherry-picked from: https://github.com/material-components/material-web/blob/a9ee4f5bc1d6702e5dc352eefed13a1d849577e3/internal/events/redispatch-event.ts#L28
5+
*/
6+
const redispatchEvent = (element: Element, event: Event) => {
7+
// For bubbling events in SSR light DOM (or composed), stop their propagation
8+
// and dispatch the copy.
9+
if (event.bubbles && (!element.shadowRoot || event.composed)) {
10+
event.stopPropagation();
11+
}
12+
13+
const newEvent = Reflect.construct(event.constructor, [
14+
event.type,
15+
event,
16+
]) as Event;
17+
18+
const dispatched = element.dispatchEvent(newEvent);
19+
20+
if (!dispatched) event.preventDefault();
21+
22+
return dispatched;
23+
};
24+
25+
export default redispatchEvent;

src/utils/index.ts

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export * from "./events";
2+
export * from "./mixins";
3+
4+
export { default as debounce } from "./debounce";
5+
export { default as logger } from "./logger";

src/utils/logger.ts

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
const logger = (
2+
message: string,
3+
scope: string,
4+
type: "error" | "default" | "warning" = "default",
5+
) => {
6+
const typesMap: Record<typeof type, Console["log"]> = {
7+
/* eslint-disable no-console */
8+
error: console.error,
9+
default: console.log,
10+
warning: console.warn,
11+
/* eslint-enable no-console */
12+
};
13+
14+
const logFn = typesMap[type];
15+
const completeMessage = `[TAPSI][${scope}]: ${message}`;
16+
17+
logFn(completeMessage);
18+
};
19+
20+
export default logger;

src/utils/mixins/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { default as withElementInternals } from "./with-element-internals";
2+
export { default as withFormAssociated } from "./with-form-associated";

src/utils/mixins/types.ts

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export type MixinBase<ExpectedBase = object> = abstract new (
2+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
3+
...args: any[]
4+
) => ExpectedBase;
5+
6+
export type MixinReturn<MixinBase, MixinClass = object> = (abstract new (
7+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
8+
...args: any[]
9+
) => MixinClass) &
10+
MixinBase;
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { type LitElement } from "lit";
2+
import type { MixinBase, MixinReturn } from "./types";
3+
4+
export const internals = Symbol("internals");
5+
6+
export interface WithElementInternals {
7+
[internals]: ElementInternals;
8+
}
9+
10+
const withElementInternals = <T extends MixinBase<LitElement>>(
11+
BaseClass: T,
12+
): MixinReturn<T, WithElementInternals> => {
13+
abstract class WithElementInternalsClass
14+
extends BaseClass
15+
implements WithElementInternals
16+
{
17+
private _internals?: ElementInternals;
18+
19+
public get [internals](): ElementInternals {
20+
if (!this._internals) {
21+
this._internals = (this as HTMLElement).attachInternals();
22+
}
23+
24+
return this._internals;
25+
}
26+
}
27+
28+
return WithElementInternalsClass;
29+
};
30+
31+
export default withElementInternals;

0 commit comments

Comments
 (0)