@oscarpalmer/oui 0.12.0 → 0.13.0
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/css/badge.css +9 -3
- package/dist/css/tooltip.css +14 -0
- package/dist/js/attributable.cjs +51 -0
- package/dist/js/attributable.js +51 -0
- package/dist/js/focus-trap.cjs +19 -62
- package/dist/js/focus-trap.js +19 -62
- package/dist/js/tooltip.cjs +203 -0
- package/dist/js/tooltip.js +202 -0
- package/package.json +15 -5
- package/src/css/badge.scss +10 -3
- package/src/css/mixins.scss +13 -0
- package/src/css/tooltip.scss +14 -0
- package/src/js/attributable.ts +70 -0
- package/src/js/focus-trap.ts +16 -64
- package/src/js/tooltip.ts +289 -0
- package/types/attributable.d.cts +5 -0
- package/types/attributable.d.ts +1 -0
- package/types/tooltip.d.cts +3 -0
- package/types/tooltip.d.ts +1 -0
package/dist/css/badge.css
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/*! https://github.com/oscarpalmer/oui */
|
|
2
2
|
|
|
3
|
+
.oui {
|
|
4
|
+
/* Colors*/
|
|
5
|
+
}
|
|
3
6
|
:where(.oui-pill, .oui-tag) {
|
|
4
7
|
--oui-shadow-mixed: color-mix(
|
|
5
8
|
in oklab,
|
|
@@ -28,9 +31,12 @@
|
|
|
28
31
|
:where(.oui-pill-tiny, .oui-tag-tiny) {
|
|
29
32
|
color: color-mix(in oklab, var(--oui-foreground, var(--oui-gray-8)), transparent 12.5%);
|
|
30
33
|
font-size: 0.75em;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
}
|
|
35
|
+
:where(.oui-pill-tiny) {
|
|
36
|
+
padding: 0.25em 0.75em;
|
|
37
|
+
}
|
|
38
|
+
:where(.oui-tag-tiny) {
|
|
39
|
+
padding: 0.25em 0.5em;
|
|
34
40
|
}
|
|
35
41
|
:where(.oui-pill-blue, .oui-tag-blue) {
|
|
36
42
|
--oui-background: var(--oui-blue-0);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
|
|
2
|
+
:where([oui-tooltip-content]) {
|
|
3
|
+
box-shadow: inset 0 1px 0 0 transparent, 0 0 0 1px rgba(0, 0, 0, 0.05), 0 1px 2px -0.5px rgba(0, 0, 0, 0.05), 0 2px 4px -1px rgba(0, 0, 0, 0.05), 0 4px 8px -2px rgba(0, 0, 0, 0.05), 0 8px 16px -4px rgba(0, 0, 0, 0.05), 0 16px 32px -8px rgba(0, 0, 0, 0.05), 0 32px 64px -16px rgba(0, 0, 0, 0.05), 0 64px 128px -32px rgba(0, 0, 0, 0.05);
|
|
4
|
+
max-width: 48ch;
|
|
5
|
+
padding: 0.75em 1em;
|
|
6
|
+
background-color: var(--oui-absolute);
|
|
7
|
+
border-radius: 0.25rem;
|
|
8
|
+
font-size: 0.875rem;
|
|
9
|
+
position: fixed;
|
|
10
|
+
inset: 0 auto auto 0;
|
|
11
|
+
z-index: 10;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
function attributable(attribute, add, remove) {
|
|
4
|
+
const observer = new MutationObserver((entries) => {
|
|
5
|
+
const { length } = entries;
|
|
6
|
+
for (let index = 0; index < length; index += 1) {
|
|
7
|
+
const entry = entries[index];
|
|
8
|
+
if (entry.type === "attributes" && entry.target instanceof HTMLElement) {
|
|
9
|
+
if (entry.target.hasAttribute(attribute)) {
|
|
10
|
+
handleAdded(attribute, [entry.target], add);
|
|
11
|
+
} else {
|
|
12
|
+
handleRemoved([entry.target], remove);
|
|
13
|
+
}
|
|
14
|
+
} else if (entry.type === "childList") {
|
|
15
|
+
handleAdded(attribute, entry.addedNodes, add);
|
|
16
|
+
handleRemoved(entry.removedNodes, remove);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
observer.observe(document, {
|
|
21
|
+
attributeFilter: [attribute],
|
|
22
|
+
attributes: true,
|
|
23
|
+
childList: true,
|
|
24
|
+
subtree: true
|
|
25
|
+
});
|
|
26
|
+
requestAnimationFrame(() => {
|
|
27
|
+
handleAdded(attribute, document.querySelectorAll(`[${attribute}]`), add);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function handleAdded(attribute, nodes, add) {
|
|
31
|
+
const elements = [...nodes].filter(
|
|
32
|
+
(node) => node instanceof HTMLElement
|
|
33
|
+
);
|
|
34
|
+
const { length } = elements;
|
|
35
|
+
for (let index = 0; index < length; index += 1) {
|
|
36
|
+
const element = elements[index];
|
|
37
|
+
if (element.hasAttribute(attribute)) {
|
|
38
|
+
add(element);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function handleRemoved(nodes, remove) {
|
|
43
|
+
const elements = [...nodes].filter(
|
|
44
|
+
(node) => node instanceof HTMLElement
|
|
45
|
+
);
|
|
46
|
+
const { length } = elements;
|
|
47
|
+
for (let index = 0; index < length; index += 1) {
|
|
48
|
+
remove(elements[index]);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.attributable = attributable;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
function attributable(attribute, add, remove) {
|
|
2
|
+
const observer = new MutationObserver((entries) => {
|
|
3
|
+
const { length } = entries;
|
|
4
|
+
for (let index = 0; index < length; index += 1) {
|
|
5
|
+
const entry = entries[index];
|
|
6
|
+
if (entry.type === "attributes" && entry.target instanceof HTMLElement) {
|
|
7
|
+
if (entry.target.hasAttribute(attribute)) {
|
|
8
|
+
handleAdded(attribute, [entry.target], add);
|
|
9
|
+
} else {
|
|
10
|
+
handleRemoved([entry.target], remove);
|
|
11
|
+
}
|
|
12
|
+
} else if (entry.type === "childList") {
|
|
13
|
+
handleAdded(attribute, entry.addedNodes, add);
|
|
14
|
+
handleRemoved(entry.removedNodes, remove);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
observer.observe(document, {
|
|
19
|
+
attributeFilter: [attribute],
|
|
20
|
+
attributes: true,
|
|
21
|
+
childList: true,
|
|
22
|
+
subtree: true
|
|
23
|
+
});
|
|
24
|
+
requestAnimationFrame(() => {
|
|
25
|
+
handleAdded(attribute, document.querySelectorAll(`[${attribute}]`), add);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function handleAdded(attribute, nodes, add) {
|
|
29
|
+
const elements = [...nodes].filter(
|
|
30
|
+
(node) => node instanceof HTMLElement
|
|
31
|
+
);
|
|
32
|
+
const { length } = elements;
|
|
33
|
+
for (let index = 0; index < length; index += 1) {
|
|
34
|
+
const element = elements[index];
|
|
35
|
+
if (element.hasAttribute(attribute)) {
|
|
36
|
+
add(element);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function handleRemoved(nodes, remove) {
|
|
41
|
+
const elements = [...nodes].filter(
|
|
42
|
+
(node) => node instanceof HTMLElement
|
|
43
|
+
);
|
|
44
|
+
const { length } = elements;
|
|
45
|
+
for (let index = 0; index < length; index += 1) {
|
|
46
|
+
remove(elements[index]);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export {
|
|
50
|
+
attributable
|
|
51
|
+
};
|
package/dist/js/focus-trap.cjs
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
2
|
const number = require("@oscarpalmer/atoms/number");
|
|
6
3
|
const event = require("@oscarpalmer/toretto/event");
|
|
7
4
|
const find = require("@oscarpalmer/toretto/find");
|
|
8
5
|
const focusable = require("@oscarpalmer/toretto/focusable");
|
|
6
|
+
const attributable = require("./attributable.cjs");
|
|
9
7
|
class FocusTrap {
|
|
10
8
|
constructor(element) {
|
|
11
|
-
__publicField(this, "active", true);
|
|
12
9
|
this.element = element;
|
|
13
10
|
element.setAttribute("aria-modal", "true");
|
|
14
11
|
element.setAttribute("tabindex", "-1");
|
|
15
12
|
}
|
|
13
|
+
active = true;
|
|
16
14
|
activate() {
|
|
17
15
|
this.element.setAttribute("aria-modal", "true");
|
|
18
16
|
this.active = true;
|
|
@@ -27,20 +25,12 @@ class FocusTrap {
|
|
|
27
25
|
inactive.add(this);
|
|
28
26
|
}
|
|
29
27
|
}
|
|
30
|
-
function
|
|
31
|
-
|
|
32
|
-
(
|
|
33
|
-
);
|
|
34
|
-
const { length } = elements;
|
|
35
|
-
for (let index = 0; index < length; index += 1) {
|
|
36
|
-
const element = elements[index];
|
|
37
|
-
if (element.hasAttribute(selector)) {
|
|
38
|
-
focusTraps.set(element, new FocusTrap(element));
|
|
39
|
-
}
|
|
28
|
+
function addFocusTrap(element) {
|
|
29
|
+
if (!focusTraps.has(element)) {
|
|
30
|
+
focusTraps.set(element, new FocusTrap(element));
|
|
40
31
|
}
|
|
41
32
|
}
|
|
42
33
|
function onEscape(event2) {
|
|
43
|
-
var _a;
|
|
44
34
|
if (event2.key !== "Escape") {
|
|
45
35
|
return;
|
|
46
36
|
}
|
|
@@ -48,7 +38,7 @@ function onEscape(event2) {
|
|
|
48
38
|
document.activeElement,
|
|
49
39
|
`[${selector}]`
|
|
50
40
|
);
|
|
51
|
-
|
|
41
|
+
focusTraps.get(element)?.inactivate();
|
|
52
42
|
}
|
|
53
43
|
function onFocusOut() {
|
|
54
44
|
if (inactive.size === 0) {
|
|
@@ -67,7 +57,6 @@ function onFocusOut() {
|
|
|
67
57
|
});
|
|
68
58
|
}
|
|
69
59
|
function onTab(event2) {
|
|
70
|
-
var _a;
|
|
71
60
|
if (event2.key !== "Tab") {
|
|
72
61
|
return;
|
|
73
62
|
}
|
|
@@ -75,7 +64,7 @@ function onTab(event2) {
|
|
|
75
64
|
event2.target,
|
|
76
65
|
`[${selector}]`
|
|
77
66
|
);
|
|
78
|
-
if (!(
|
|
67
|
+
if (!(focusTraps.get(element)?.active ?? false)) {
|
|
79
68
|
return;
|
|
80
69
|
}
|
|
81
70
|
event2.preventDefault();
|
|
@@ -95,53 +84,21 @@ function onTab(event2) {
|
|
|
95
84
|
elements[next].focus();
|
|
96
85
|
}
|
|
97
86
|
}
|
|
98
|
-
function removeFocusTraps(
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
(node) => node instanceof HTMLElement
|
|
102
|
-
);
|
|
103
|
-
const { length } = elements;
|
|
104
|
-
for (let index = 0; index < length; index += 1) {
|
|
105
|
-
const element = elements[index];
|
|
106
|
-
(_a = focusTraps.get(element)) == null ? void 0 : _a.destroy();
|
|
107
|
-
focusTraps.delete(element);
|
|
108
|
-
}
|
|
87
|
+
function removeFocusTraps(element) {
|
|
88
|
+
focusTraps.get(element)?.destroy();
|
|
89
|
+
focusTraps.delete(element);
|
|
109
90
|
}
|
|
110
91
|
const focusTraps = /* @__PURE__ */ new WeakMap();
|
|
111
92
|
const inactive = /* @__PURE__ */ new Set();
|
|
112
|
-
const observer = new MutationObserver((entries) => {
|
|
113
|
-
const { length } = entries;
|
|
114
|
-
for (let index = 0; index < length; index += 1) {
|
|
115
|
-
const entry = entries[index];
|
|
116
|
-
if (entry.type === "attributes" && entry.target instanceof HTMLElement) {
|
|
117
|
-
if (entry.target.hasAttribute(selector)) {
|
|
118
|
-
addFocusTraps([entry.target]);
|
|
119
|
-
} else {
|
|
120
|
-
removeFocusTraps([entry.target]);
|
|
121
|
-
}
|
|
122
|
-
} else if (entry.type === "childList") {
|
|
123
|
-
addFocusTraps(entry.addedNodes);
|
|
124
|
-
removeFocusTraps(entry.removedNodes);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
93
|
const selector = "oui-focus-trap";
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
childList: true,
|
|
133
|
-
subtree: true
|
|
94
|
+
attributable.attributable(selector, addFocusTrap, removeFocusTraps);
|
|
95
|
+
event.on(document, "focusout", onFocusOut, {
|
|
96
|
+
capture: true
|
|
134
97
|
});
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
capture: true,
|
|
142
|
-
passive: false
|
|
143
|
-
});
|
|
144
|
-
event.on(document, "keydown", onEscape, {
|
|
145
|
-
passive: false
|
|
146
|
-
});
|
|
98
|
+
event.on(document, "keydown", onTab, {
|
|
99
|
+
capture: true,
|
|
100
|
+
passive: false
|
|
101
|
+
});
|
|
102
|
+
event.on(document, "keydown", onEscape, {
|
|
103
|
+
passive: false
|
|
147
104
|
});
|
package/dist/js/focus-trap.js
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
1
|
import { clamp } from "@oscarpalmer/atoms/number";
|
|
5
2
|
import { on } from "@oscarpalmer/toretto/event";
|
|
6
3
|
import { findAncestor } from "@oscarpalmer/toretto/find";
|
|
7
4
|
import { getFocusable } from "@oscarpalmer/toretto/focusable";
|
|
5
|
+
import { attributable } from "./attributable.js";
|
|
8
6
|
class FocusTrap {
|
|
9
7
|
constructor(element) {
|
|
10
|
-
__publicField(this, "active", true);
|
|
11
8
|
this.element = element;
|
|
12
9
|
element.setAttribute("aria-modal", "true");
|
|
13
10
|
element.setAttribute("tabindex", "-1");
|
|
14
11
|
}
|
|
12
|
+
active = true;
|
|
15
13
|
activate() {
|
|
16
14
|
this.element.setAttribute("aria-modal", "true");
|
|
17
15
|
this.active = true;
|
|
@@ -26,20 +24,12 @@ class FocusTrap {
|
|
|
26
24
|
inactive.add(this);
|
|
27
25
|
}
|
|
28
26
|
}
|
|
29
|
-
function
|
|
30
|
-
|
|
31
|
-
(
|
|
32
|
-
);
|
|
33
|
-
const { length } = elements;
|
|
34
|
-
for (let index = 0; index < length; index += 1) {
|
|
35
|
-
const element = elements[index];
|
|
36
|
-
if (element.hasAttribute(selector)) {
|
|
37
|
-
focusTraps.set(element, new FocusTrap(element));
|
|
38
|
-
}
|
|
27
|
+
function addFocusTrap(element) {
|
|
28
|
+
if (!focusTraps.has(element)) {
|
|
29
|
+
focusTraps.set(element, new FocusTrap(element));
|
|
39
30
|
}
|
|
40
31
|
}
|
|
41
32
|
function onEscape(event) {
|
|
42
|
-
var _a;
|
|
43
33
|
if (event.key !== "Escape") {
|
|
44
34
|
return;
|
|
45
35
|
}
|
|
@@ -47,7 +37,7 @@ function onEscape(event) {
|
|
|
47
37
|
document.activeElement,
|
|
48
38
|
`[${selector}]`
|
|
49
39
|
);
|
|
50
|
-
|
|
40
|
+
focusTraps.get(element)?.inactivate();
|
|
51
41
|
}
|
|
52
42
|
function onFocusOut() {
|
|
53
43
|
if (inactive.size === 0) {
|
|
@@ -66,7 +56,6 @@ function onFocusOut() {
|
|
|
66
56
|
});
|
|
67
57
|
}
|
|
68
58
|
function onTab(event) {
|
|
69
|
-
var _a;
|
|
70
59
|
if (event.key !== "Tab") {
|
|
71
60
|
return;
|
|
72
61
|
}
|
|
@@ -74,7 +63,7 @@ function onTab(event) {
|
|
|
74
63
|
event.target,
|
|
75
64
|
`[${selector}]`
|
|
76
65
|
);
|
|
77
|
-
if (!(
|
|
66
|
+
if (!(focusTraps.get(element)?.active ?? false)) {
|
|
78
67
|
return;
|
|
79
68
|
}
|
|
80
69
|
event.preventDefault();
|
|
@@ -94,53 +83,21 @@ function onTab(event) {
|
|
|
94
83
|
elements[next].focus();
|
|
95
84
|
}
|
|
96
85
|
}
|
|
97
|
-
function removeFocusTraps(
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
(node) => node instanceof HTMLElement
|
|
101
|
-
);
|
|
102
|
-
const { length } = elements;
|
|
103
|
-
for (let index = 0; index < length; index += 1) {
|
|
104
|
-
const element = elements[index];
|
|
105
|
-
(_a = focusTraps.get(element)) == null ? void 0 : _a.destroy();
|
|
106
|
-
focusTraps.delete(element);
|
|
107
|
-
}
|
|
86
|
+
function removeFocusTraps(element) {
|
|
87
|
+
focusTraps.get(element)?.destroy();
|
|
88
|
+
focusTraps.delete(element);
|
|
108
89
|
}
|
|
109
90
|
const focusTraps = /* @__PURE__ */ new WeakMap();
|
|
110
91
|
const inactive = /* @__PURE__ */ new Set();
|
|
111
|
-
const observer = new MutationObserver((entries) => {
|
|
112
|
-
const { length } = entries;
|
|
113
|
-
for (let index = 0; index < length; index += 1) {
|
|
114
|
-
const entry = entries[index];
|
|
115
|
-
if (entry.type === "attributes" && entry.target instanceof HTMLElement) {
|
|
116
|
-
if (entry.target.hasAttribute(selector)) {
|
|
117
|
-
addFocusTraps([entry.target]);
|
|
118
|
-
} else {
|
|
119
|
-
removeFocusTraps([entry.target]);
|
|
120
|
-
}
|
|
121
|
-
} else if (entry.type === "childList") {
|
|
122
|
-
addFocusTraps(entry.addedNodes);
|
|
123
|
-
removeFocusTraps(entry.removedNodes);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
92
|
const selector = "oui-focus-trap";
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
childList: true,
|
|
132
|
-
subtree: true
|
|
93
|
+
attributable(selector, addFocusTrap, removeFocusTraps);
|
|
94
|
+
on(document, "focusout", onFocusOut, {
|
|
95
|
+
capture: true
|
|
133
96
|
});
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
capture: true,
|
|
141
|
-
passive: false
|
|
142
|
-
});
|
|
143
|
-
on(document, "keydown", onEscape, {
|
|
144
|
-
passive: false
|
|
145
|
-
});
|
|
97
|
+
on(document, "keydown", onTab, {
|
|
98
|
+
capture: true,
|
|
99
|
+
passive: false
|
|
100
|
+
});
|
|
101
|
+
on(document, "keydown", onEscape, {
|
|
102
|
+
passive: false
|
|
146
103
|
});
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const is = require("@oscarpalmer/atoms/is");
|
|
3
|
+
const event = require("@oscarpalmer/toretto/event");
|
|
4
|
+
const attributable = require("./attributable.cjs");
|
|
5
|
+
class Tooltip {
|
|
6
|
+
constructor(parent) {
|
|
7
|
+
this.parent = parent;
|
|
8
|
+
this.element = getContent(parent);
|
|
9
|
+
if (this.element != null) {
|
|
10
|
+
parent.insertAdjacentElement("afterend", this.element);
|
|
11
|
+
initialize(this);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
abortController = new AbortController();
|
|
15
|
+
activate;
|
|
16
|
+
active = false;
|
|
17
|
+
deactivate;
|
|
18
|
+
element;
|
|
19
|
+
frame;
|
|
20
|
+
destroy() {
|
|
21
|
+
deactivate(this);
|
|
22
|
+
this.abortController.abort();
|
|
23
|
+
this.abortController = void 0;
|
|
24
|
+
this.activate = void 0;
|
|
25
|
+
this.deactivate = void 0;
|
|
26
|
+
this.element = void 0;
|
|
27
|
+
this.frame = void 0;
|
|
28
|
+
this.parent = void 0;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function activate(tooltip) {
|
|
32
|
+
stop(tooltip);
|
|
33
|
+
if (tooltip.active) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
tooltip.activate = +setTimeout(() => {
|
|
37
|
+
tooltip.active = true;
|
|
38
|
+
active.add(tooltip);
|
|
39
|
+
document.body.append(tooltip.element);
|
|
40
|
+
tooltip.element.hidden = false;
|
|
41
|
+
update(tooltip);
|
|
42
|
+
}, 250);
|
|
43
|
+
}
|
|
44
|
+
function addTooltip(element) {
|
|
45
|
+
if (!tooltips.has(element)) {
|
|
46
|
+
tooltips.set(element, new Tooltip(element));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function deactivate(tooltip, time) {
|
|
50
|
+
stop(tooltip);
|
|
51
|
+
if (!tooltip.active) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
tooltip.deactivate = +setTimeout(() => {
|
|
55
|
+
tooltip.active = false;
|
|
56
|
+
active.delete(tooltip);
|
|
57
|
+
tooltip.element.hidden = true;
|
|
58
|
+
tooltip.parent.insertAdjacentElement("afterend", tooltip.element);
|
|
59
|
+
}, time ?? 250);
|
|
60
|
+
}
|
|
61
|
+
function getContent(parent) {
|
|
62
|
+
const wrapper = getWrapper(parent);
|
|
63
|
+
const ids = (parent.getAttribute("aria-describedby") ?? "").split(/\s+/);
|
|
64
|
+
parent.setAttribute("aria-describedby", wrapper.id);
|
|
65
|
+
const elements = ids.map(
|
|
66
|
+
(id) => is.isNullableOrWhitespace(id) ? void 0 : document.querySelector(`#${id}`)
|
|
67
|
+
).filter((element) => element instanceof HTMLElement);
|
|
68
|
+
if (elements.length > 0) {
|
|
69
|
+
for (const element of elements) {
|
|
70
|
+
element.hidden = false;
|
|
71
|
+
wrapper.append(element);
|
|
72
|
+
}
|
|
73
|
+
return wrapper;
|
|
74
|
+
}
|
|
75
|
+
let content = parent.getAttribute("aria-description");
|
|
76
|
+
if (is.isNullableOrWhitespace(content)) {
|
|
77
|
+
content = parent.getAttribute("aria-label");
|
|
78
|
+
if (is.isNullableOrWhitespace(content)) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const paragraph = document.createElement("p");
|
|
83
|
+
paragraph.textContent = content;
|
|
84
|
+
wrapper.append(paragraph);
|
|
85
|
+
return wrapper;
|
|
86
|
+
}
|
|
87
|
+
function getTop(parent, content) {
|
|
88
|
+
let top = parent.top - content.height - margin;
|
|
89
|
+
if (top - margin >= 0) {
|
|
90
|
+
return top;
|
|
91
|
+
}
|
|
92
|
+
top = parent.bottom + margin;
|
|
93
|
+
if (top + content.height + margin <= window.innerHeight) {
|
|
94
|
+
return top;
|
|
95
|
+
}
|
|
96
|
+
return parent.top + (parent.height - content.height) / 2;
|
|
97
|
+
}
|
|
98
|
+
function getWrapper(parent) {
|
|
99
|
+
const wrapper = document.createElement("div");
|
|
100
|
+
wrapper.setAttribute(`${selector}-content`, "");
|
|
101
|
+
wrapper.className = parent.getAttribute(`${selector}-class`) ?? "";
|
|
102
|
+
wrapper.hidden = true;
|
|
103
|
+
wrapper.id = `${selector}-${++index}`;
|
|
104
|
+
wrapper.role = "tooltip";
|
|
105
|
+
wrapper.tabIndex = -1;
|
|
106
|
+
return wrapper;
|
|
107
|
+
}
|
|
108
|
+
function getX(parent, content) {
|
|
109
|
+
if (content.width + 2 * margin >= window.innerWidth) {
|
|
110
|
+
return {
|
|
111
|
+
left: margin,
|
|
112
|
+
right: margin
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
const left = parent.left + (parent.width - content.width) / 2;
|
|
116
|
+
const right = window.innerWidth - margin;
|
|
117
|
+
if (left < margin) {
|
|
118
|
+
return {
|
|
119
|
+
left: margin
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
if (left + content.width > right) {
|
|
123
|
+
return {
|
|
124
|
+
right: margin
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
left
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function initialize(tooltip) {
|
|
132
|
+
const elements = [tooltip.parent, tooltip.element];
|
|
133
|
+
for (const element of elements) {
|
|
134
|
+
for (const event$1 of activateEvents) {
|
|
135
|
+
event.on(
|
|
136
|
+
element,
|
|
137
|
+
event$1,
|
|
138
|
+
() => {
|
|
139
|
+
activate(tooltip);
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
signal: tooltip.abortController.signal
|
|
143
|
+
}
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
for (const event$1 of deactivateEvents) {
|
|
147
|
+
event.on(
|
|
148
|
+
element,
|
|
149
|
+
event$1,
|
|
150
|
+
() => {
|
|
151
|
+
deactivate(tooltip);
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
signal: tooltip.abortController.signal
|
|
155
|
+
}
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function removeTooltip(element) {
|
|
161
|
+
tooltips.get(element)?.destroy();
|
|
162
|
+
tooltips.delete(element);
|
|
163
|
+
}
|
|
164
|
+
function stop(tooltip) {
|
|
165
|
+
if (tooltip.frame != null) {
|
|
166
|
+
cancelAnimationFrame(tooltip.frame);
|
|
167
|
+
tooltip.frame = void 0;
|
|
168
|
+
}
|
|
169
|
+
if (tooltip.activate != null) {
|
|
170
|
+
clearTimeout(tooltip.activate);
|
|
171
|
+
tooltip.activate = void 0;
|
|
172
|
+
}
|
|
173
|
+
if (tooltip.deactivate != null) {
|
|
174
|
+
clearTimeout(tooltip.deactivate);
|
|
175
|
+
tooltip.deactivate = void 0;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
function update(tooltip) {
|
|
179
|
+
function run() {
|
|
180
|
+
const parentRect = tooltip.parent.getBoundingClientRect();
|
|
181
|
+
const contentRect = tooltip.element.getBoundingClientRect();
|
|
182
|
+
const top = getTop(parentRect, contentRect);
|
|
183
|
+
const { left, right } = getX(parentRect, contentRect);
|
|
184
|
+
tooltip.element.style.inset = `${top}px ${right == null ? "auto" : `${right}px`} auto ${left == null ? "auto" : `${left}px`}`;
|
|
185
|
+
tooltip.frame = requestAnimationFrame(run);
|
|
186
|
+
}
|
|
187
|
+
tooltip.frame = requestAnimationFrame(run);
|
|
188
|
+
}
|
|
189
|
+
const active = /* @__PURE__ */ new Set();
|
|
190
|
+
const activateEvents = ["focus", "mouseenter", "touchstart"];
|
|
191
|
+
const deactivateEvents = ["blur", "mouseleave"];
|
|
192
|
+
const margin = Number.parseInt(getComputedStyle(document.documentElement).fontSize, 10) / 4;
|
|
193
|
+
const selector = "oui-tooltip";
|
|
194
|
+
const tooltips = /* @__PURE__ */ new WeakMap();
|
|
195
|
+
let index = 0;
|
|
196
|
+
attributable.attributable(selector, addTooltip, removeTooltip);
|
|
197
|
+
event.on(document, "keydown", (event2) => {
|
|
198
|
+
if (event2.key === "Escape") {
|
|
199
|
+
for (const tooltip of active) {
|
|
200
|
+
deactivate(tooltip, 0);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
});
|