@base-ripple/core 1.0.0 → 1.0.2
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/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,179 +1 @@
|
|
|
1
|
-
|
|
2
|
-
let m = !1;
|
|
3
|
-
function S() {
|
|
4
|
-
m || (m = !0, addEventListener("blur", c), addEventListener("pagehide", c), addEventListener("beforeunload", c), addEventListener("pointerup", h, { passive: !0 }), addEventListener("pointercancel", h, { passive: !0 }), document.addEventListener("visibilitychange", B));
|
|
5
|
-
}
|
|
6
|
-
function N() {
|
|
7
|
-
!m || f.size > 0 || (m = !1, removeEventListener("blur", c), removeEventListener("pagehide", c), removeEventListener("beforeunload", c), removeEventListener("pointerup", h), removeEventListener("pointercancel", h), document.removeEventListener("visibilitychange", B));
|
|
8
|
-
}
|
|
9
|
-
function c() {
|
|
10
|
-
for (const e of f)
|
|
11
|
-
e.fadeAll();
|
|
12
|
-
}
|
|
13
|
-
function h(e) {
|
|
14
|
-
for (const i of f)
|
|
15
|
-
i.fadeFromPointer(e);
|
|
16
|
-
}
|
|
17
|
-
function B() {
|
|
18
|
-
document.visibilityState === "hidden" && c();
|
|
19
|
-
}
|
|
20
|
-
function _(e, {
|
|
21
|
-
origin: i = "pointer",
|
|
22
|
-
sizeOffset: s = 0,
|
|
23
|
-
attributes: n
|
|
24
|
-
} = {}) {
|
|
25
|
-
const a = /* @__PURE__ */ new Set(), o = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map(), b = i === "pointer";
|
|
26
|
-
let v = !1, u = O();
|
|
27
|
-
const g = (t, r, l) => ({
|
|
28
|
-
from: {
|
|
29
|
-
size: 0,
|
|
30
|
-
x: r,
|
|
31
|
-
y: l
|
|
32
|
-
},
|
|
33
|
-
to: {
|
|
34
|
-
size: (b ? Q(
|
|
35
|
-
t.width,
|
|
36
|
-
t.height,
|
|
37
|
-
r,
|
|
38
|
-
l
|
|
39
|
-
) : K(
|
|
40
|
-
t.width,
|
|
41
|
-
t.height
|
|
42
|
-
)) + s,
|
|
43
|
-
x: b ? r : t.width / 2,
|
|
44
|
-
y: b ? l : t.height / 2
|
|
45
|
-
}
|
|
46
|
-
}), x = (t) => {
|
|
47
|
-
if (t.defaultPrevented || I(e) || u) return;
|
|
48
|
-
const r = e.getBoundingClientRect(), l = g(
|
|
49
|
-
r,
|
|
50
|
-
t.clientX - r.x,
|
|
51
|
-
t.clientY - r.y
|
|
52
|
-
), p = D({
|
|
53
|
-
rippleKeyframes: l,
|
|
54
|
-
removeHandler: R,
|
|
55
|
-
attributes: n
|
|
56
|
-
});
|
|
57
|
-
a.add(p), o.set(t.pointerId, p), e.appendChild(p);
|
|
58
|
-
}, w = (t) => {
|
|
59
|
-
if (t.defaultPrevented || I(e) || u || t.repeat || d.has(t.code) || !F(t.code) || q(t.target)) return;
|
|
60
|
-
const r = e.getBoundingClientRect(), l = g(
|
|
61
|
-
r,
|
|
62
|
-
r.width / 2,
|
|
63
|
-
r.height / 2
|
|
64
|
-
), p = D({
|
|
65
|
-
rippleKeyframes: l,
|
|
66
|
-
removeHandler: R,
|
|
67
|
-
attributes: n
|
|
68
|
-
});
|
|
69
|
-
a.add(p), d.set(t.code, p), e.appendChild(p);
|
|
70
|
-
}, y = (t) => {
|
|
71
|
-
t.style.opacity = "0";
|
|
72
|
-
}, E = (t) => {
|
|
73
|
-
const r = o.get(t.pointerId);
|
|
74
|
-
r && (y(r), o.delete(t.pointerId));
|
|
75
|
-
}, z = (t) => {
|
|
76
|
-
const r = d.get(t.code);
|
|
77
|
-
r && (y(r), d.delete(t.code));
|
|
78
|
-
}, L = () => {
|
|
79
|
-
for (const t of o.values()) y(t);
|
|
80
|
-
o.clear();
|
|
81
|
-
for (const t of d.values()) y(t);
|
|
82
|
-
d.clear();
|
|
83
|
-
}, R = (t) => {
|
|
84
|
-
a.delete(t);
|
|
85
|
-
for (const [r, l] of o)
|
|
86
|
-
if (l === t) {
|
|
87
|
-
o.delete(r);
|
|
88
|
-
break;
|
|
89
|
-
}
|
|
90
|
-
for (const [r, l] of d)
|
|
91
|
-
if (l === t) {
|
|
92
|
-
d.delete(r);
|
|
93
|
-
break;
|
|
94
|
-
}
|
|
95
|
-
t.remove();
|
|
96
|
-
}, P = () => {
|
|
97
|
-
for (const t of a)
|
|
98
|
-
t.remove();
|
|
99
|
-
a.clear(), o.clear(), d.clear();
|
|
100
|
-
}, M = () => {
|
|
101
|
-
v || (e.addEventListener("pointerdown", x, {
|
|
102
|
-
passive: !0
|
|
103
|
-
}), v = !0);
|
|
104
|
-
}, k = () => {
|
|
105
|
-
v && (e.removeEventListener("pointerdown", x), v = !1);
|
|
106
|
-
}, G = T((t) => {
|
|
107
|
-
u !== t && (u = t, u ? (k(), P()) : M());
|
|
108
|
-
}), A = (t) => {
|
|
109
|
-
F(t.code) && z(t);
|
|
110
|
-
};
|
|
111
|
-
u || M(), e.addEventListener("keyup", A), e.addEventListener("keydown", w), e.addEventListener("contextmenu", L), e.addEventListener("pointerleave", E, {
|
|
112
|
-
passive: !0
|
|
113
|
-
}), S();
|
|
114
|
-
const C = {
|
|
115
|
-
fadeAll: L,
|
|
116
|
-
fadeFromPointer: E
|
|
117
|
-
};
|
|
118
|
-
return f.add(C), () => {
|
|
119
|
-
G(), k(), e.removeEventListener("keyup", A), e.removeEventListener("keydown", w), e.removeEventListener("contextmenu", L), e.removeEventListener("pointerleave", E), f.delete(C), N(), P();
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
const H = "(prefers-reduced-motion: reduce)";
|
|
123
|
-
function O() {
|
|
124
|
-
return typeof matchMedia != "function" ? !1 : matchMedia(H).matches;
|
|
125
|
-
}
|
|
126
|
-
function T(e) {
|
|
127
|
-
if (typeof matchMedia != "function") return () => {
|
|
128
|
-
};
|
|
129
|
-
const i = matchMedia(H), s = (n) => e(n.matches);
|
|
130
|
-
return typeof i.addEventListener == "function" ? (i.addEventListener("change", s), () => i.removeEventListener("change", s)) : typeof i.addListener == "function" ? (i.addListener(s), () => i.removeListener(s)) : () => {
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
function D({
|
|
134
|
-
rippleKeyframes: e,
|
|
135
|
-
removeHandler: i,
|
|
136
|
-
attributes: s
|
|
137
|
-
}) {
|
|
138
|
-
const n = document.createElement("span");
|
|
139
|
-
if (n.setAttribute("aria-hidden", "true"), n.className = "base-ripple", n.style.width = e.to.size + "px", n.style.height = e.to.size + "px", n.style.setProperty(
|
|
140
|
-
"--base-ripple-keyframes-from-x",
|
|
141
|
-
e.from.x + "px"
|
|
142
|
-
), n.style.setProperty(
|
|
143
|
-
"--base-ripple-keyframes-from-y",
|
|
144
|
-
e.from.y + "px"
|
|
145
|
-
), n.style.setProperty(
|
|
146
|
-
"--base-ripple-keyframes-to-x",
|
|
147
|
-
e.to.x + "px"
|
|
148
|
-
), n.style.setProperty(
|
|
149
|
-
"--base-ripple-keyframes-to-y",
|
|
150
|
-
e.to.y + "px"
|
|
151
|
-
), s)
|
|
152
|
-
for (const [o, d] of Object.entries(s))
|
|
153
|
-
n.setAttribute(o, d);
|
|
154
|
-
const a = (o) => {
|
|
155
|
-
o.propertyName === "opacity" && (i(n), n.removeEventListener("transitionend", a));
|
|
156
|
-
};
|
|
157
|
-
return n.addEventListener("transitionend", a), n;
|
|
158
|
-
}
|
|
159
|
-
function I(e) {
|
|
160
|
-
const i = e.getAttribute("aria-disabled");
|
|
161
|
-
return i !== null ? i.toLowerCase() === "true" : "disabled" in e && !!e.disabled;
|
|
162
|
-
}
|
|
163
|
-
function F(e) {
|
|
164
|
-
return e === "Space" || e === "Enter" || e === "NumpadEnter";
|
|
165
|
-
}
|
|
166
|
-
const U = 'input:not([type]),input[type="text"],input[type="search"],input[type="url"],input[type="tel"],input[type="email"],input[type="password"],input[type="number"],input[type="date"],input[type="time"],input[type="datetime-local"],input[type="month"],input[type="week"],textarea,[contenteditable]';
|
|
167
|
-
function q(e) {
|
|
168
|
-
return e instanceof Element ? !!e.closest(U) : !1;
|
|
169
|
-
}
|
|
170
|
-
function K(e, i) {
|
|
171
|
-
return Math.sqrt(e * e + i * i);
|
|
172
|
-
}
|
|
173
|
-
function Q(e, i, s, n) {
|
|
174
|
-
const a = Math.max(s, e - s), o = Math.max(n, i - n);
|
|
175
|
-
return 2 * Math.sqrt(a * a + o * o);
|
|
176
|
-
}
|
|
177
|
-
export {
|
|
178
|
-
_ as attachBaseRipple
|
|
179
|
-
};
|
|
1
|
+
export * from "./lib/attach-base-ripple.js";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type AttachBaseRippleOptions = {
|
|
2
|
+
origin?: "pointer" | "center";
|
|
3
|
+
sizeOffset?: number;
|
|
4
|
+
attributes?: Record<string, string>;
|
|
5
|
+
};
|
|
6
|
+
type Dispose = () => void;
|
|
7
|
+
export declare function attachBaseRipple(container: HTMLElement, { origin, sizeOffset, attributes, }?: AttachBaseRippleOptions): Dispose;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=attach-base-ripple.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attach-base-ripple.d.ts","sourceRoot":"","sources":["../../src/lib/attach-base-ripple.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC,CAAC;AAeF,KAAK,OAAO,GAAG,MAAM,IAAI,CAAC;AA4D1B,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,WAAW,EACtB,EACE,MAAkB,EAClB,UAAc,EACd,UAAU,GACX,GAAE,uBAA4B,GAC9B,OAAO,CAmMT"}
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
// region TYPES
|
|
2
|
+
// endregion TYPES
|
|
3
|
+
// region GLOBALS
|
|
4
|
+
const globalHandlers = new Set();
|
|
5
|
+
let globalsInstalled = false;
|
|
6
|
+
function installGlobalListeners() {
|
|
7
|
+
if (globalsInstalled)
|
|
8
|
+
return;
|
|
9
|
+
globalsInstalled = true;
|
|
10
|
+
addEventListener("blur", onGlobalFadeAll);
|
|
11
|
+
addEventListener("pagehide", onGlobalFadeAll);
|
|
12
|
+
addEventListener("beforeunload", onGlobalFadeAll);
|
|
13
|
+
addEventListener("pointerup", onGlobalFadeFromPointer, { passive: true });
|
|
14
|
+
addEventListener("pointercancel", onGlobalFadeFromPointer, { passive: true });
|
|
15
|
+
document.addEventListener("visibilitychange", onGlobalVisibilityChange);
|
|
16
|
+
}
|
|
17
|
+
function uninstallGlobalListenersIfIdle() {
|
|
18
|
+
if (!globalsInstalled || globalHandlers.size > 0)
|
|
19
|
+
return;
|
|
20
|
+
globalsInstalled = false;
|
|
21
|
+
removeEventListener("blur", onGlobalFadeAll);
|
|
22
|
+
removeEventListener("pagehide", onGlobalFadeAll);
|
|
23
|
+
removeEventListener("beforeunload", onGlobalFadeAll);
|
|
24
|
+
removeEventListener("pointerup", onGlobalFadeFromPointer);
|
|
25
|
+
removeEventListener("pointercancel", onGlobalFadeFromPointer);
|
|
26
|
+
document.removeEventListener("visibilitychange", onGlobalVisibilityChange);
|
|
27
|
+
}
|
|
28
|
+
function onGlobalFadeAll() {
|
|
29
|
+
for (const handler of globalHandlers) {
|
|
30
|
+
handler.fadeAll();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function onGlobalFadeFromPointer(event) {
|
|
34
|
+
for (const handler of globalHandlers) {
|
|
35
|
+
handler.fadeFromPointer(event);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function onGlobalVisibilityChange() {
|
|
39
|
+
if (document.visibilityState === "hidden") {
|
|
40
|
+
onGlobalFadeAll();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// endregion GLOBALS
|
|
44
|
+
// region MAIN
|
|
45
|
+
export function attachBaseRipple(container, { origin = "pointer", sizeOffset = 0, attributes, } = {}) {
|
|
46
|
+
const ripples = new Set();
|
|
47
|
+
const activePointerRipples = new Map();
|
|
48
|
+
const activeKeyRipples = new Map();
|
|
49
|
+
const isPointerOrigin = origin === "pointer";
|
|
50
|
+
let pointerDownInstalled = false;
|
|
51
|
+
let reducedMotion = prefersReducedMotion();
|
|
52
|
+
const createRippleKeyframes = (containerRect, fromX, fromY) => ({
|
|
53
|
+
from: {
|
|
54
|
+
size: 0,
|
|
55
|
+
x: fromX,
|
|
56
|
+
y: fromY,
|
|
57
|
+
},
|
|
58
|
+
to: {
|
|
59
|
+
size: (isPointerOrigin
|
|
60
|
+
? rectBoundingCircleDiameterFromPoint(containerRect.width, containerRect.height, fromX, fromY)
|
|
61
|
+
: rectBoundingCircleDiameter(containerRect.width, containerRect.height)) + sizeOffset,
|
|
62
|
+
x: isPointerOrigin ? fromX : containerRect.width / 2,
|
|
63
|
+
y: isPointerOrigin ? fromY : containerRect.height / 2,
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
const createPointerRipple = (event) => {
|
|
67
|
+
if (event.defaultPrevented)
|
|
68
|
+
return;
|
|
69
|
+
if (isDisabled(container))
|
|
70
|
+
return;
|
|
71
|
+
if (reducedMotion)
|
|
72
|
+
return;
|
|
73
|
+
const containerRect = container.getBoundingClientRect();
|
|
74
|
+
const rippleKeyframes = createRippleKeyframes(containerRect, event.clientX - containerRect.x, event.clientY - containerRect.y);
|
|
75
|
+
const ripple = createRipple({
|
|
76
|
+
rippleKeyframes,
|
|
77
|
+
removeHandler: removeRipple,
|
|
78
|
+
attributes,
|
|
79
|
+
});
|
|
80
|
+
ripples.add(ripple);
|
|
81
|
+
activePointerRipples.set(event.pointerId, ripple);
|
|
82
|
+
container.appendChild(ripple);
|
|
83
|
+
};
|
|
84
|
+
const createKeyRipple = (event) => {
|
|
85
|
+
if (event.defaultPrevented)
|
|
86
|
+
return;
|
|
87
|
+
if (isDisabled(container))
|
|
88
|
+
return;
|
|
89
|
+
if (reducedMotion)
|
|
90
|
+
return;
|
|
91
|
+
if (event.repeat)
|
|
92
|
+
return;
|
|
93
|
+
if (activeKeyRipples.has(event.code))
|
|
94
|
+
return;
|
|
95
|
+
if (!isActivationKey(event.code))
|
|
96
|
+
return;
|
|
97
|
+
if (isEditableTarget(event.target))
|
|
98
|
+
return;
|
|
99
|
+
const containerRect = container.getBoundingClientRect();
|
|
100
|
+
const rippleKeyframes = createRippleKeyframes(containerRect, containerRect.width / 2, containerRect.height / 2);
|
|
101
|
+
const ripple = createRipple({
|
|
102
|
+
rippleKeyframes,
|
|
103
|
+
removeHandler: removeRipple,
|
|
104
|
+
attributes,
|
|
105
|
+
});
|
|
106
|
+
ripples.add(ripple);
|
|
107
|
+
activeKeyRipples.set(event.code, ripple);
|
|
108
|
+
container.appendChild(ripple);
|
|
109
|
+
};
|
|
110
|
+
const fadeRipple = (ripple) => {
|
|
111
|
+
ripple.style.opacity = "0";
|
|
112
|
+
};
|
|
113
|
+
const fadeActivePointerRipple = (event) => {
|
|
114
|
+
const rippleToFade = activePointerRipples.get(event.pointerId);
|
|
115
|
+
if (!rippleToFade)
|
|
116
|
+
return;
|
|
117
|
+
fadeRipple(rippleToFade);
|
|
118
|
+
activePointerRipples.delete(event.pointerId);
|
|
119
|
+
};
|
|
120
|
+
const fadeActiveKeyRipple = (event) => {
|
|
121
|
+
const rippleToFade = activeKeyRipples.get(event.code);
|
|
122
|
+
if (!rippleToFade)
|
|
123
|
+
return;
|
|
124
|
+
fadeRipple(rippleToFade);
|
|
125
|
+
activeKeyRipples.delete(event.code);
|
|
126
|
+
};
|
|
127
|
+
const fadeAllActiveRipples = () => {
|
|
128
|
+
for (const ripple of activePointerRipples.values())
|
|
129
|
+
fadeRipple(ripple);
|
|
130
|
+
activePointerRipples.clear();
|
|
131
|
+
for (const ripple of activeKeyRipples.values())
|
|
132
|
+
fadeRipple(ripple);
|
|
133
|
+
activeKeyRipples.clear();
|
|
134
|
+
};
|
|
135
|
+
const removeRipple = (ripple) => {
|
|
136
|
+
ripples.delete(ripple);
|
|
137
|
+
for (const [pointerId, activeRipple] of activePointerRipples) {
|
|
138
|
+
if (activeRipple === ripple) {
|
|
139
|
+
activePointerRipples.delete(pointerId);
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
for (const [code, activeRipple] of activeKeyRipples) {
|
|
144
|
+
if (activeRipple === ripple) {
|
|
145
|
+
activeKeyRipples.delete(code);
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
ripple.remove();
|
|
150
|
+
};
|
|
151
|
+
const removeAllRipples = () => {
|
|
152
|
+
for (const ripple of ripples) {
|
|
153
|
+
ripple.remove();
|
|
154
|
+
}
|
|
155
|
+
ripples.clear();
|
|
156
|
+
activePointerRipples.clear();
|
|
157
|
+
activeKeyRipples.clear();
|
|
158
|
+
};
|
|
159
|
+
const addPointerDownListener = () => {
|
|
160
|
+
if (pointerDownInstalled)
|
|
161
|
+
return;
|
|
162
|
+
container.addEventListener("pointerdown", createPointerRipple, {
|
|
163
|
+
passive: true,
|
|
164
|
+
});
|
|
165
|
+
pointerDownInstalled = true;
|
|
166
|
+
};
|
|
167
|
+
const removePointerDownListener = () => {
|
|
168
|
+
if (!pointerDownInstalled)
|
|
169
|
+
return;
|
|
170
|
+
container.removeEventListener("pointerdown", createPointerRipple);
|
|
171
|
+
pointerDownInstalled = false;
|
|
172
|
+
};
|
|
173
|
+
const unsubscribeReducedMotion = observeReducedMotion((nextReducedMotion) => {
|
|
174
|
+
if (reducedMotion === nextReducedMotion)
|
|
175
|
+
return;
|
|
176
|
+
reducedMotion = nextReducedMotion;
|
|
177
|
+
if (reducedMotion) {
|
|
178
|
+
removePointerDownListener();
|
|
179
|
+
removeAllRipples();
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
addPointerDownListener();
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
const keyUpHandler = (event) => {
|
|
186
|
+
if (!isActivationKey(event.code))
|
|
187
|
+
return;
|
|
188
|
+
fadeActiveKeyRipple(event);
|
|
189
|
+
};
|
|
190
|
+
if (!reducedMotion)
|
|
191
|
+
addPointerDownListener();
|
|
192
|
+
container.addEventListener("keyup", keyUpHandler);
|
|
193
|
+
container.addEventListener("keydown", createKeyRipple);
|
|
194
|
+
container.addEventListener("contextmenu", fadeAllActiveRipples);
|
|
195
|
+
container.addEventListener("pointerleave", fadeActivePointerRipple, {
|
|
196
|
+
passive: true,
|
|
197
|
+
});
|
|
198
|
+
installGlobalListeners();
|
|
199
|
+
const globalHandler = {
|
|
200
|
+
fadeAll: fadeAllActiveRipples,
|
|
201
|
+
fadeFromPointer: fadeActivePointerRipple,
|
|
202
|
+
};
|
|
203
|
+
globalHandlers.add(globalHandler);
|
|
204
|
+
return () => {
|
|
205
|
+
unsubscribeReducedMotion();
|
|
206
|
+
removePointerDownListener();
|
|
207
|
+
container.removeEventListener("keyup", keyUpHandler);
|
|
208
|
+
container.removeEventListener("keydown", createKeyRipple);
|
|
209
|
+
container.removeEventListener("contextmenu", fadeAllActiveRipples);
|
|
210
|
+
container.removeEventListener("pointerleave", fadeActivePointerRipple);
|
|
211
|
+
globalHandlers.delete(globalHandler);
|
|
212
|
+
uninstallGlobalListenersIfIdle();
|
|
213
|
+
removeAllRipples();
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
// endregion MAIN
|
|
217
|
+
// region REDUCED MOTION
|
|
218
|
+
const REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
|
|
219
|
+
function prefersReducedMotion() {
|
|
220
|
+
if (typeof matchMedia !== "function")
|
|
221
|
+
return false;
|
|
222
|
+
return matchMedia(REDUCED_MOTION_QUERY).matches;
|
|
223
|
+
}
|
|
224
|
+
function observeReducedMotion(onChange) {
|
|
225
|
+
if (typeof matchMedia !== "function")
|
|
226
|
+
return () => { };
|
|
227
|
+
const mediaQueryList = matchMedia(REDUCED_MOTION_QUERY);
|
|
228
|
+
const handler = (event) => onChange(event.matches);
|
|
229
|
+
if (typeof mediaQueryList.addEventListener === "function") {
|
|
230
|
+
mediaQueryList.addEventListener("change", handler);
|
|
231
|
+
return () => mediaQueryList.removeEventListener("change", handler);
|
|
232
|
+
}
|
|
233
|
+
if (typeof mediaQueryList.addListener === "function") {
|
|
234
|
+
mediaQueryList.addListener(handler);
|
|
235
|
+
return () => mediaQueryList.removeListener(handler);
|
|
236
|
+
}
|
|
237
|
+
return () => { };
|
|
238
|
+
}
|
|
239
|
+
// endregion REDUCED MOTION
|
|
240
|
+
// region OTHER UTILITIES
|
|
241
|
+
function createRipple({ rippleKeyframes, removeHandler, attributes, }) {
|
|
242
|
+
const ripple = document.createElement("span");
|
|
243
|
+
ripple.setAttribute("aria-hidden", "true");
|
|
244
|
+
ripple.className = "base-ripple";
|
|
245
|
+
ripple.style.width = rippleKeyframes.to.size + "px";
|
|
246
|
+
ripple.style.height = rippleKeyframes.to.size + "px";
|
|
247
|
+
ripple.style.setProperty("--base-ripple-keyframes-from-x", rippleKeyframes.from.x + "px");
|
|
248
|
+
ripple.style.setProperty("--base-ripple-keyframes-from-y", rippleKeyframes.from.y + "px");
|
|
249
|
+
ripple.style.setProperty("--base-ripple-keyframes-to-x", rippleKeyframes.to.x + "px");
|
|
250
|
+
ripple.style.setProperty("--base-ripple-keyframes-to-y", rippleKeyframes.to.y + "px");
|
|
251
|
+
if (attributes)
|
|
252
|
+
for (const [key, value] of Object.entries(attributes))
|
|
253
|
+
ripple.setAttribute(key, value);
|
|
254
|
+
const transitionEndHandler = (event) => {
|
|
255
|
+
if (event.propertyName !== "opacity")
|
|
256
|
+
return;
|
|
257
|
+
removeHandler(ripple);
|
|
258
|
+
ripple.removeEventListener("transitionend", transitionEndHandler);
|
|
259
|
+
};
|
|
260
|
+
ripple.addEventListener("transitionend", transitionEndHandler);
|
|
261
|
+
return ripple;
|
|
262
|
+
}
|
|
263
|
+
function isDisabled(element) {
|
|
264
|
+
const ariaDisabled = element.getAttribute("aria-disabled");
|
|
265
|
+
if (ariaDisabled !== null)
|
|
266
|
+
return ariaDisabled.toLowerCase() === "true";
|
|
267
|
+
return ("disabled" in element && Boolean(element.disabled));
|
|
268
|
+
}
|
|
269
|
+
function isActivationKey(code) {
|
|
270
|
+
return code === "Space" || code === "Enter" || code === "NumpadEnter";
|
|
271
|
+
}
|
|
272
|
+
const editableSelector = "input:not([type])," +
|
|
273
|
+
'input[type="text"],' +
|
|
274
|
+
'input[type="search"],' +
|
|
275
|
+
'input[type="url"],' +
|
|
276
|
+
'input[type="tel"],' +
|
|
277
|
+
'input[type="email"],' +
|
|
278
|
+
'input[type="password"],' +
|
|
279
|
+
'input[type="number"],' +
|
|
280
|
+
'input[type="date"],' +
|
|
281
|
+
'input[type="time"],' +
|
|
282
|
+
'input[type="datetime-local"],' +
|
|
283
|
+
'input[type="month"],' +
|
|
284
|
+
'input[type="week"],' +
|
|
285
|
+
"textarea," +
|
|
286
|
+
"[contenteditable]";
|
|
287
|
+
function isEditableTarget(target) {
|
|
288
|
+
if (!(target instanceof Element))
|
|
289
|
+
return false;
|
|
290
|
+
return Boolean(target.closest(editableSelector));
|
|
291
|
+
}
|
|
292
|
+
function rectBoundingCircleDiameter(width, height) {
|
|
293
|
+
return Math.sqrt(width * width + height * height);
|
|
294
|
+
}
|
|
295
|
+
function rectBoundingCircleDiameterFromPoint(width, height, x, y) {
|
|
296
|
+
const dx = Math.max(x, width - x);
|
|
297
|
+
const dy = Math.max(y, height - y);
|
|
298
|
+
return 2 * Math.sqrt(dx * dx + dy * dy);
|
|
299
|
+
}
|
|
300
|
+
// endregion OTHER UTILITIES
|
package/package.json
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@base-ripple/core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"homepage": "https://base-ripple.vercel.app/",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/circulo-ai/base-ripple"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [
|
|
10
|
+
"ripple",
|
|
11
|
+
"ripple-effect",
|
|
12
|
+
"interaction",
|
|
13
|
+
"feedback",
|
|
14
|
+
"ui",
|
|
15
|
+
"css",
|
|
16
|
+
"dom",
|
|
17
|
+
"accessibility",
|
|
18
|
+
"typescript",
|
|
19
|
+
"vanilla-js"
|
|
20
|
+
],
|
|
4
21
|
"type": "module",
|
|
5
22
|
"main": "./dist/index.js",
|
|
6
23
|
"module": "./dist/index.js",
|
|
@@ -25,9 +42,6 @@
|
|
|
25
42
|
"dist",
|
|
26
43
|
"!**/*.tsbuildinfo"
|
|
27
44
|
],
|
|
28
|
-
"dependencies": {
|
|
29
|
-
"tslib": "^2.3.0"
|
|
30
|
-
},
|
|
31
45
|
"nx": {
|
|
32
46
|
"tags": [
|
|
33
47
|
"scope:core"
|