@oscarpalmer/oui 0.13.0 → 0.15.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/README.md +2 -0
- package/dist/css/popover.css +9 -0
- package/dist/css/tooltip.css +9 -3
- package/dist/css/value.css +1 -0
- package/dist/js/floatable.cjs +134 -0
- package/dist/js/floatable.js +134 -0
- package/dist/js/focus-trap/embedded.cjs +150 -0
- package/dist/js/focus-trap/embedded.js +150 -0
- package/dist/js/focus-trap/standalone.cjs +8 -0
- package/dist/js/focus-trap/standalone.js +7 -0
- package/dist/js/index.cjs +5 -1
- package/dist/js/index.js +6 -1
- package/dist/js/popover.cjs +160 -0
- package/dist/js/popover.js +160 -0
- package/dist/js/tooltip.cjs +83 -126
- package/dist/js/tooltip.js +83 -126
- package/package.json +7 -7
- package/src/css/popover.scss +9 -0
- package/src/css/tooltip.scss +7 -3
- package/src/js/floatable.ts +196 -0
- package/src/js/focus-trap/embedded.ts +215 -0
- package/src/js/focus-trap/standalone.ts +9 -0
- package/src/js/index.ts +3 -1
- package/src/js/popover.ts +221 -0
- package/src/js/tooltip.ts +97 -161
- package/types/floatable.d.cts +16 -0
- package/types/floatable.d.ts +12 -0
- package/types/focus-trap/embedded.d.cts +15 -0
- package/types/focus-trap/embedded.d.ts +11 -0
- package/types/index.d.cts +11 -0
- package/types/index.d.ts +3 -1
- package/types/popover.d.cts +14 -0
- package/types/popover.d.ts +15 -0
- package/dist/js/focus-trap.cjs +0 -104
- package/dist/js/focus-trap.js +0 -103
- package/src/js/focus-trap.ts +0 -133
- /package/types/{focus-trap.d.cts → focus-trap/standalone.d.cts} +0 -0
- /package/types/{focus-trap.d.ts → focus-trap/standalone.d.ts} +0 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const is = require("@oscarpalmer/atoms/is");
|
|
4
|
+
const event = require("@oscarpalmer/toretto/event");
|
|
5
|
+
const find = require("@oscarpalmer/toretto/find");
|
|
6
|
+
const focusable = require("@oscarpalmer/toretto/focusable");
|
|
7
|
+
const floatable = require("./floatable.cjs");
|
|
8
|
+
const focusTrap_embedded = require("./focus-trap/embedded.cjs");
|
|
9
|
+
const mapped = /* @__PURE__ */ new Map();
|
|
10
|
+
let index = 0;
|
|
11
|
+
class OuiPopoverElement extends HTMLElement {
|
|
12
|
+
#floatable;
|
|
13
|
+
#focusTrap;
|
|
14
|
+
constructor() {
|
|
15
|
+
super();
|
|
16
|
+
const content = this.querySelector(":scope > [oui-popover-content]");
|
|
17
|
+
const toggle2 = this.querySelector(":scope > [oui-popover-toggle]");
|
|
18
|
+
if (!(content instanceof HTMLElement)) {
|
|
19
|
+
throw new Error(
|
|
20
|
+
"A oui-popover must have a direct child element with the [oui-popover-content]-attribute"
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
if (!(toggle2 instanceof HTMLButtonElement)) {
|
|
24
|
+
throw new Error(
|
|
25
|
+
"A oui-popover must have a direct child element with the [oui-popover-toggle]-attribute and be a button"
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
content.hidden = true;
|
|
29
|
+
content.setAttribute("role", "dialog");
|
|
30
|
+
content.setAttribute("oui-focus-trap", "");
|
|
31
|
+
content.setAttribute("oui-focus-trap-noescape", "");
|
|
32
|
+
if (is.isNullableOrWhitespace(content.id)) {
|
|
33
|
+
content.setAttribute("id", `oui-popover-content-${++index}`);
|
|
34
|
+
}
|
|
35
|
+
toggle2.setAttribute("aria-controls", content.id);
|
|
36
|
+
toggle2.setAttribute("aria-haspopup", "dialog");
|
|
37
|
+
this.#floatable = new floatable.Floatable(toggle2, content);
|
|
38
|
+
this.#focusTrap = focusTrap_embedded.createFocusTrap(content);
|
|
39
|
+
mapped.set(toggle2, this.#floatable);
|
|
40
|
+
mapped.set(content, this.#floatable);
|
|
41
|
+
}
|
|
42
|
+
close() {
|
|
43
|
+
this.hidePopover();
|
|
44
|
+
}
|
|
45
|
+
hidePopover() {
|
|
46
|
+
if (this.#floatable.active) {
|
|
47
|
+
closeAbove(this.#floatable.content);
|
|
48
|
+
floatable.deactivate(this.#floatable, active, order);
|
|
49
|
+
this.#floatable.anchor.focus();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
open() {
|
|
53
|
+
this.showPopover();
|
|
54
|
+
}
|
|
55
|
+
showPopover() {
|
|
56
|
+
if (!this.#floatable.active) {
|
|
57
|
+
toggle(this.#floatable.anchor);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
toggle() {
|
|
61
|
+
this.togglePopover();
|
|
62
|
+
}
|
|
63
|
+
togglePopover(options) {
|
|
64
|
+
if (typeof options === "boolean") {
|
|
65
|
+
if (options === true) {
|
|
66
|
+
this.showPopover();
|
|
67
|
+
} else {
|
|
68
|
+
this.hidePopover();
|
|
69
|
+
}
|
|
70
|
+
return options;
|
|
71
|
+
}
|
|
72
|
+
if (this.#floatable.active) {
|
|
73
|
+
this.hidePopover();
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
this.showPopover();
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function closeAll() {
|
|
81
|
+
for (const floatable$1 of active) {
|
|
82
|
+
floatable.deactivate(floatable$1, active, order);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function closeAbove(element) {
|
|
86
|
+
const index2 = order.findIndex(
|
|
87
|
+
(floatable2) => floatable2.anchor === element || floatable2.content === element
|
|
88
|
+
);
|
|
89
|
+
if (index2 === -1 || index2 === order.length - 1) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
while (index2 < order.length - 1) {
|
|
93
|
+
const floatable$1 = order.pop();
|
|
94
|
+
if (floatable$1 != null) {
|
|
95
|
+
floatable.deactivate(floatable$1, active, order);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
order[index2].content.focus();
|
|
99
|
+
}
|
|
100
|
+
function focus(content) {
|
|
101
|
+
let target = focusable.getFocusable(content)[0];
|
|
102
|
+
if (!(target instanceof HTMLElement)) {
|
|
103
|
+
target = content;
|
|
104
|
+
}
|
|
105
|
+
requestAnimationFrame(() => {
|
|
106
|
+
target.focus();
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
function onClick(event2) {
|
|
110
|
+
const related = find.findAncestor(
|
|
111
|
+
event2.target,
|
|
112
|
+
"[oui-popover-toggle], [oui-popover-content]"
|
|
113
|
+
);
|
|
114
|
+
if (!(related instanceof HTMLElement)) {
|
|
115
|
+
closeAll();
|
|
116
|
+
} else if (related.hasAttribute("oui-popover-content")) {
|
|
117
|
+
closeAbove(related);
|
|
118
|
+
} else {
|
|
119
|
+
toggle(related);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function onKeydown(event2) {
|
|
123
|
+
if (event2.key !== "Escape" || order.length === 0) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const related = find.findAncestor(event2.target, "[oui-popover-content]");
|
|
127
|
+
if (!(related instanceof HTMLElement)) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
closeAbove(related);
|
|
131
|
+
const floatable$1 = mapped.get(related);
|
|
132
|
+
if (floatable$1 != null) {
|
|
133
|
+
floatable.deactivate(floatable$1, active, order);
|
|
134
|
+
floatable$1.anchor.focus();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function toggle(anchor) {
|
|
138
|
+
const content = find.findAncestor(anchor, "[oui-popover-content]");
|
|
139
|
+
if (content instanceof HTMLElement) {
|
|
140
|
+
closeAbove(content);
|
|
141
|
+
} else {
|
|
142
|
+
closeAll();
|
|
143
|
+
}
|
|
144
|
+
const floatable$1 = mapped.get(anchor);
|
|
145
|
+
if (floatable$1 == null) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (floatable$1.active) {
|
|
149
|
+
floatable.deactivate(floatable$1, active, order);
|
|
150
|
+
} else {
|
|
151
|
+
floatable.activate(floatable$1, active, order);
|
|
152
|
+
focus(floatable$1.content);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
customElements.define("oui-popover", OuiPopoverElement);
|
|
156
|
+
event.on(document, "click", onClick);
|
|
157
|
+
event.on(document, "keydown", onKeydown);
|
|
158
|
+
const active = /* @__PURE__ */ new Set();
|
|
159
|
+
const order = [];
|
|
160
|
+
exports.OuiPopoverElement = OuiPopoverElement;
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
|
|
2
|
+
import { on } from "@oscarpalmer/toretto/event";
|
|
3
|
+
import { findAncestor } from "@oscarpalmer/toretto/find";
|
|
4
|
+
import { getFocusable } from "@oscarpalmer/toretto/focusable";
|
|
5
|
+
import { Floatable, deactivate, activate } from "./floatable.js";
|
|
6
|
+
import { createFocusTrap } from "./focus-trap/embedded.js";
|
|
7
|
+
const mapped = /* @__PURE__ */ new Map();
|
|
8
|
+
let index = 0;
|
|
9
|
+
class OuiPopoverElement extends HTMLElement {
|
|
10
|
+
#floatable;
|
|
11
|
+
#focusTrap;
|
|
12
|
+
constructor() {
|
|
13
|
+
super();
|
|
14
|
+
const content = this.querySelector(":scope > [oui-popover-content]");
|
|
15
|
+
const toggle2 = this.querySelector(":scope > [oui-popover-toggle]");
|
|
16
|
+
if (!(content instanceof HTMLElement)) {
|
|
17
|
+
throw new Error(
|
|
18
|
+
"A oui-popover must have a direct child element with the [oui-popover-content]-attribute"
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
if (!(toggle2 instanceof HTMLButtonElement)) {
|
|
22
|
+
throw new Error(
|
|
23
|
+
"A oui-popover must have a direct child element with the [oui-popover-toggle]-attribute and be a button"
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
content.hidden = true;
|
|
27
|
+
content.setAttribute("role", "dialog");
|
|
28
|
+
content.setAttribute("oui-focus-trap", "");
|
|
29
|
+
content.setAttribute("oui-focus-trap-noescape", "");
|
|
30
|
+
if (isNullableOrWhitespace(content.id)) {
|
|
31
|
+
content.setAttribute("id", `oui-popover-content-${++index}`);
|
|
32
|
+
}
|
|
33
|
+
toggle2.setAttribute("aria-controls", content.id);
|
|
34
|
+
toggle2.setAttribute("aria-haspopup", "dialog");
|
|
35
|
+
this.#floatable = new Floatable(toggle2, content);
|
|
36
|
+
this.#focusTrap = createFocusTrap(content);
|
|
37
|
+
mapped.set(toggle2, this.#floatable);
|
|
38
|
+
mapped.set(content, this.#floatable);
|
|
39
|
+
}
|
|
40
|
+
close() {
|
|
41
|
+
this.hidePopover();
|
|
42
|
+
}
|
|
43
|
+
hidePopover() {
|
|
44
|
+
if (this.#floatable.active) {
|
|
45
|
+
closeAbove(this.#floatable.content);
|
|
46
|
+
deactivate(this.#floatable, active, order);
|
|
47
|
+
this.#floatable.anchor.focus();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
open() {
|
|
51
|
+
this.showPopover();
|
|
52
|
+
}
|
|
53
|
+
showPopover() {
|
|
54
|
+
if (!this.#floatable.active) {
|
|
55
|
+
toggle(this.#floatable.anchor);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
toggle() {
|
|
59
|
+
this.togglePopover();
|
|
60
|
+
}
|
|
61
|
+
togglePopover(options) {
|
|
62
|
+
if (typeof options === "boolean") {
|
|
63
|
+
if (options === true) {
|
|
64
|
+
this.showPopover();
|
|
65
|
+
} else {
|
|
66
|
+
this.hidePopover();
|
|
67
|
+
}
|
|
68
|
+
return options;
|
|
69
|
+
}
|
|
70
|
+
if (this.#floatable.active) {
|
|
71
|
+
this.hidePopover();
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
this.showPopover();
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function closeAll() {
|
|
79
|
+
for (const floatable of active) {
|
|
80
|
+
deactivate(floatable, active, order);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function closeAbove(element) {
|
|
84
|
+
const index2 = order.findIndex(
|
|
85
|
+
(floatable) => floatable.anchor === element || floatable.content === element
|
|
86
|
+
);
|
|
87
|
+
if (index2 === -1 || index2 === order.length - 1) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
while (index2 < order.length - 1) {
|
|
91
|
+
const floatable = order.pop();
|
|
92
|
+
if (floatable != null) {
|
|
93
|
+
deactivate(floatable, active, order);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
order[index2].content.focus();
|
|
97
|
+
}
|
|
98
|
+
function focus(content) {
|
|
99
|
+
let target = getFocusable(content)[0];
|
|
100
|
+
if (!(target instanceof HTMLElement)) {
|
|
101
|
+
target = content;
|
|
102
|
+
}
|
|
103
|
+
requestAnimationFrame(() => {
|
|
104
|
+
target.focus();
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
function onClick(event) {
|
|
108
|
+
const related = findAncestor(
|
|
109
|
+
event.target,
|
|
110
|
+
"[oui-popover-toggle], [oui-popover-content]"
|
|
111
|
+
);
|
|
112
|
+
if (!(related instanceof HTMLElement)) {
|
|
113
|
+
closeAll();
|
|
114
|
+
} else if (related.hasAttribute("oui-popover-content")) {
|
|
115
|
+
closeAbove(related);
|
|
116
|
+
} else {
|
|
117
|
+
toggle(related);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function onKeydown(event) {
|
|
121
|
+
if (event.key !== "Escape" || order.length === 0) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const related = findAncestor(event.target, "[oui-popover-content]");
|
|
125
|
+
if (!(related instanceof HTMLElement)) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
closeAbove(related);
|
|
129
|
+
const floatable = mapped.get(related);
|
|
130
|
+
if (floatable != null) {
|
|
131
|
+
deactivate(floatable, active, order);
|
|
132
|
+
floatable.anchor.focus();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function toggle(anchor) {
|
|
136
|
+
const content = findAncestor(anchor, "[oui-popover-content]");
|
|
137
|
+
if (content instanceof HTMLElement) {
|
|
138
|
+
closeAbove(content);
|
|
139
|
+
} else {
|
|
140
|
+
closeAll();
|
|
141
|
+
}
|
|
142
|
+
const floatable = mapped.get(anchor);
|
|
143
|
+
if (floatable == null) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (floatable.active) {
|
|
147
|
+
deactivate(floatable, active, order);
|
|
148
|
+
} else {
|
|
149
|
+
activate(floatable, active, order);
|
|
150
|
+
focus(floatable.content);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
customElements.define("oui-popover", OuiPopoverElement);
|
|
154
|
+
on(document, "click", onClick);
|
|
155
|
+
on(document, "keydown", onKeydown);
|
|
156
|
+
const active = /* @__PURE__ */ new Set();
|
|
157
|
+
const order = [];
|
|
158
|
+
export {
|
|
159
|
+
OuiPopoverElement
|
|
160
|
+
};
|
package/dist/js/tooltip.cjs
CHANGED
|
@@ -2,144 +2,120 @@
|
|
|
2
2
|
const is = require("@oscarpalmer/atoms/is");
|
|
3
3
|
const event = require("@oscarpalmer/toretto/event");
|
|
4
4
|
const attributable = require("./attributable.cjs");
|
|
5
|
+
const floatable = require("./floatable.cjs");
|
|
5
6
|
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
7
|
abortController = new AbortController();
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
8
|
+
attributes;
|
|
9
|
+
floatable;
|
|
10
|
+
constructor(anchor, content) {
|
|
11
|
+
this.attributes = content.attributes;
|
|
12
|
+
this.floatable = new floatable.Floatable(anchor, content.element);
|
|
13
|
+
initialize(this);
|
|
14
|
+
}
|
|
20
15
|
destroy() {
|
|
21
|
-
deactivate(this);
|
|
16
|
+
floatable.deactivate(this.floatable, active);
|
|
17
|
+
reset(this.floatable.anchor, this.attributes);
|
|
22
18
|
this.abortController.abort();
|
|
19
|
+
this.floatable.content.remove();
|
|
20
|
+
this.floatable.destroy();
|
|
23
21
|
this.abortController = void 0;
|
|
24
|
-
this.
|
|
25
|
-
this.
|
|
26
|
-
this.element = void 0;
|
|
27
|
-
this.frame = void 0;
|
|
28
|
-
this.parent = void 0;
|
|
22
|
+
this.attributes = void 0;
|
|
23
|
+
this.floatable = void 0;
|
|
29
24
|
}
|
|
30
25
|
}
|
|
31
|
-
function
|
|
32
|
-
|
|
33
|
-
if (tooltip.active) {
|
|
26
|
+
function addTooltip(anchor) {
|
|
27
|
+
if (tooltips.has(anchor)) {
|
|
34
28
|
return;
|
|
35
29
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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));
|
|
30
|
+
const content = getContent(anchor);
|
|
31
|
+
if (content != null) {
|
|
32
|
+
tooltips.set(anchor, new Tooltip(anchor, content));
|
|
47
33
|
}
|
|
48
34
|
}
|
|
49
|
-
function
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
35
|
+
function getContent(anchor) {
|
|
36
|
+
const attributes = {
|
|
37
|
+
ariaDescribedby: anchor.getAttribute("aria-describedby"),
|
|
38
|
+
ariaLabelledBy: anchor.getAttribute("aria-labelledby")
|
|
39
|
+
};
|
|
40
|
+
const wrapper = getWrapper(anchor);
|
|
41
|
+
const labelledElements = getElements(attributes.ariaLabelledBy);
|
|
42
|
+
if (labelledElements.length > 0) {
|
|
43
|
+
anchor.setAttribute("aria-labelledby", wrapper.id);
|
|
44
|
+
for (const element of labelledElements) {
|
|
45
|
+
wrapper.append(element);
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
attributes,
|
|
49
|
+
element: wrapper
|
|
50
|
+
};
|
|
53
51
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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;
|
|
52
|
+
const describedElements = getElements(attributes.ariaDescribedby);
|
|
53
|
+
if (describedElements.length > 0) {
|
|
54
|
+
anchor.setAttribute("aria-describedby", wrapper.id);
|
|
55
|
+
for (const element of describedElements) {
|
|
71
56
|
wrapper.append(element);
|
|
72
57
|
}
|
|
73
|
-
return
|
|
58
|
+
return {
|
|
59
|
+
attributes,
|
|
60
|
+
element: wrapper
|
|
61
|
+
};
|
|
74
62
|
}
|
|
75
|
-
let content =
|
|
63
|
+
let content = anchor.getAttribute("aria-label");
|
|
76
64
|
if (is.isNullableOrWhitespace(content)) {
|
|
77
|
-
content =
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
65
|
+
content = anchor.getAttribute("aria-description");
|
|
66
|
+
}
|
|
67
|
+
if (is.isNullableOrWhitespace(content)) {
|
|
68
|
+
return;
|
|
81
69
|
}
|
|
82
70
|
const paragraph = document.createElement("p");
|
|
83
71
|
paragraph.textContent = content;
|
|
84
72
|
wrapper.append(paragraph);
|
|
85
|
-
return
|
|
73
|
+
return {
|
|
74
|
+
attributes,
|
|
75
|
+
element: wrapper
|
|
76
|
+
};
|
|
86
77
|
}
|
|
87
|
-
function
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
78
|
+
function getElements(attribute) {
|
|
79
|
+
const ids = attribute?.split(/\s+/) ?? [];
|
|
80
|
+
const elements = [];
|
|
81
|
+
for (const id of ids) {
|
|
82
|
+
if (is.isNullableOrWhitespace(id)) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const element = document.querySelector(`#${id}`);
|
|
86
|
+
if (element instanceof HTMLElement) {
|
|
87
|
+
const cloned = element.cloneNode(true);
|
|
88
|
+
cloned.hidden = false;
|
|
89
|
+
elements.push(cloned);
|
|
90
|
+
}
|
|
95
91
|
}
|
|
96
|
-
return
|
|
92
|
+
return elements;
|
|
97
93
|
}
|
|
98
|
-
function getWrapper(
|
|
94
|
+
function getWrapper(anchor) {
|
|
99
95
|
const wrapper = document.createElement("div");
|
|
100
96
|
wrapper.setAttribute(`${selector}-content`, "");
|
|
101
|
-
wrapper.className =
|
|
97
|
+
wrapper.className = anchor.getAttribute(`${selector}-class`) ?? "";
|
|
102
98
|
wrapper.hidden = true;
|
|
103
99
|
wrapper.id = `${selector}-${++index}`;
|
|
104
100
|
wrapper.role = "tooltip";
|
|
105
101
|
wrapper.tabIndex = -1;
|
|
106
102
|
return wrapper;
|
|
107
103
|
}
|
|
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
104
|
function initialize(tooltip) {
|
|
132
|
-
const
|
|
105
|
+
const { abortController, floatable: floatable$1 } = tooltip;
|
|
106
|
+
const { anchor, content } = floatable$1;
|
|
107
|
+
anchor.insertAdjacentElement("afterend", content);
|
|
108
|
+
const elements = [anchor, content];
|
|
133
109
|
for (const element of elements) {
|
|
134
110
|
for (const event$1 of activateEvents) {
|
|
135
111
|
event.on(
|
|
136
112
|
element,
|
|
137
113
|
event$1,
|
|
138
114
|
() => {
|
|
139
|
-
activate(
|
|
115
|
+
floatable.activate(floatable$1, active, void 0, 250);
|
|
140
116
|
},
|
|
141
117
|
{
|
|
142
|
-
signal:
|
|
118
|
+
signal: abortController.signal
|
|
143
119
|
}
|
|
144
120
|
);
|
|
145
121
|
}
|
|
@@ -148,10 +124,10 @@ function initialize(tooltip) {
|
|
|
148
124
|
element,
|
|
149
125
|
event$1,
|
|
150
126
|
() => {
|
|
151
|
-
deactivate(
|
|
127
|
+
floatable.deactivate(floatable$1, active, void 0, 250);
|
|
152
128
|
},
|
|
153
129
|
{
|
|
154
|
-
signal:
|
|
130
|
+
signal: abortController.signal
|
|
155
131
|
}
|
|
156
132
|
);
|
|
157
133
|
}
|
|
@@ -161,43 +137,24 @@ function removeTooltip(element) {
|
|
|
161
137
|
tooltips.get(element)?.destroy();
|
|
162
138
|
tooltips.delete(element);
|
|
163
139
|
}
|
|
164
|
-
function
|
|
165
|
-
if (
|
|
166
|
-
|
|
167
|
-
|
|
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);
|
|
140
|
+
function reset(anchor, attributes) {
|
|
141
|
+
if (attributes.ariaDescribedby == null) {
|
|
142
|
+
anchor.removeAttribute("aria-describedby");
|
|
143
|
+
} else {
|
|
144
|
+
anchor.setAttribute("aria-describedby", attributes.ariaDescribedby);
|
|
186
145
|
}
|
|
187
|
-
tooltip.frame = requestAnimationFrame(run);
|
|
188
146
|
}
|
|
189
147
|
const active = /* @__PURE__ */ new Set();
|
|
190
148
|
const activateEvents = ["focus", "mouseenter", "touchstart"];
|
|
191
149
|
const deactivateEvents = ["blur", "mouseleave"];
|
|
192
|
-
const margin = Number.parseInt(getComputedStyle(document.documentElement).fontSize, 10) / 4;
|
|
193
150
|
const selector = "oui-tooltip";
|
|
194
151
|
const tooltips = /* @__PURE__ */ new WeakMap();
|
|
195
152
|
let index = 0;
|
|
196
153
|
attributable.attributable(selector, addTooltip, removeTooltip);
|
|
197
154
|
event.on(document, "keydown", (event2) => {
|
|
198
155
|
if (event2.key === "Escape") {
|
|
199
|
-
for (const
|
|
200
|
-
deactivate(
|
|
156
|
+
for (const floatable$1 of active) {
|
|
157
|
+
floatable.deactivate(floatable$1, active);
|
|
201
158
|
}
|
|
202
159
|
}
|
|
203
160
|
});
|