@oscarpalmer/oui 0.14.0 → 0.16.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/button.css +0 -3
- package/dist/css/popover.css +9 -0
- package/dist/css/splitter.css +78 -0
- package/dist/css/tooltip.css +0 -3
- package/dist/js/floatable.cjs +22 -9
- package/dist/js/floatable.js +22 -9
- 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/splitter.cjs +211 -0
- package/dist/js/splitter.js +211 -0
- package/dist/js/tooltip.cjs +2 -3
- package/dist/js/tooltip.js +2 -3
- package/package.json +25 -5
- package/src/css/button.scss +0 -3
- package/src/css/popover.scss +9 -0
- package/src/css/splitter.scss +87 -0
- package/src/css/tooltip.scss +0 -3
- package/src/js/floatable.ts +53 -25
- 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/splitter.ts +317 -0
- package/src/js/tooltip.ts +2 -4
- package/types/floatable.d.cts +2 -2
- package/types/floatable.d.ts +2 -2
- 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/types/splitter.d.cts +10 -0
- package/types/splitter.d.ts +11 -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,211 @@
|
|
|
1
|
+
import { clamp } from "@oscarpalmer/atoms/number";
|
|
2
|
+
import { on, getPosition } from "@oscarpalmer/toretto/event";
|
|
3
|
+
import { findAncestor } from "@oscarpalmer/toretto/find";
|
|
4
|
+
class OuiSplitterElement extends HTMLElement {
|
|
5
|
+
#splitter;
|
|
6
|
+
constructor() {
|
|
7
|
+
super();
|
|
8
|
+
const panels = [...this.children].filter(
|
|
9
|
+
(child) => child instanceof HTMLElement
|
|
10
|
+
);
|
|
11
|
+
if (panels.length !== 2) {
|
|
12
|
+
throw new Error("oui-splitter must have exactly two panels.");
|
|
13
|
+
}
|
|
14
|
+
this.#splitter = new Splitter(this, panels);
|
|
15
|
+
}
|
|
16
|
+
connectedCallback() {
|
|
17
|
+
if (this.#splitter.types.auto) {
|
|
18
|
+
observer.observe(this);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
disconnectedCallback() {
|
|
22
|
+
if (this.#splitter.types.auto) {
|
|
23
|
+
observer.unobserve(this);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
class Splitter {
|
|
28
|
+
constructor(element, panels) {
|
|
29
|
+
this.element = element;
|
|
30
|
+
this.panels = panels;
|
|
31
|
+
this.handle = createHandle();
|
|
32
|
+
this.rectangle = element.getBoundingClientRect();
|
|
33
|
+
this.separator = createSeparator();
|
|
34
|
+
this.separator.append(this.handle);
|
|
35
|
+
panels[0].insertAdjacentElement("afterend", this.separator);
|
|
36
|
+
mapped.set(element, this);
|
|
37
|
+
mapped.set(this.handle, this);
|
|
38
|
+
setSize(this, this.flex.value);
|
|
39
|
+
this.types = getTypes(this);
|
|
40
|
+
if (this.types.horizontal) {
|
|
41
|
+
this.element.setAttribute("oui-splitter-horizontal", "");
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
flex = {
|
|
45
|
+
previous: 0.5,
|
|
46
|
+
value: 0.5
|
|
47
|
+
};
|
|
48
|
+
handle;
|
|
49
|
+
rectangle;
|
|
50
|
+
separator;
|
|
51
|
+
types;
|
|
52
|
+
}
|
|
53
|
+
function createHandle() {
|
|
54
|
+
const handle = document.createElement("span");
|
|
55
|
+
handle.tabIndex = 0;
|
|
56
|
+
handle.setAttribute("aria-label", "Resize panels");
|
|
57
|
+
handle.setAttribute("oui-splitter-handle", "");
|
|
58
|
+
return handle;
|
|
59
|
+
}
|
|
60
|
+
function createSeparator() {
|
|
61
|
+
const separator = document.createElement("div");
|
|
62
|
+
separator.setAttribute("oui-splitter-separator", "");
|
|
63
|
+
return separator;
|
|
64
|
+
}
|
|
65
|
+
function getFlex(splitter2, value) {
|
|
66
|
+
const { height, left, top, width } = splitter2.rectangle;
|
|
67
|
+
const offset = value - (splitter2.types.horizontal ? top : left);
|
|
68
|
+
const fraction = offset / (splitter2.types.horizontal ? height : width);
|
|
69
|
+
return clamp(fraction, 0.1, 0.9);
|
|
70
|
+
}
|
|
71
|
+
function getTypes(splitter2, width, height) {
|
|
72
|
+
const type = splitter2.element.getAttribute("type")?.trim() ?? "";
|
|
73
|
+
if (type === "horizontal") {
|
|
74
|
+
return {
|
|
75
|
+
auto: false,
|
|
76
|
+
horizontal: true
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
if (type === "auto") {
|
|
80
|
+
return {
|
|
81
|
+
auto: true,
|
|
82
|
+
horizontal: (height ?? splitter2.rectangle.height) > (width ?? splitter2.rectangle.width)
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
auto: false,
|
|
87
|
+
horizontal: false
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function onEnd(reset) {
|
|
91
|
+
if (splitter != null) {
|
|
92
|
+
splitter.handle.removeAttribute("oui-splitter-active");
|
|
93
|
+
splitter.separator.removeAttribute("oui-splitter-active");
|
|
94
|
+
if (reset) {
|
|
95
|
+
setSize(splitter, splitter.flex.previous);
|
|
96
|
+
} else {
|
|
97
|
+
splitter.flex.previous = splitter.flex.value;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
splitter = void 0;
|
|
101
|
+
}
|
|
102
|
+
function onKeydown(event) {
|
|
103
|
+
switch (true) {
|
|
104
|
+
case allKeys.has(event.key):
|
|
105
|
+
onNavigate(event);
|
|
106
|
+
break;
|
|
107
|
+
case event.key === "Escape":
|
|
108
|
+
onEnd(true);
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function onMousedown(event) {
|
|
113
|
+
splitter = mapped.get(
|
|
114
|
+
findAncestor(
|
|
115
|
+
event.target,
|
|
116
|
+
"[oui-splitter-handle]"
|
|
117
|
+
)
|
|
118
|
+
);
|
|
119
|
+
if (splitter == null) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
splitter.handle.setAttribute("oui-splitter-active", "");
|
|
123
|
+
splitter.separator.setAttribute("oui-splitter-active", "");
|
|
124
|
+
splitter.rectangle = splitter.element.getBoundingClientRect();
|
|
125
|
+
}
|
|
126
|
+
function onMousemove(event) {
|
|
127
|
+
if (splitter == null) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const position = getPosition(event);
|
|
131
|
+
if (position != null) {
|
|
132
|
+
splitter.flex.value = getFlex(
|
|
133
|
+
splitter,
|
|
134
|
+
splitter.types.horizontal ? position.y : position.x
|
|
135
|
+
);
|
|
136
|
+
setSize(splitter, splitter.flex.value);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
function onMouseup() {
|
|
140
|
+
if (splitter != null) {
|
|
141
|
+
onEnd(false);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
function onNavigate(event) {
|
|
145
|
+
const splitter2 = mapped.get(
|
|
146
|
+
findAncestor(
|
|
147
|
+
event.target,
|
|
148
|
+
"[oui-splitter-handle]"
|
|
149
|
+
)
|
|
150
|
+
);
|
|
151
|
+
if (splitter2 == null) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (absoluteKeys.has(event.key)) {
|
|
155
|
+
setSize(splitter2, event.key === "End" ? 0.9 : 0.1, true);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (splitter2.types.horizontal && !horizontalKeys.has(event.key) || !splitter2.types.horizontal && !verticalKeys.has(event.key)) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const modifier = negativeKeys.has(event.key) ? -1 : 1;
|
|
162
|
+
setSize(splitter2, splitter2.flex.value + modifier * 0.05, true);
|
|
163
|
+
}
|
|
164
|
+
function onObservation(entries) {
|
|
165
|
+
if (frame != null) {
|
|
166
|
+
cancelAnimationFrame(frame);
|
|
167
|
+
}
|
|
168
|
+
frame = requestAnimationFrame(() => {
|
|
169
|
+
for (const entry of entries) {
|
|
170
|
+
const splitter2 = mapped.get(entry.target);
|
|
171
|
+
if (splitter2 == null) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
splitter2.types = getTypes(
|
|
175
|
+
splitter2,
|
|
176
|
+
entry.contentRect.width,
|
|
177
|
+
entry.contentRect.height
|
|
178
|
+
);
|
|
179
|
+
if (splitter2.types.horizontal) {
|
|
180
|
+
splitter2.element.setAttribute("oui-splitter-horizontal", "");
|
|
181
|
+
} else {
|
|
182
|
+
splitter2.element.removeAttribute("oui-splitter-horizontal");
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
frame = void 0;
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
function setSize(splitter2, size, previous) {
|
|
189
|
+
splitter2.flex.value = size;
|
|
190
|
+
if (previous) {
|
|
191
|
+
splitter2.flex.previous = size;
|
|
192
|
+
}
|
|
193
|
+
splitter2.element.style.setProperty("--oui-splitter-size", `${size}`);
|
|
194
|
+
}
|
|
195
|
+
const absoluteKeys = /* @__PURE__ */ new Set(["End", "Home"]);
|
|
196
|
+
const horizontalKeys = /* @__PURE__ */ new Set(["ArrowDown", "ArrowUp"]);
|
|
197
|
+
const mapped = /* @__PURE__ */ new WeakMap();
|
|
198
|
+
const observer = new ResizeObserver(onObservation);
|
|
199
|
+
const negativeKeys = /* @__PURE__ */ new Set(["ArrowLeft", "ArrowUp"]);
|
|
200
|
+
const verticalKeys = /* @__PURE__ */ new Set(["ArrowLeft", "ArrowRight"]);
|
|
201
|
+
const allKeys = /* @__PURE__ */ new Set([...absoluteKeys, ...horizontalKeys, ...verticalKeys]);
|
|
202
|
+
let frame;
|
|
203
|
+
let splitter;
|
|
204
|
+
customElements.define("oui-splitter", OuiSplitterElement);
|
|
205
|
+
on(document, "keydown", onKeydown);
|
|
206
|
+
on(document, "mousedown", onMousedown);
|
|
207
|
+
on(document, "mousemove", onMousemove);
|
|
208
|
+
on(document, "mouseup", onMouseup);
|
|
209
|
+
export {
|
|
210
|
+
OuiSplitterElement
|
|
211
|
+
};
|
package/dist/js/tooltip.cjs
CHANGED
|
@@ -112,7 +112,7 @@ function initialize(tooltip) {
|
|
|
112
112
|
element,
|
|
113
113
|
event$1,
|
|
114
114
|
() => {
|
|
115
|
-
floatable.activate(floatable$1, active, 250);
|
|
115
|
+
floatable.activate(floatable$1, active, void 0, 250);
|
|
116
116
|
},
|
|
117
117
|
{
|
|
118
118
|
signal: abortController.signal
|
|
@@ -124,7 +124,7 @@ function initialize(tooltip) {
|
|
|
124
124
|
element,
|
|
125
125
|
event$1,
|
|
126
126
|
() => {
|
|
127
|
-
floatable.deactivate(floatable$1, active, 250);
|
|
127
|
+
floatable.deactivate(floatable$1, active, void 0, 250);
|
|
128
128
|
},
|
|
129
129
|
{
|
|
130
130
|
signal: abortController.signal
|
|
@@ -138,7 +138,6 @@ function removeTooltip(element) {
|
|
|
138
138
|
tooltips.delete(element);
|
|
139
139
|
}
|
|
140
140
|
function reset(anchor, attributes) {
|
|
141
|
-
console.log("reset", anchor, attributes);
|
|
142
141
|
if (attributes.ariaDescribedby == null) {
|
|
143
142
|
anchor.removeAttribute("aria-describedby");
|
|
144
143
|
} else {
|
package/dist/js/tooltip.js
CHANGED
|
@@ -111,7 +111,7 @@ function initialize(tooltip) {
|
|
|
111
111
|
element,
|
|
112
112
|
event,
|
|
113
113
|
() => {
|
|
114
|
-
activate(floatable, active, 250);
|
|
114
|
+
activate(floatable, active, void 0, 250);
|
|
115
115
|
},
|
|
116
116
|
{
|
|
117
117
|
signal: abortController.signal
|
|
@@ -123,7 +123,7 @@ function initialize(tooltip) {
|
|
|
123
123
|
element,
|
|
124
124
|
event,
|
|
125
125
|
() => {
|
|
126
|
-
deactivate(floatable, active, 250);
|
|
126
|
+
deactivate(floatable, active, void 0, 250);
|
|
127
127
|
},
|
|
128
128
|
{
|
|
129
129
|
signal: abortController.signal
|
|
@@ -137,7 +137,6 @@ function removeTooltip(element) {
|
|
|
137
137
|
tooltips.delete(element);
|
|
138
138
|
}
|
|
139
139
|
function reset(anchor, attributes) {
|
|
140
|
-
console.log("reset", anchor, attributes);
|
|
141
140
|
if (attributes.ariaDescribedby == null) {
|
|
142
141
|
anchor.removeAttribute("aria-describedby");
|
|
143
142
|
} else {
|
package/package.json
CHANGED
|
@@ -41,12 +41,32 @@
|
|
|
41
41
|
},
|
|
42
42
|
"./focus-trap": {
|
|
43
43
|
"import": {
|
|
44
|
-
"types": "./types/focus-trap.d.ts",
|
|
45
|
-
"default": "./dist/js/focus-trap.js"
|
|
44
|
+
"types": "./types/focus-trap/standalone.d.ts",
|
|
45
|
+
"default": "./dist/js/focus-trap/standalone.js"
|
|
46
46
|
},
|
|
47
47
|
"require": {
|
|
48
|
-
"types": "./types/focus-trap.d.cts",
|
|
49
|
-
"default": "./dist/js/focus-trap.cjs"
|
|
48
|
+
"types": "./types/focus-trap/standalone.d.cts",
|
|
49
|
+
"default": "./dist/js/focus-trap/standalone.cjs"
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"./popover": {
|
|
53
|
+
"import": {
|
|
54
|
+
"types": "./types/popover.d.ts",
|
|
55
|
+
"default": "./dist/js/popover.js"
|
|
56
|
+
},
|
|
57
|
+
"require": {
|
|
58
|
+
"types": "./types/popover.d.cts",
|
|
59
|
+
"default": "./dist/js/popover.cjs"
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"./splitter": {
|
|
63
|
+
"import": {
|
|
64
|
+
"types": "./types/splitter.d.ts",
|
|
65
|
+
"default": "./dist/js/splitter.js"
|
|
66
|
+
},
|
|
67
|
+
"require": {
|
|
68
|
+
"types": "./types/splitter.d.cts",
|
|
69
|
+
"default": "./dist/js/splitter.cjs"
|
|
50
70
|
}
|
|
51
71
|
},
|
|
52
72
|
"./tooltip": {
|
|
@@ -94,5 +114,5 @@
|
|
|
94
114
|
},
|
|
95
115
|
"type": "module",
|
|
96
116
|
"types": "types/index.d.cts",
|
|
97
|
-
"version": "0.
|
|
117
|
+
"version": "0.16.0"
|
|
98
118
|
}
|
package/src/css/button.scss
CHANGED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
@use 'mixins.scss' as mixins;
|
|
2
|
+
|
|
3
|
+
oui-splitter {
|
|
4
|
+
:where(&) {
|
|
5
|
+
display: flex;
|
|
6
|
+
flex-flow: row nowrap;
|
|
7
|
+
flex: 1;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
:where(& > :first-child) {
|
|
11
|
+
flex: var(--oui-splitter-size, .5);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
:where(& > :last-child) {
|
|
15
|
+
flex: calc(1 - var(--oui-splitter-size, .5));
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
:where([oui-splitter-separator]) {
|
|
20
|
+
width: .25rem;
|
|
21
|
+
background-color: rgba(0, 0, 0, 0.1);
|
|
22
|
+
border-radius: .25rem;
|
|
23
|
+
position: relative;
|
|
24
|
+
transition: background .125s ease-in-out;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
:where([oui-splitter-separator]:has([oui-splitter-handle]:focus)),
|
|
28
|
+
:where([oui-splitter-separator]:has([oui-splitter-handle]:hover)),
|
|
29
|
+
:where([oui-splitter-separator][oui-splitter-active]) {
|
|
30
|
+
background-color: rgba(0, 0, 255, .1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
:where([oui-splitter-handle]) {
|
|
34
|
+
width: 2rem;
|
|
35
|
+
height: 4rem;
|
|
36
|
+
padding: .875rem;
|
|
37
|
+
position: absolute;
|
|
38
|
+
inset: 50% auto auto 50%;
|
|
39
|
+
transform: translate3d(-50%, -50%, 0);
|
|
40
|
+
cursor: ew-resize;
|
|
41
|
+
|
|
42
|
+
&:focus {
|
|
43
|
+
outline: none;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
&::after {
|
|
47
|
+
content: '';
|
|
48
|
+
width: 100%;
|
|
49
|
+
height: 100%;
|
|
50
|
+
display: block;
|
|
51
|
+
background-color: rgba(0, 0, 0, 0.25);
|
|
52
|
+
outline: .25rem solid transparent;
|
|
53
|
+
outline-offset: .25rem;
|
|
54
|
+
border-radius: .25rem;
|
|
55
|
+
transition: background .125s ease-in-out, outline .125s ease-in-out;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
:where([oui-splitter-handle]:focus),
|
|
60
|
+
:where([oui-splitter-handle]:hover),
|
|
61
|
+
:where([oui-splitter-handle][oui-splitter-active]) {
|
|
62
|
+
&::after {
|
|
63
|
+
background-color: rgba(0, 0, 255, .25);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
:where([oui-splitter-handle]:focus-visible)::after {
|
|
68
|
+
outline-color: rgba(0, 0, 255, .25);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
oui-splitter[type='horizontal' i],
|
|
72
|
+
oui-splitter[oui-splitter-horizontal] {
|
|
73
|
+
:where(&) {
|
|
74
|
+
flex-flow: column nowrap;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
:where(& [oui-splitter-separator]) {
|
|
78
|
+
width: 100%;
|
|
79
|
+
height: .25rem;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
:where(& [oui-splitter-handle]) {
|
|
83
|
+
width: 4rem;
|
|
84
|
+
height: 2rem;
|
|
85
|
+
cursor: ns-resize;
|
|
86
|
+
}
|
|
87
|
+
}
|
package/src/css/tooltip.scss
CHANGED
package/src/js/floatable.ts
CHANGED
|
@@ -1,27 +1,30 @@
|
|
|
1
1
|
export class Floatable {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
2
|
+
activate: number | undefined;
|
|
3
|
+
active = false;
|
|
4
|
+
deactivate: number | undefined;
|
|
5
|
+
frame: DOMHighResTimeStamp | undefined;
|
|
6
|
+
|
|
7
|
+
constructor(
|
|
8
|
+
public anchor: HTMLElement,
|
|
9
|
+
public content: HTMLElement,
|
|
10
|
+
) {
|
|
11
|
+
setStyles(content);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
destroy(): void {
|
|
15
|
+
this.activate = undefined;
|
|
16
|
+
this.deactivate = undefined;
|
|
17
|
+
this.frame = undefined;
|
|
18
|
+
|
|
19
|
+
this.anchor = undefined as never;
|
|
20
|
+
this.content = undefined as never;
|
|
21
|
+
}
|
|
19
22
|
}
|
|
20
|
-
}
|
|
21
23
|
|
|
22
24
|
export function activate(
|
|
23
25
|
floatable: Floatable,
|
|
24
26
|
active: Set<Floatable>,
|
|
27
|
+
order?: Floatable[],
|
|
25
28
|
time?: number,
|
|
26
29
|
): void {
|
|
27
30
|
stop(floatable);
|
|
@@ -31,10 +34,10 @@ export function activate(
|
|
|
31
34
|
}
|
|
32
35
|
|
|
33
36
|
if (time == null || time === 0) {
|
|
34
|
-
onActivate(floatable, active);
|
|
37
|
+
onActivate(floatable, active, order);
|
|
35
38
|
} else {
|
|
36
39
|
floatable.activate = +setTimeout(() => {
|
|
37
|
-
onActivate(floatable, active);
|
|
40
|
+
onActivate(floatable, active, order);
|
|
38
41
|
}, time);
|
|
39
42
|
}
|
|
40
43
|
}
|
|
@@ -42,6 +45,7 @@ export function activate(
|
|
|
42
45
|
export function deactivate(
|
|
43
46
|
floatable: Floatable,
|
|
44
47
|
active: Set<Floatable>,
|
|
48
|
+
order?: Floatable[],
|
|
45
49
|
time?: number,
|
|
46
50
|
): void {
|
|
47
51
|
stop(floatable);
|
|
@@ -51,10 +55,10 @@ export function deactivate(
|
|
|
51
55
|
}
|
|
52
56
|
|
|
53
57
|
if (time == null || time === 0) {
|
|
54
|
-
onDeactivate(floatable, active);
|
|
58
|
+
onDeactivate(floatable, active, order);
|
|
55
59
|
} else {
|
|
56
60
|
floatable.deactivate = +setTimeout(() => {
|
|
57
|
-
onDeactivate(floatable, active);
|
|
61
|
+
onDeactivate(floatable, active, order);
|
|
58
62
|
}, time);
|
|
59
63
|
}
|
|
60
64
|
}
|
|
@@ -106,11 +110,19 @@ function getY(anchor: DOMRect, content: DOMRect): number {
|
|
|
106
110
|
return anchor.top + (anchor.height - content.height) / 2;
|
|
107
111
|
}
|
|
108
112
|
|
|
109
|
-
function onActivate(
|
|
113
|
+
function onActivate(
|
|
114
|
+
floatable: Floatable,
|
|
115
|
+
active: Set<Floatable>,
|
|
116
|
+
order?: Floatable[],
|
|
117
|
+
): void {
|
|
110
118
|
floatable.active = true;
|
|
111
119
|
|
|
112
120
|
active.add(floatable);
|
|
113
121
|
|
|
122
|
+
if (order != null) {
|
|
123
|
+
order.push(floatable);
|
|
124
|
+
}
|
|
125
|
+
|
|
114
126
|
document.body.append(floatable.content);
|
|
115
127
|
|
|
116
128
|
floatable.content.hidden = false;
|
|
@@ -118,11 +130,21 @@ function onActivate(floatable: Floatable, active: Set<Floatable>): void {
|
|
|
118
130
|
update(floatable);
|
|
119
131
|
}
|
|
120
132
|
|
|
121
|
-
function onDeactivate(
|
|
133
|
+
function onDeactivate(
|
|
134
|
+
floatable: Floatable,
|
|
135
|
+
active: Set<Floatable>,
|
|
136
|
+
order?: Floatable[],
|
|
137
|
+
): void {
|
|
122
138
|
floatable.active = false;
|
|
123
139
|
|
|
124
140
|
active.delete(floatable);
|
|
125
141
|
|
|
142
|
+
const index = order?.indexOf(floatable) ?? -1;
|
|
143
|
+
|
|
144
|
+
if (index > -1) {
|
|
145
|
+
order?.splice(index, 1);
|
|
146
|
+
}
|
|
147
|
+
|
|
126
148
|
floatable.content.hidden = true;
|
|
127
149
|
|
|
128
150
|
floatable.anchor.insertAdjacentElement('afterend', floatable.content);
|
|
@@ -144,6 +166,12 @@ function update(floatable: Floatable): void {
|
|
|
144
166
|
floatable.frame = requestAnimationFrame(run);
|
|
145
167
|
}
|
|
146
168
|
|
|
169
|
+
function setStyles(content: HTMLElement): void {
|
|
170
|
+
content.style.position = 'fixed';
|
|
171
|
+
content.style.inset = '0 auto auto 0';
|
|
172
|
+
content.style.zIndex = '10';
|
|
173
|
+
}
|
|
174
|
+
|
|
147
175
|
function stop(floatable: Floatable): void {
|
|
148
176
|
if (floatable.frame != null) {
|
|
149
177
|
cancelAnimationFrame(floatable.frame);
|
|
@@ -165,4 +193,4 @@ function stop(floatable: Floatable): void {
|
|
|
165
193
|
//
|
|
166
194
|
|
|
167
195
|
const margin =
|
|
168
|
-
Number.parseInt(getComputedStyle(document.documentElement).fontSize, 10) /
|
|
196
|
+
Number.parseInt(getComputedStyle(document.documentElement).fontSize, 10) / 2;
|