@oscarpalmer/oui 0.19.0 → 0.20.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/a11y.css +0 -1
- package/dist/css/form.css +0 -1
- package/dist/css/popover.css +22 -0
- package/dist/css/reset.css +8 -8
- package/dist/css/table.css +1 -1
- package/dist/css/tooltip.css +43 -0
- package/dist/js/attributable.d.mts +4 -0
- package/dist/js/{attributable.full.js → attributable.mjs} +8 -1
- package/dist/js/floatable.d.mts +26 -0
- package/dist/js/{floatable.js → floatable.mjs} +73 -50
- package/dist/js/focus-trap/embedded.d.mts +26 -0
- package/dist/js/focus-trap/{embedded.js → embedded.mjs} +10 -8
- package/dist/js/focus-trap/standalone.d.mts +1 -0
- package/dist/js/focus-trap/{standalone.js → standalone.mjs} +5 -2
- package/dist/js/index.d.mts +4 -0
- package/dist/js/index.mjs +5 -0
- package/dist/js/popover.d.mts +20 -0
- package/dist/js/{popover.js → popover.mjs} +10 -8
- package/dist/js/splitter.d.mts +25 -0
- package/dist/js/{splitter.js → splitter.mjs} +58 -56
- package/dist/js/tooltip.d.mts +4 -0
- package/dist/js/{tooltip.js → tooltip.mjs} +20 -18
- package/package.json +64 -69
- package/src/css/mixins.scss +30 -1
- package/src/css/popover.scss +6 -1
- package/src/css/reset.scss +4 -4
- package/src/css/table.scss +1 -1
- package/src/css/tooltip.scss +55 -1
- package/src/js/attributable.ts +11 -1
- package/src/js/floatable.ts +136 -58
- package/src/js/focus-trap/embedded.ts +4 -10
- package/src/js/splitter.ts +2 -5
- package/src/js/tooltip.ts +5 -5
- package/dist/js/attributable.js +0 -36
- package/dist/js/floatable.full.js +0 -398
- package/dist/js/focus-trap/embedded.full.js +0 -408
- package/dist/js/focus-trap/standalone.full.js +0 -447
- package/dist/js/index.js +0 -5
- package/dist/js/oui.full.js +0 -1573
- package/dist/js/popover.full.js +0 -760
- package/dist/js/splitter.full.js +0 -769
- package/dist/js/tooltip.full.js +0 -613
- package/types/attributable.d.ts +0 -1
- package/types/floatable.d.ts +0 -24
- package/types/focus-trap/embedded.d.ts +0 -24
- package/types/focus-trap/standalone.d.ts +0 -1
- package/types/index.d.ts +0 -4
- package/types/popover.d.ts +0 -17
- package/types/splitter.d.ts +0 -23
- package/types/tooltip.d.ts +0 -2
package/dist/css/a11y.css
CHANGED
package/dist/css/form.css
CHANGED
package/dist/css/popover.css
CHANGED
|
@@ -1,12 +1,34 @@
|
|
|
1
1
|
|
|
2
2
|
:where([oui-popover-content]) {
|
|
3
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
|
+
--margin-left: 0;
|
|
5
|
+
--margin-top: 0;
|
|
6
|
+
margin: var(--margin-top, 0) 0 0 var(--margin-left, 0);
|
|
7
|
+
pointer-events: all !important;
|
|
8
|
+
}
|
|
9
|
+
:where([oui-popover-content])[position^=above], :where([oui-popover-content])[position^=top] {
|
|
10
|
+
--margin-top: -0.5rem;
|
|
11
|
+
}
|
|
12
|
+
:where([oui-popover-content])[position^=below], :where([oui-popover-content])[position^=bottom] {
|
|
13
|
+
--margin-top: 0.5rem;
|
|
14
|
+
}
|
|
15
|
+
:where([oui-popover-content])[position^=end], :where([oui-popover-content])[position^=right] {
|
|
16
|
+
--margin-left: 0.5rem;
|
|
17
|
+
}
|
|
18
|
+
:where([oui-popover-content])[position^=left], :where([oui-popover-content])[position^=start] {
|
|
19
|
+
--margin-left: -0.5rem;
|
|
20
|
+
}
|
|
21
|
+
:where([oui-popover-content]) {
|
|
4
22
|
padding: 1rem;
|
|
23
|
+
overscroll-behavior: contain;
|
|
5
24
|
background-color: var(--oui-absolute);
|
|
6
25
|
border-radius: 0.5rem;
|
|
7
26
|
}
|
|
8
27
|
:where([oui-popover-content]):focus {
|
|
9
28
|
outline: none;
|
|
10
29
|
}
|
|
30
|
+
:where([oui-popover-content]) * {
|
|
31
|
+
overscroll-behavior: contain;
|
|
32
|
+
}
|
|
11
33
|
|
|
12
34
|
|
package/dist/css/reset.css
CHANGED
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
-moz-tab-size: 4;
|
|
57
57
|
-o-tab-size: 4;
|
|
58
58
|
tab-size: 4;
|
|
59
|
-
|
|
59
|
+
overflow-wrap: break-word;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
:where(body) {
|
|
@@ -105,9 +105,9 @@ input[type=reset i],
|
|
|
105
105
|
input[type=submit i],
|
|
106
106
|
summary) {
|
|
107
107
|
/** Correct the inability to style clickable types in iOS [HR][RS][SE] */
|
|
108
|
-
-webkit-appearance:
|
|
109
|
-
-moz-appearance:
|
|
110
|
-
appearance:
|
|
108
|
+
-webkit-appearance: auto;
|
|
109
|
+
-moz-appearance: auto;
|
|
110
|
+
appearance: auto;
|
|
111
111
|
/** Ditto */
|
|
112
112
|
cursor: pointer;
|
|
113
113
|
}
|
|
@@ -174,7 +174,7 @@ summary) {
|
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
:where(small, sub, sup) {
|
|
177
|
-
font-size: 0.
|
|
177
|
+
font-size: 0.875em;
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
:where(sub, sup) {
|
|
@@ -277,9 +277,9 @@ summary) {
|
|
|
277
277
|
|
|
278
278
|
::file-selector-button {
|
|
279
279
|
/** Correct the inability to style upload buttons in iOS and Safari [RS][SE] */
|
|
280
|
-
-webkit-appearance:
|
|
281
|
-
-moz-appearance:
|
|
282
|
-
appearance:
|
|
280
|
+
-webkit-appearance: auto;
|
|
281
|
+
-moz-appearance: auto;
|
|
282
|
+
appearance: auto;
|
|
283
283
|
color: inherit;
|
|
284
284
|
font: inherit;
|
|
285
285
|
line-height: 1.25;
|
package/dist/css/table.css
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
:where(.oui-table_wrapper) {
|
|
7
7
|
max-height: 32em;
|
|
8
8
|
overflow: auto;
|
|
9
|
+
overscroll-behavior: contain;
|
|
9
10
|
border: 1px solid var(--oui-gray-3);
|
|
10
11
|
border-radius: 0.25em;
|
|
11
12
|
position: relative;
|
|
12
|
-
overscroll-behavior-y: none;
|
|
13
13
|
}
|
|
14
14
|
:where(.oui-table caption) {
|
|
15
15
|
height: 2rem;
|
package/dist/css/tooltip.css
CHANGED
|
@@ -27,6 +27,24 @@ var)) {
|
|
|
27
27
|
|
|
28
28
|
:where([oui-tooltip-content]) {
|
|
29
29
|
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);
|
|
30
|
+
--margin-left: 0;
|
|
31
|
+
--margin-top: 0;
|
|
32
|
+
margin: var(--margin-top, 0) 0 0 var(--margin-left, 0);
|
|
33
|
+
pointer-events: all !important;
|
|
34
|
+
}
|
|
35
|
+
:where([oui-tooltip-content])[position^=above], :where([oui-tooltip-content])[position^=top] {
|
|
36
|
+
--margin-top: -0.5rem;
|
|
37
|
+
}
|
|
38
|
+
:where([oui-tooltip-content])[position^=below], :where([oui-tooltip-content])[position^=bottom] {
|
|
39
|
+
--margin-top: 0.5rem;
|
|
40
|
+
}
|
|
41
|
+
:where([oui-tooltip-content])[position^=end], :where([oui-tooltip-content])[position^=right] {
|
|
42
|
+
--margin-left: 0.5rem;
|
|
43
|
+
}
|
|
44
|
+
:where([oui-tooltip-content])[position^=left], :where([oui-tooltip-content])[position^=start] {
|
|
45
|
+
--margin-left: -0.5rem;
|
|
46
|
+
}
|
|
47
|
+
:where([oui-tooltip-content]) {
|
|
30
48
|
max-width: 48ch;
|
|
31
49
|
padding: 0.75em 1em;
|
|
32
50
|
opacity: 0;
|
|
@@ -36,6 +54,31 @@ var)) {
|
|
|
36
54
|
transition: opacity 0.125s ease-in-out;
|
|
37
55
|
transition-delay: 0s;
|
|
38
56
|
}
|
|
57
|
+
:where([oui-tooltip-content])::after {
|
|
58
|
+
content: "";
|
|
59
|
+
opacity: 0;
|
|
60
|
+
position: absolute;
|
|
61
|
+
}
|
|
62
|
+
:where([oui-tooltip-content])[position^=above]::after, :where([oui-tooltip-content])[position^=below]::after, :where([oui-tooltip-content])[position^=bottom]::after, :where([oui-tooltip-content])[position^=top]::after {
|
|
63
|
+
width: 100%;
|
|
64
|
+
height: 0.5rem;
|
|
65
|
+
}
|
|
66
|
+
:where([oui-tooltip-content])[position^=above]::after, :where([oui-tooltip-content])[position^=top]::after {
|
|
67
|
+
inset: 100% 0 0;
|
|
68
|
+
}
|
|
69
|
+
:where([oui-tooltip-content])[position^=below]::after, :where([oui-tooltip-content])[position^=bottom]::after {
|
|
70
|
+
inset: -5rem 0 0;
|
|
71
|
+
}
|
|
72
|
+
:where([oui-tooltip-content])[position^=end]::after, :where([oui-tooltip-content])[position^=left]::after, :where([oui-tooltip-content])[position^=right]::after, :where([oui-tooltip-content])[position^=start]::after {
|
|
73
|
+
width: 0.5rem;
|
|
74
|
+
height: 100%;
|
|
75
|
+
}
|
|
76
|
+
:where([oui-tooltip-content])[position^=end]::after, :where([oui-tooltip-content])[position^=right]::after {
|
|
77
|
+
inset: 0 0 0 -0.5rem;
|
|
78
|
+
}
|
|
79
|
+
:where([oui-tooltip-content])[position^=left]::after, :where([oui-tooltip-content])[position^=start]::after {
|
|
80
|
+
inset: 0 0 0 100%;
|
|
81
|
+
}
|
|
39
82
|
|
|
40
83
|
:where([oui-tooltip-content][oui-tooltip-content-active]) {
|
|
41
84
|
opacity: 1;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
//#region src/js/attributable.ts
|
|
1
2
|
function attributable(attribute, add, remove) {
|
|
2
3
|
new MutationObserver((entries) => {
|
|
3
4
|
const { length } = entries;
|
|
@@ -26,11 +27,17 @@ function handleAdded(attribute, nodes, add) {
|
|
|
26
27
|
for (let index = 0; index < length; index += 1) {
|
|
27
28
|
const element = elements[index];
|
|
28
29
|
if (element.hasAttribute(attribute)) add(element);
|
|
30
|
+
if (element.hasChildNodes()) handleAdded(attribute, element.childNodes, add);
|
|
29
31
|
}
|
|
30
32
|
}
|
|
31
33
|
function handleRemoved(nodes, remove) {
|
|
32
34
|
const elements = [...nodes].filter((node) => node instanceof HTMLElement);
|
|
33
35
|
const { length } = elements;
|
|
34
|
-
for (let index = 0; index < length; index += 1)
|
|
36
|
+
for (let index = 0; index < length; index += 1) {
|
|
37
|
+
const element = elements[index];
|
|
38
|
+
remove(element);
|
|
39
|
+
if (element.hasChildNodes()) handleRemoved(element.childNodes, remove);
|
|
40
|
+
}
|
|
35
41
|
}
|
|
42
|
+
//#endregion
|
|
36
43
|
export { attributable };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//#region src/js/floatable.d.ts
|
|
2
|
+
declare class Floatable {
|
|
3
|
+
readonly options: Options;
|
|
4
|
+
active: boolean;
|
|
5
|
+
disabled: boolean;
|
|
6
|
+
frame: DOMHighResTimeStamp | undefined;
|
|
7
|
+
ignoreFocus: boolean;
|
|
8
|
+
constructor(options: Options);
|
|
9
|
+
destroy(): void;
|
|
10
|
+
disable(): void;
|
|
11
|
+
enable(): void;
|
|
12
|
+
toggle(active: boolean, ignoreFocus?: boolean): void;
|
|
13
|
+
}
|
|
14
|
+
type Options = {
|
|
15
|
+
anchor: HTMLElement;
|
|
16
|
+
content: HTMLElement;
|
|
17
|
+
defaultPosition: Position;
|
|
18
|
+
interactive: boolean;
|
|
19
|
+
positionAttribute: string;
|
|
20
|
+
preferAbove: boolean;
|
|
21
|
+
onAfter?: (active: boolean) => void;
|
|
22
|
+
};
|
|
23
|
+
type Position = 'above' | 'above-end' | 'above-start' | 'below' | 'below-end' | 'below-start' | 'end' | 'end-bottom' | 'end-top' | 'horizontal' | 'horizontal-bottom' | 'horizontal-top' | 'start' | 'start-bottom' | 'start-top' | 'vertical' | 'vertical-end' | 'vertical-start';
|
|
24
|
+
declare function deactivate(floatable: Floatable): void;
|
|
25
|
+
//#endregion
|
|
26
|
+
export { Floatable, deactivate };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { on } from "@oscarpalmer/toretto/event";
|
|
2
2
|
import { findAncestor } from "@oscarpalmer/toretto/find";
|
|
3
|
+
//#region src/js/floatable.ts
|
|
3
4
|
var Floatable = class {
|
|
4
5
|
active = false;
|
|
5
6
|
disabled = false;
|
|
@@ -74,44 +75,68 @@ function deactivate(floatable) {
|
|
|
74
75
|
floatable.options.anchor.insertAdjacentElement(INSERT_AFTEREND, floatable.options.content);
|
|
75
76
|
floatable.options.onAfter?.(false);
|
|
76
77
|
}
|
|
78
|
+
function getAttribute(position, anchor, top, left) {
|
|
79
|
+
switch (position) {
|
|
80
|
+
case "horizontal":
|
|
81
|
+
case "horizontal-bottom":
|
|
82
|
+
case "horizontal-top": return position.replace("horizontal", left >= anchor.right ? "right" : "left");
|
|
83
|
+
case "vertical":
|
|
84
|
+
case "vertical-end":
|
|
85
|
+
case "vertical-start": return position.replace("vertical", top >= anchor.bottom ? "bottom" : "top");
|
|
86
|
+
default: break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function getMargin() {
|
|
90
|
+
try {
|
|
91
|
+
const fontsize = parseFloat(getComputedStyle(document.documentElement).fontSize);
|
|
92
|
+
if (Number.isNaN(fontsize)) return 5;
|
|
93
|
+
const margin = fontsize / 2;
|
|
94
|
+
return margin < 5 ? 5 : margin;
|
|
95
|
+
} catch {
|
|
96
|
+
return 5;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
77
99
|
function getState() {
|
|
78
100
|
return window._oscarpalmer_oui_floatable;
|
|
79
101
|
}
|
|
80
|
-
function getX(anchor, content, position) {
|
|
81
|
-
if (position
|
|
82
|
-
const
|
|
83
|
-
|
|
102
|
+
function getX(anchor, content, position, margin) {
|
|
103
|
+
if (position === "above" || position === "below" || position === "vertical") {
|
|
104
|
+
const center = anchor.left + anchor.width / 2;
|
|
105
|
+
const width = content.width / 2;
|
|
106
|
+
if (center + width + margin >= document.body.clientWidth) return document.body.clientWidth - content.width - margin / 2;
|
|
107
|
+
if (center - width - margin <= 0) return margin / 2;
|
|
108
|
+
return center - width;
|
|
84
109
|
}
|
|
85
|
-
if (position.
|
|
86
|
-
|
|
87
|
-
|
|
110
|
+
if (position.startsWith("end")) return anchor.right;
|
|
111
|
+
if (position.startsWith("start")) return anchor.left - content.width;
|
|
112
|
+
if (position.endsWith("end")) return anchor.right - content.width - margin <= 0 ? margin / 2 : anchor.right - content.width;
|
|
113
|
+
if (position.endsWith("start")) {
|
|
114
|
+
if (anchor.left + content.width + margin >= document.body.clientWidth) return document.body.clientWidth - content.width - margin / 2;
|
|
115
|
+
return anchor.left - margin <= 0 ? margin / 2 : anchor.left;
|
|
88
116
|
}
|
|
89
|
-
if (position.startsWith(
|
|
90
|
-
if (
|
|
91
|
-
|
|
92
|
-
if (anchor.right + content.width <= window.innerWidth) return anchor.right;
|
|
93
|
-
return anchor.left - content.width;
|
|
94
|
-
}
|
|
95
|
-
const left = anchor.left + (anchor.width - content.width) / 2;
|
|
96
|
-
return left < 0 ? 0 : left;
|
|
117
|
+
if (!position.startsWith("horizontal")) return 0;
|
|
118
|
+
if (anchor.right + content.width + margin >= document.body.clientWidth) return anchor.left - content.width;
|
|
119
|
+
return anchor.right;
|
|
97
120
|
}
|
|
98
|
-
function getY(anchor, content, position, preferAbove) {
|
|
99
|
-
if (position
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
if (position.endsWith(POSITION_TOP)) {
|
|
106
|
-
const top = anchor.top;
|
|
107
|
-
return top + content.height > window.innerHeight ? window.innerHeight - content.height : top;
|
|
121
|
+
function getY(anchor, content, position, margin, preferAbove) {
|
|
122
|
+
if (position === "end" || position === "start" || position === "horizontal") {
|
|
123
|
+
const center = anchor.top + anchor.height / 2;
|
|
124
|
+
const height = content.height / 2;
|
|
125
|
+
if (center + height + margin >= document.body.clientHeight) return document.body.clientHeight - content.height - margin / 2;
|
|
126
|
+
if (center - height - margin <= 0) return margin / 2;
|
|
127
|
+
return center - height;
|
|
108
128
|
}
|
|
109
|
-
if (position.startsWith(
|
|
110
|
-
|
|
111
|
-
|
|
129
|
+
if (position.startsWith("above")) return anchor.top - content.height;
|
|
130
|
+
if (position.startsWith("below")) return anchor.bottom;
|
|
131
|
+
if (position.endsWith("bottom")) return anchor.bottom - content.height - margin <= 0 ? margin / 2 : anchor.bottom - content.height;
|
|
132
|
+
if (position.endsWith("top")) return anchor.top + content.height + margin >= document.body.clientHeight ? document.body.clientHeight - content.height - margin : anchor.top;
|
|
133
|
+
if (!position.startsWith("vertical")) return 0;
|
|
134
|
+
if (preferAbove) {
|
|
135
|
+
if (anchor.top - content.height - margin <= 0 && anchor.bottom + content.height + margin <= document.body.clientHeight) return anchor.bottom;
|
|
112
136
|
return anchor.top - content.height;
|
|
113
137
|
}
|
|
114
|
-
|
|
138
|
+
if (anchor.bottom + content.height + margin >= document.body.clientHeight) return anchor.top - content.height;
|
|
139
|
+
return anchor.bottom;
|
|
115
140
|
}
|
|
116
141
|
function initialize(floatable) {
|
|
117
142
|
const { anchor, content, interactive } = floatable.options;
|
|
@@ -130,7 +155,7 @@ function isDisabled(element) {
|
|
|
130
155
|
return element.disabled || element.readOnly || element.getAttribute("aria-disabled") === "true";
|
|
131
156
|
}
|
|
132
157
|
function onClick(event) {
|
|
133
|
-
const related = findAncestor(event
|
|
158
|
+
const related = findAncestor(event, SELECTOR_ALL);
|
|
134
159
|
if (!(related instanceof HTMLElement)) closeAll();
|
|
135
160
|
else if (related.hasAttribute(ATTRIBUTE_CONTENT)) closeAbove(related);
|
|
136
161
|
else if (!isDisabled(related)) toggle(related);
|
|
@@ -140,12 +165,17 @@ function onKeyDown(event) {
|
|
|
140
165
|
const state = getState();
|
|
141
166
|
if (state == null || state.active.size === 0) return;
|
|
142
167
|
closeNonInteractive(state);
|
|
143
|
-
const related = findAncestor(event
|
|
168
|
+
const related = findAncestor(event, SELECTOR_CONTENT);
|
|
144
169
|
if (!(related instanceof HTMLElement)) return;
|
|
145
170
|
closeAbove(related);
|
|
146
171
|
const floatable = state.mapped.get(related);
|
|
147
172
|
if (floatable != null) floatable.toggle(false);
|
|
148
173
|
}
|
|
174
|
+
function setAttribute(position, anchor, floater, top, left) {
|
|
175
|
+
let actual;
|
|
176
|
+
if (/^(horizontal|vertical)/.test(position)) actual = getAttribute(position, anchor, top, left);
|
|
177
|
+
floater.setAttribute("position", actual ?? position);
|
|
178
|
+
}
|
|
149
179
|
function stop(floatable) {
|
|
150
180
|
if (floatable.frame != null) cancelAnimationFrame(floatable.frame);
|
|
151
181
|
floatable.frame = void 0;
|
|
@@ -165,6 +195,7 @@ function toggle(anchor) {
|
|
|
165
195
|
function updatePosition(floatable) {
|
|
166
196
|
let position = floatable.options.anchor.getAttribute(floatable.options.positionAttribute)?.trim() ?? floatable.options.defaultPosition;
|
|
167
197
|
if (!POSITIONS.has(position)) position = floatable.options.defaultPosition;
|
|
198
|
+
const margin = getMargin();
|
|
168
199
|
let previousAnchor;
|
|
169
200
|
let previousContent;
|
|
170
201
|
let calculated = false;
|
|
@@ -185,8 +216,9 @@ function updatePosition(floatable) {
|
|
|
185
216
|
function update(anchor, content) {
|
|
186
217
|
previousAnchor = anchor;
|
|
187
218
|
previousContent = content;
|
|
188
|
-
const left = getX(anchor, content, position);
|
|
189
|
-
const top = getY(anchor, content, position, floatable.options.preferAbove);
|
|
219
|
+
const left = getX(anchor, content, position, margin);
|
|
220
|
+
const top = getY(anchor, content, position, margin, floatable.options.preferAbove);
|
|
221
|
+
setAttribute(position, anchor, floatable.options.content, top, left);
|
|
190
222
|
if (top + content.height > window.innerHeight) floatable.options.content.style.height = `${window.innerHeight - top}px`;
|
|
191
223
|
else floatable.options.content.style.height = "";
|
|
192
224
|
if (left + content.width > window.innerWidth) floatable.options.content.style.width = `${window.innerWidth - left}px`;
|
|
@@ -200,20 +232,10 @@ function updatePosition(floatable) {
|
|
|
200
232
|
}
|
|
201
233
|
floatable.frame = requestAnimationFrame(run);
|
|
202
234
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
var POSITION_BELOW = "below";
|
|
208
|
-
var POSITION_BOTTOM = "bottom";
|
|
209
|
-
var POSITION_END = "end";
|
|
210
|
-
var POSITION_HORIZONTAL = "horizontal";
|
|
211
|
-
var POSITION_START = "start";
|
|
212
|
-
var POSITION_SUFFIX_END = "-end";
|
|
213
|
-
var POSITION_SUFFIX_START = "-start";
|
|
214
|
-
var POSITION_TOP = "top";
|
|
215
|
-
var POSITION_VERTICAL = "vertical";
|
|
216
|
-
var POSITIONS = new Set([
|
|
235
|
+
const ATTRIBUTE_ANCHOR = "oui-floatable-anchor";
|
|
236
|
+
const ATTRIBUTE_CONTENT = "oui-floatable-content";
|
|
237
|
+
const INSERT_AFTEREND = "afterend";
|
|
238
|
+
const POSITIONS = new Set([
|
|
217
239
|
"above",
|
|
218
240
|
"above-end",
|
|
219
241
|
"above-start",
|
|
@@ -233,14 +255,14 @@ var POSITIONS = new Set([
|
|
|
233
255
|
"vertical-end",
|
|
234
256
|
"vertical-start"
|
|
235
257
|
]);
|
|
236
|
-
|
|
258
|
+
const PROPERTIES = [
|
|
237
259
|
"bottom",
|
|
238
260
|
"left",
|
|
239
261
|
"right",
|
|
240
262
|
"top"
|
|
241
263
|
];
|
|
242
|
-
|
|
243
|
-
|
|
264
|
+
const SELECTOR_ALL = `[${ATTRIBUTE_ANCHOR}], [${ATTRIBUTE_CONTENT}]`;
|
|
265
|
+
const SELECTOR_CONTENT = `[${ATTRIBUTE_CONTENT}]`;
|
|
244
266
|
if (window._oscarpalmer_oui_floatable == null) {
|
|
245
267
|
Object.defineProperty(window, "_oscarpalmer_oui_floatable", {
|
|
246
268
|
enumerable: false,
|
|
@@ -258,4 +280,5 @@ if (window._oscarpalmer_oui_floatable == null) {
|
|
|
258
280
|
onClick(event);
|
|
259
281
|
});
|
|
260
282
|
}
|
|
283
|
+
//#endregion
|
|
261
284
|
export { Floatable, deactivate };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//#region src/js/focus-trap/embedded.d.ts
|
|
2
|
+
declare class FocusTrap {
|
|
3
|
+
disabled: boolean;
|
|
4
|
+
connected: boolean;
|
|
5
|
+
element: HTMLElement;
|
|
6
|
+
embedded: boolean;
|
|
7
|
+
get contain(): boolean;
|
|
8
|
+
get noescape(): boolean;
|
|
9
|
+
constructor(element: HTMLElement, options?: Options);
|
|
10
|
+
connect(): void;
|
|
11
|
+
destroy(): void;
|
|
12
|
+
disable(): void;
|
|
13
|
+
disconnect(): void;
|
|
14
|
+
enable(): void;
|
|
15
|
+
focus(last: boolean): void;
|
|
16
|
+
}
|
|
17
|
+
type Options = {
|
|
18
|
+
noescape: boolean;
|
|
19
|
+
};
|
|
20
|
+
declare function createFocusTrap(element: HTMLElement, options?: Options): FocusTrap;
|
|
21
|
+
declare const FOCUS_TRAP_SELECTOR = "oui-focus-trap";
|
|
22
|
+
declare const FOCUS_TRAP_CONTAIN = "oui-focus-trap-contain";
|
|
23
|
+
declare const FOCUS_TRAP_NOESCAPE = "oui-focus-trap-noescape";
|
|
24
|
+
declare const FOCUSTRAPS_ALL: WeakMap<HTMLElement, FocusTrap>;
|
|
25
|
+
//#endregion
|
|
26
|
+
export { FOCUSTRAPS_ALL, FOCUS_TRAP_CONTAIN, FOCUS_TRAP_NOESCAPE, FOCUS_TRAP_SELECTOR, FocusTrap, createFocusTrap };
|
|
@@ -2,6 +2,7 @@ import { on } from "@oscarpalmer/toretto/event";
|
|
|
2
2
|
import { findAncestor } from "@oscarpalmer/toretto/find";
|
|
3
3
|
import { clamp } from "@oscarpalmer/atoms/number";
|
|
4
4
|
import { getFocusable } from "@oscarpalmer/toretto/focusable";
|
|
5
|
+
//#region src/js/focus-trap/embedded.ts
|
|
5
6
|
var FocusTrap = class {
|
|
6
7
|
disabled = false;
|
|
7
8
|
connected = true;
|
|
@@ -48,7 +49,7 @@ function createFocusTrap(element, options) {
|
|
|
48
49
|
return focusTrap;
|
|
49
50
|
}
|
|
50
51
|
function onEscape(event) {
|
|
51
|
-
let element = findAncestor(event
|
|
52
|
+
let element = findAncestor(event, ATTRIBUTE_SELECTOR);
|
|
52
53
|
let focusTrap = FOCUSTRAPS_ALL.get(element);
|
|
53
54
|
if (element == null || focusTrap == null) return;
|
|
54
55
|
while (focusTrap.disabled) {
|
|
@@ -60,7 +61,7 @@ function onEscape(event) {
|
|
|
60
61
|
focusTrap?.disable();
|
|
61
62
|
}
|
|
62
63
|
function onFocusIn(event) {
|
|
63
|
-
lastTarget = FOCUSTRAPS_ALL.get(findAncestor(event
|
|
64
|
+
lastTarget = FOCUSTRAPS_ALL.get(findAncestor(event, ATTRIBUTE_SELECTOR)) == null ? void 0 : event.target;
|
|
64
65
|
}
|
|
65
66
|
function onKeydown(event) {
|
|
66
67
|
switch (event.key) {
|
|
@@ -75,7 +76,7 @@ function onKeydown(event) {
|
|
|
75
76
|
}
|
|
76
77
|
function onPointerdown(event) {
|
|
77
78
|
const lastFocusTrap = findAncestor(lastTarget, ATTRIBUTE_SELECTOR);
|
|
78
|
-
const nextFocusTrap = findAncestor(event
|
|
79
|
+
const nextFocusTrap = findAncestor(event, ATTRIBUTE_SELECTOR);
|
|
79
80
|
if (lastFocusTrap != null && nextFocusTrap !== lastFocusTrap) {
|
|
80
81
|
if (FOCUSTRAPS_ALL.get(lastFocusTrap)?.contain ?? false) {
|
|
81
82
|
event.preventDefault();
|
|
@@ -86,7 +87,7 @@ function onPointerdown(event) {
|
|
|
86
87
|
for (const focusTrap of FOCUSTRAPS_DISABLED) if (focusTrap.element !== nextFocusTrap) focusTrap.enable();
|
|
87
88
|
}
|
|
88
89
|
function onTab(event) {
|
|
89
|
-
const element = findAncestor(event
|
|
90
|
+
const element = findAncestor(event, ATTRIBUTE_SELECTOR);
|
|
90
91
|
const focusTrap = FOCUSTRAPS_ALL.get(element);
|
|
91
92
|
if (focusTrap == null) return;
|
|
92
93
|
if (!focusTrap.disabled) event.preventDefault();
|
|
@@ -133,18 +134,19 @@ function tabToTrap(focusTrap, elements, element, index) {
|
|
|
133
134
|
}
|
|
134
135
|
}
|
|
135
136
|
const FOCUS_TRAP_SELECTOR = "oui-focus-trap";
|
|
136
|
-
|
|
137
|
-
|
|
137
|
+
const ATTRIBUTE_SELECTOR = `[${FOCUS_TRAP_SELECTOR}]`;
|
|
138
|
+
const EVENT_OPTIONS = {
|
|
138
139
|
capture: true,
|
|
139
140
|
passive: false
|
|
140
141
|
};
|
|
141
142
|
const FOCUS_TRAP_CONTAIN = `${FOCUS_TRAP_SELECTOR}-contain`;
|
|
142
143
|
const FOCUS_TRAP_NOESCAPE = `${FOCUS_TRAP_SELECTOR}-noescape`;
|
|
143
144
|
const FOCUSTRAPS_ALL = /* @__PURE__ */ new WeakMap();
|
|
144
|
-
|
|
145
|
-
|
|
145
|
+
const FOCUSTRAPS_DISABLED = /* @__PURE__ */ new Set();
|
|
146
|
+
let lastTarget;
|
|
146
147
|
on(document, "focusin", onFocusIn, EVENT_OPTIONS);
|
|
147
148
|
on(document, "keydown", onKeydown, EVENT_OPTIONS);
|
|
148
149
|
on(document, "mousedown", onPointerdown, EVENT_OPTIONS);
|
|
149
150
|
on(document, "touchstart", onPointerdown, EVENT_OPTIONS);
|
|
151
|
+
//#endregion
|
|
150
152
|
export { FOCUSTRAPS_ALL, FOCUS_TRAP_CONTAIN, FOCUS_TRAP_NOESCAPE, FOCUS_TRAP_SELECTOR, FocusTrap, createFocusTrap };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import { attributable } from "../attributable.
|
|
2
|
-
import { FOCUSTRAPS_ALL, FOCUS_TRAP_SELECTOR, createFocusTrap } from "./embedded.
|
|
1
|
+
import { attributable } from "../attributable.mjs";
|
|
2
|
+
import { FOCUSTRAPS_ALL, FOCUS_TRAP_SELECTOR, createFocusTrap } from "./embedded.mjs";
|
|
3
|
+
//#region src/js/focus-trap/standalone.ts
|
|
3
4
|
function removeFocusTraps(element) {
|
|
4
5
|
FOCUSTRAPS_ALL.get(element)?.destroy();
|
|
5
6
|
FOCUSTRAPS_ALL.delete(element);
|
|
6
7
|
}
|
|
7
8
|
attributable(FOCUS_TRAP_SELECTOR, createFocusTrap, removeFocusTraps);
|
|
9
|
+
//#endregion
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/js/popover.d.ts
|
|
2
|
+
declare global {
|
|
3
|
+
interface HTMLElementTagNameMap {
|
|
4
|
+
'oui-popover': OuiPopoverElement;
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
declare class OuiPopoverElement extends HTMLElement {
|
|
8
|
+
#private;
|
|
9
|
+
constructor();
|
|
10
|
+
close(): void;
|
|
11
|
+
connectedCallback(): void;
|
|
12
|
+
disconnectedCallback(): void;
|
|
13
|
+
hidePopover(): void;
|
|
14
|
+
open(): void;
|
|
15
|
+
showPopover(): void;
|
|
16
|
+
toggle(): void;
|
|
17
|
+
togglePopover(options?: boolean): boolean;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { OuiPopoverElement };
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { Floatable } from "./floatable.
|
|
2
|
-
import { createFocusTrap } from "./focus-trap/embedded.
|
|
1
|
+
import { Floatable } from "./floatable.mjs";
|
|
2
|
+
import { createFocusTrap } from "./focus-trap/embedded.mjs";
|
|
3
3
|
import { getFocusable } from "@oscarpalmer/toretto/focusable";
|
|
4
4
|
import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
|
|
5
|
-
|
|
5
|
+
//#region src/js/popover.ts
|
|
6
|
+
let index = 0;
|
|
6
7
|
var OuiPopoverElement = class extends HTMLElement {
|
|
7
8
|
#floatable;
|
|
8
9
|
#focusTrap;
|
|
@@ -78,10 +79,11 @@ function focus(content) {
|
|
|
78
79
|
target.focus();
|
|
79
80
|
});
|
|
80
81
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
const ATTRIBUTE_ID_PREFIX = "oui_popover_content_";
|
|
83
|
+
const POPOVERS = /* @__PURE__ */ new Map();
|
|
84
|
+
const SELECTOR = "oui-popover";
|
|
85
|
+
const SELECTOR_CONTENT = `:scope > [${SELECTOR}-content]`;
|
|
86
|
+
const SELECTOR_TOGGLE = `:scope > [${SELECTOR}-toggle]`;
|
|
86
87
|
customElements.define(SELECTOR, OuiPopoverElement);
|
|
88
|
+
//#endregion
|
|
87
89
|
export { OuiPopoverElement };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//#region src/js/splitter.d.ts
|
|
2
|
+
declare global {
|
|
3
|
+
interface HTMLElementTagNameMap {
|
|
4
|
+
[SELECTOR]: OuiSplitterElement;
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
declare class OuiSplitterElement extends HTMLElement {
|
|
8
|
+
#private;
|
|
9
|
+
static readonly observedAttributes: string[];
|
|
10
|
+
get max(): number;
|
|
11
|
+
set max(value: number);
|
|
12
|
+
get min(): number;
|
|
13
|
+
set min(value: number);
|
|
14
|
+
get size(): number;
|
|
15
|
+
set size(value: number);
|
|
16
|
+
get type(): string;
|
|
17
|
+
set type(value: string);
|
|
18
|
+
constructor();
|
|
19
|
+
connectedCallback(): void;
|
|
20
|
+
disconnectedCallback(): void;
|
|
21
|
+
attributeChangedCallback(name: string): void;
|
|
22
|
+
}
|
|
23
|
+
declare const SELECTOR = "oui-splitter";
|
|
24
|
+
//#endregion
|
|
25
|
+
export { OuiSplitterElement };
|