@oscarpalmer/oui 0.23.1 → 0.25.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/{tooltip.css → floatable.css} +59 -24
- package/dist/css/reset.css +17 -0
- package/dist/js/dialog.d.mts +38 -0
- package/dist/js/dialog.mjs +92 -0
- package/dist/js/embedded-84gxpReS.d.mts +64 -0
- package/dist/js/embedded-BpwzMSEF.d.mts +26 -0
- package/dist/js/floatable/embedded.d.mts +2 -0
- package/dist/js/floatable/embedded.mjs +146 -0
- package/dist/js/floatable/standalone.d.mts +2 -0
- package/dist/js/floatable/standalone.mjs +2 -0
- package/dist/js/focus-trap/embedded.d.mts +1 -25
- package/dist/js/focus-trap/embedded.mjs +1 -1
- package/dist/js/index.d.mts +5 -2
- package/dist/js/index.mjs +7 -4
- package/dist/js/internal/attributable.mjs +4 -3
- package/dist/js/internal/draggable.mjs +1 -1
- package/dist/js/popover.d.mts +38 -1
- package/dist/js/popover.mjs +81 -38
- package/dist/js/sortable.mjs +7 -5
- package/dist/js/splitter.mjs +18 -14
- package/dist/js/tooltip.d.mts +33 -1
- package/dist/js/tooltip.mjs +91 -48
- package/package.json +2 -2
- package/src/css/{tooltip.scss → floatable.scss} +47 -5
- package/src/css/mixins.scss +0 -2
- package/src/css/reset.scss +17 -0
- package/src/js/dialog.ts +188 -0
- package/src/js/floatable/embedded.ts +302 -0
- package/src/js/floatable/standalone.ts +1 -0
- package/src/js/index.ts +4 -2
- package/src/js/internal/attributable.ts +5 -3
- package/src/js/popover.ts +146 -48
- package/src/js/sortable.ts +8 -5
- package/src/js/splitter.ts +26 -9
- package/src/js/tooltip.ts +138 -51
- package/dist/css/popover.css +0 -30
- package/dist/js/internal/floatable.d.mts +0 -18
- package/dist/js/internal/floatable.mjs +0 -67
- package/src/css/popover.scss +0 -10
- package/src/js/internal/floatable.ts +0 -118
package/dist/js/popover.mjs
CHANGED
|
@@ -1,60 +1,103 @@
|
|
|
1
|
+
import { createFloatable, getOnBeforeToggleListener } from "./floatable/embedded.mjs";
|
|
1
2
|
import { attributable } from "./internal/attributable.mjs";
|
|
2
|
-
import { createFocusTrap
|
|
3
|
-
import { createFloatable, removeFloatable } from "./internal/floatable.mjs";
|
|
3
|
+
import { createFocusTrap } from "./focus-trap/embedded.mjs";
|
|
4
4
|
import { on } from "@oscarpalmer/toretto/event";
|
|
5
|
+
import { isHTMLOrSVGElement } from "@oscarpalmer/toretto/is";
|
|
5
6
|
//#region src/js/popover.ts
|
|
6
|
-
var
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
this
|
|
16
|
-
this.
|
|
17
|
-
this.listener = on(element, EVENT_TOGGLE, (event) => {
|
|
18
|
-
if (event.newState === STATE_OPEN) {
|
|
19
|
-
ignoreFocus = false;
|
|
20
|
-
this.floatable?.update();
|
|
21
|
-
element.focus();
|
|
22
|
-
} else if (!ignoreFocus) this.anchor?.focus();
|
|
23
|
-
});
|
|
24
|
-
this.element.setAttribute(ATTRIBUTE_CONTENT, "");
|
|
25
|
-
this.floatable?.update();
|
|
7
|
+
var OuiPopover = class {
|
|
8
|
+
#state;
|
|
9
|
+
/**
|
|
10
|
+
* Is the popover open?
|
|
11
|
+
*/
|
|
12
|
+
get open() {
|
|
13
|
+
return this.#state.content.checkVisibility();
|
|
14
|
+
}
|
|
15
|
+
constructor(state) {
|
|
16
|
+
this.#state = state;
|
|
17
|
+
this.#state.floatable.update();
|
|
26
18
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
this.
|
|
32
|
-
|
|
33
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Closes the popover
|
|
21
|
+
*/
|
|
22
|
+
hide() {
|
|
23
|
+
this.#state.floatable.hide();
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Opens the popover
|
|
27
|
+
*/
|
|
28
|
+
show() {
|
|
29
|
+
this.#state.floatable.show();
|
|
34
30
|
}
|
|
35
31
|
};
|
|
32
|
+
function destroyPopover(state) {
|
|
33
|
+
state.floatable.destroy();
|
|
34
|
+
state.focusTrap?.destroy();
|
|
35
|
+
for (const listener of state.listeners) listener();
|
|
36
|
+
state.anchor = void 0;
|
|
37
|
+
state.content = void 0;
|
|
38
|
+
state.floatable = void 0;
|
|
39
|
+
state.focusTrap = void 0;
|
|
40
|
+
state.listeners = void 0;
|
|
41
|
+
state.popover = void 0;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get the _OuiPopover_ for an element
|
|
45
|
+
*
|
|
46
|
+
* @param element Element to get _OuiPopover_ for
|
|
47
|
+
* @returns _OuiPopover_ instance
|
|
48
|
+
*/
|
|
49
|
+
function getPopover(element) {
|
|
50
|
+
return states.get(element)?.popover;
|
|
51
|
+
}
|
|
52
|
+
function getState(anchor, content) {
|
|
53
|
+
const state = {
|
|
54
|
+
anchor,
|
|
55
|
+
content,
|
|
56
|
+
floatable: createFloatable(anchor, content, options, false),
|
|
57
|
+
focusTrap: content.getAttribute(ARIA_MODAL) === TRUE ? createFocusTrap(content, { noescape: true }) : void 0,
|
|
58
|
+
listeners: [getOnBeforeToggleListener(content), on(content, EVENT_TOGGLE, (event) => {
|
|
59
|
+
if (event.newState === STATE_OPEN) {
|
|
60
|
+
ignoreFocus = false;
|
|
61
|
+
state.floatable?.update();
|
|
62
|
+
content.setAttribute(ATTRIBUTE_OPEN, "");
|
|
63
|
+
content.focus();
|
|
64
|
+
} else {
|
|
65
|
+
content.removeAttribute(ATTRIBUTE_OPEN);
|
|
66
|
+
if (!ignoreFocus) anchor?.focus();
|
|
67
|
+
}
|
|
68
|
+
})],
|
|
69
|
+
popover: void 0
|
|
70
|
+
};
|
|
71
|
+
state.popover = new OuiPopover(state);
|
|
72
|
+
return state;
|
|
73
|
+
}
|
|
36
74
|
function onAdd(element) {
|
|
37
|
-
if (
|
|
75
|
+
if (states.has(element) || element.hasAttribute("oui-floatable")) return;
|
|
76
|
+
const anchor = element.ownerDocument.querySelector(`[popovertarget="${element.id}"]`);
|
|
77
|
+
if (isHTMLOrSVGElement(anchor)) states.set(element, getState(anchor, element));
|
|
38
78
|
}
|
|
39
79
|
function onPointerdown() {
|
|
40
80
|
ignoreFocus = true;
|
|
41
81
|
}
|
|
42
82
|
function onRemove(element) {
|
|
43
|
-
|
|
44
|
-
|
|
83
|
+
const state = states.get(element);
|
|
84
|
+
if (state == null) return;
|
|
85
|
+
destroyPopover(state);
|
|
86
|
+
states.delete(element);
|
|
45
87
|
}
|
|
46
|
-
const ATTRIBUTE = "popover";
|
|
47
|
-
const
|
|
88
|
+
const ATTRIBUTE = "oui-popover";
|
|
89
|
+
const ARIA_MODAL = "aria-modal";
|
|
90
|
+
const ATTRIBUTE_OPEN = `${ATTRIBUTE}-open`;
|
|
48
91
|
const EVENT_TOGGLE = "toggle";
|
|
49
|
-
const POPOVER_HINT = "hint";
|
|
50
92
|
const STATE_OPEN = "open";
|
|
51
|
-
const
|
|
93
|
+
const TRUE = "true";
|
|
52
94
|
const options = {
|
|
53
|
-
attribute:
|
|
95
|
+
attribute: `${ATTRIBUTE}position`,
|
|
54
96
|
position: "below-start"
|
|
55
97
|
};
|
|
98
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
56
99
|
let ignoreFocus = false;
|
|
57
100
|
on(document, "pointerdown", onPointerdown, { capture: true });
|
|
58
101
|
attributable(ATTRIBUTE, onAdd, onRemove);
|
|
59
102
|
//#endregion
|
|
60
|
-
export {};
|
|
103
|
+
export { getPopover };
|
package/dist/js/sortable.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { attributable } from "./internal/attributable.mjs";
|
|
2
2
|
import { Draggable, addDraggable, removeDraggable } from "./internal/draggable.mjs";
|
|
3
3
|
import { getPosition } from "@oscarpalmer/toretto/event";
|
|
4
|
+
import { isHTMLOrSVGElement } from "@oscarpalmer/toretto/is";
|
|
4
5
|
import { findAncestor, getElementFromPosition } from "@oscarpalmer/toretto/find";
|
|
5
6
|
import { createElement } from "@oscarpalmer/toretto/create";
|
|
6
7
|
//#region src/js/sortable.ts
|
|
@@ -177,12 +178,13 @@ function setPlaceholder(state, sortable, origin) {
|
|
|
177
178
|
parent: sortable.element,
|
|
178
179
|
placeholder: element,
|
|
179
180
|
create: (value) => {
|
|
180
|
-
if (!(value
|
|
181
|
-
|
|
182
|
-
|
|
181
|
+
if (!isHTMLOrSVGElement(value)) return;
|
|
182
|
+
const element = value;
|
|
183
|
+
placeholder.drag.custom = element;
|
|
184
|
+
updatePlaceholder(sortable, element);
|
|
183
185
|
state.element = {
|
|
184
|
-
rectangle:
|
|
185
|
-
node:
|
|
186
|
+
rectangle: element.getBoundingClientRect(),
|
|
187
|
+
node: element
|
|
186
188
|
};
|
|
187
189
|
}
|
|
188
190
|
}
|
package/dist/js/splitter.mjs
CHANGED
|
@@ -1,24 +1,28 @@
|
|
|
1
|
-
import { clamp } from "@oscarpalmer/atoms/number";
|
|
2
1
|
import { getPosition, on } from "@oscarpalmer/toretto/event";
|
|
2
|
+
import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
|
|
3
|
+
import { clamp } from "@oscarpalmer/atoms/number";
|
|
3
4
|
import { findAncestor } from "@oscarpalmer/toretto/find";
|
|
4
5
|
import { toggleStyles } from "@oscarpalmer/toretto/style";
|
|
5
6
|
import supportsTouch from "@oscarpalmer/toretto/touch";
|
|
6
|
-
import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
|
|
7
7
|
import { round } from "@oscarpalmer/atoms/math";
|
|
8
8
|
//#region src/js/splitter.ts
|
|
9
|
+
const ATTRIBUTE_MAX = "max";
|
|
10
|
+
const ATTRIBUTE_MIN = "min";
|
|
11
|
+
const ATTRIBUTE_SIZE = "size";
|
|
12
|
+
const ATTRIBUTE_TYPE = "type";
|
|
9
13
|
var OuiSplitterElement = class extends HTMLElement {
|
|
10
14
|
static observedAttributes = [
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
ATTRIBUTE_MAX,
|
|
16
|
+
ATTRIBUTE_MIN,
|
|
17
|
+
ATTRIBUTE_SIZE,
|
|
18
|
+
ATTRIBUTE_TYPE
|
|
15
19
|
];
|
|
16
20
|
#splitter;
|
|
17
21
|
get max() {
|
|
18
22
|
return this.#splitter.values.max;
|
|
19
23
|
}
|
|
20
24
|
set max(value) {
|
|
21
|
-
this.setAttribute(
|
|
25
|
+
this.setAttribute(ATTRIBUTE_MAX, String(value));
|
|
22
26
|
}
|
|
23
27
|
get min() {
|
|
24
28
|
return this.#splitter.values.min;
|
|
@@ -52,12 +56,12 @@ var OuiSplitterElement = class extends HTMLElement {
|
|
|
52
56
|
}
|
|
53
57
|
attributeChangedCallback(name) {
|
|
54
58
|
switch (name) {
|
|
55
|
-
case
|
|
56
|
-
case
|
|
57
|
-
case
|
|
59
|
+
case ATTRIBUTE_MAX:
|
|
60
|
+
case ATTRIBUTE_MIN:
|
|
61
|
+
case ATTRIBUTE_SIZE:
|
|
58
62
|
this.#splitter.updateValues();
|
|
59
63
|
break;
|
|
60
|
-
case
|
|
64
|
+
case ATTRIBUTE_TYPE:
|
|
61
65
|
this.#splitter.updateOrientation();
|
|
62
66
|
break;
|
|
63
67
|
default: break;
|
|
@@ -157,14 +161,14 @@ function getValue(element, name, defaultValue) {
|
|
|
157
161
|
}
|
|
158
162
|
function getValues(element) {
|
|
159
163
|
const values = {
|
|
160
|
-
max: getValue(element,
|
|
161
|
-
min: getValue(element,
|
|
164
|
+
max: getValue(element, ATTRIBUTE_MAX, NAVIGATION_MAXIMUM_PERCENTAGE),
|
|
165
|
+
min: getValue(element, ATTRIBUTE_MIN, NAVIGATION_MINIMUM_PERCENTAGE),
|
|
162
166
|
now: {
|
|
163
167
|
current: .5,
|
|
164
168
|
previous: .5
|
|
165
169
|
}
|
|
166
170
|
};
|
|
167
|
-
const value = getContained(values.min, getValue(element,
|
|
171
|
+
const value = getContained(values.min, getValue(element, ATTRIBUTE_SIZE, values.now.current), values.max);
|
|
168
172
|
values.now.current = value;
|
|
169
173
|
values.now.previous = value;
|
|
170
174
|
return values;
|
package/dist/js/tooltip.d.mts
CHANGED
|
@@ -1,4 +1,36 @@
|
|
|
1
|
+
import { n as OuiFloatable } from "./embedded-84gxpReS.mjs";
|
|
2
|
+
|
|
1
3
|
//#region src/js/tooltip.d.ts
|
|
4
|
+
declare class OuiTooltip {
|
|
5
|
+
#private;
|
|
6
|
+
/**
|
|
7
|
+
* Is the tooltip open?
|
|
8
|
+
*/
|
|
9
|
+
get open(): boolean;
|
|
10
|
+
constructor(state: OuiTooltipState);
|
|
11
|
+
/**
|
|
12
|
+
* Closes the tooltip
|
|
13
|
+
*/
|
|
14
|
+
hide(): void;
|
|
15
|
+
/**
|
|
16
|
+
* Opens the tooltip
|
|
17
|
+
*/
|
|
18
|
+
show(): void;
|
|
19
|
+
}
|
|
20
|
+
type OuiTooltipState = {
|
|
21
|
+
anchor: HTMLElement;
|
|
22
|
+
content: HTMLElement;
|
|
23
|
+
floatable: OuiFloatable;
|
|
24
|
+
timer?: number;
|
|
25
|
+
tooltip: OuiTooltip;
|
|
26
|
+
};
|
|
27
|
+
declare function getTooltip(element: HTMLElement): OuiTooltip | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* Set the delay before showing the tooltip, in milliseconds
|
|
30
|
+
*
|
|
31
|
+
* _(Default delay is half a second, or 500 milliseconds)_
|
|
32
|
+
* @param value Delay in milliseconds
|
|
33
|
+
*/
|
|
2
34
|
declare function setTooltipDelay(value: number): void;
|
|
3
35
|
//#endregion
|
|
4
|
-
export { setTooltipDelay };
|
|
36
|
+
export { type OuiTooltip, getTooltip, setTooltipDelay };
|
package/dist/js/tooltip.mjs
CHANGED
|
@@ -1,27 +1,34 @@
|
|
|
1
|
+
import { createFloatable } from "./floatable/embedded.mjs";
|
|
1
2
|
import { attributable } from "./internal/attributable.mjs";
|
|
2
|
-
import { Floatable } from "./internal/floatable.mjs";
|
|
3
3
|
import { on } from "@oscarpalmer/toretto/event";
|
|
4
|
+
import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
|
|
5
|
+
import { isHTMLOrSVGElement } from "@oscarpalmer/toretto/is";
|
|
4
6
|
import { findAncestor } from "@oscarpalmer/toretto/find";
|
|
5
7
|
import { createElement } from "@oscarpalmer/toretto/create";
|
|
6
|
-
import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
|
|
7
8
|
//#region src/js/tooltip.ts
|
|
8
|
-
var
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
this.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
9
|
+
var OuiTooltip = class {
|
|
10
|
+
#state;
|
|
11
|
+
/**
|
|
12
|
+
* Is the tooltip open?
|
|
13
|
+
*/
|
|
14
|
+
get open() {
|
|
15
|
+
return this.#state.content.checkVisibility();
|
|
16
|
+
}
|
|
17
|
+
constructor(state) {
|
|
18
|
+
this.#state = state;
|
|
19
|
+
state.floatable.update();
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Closes the tooltip
|
|
23
|
+
*/
|
|
24
|
+
hide() {
|
|
25
|
+
this.#state.floatable.hide();
|
|
20
26
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Opens the tooltip
|
|
29
|
+
*/
|
|
30
|
+
show() {
|
|
31
|
+
this.#state.floatable.show();
|
|
25
32
|
}
|
|
26
33
|
};
|
|
27
34
|
function activate(event, focus) {
|
|
@@ -29,34 +36,47 @@ function activate(event, focus) {
|
|
|
29
36
|
const content = findAncestor(event, SELECTOR_CONTENT);
|
|
30
37
|
if (anchor == null && content == null) {
|
|
31
38
|
if (!focused) {
|
|
32
|
-
closeTooltip(
|
|
33
|
-
|
|
39
|
+
closeTooltip(activeState);
|
|
40
|
+
activeState = void 0;
|
|
41
|
+
activeTooltip = void 0;
|
|
34
42
|
}
|
|
35
43
|
return;
|
|
36
44
|
}
|
|
37
|
-
const
|
|
38
|
-
if (
|
|
39
|
-
const shouldDelay =
|
|
40
|
-
closeTooltip(
|
|
41
|
-
|
|
45
|
+
const state = states.get(anchor ?? content);
|
|
46
|
+
if (state == null || state.tooltip === activeTooltip) return;
|
|
47
|
+
const shouldDelay = activeTooltip == null;
|
|
48
|
+
closeTooltip(activeState);
|
|
49
|
+
activeState = state;
|
|
50
|
+
activeTooltip = state.tooltip;
|
|
42
51
|
focused = focus;
|
|
43
|
-
|
|
44
|
-
|
|
52
|
+
state.timer = setTimeout(() => {
|
|
53
|
+
state.content.showPopover({ source: state.anchor });
|
|
45
54
|
setTimeout(() => {
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
state.floatable.update();
|
|
56
|
+
state.content.setAttribute(ATTRIBUTE_CONTENT_OPEN, "");
|
|
48
57
|
});
|
|
49
58
|
}, shouldDelay ? delay : 0);
|
|
50
59
|
}
|
|
51
|
-
function closeTooltip(
|
|
52
|
-
if (
|
|
53
|
-
if (
|
|
54
|
-
|
|
55
|
-
|
|
60
|
+
function closeTooltip(state) {
|
|
61
|
+
if (state == null) return;
|
|
62
|
+
if (state.timer != null) clearTimeout(state.timer);
|
|
63
|
+
state.content?.hidePopover();
|
|
64
|
+
state.content?.removeAttribute(ATTRIBUTE_CONTENT_OPEN);
|
|
56
65
|
}
|
|
57
66
|
function createTooltip(anchor) {
|
|
58
67
|
const content = getContent(anchor);
|
|
59
|
-
if (content
|
|
68
|
+
if (content == null) return;
|
|
69
|
+
anchor.insertAdjacentElement("afterend", content);
|
|
70
|
+
states.set(anchor, getState(anchor, content));
|
|
71
|
+
}
|
|
72
|
+
function destroyTooltip(state) {
|
|
73
|
+
clearTimeout(state.timer);
|
|
74
|
+
state.content.remove();
|
|
75
|
+
state.floatable.destroy();
|
|
76
|
+
state.anchor = void 0;
|
|
77
|
+
state.content = void 0;
|
|
78
|
+
state.floatable = void 0;
|
|
79
|
+
state.tooltip = void 0;
|
|
60
80
|
}
|
|
61
81
|
function findElements(attribute) {
|
|
62
82
|
const ids = attribute?.split(EXPRESSION_WHITESPACE) ?? [];
|
|
@@ -64,7 +84,7 @@ function findElements(attribute) {
|
|
|
64
84
|
for (const id of ids) {
|
|
65
85
|
if (isNullableOrWhitespace(id)) continue;
|
|
66
86
|
const element = document.querySelector(`#${id}`);
|
|
67
|
-
if (element
|
|
87
|
+
if (isHTMLOrSVGElement(element)) {
|
|
68
88
|
const cloned = element.cloneNode(true);
|
|
69
89
|
cloned.hidden = false;
|
|
70
90
|
elements.push(cloned);
|
|
@@ -96,28 +116,50 @@ function getElements(anchor) {
|
|
|
96
116
|
paragraph.textContent = content;
|
|
97
117
|
return [paragraph];
|
|
98
118
|
}
|
|
119
|
+
function getState(anchor, content) {
|
|
120
|
+
const state = {
|
|
121
|
+
anchor,
|
|
122
|
+
content,
|
|
123
|
+
floatable: createFloatable(anchor, content, options, false),
|
|
124
|
+
tooltip: null
|
|
125
|
+
};
|
|
126
|
+
state.tooltip = new OuiTooltip(state);
|
|
127
|
+
return state;
|
|
128
|
+
}
|
|
129
|
+
function getTooltip(element) {
|
|
130
|
+
return states.get(element)?.tooltip;
|
|
131
|
+
}
|
|
99
132
|
function onAdd(element) {
|
|
100
|
-
if (!
|
|
133
|
+
if (!states.has(element)) createTooltip(element);
|
|
101
134
|
}
|
|
102
135
|
function onFocusin(event) {
|
|
103
136
|
activate(event, true);
|
|
104
137
|
}
|
|
105
138
|
function onFocusout() {
|
|
106
|
-
if (
|
|
139
|
+
if (activeTooltip == null) return;
|
|
107
140
|
if (focusTimer != null) clearTimeout(focusTimer);
|
|
108
141
|
focusTimer = setTimeout(() => {
|
|
109
|
-
if (
|
|
110
|
-
closeTooltip(
|
|
111
|
-
|
|
142
|
+
if (activeTooltip == null || document.activeElement == null || findAncestor(document.activeElement, SELECTOR) != null) return;
|
|
143
|
+
closeTooltip(activeState);
|
|
144
|
+
activeState = void 0;
|
|
145
|
+
activeTooltip = void 0;
|
|
112
146
|
});
|
|
113
147
|
}
|
|
114
148
|
function onPointermove(event) {
|
|
115
149
|
activate(event, false);
|
|
116
150
|
}
|
|
117
151
|
function onRemove(element) {
|
|
118
|
-
|
|
119
|
-
|
|
152
|
+
const state = states.get(element);
|
|
153
|
+
if (state == null) return;
|
|
154
|
+
destroyTooltip(state);
|
|
155
|
+
states.delete(element);
|
|
120
156
|
}
|
|
157
|
+
/**
|
|
158
|
+
* Set the delay before showing the tooltip, in milliseconds
|
|
159
|
+
*
|
|
160
|
+
* _(Default delay is half a second, or 500 milliseconds)_
|
|
161
|
+
* @param value Delay in milliseconds
|
|
162
|
+
*/
|
|
121
163
|
function setTooltipDelay(value) {
|
|
122
164
|
if (typeof value === "number" && !Number.isNaN(value) && value >= 0) delay = value;
|
|
123
165
|
}
|
|
@@ -129,21 +171,22 @@ const CONTENT_TAGNAME = "div";
|
|
|
129
171
|
const EXPRESSION_WHITESPACE = /\s+/;
|
|
130
172
|
const ATTRIBUTE = "oui-tooltip";
|
|
131
173
|
const ATTRIBUTE_CONTENT = `${ATTRIBUTE}-content`;
|
|
132
|
-
const
|
|
174
|
+
const ATTRIBUTE_CONTENT_OPEN = `${ATTRIBUTE_CONTENT}-open`;
|
|
133
175
|
const SELECTOR = `[${ATTRIBUTE}]`;
|
|
134
176
|
const SELECTOR_CONTENT = `[${ATTRIBUTE_CONTENT}]`;
|
|
135
|
-
const
|
|
177
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
136
178
|
const options = {
|
|
137
|
-
attribute:
|
|
179
|
+
attribute: `${ATTRIBUTE}-position`,
|
|
138
180
|
position: "above"
|
|
139
181
|
};
|
|
140
182
|
let delay = 500;
|
|
141
183
|
let focused = false;
|
|
142
|
-
let
|
|
184
|
+
let activeState;
|
|
185
|
+
let activeTooltip;
|
|
143
186
|
let focusTimer;
|
|
144
187
|
on(document, "focusin", onFocusin);
|
|
145
188
|
on(document, "focusout", onFocusout);
|
|
146
189
|
on(document, "pointermove", onPointermove);
|
|
147
190
|
attributable(ATTRIBUTE, onAdd, onRemove);
|
|
148
191
|
//#endregion
|
|
149
|
-
export { setTooltipDelay };
|
|
192
|
+
export { getTooltip, setTooltipDelay };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oscarpalmer/oui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "Styles, components, and utilities for building websites and applications.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"css",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"@oscarpalmer/toretto": "^0.46"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
|
-
"@oxlint/plugins": "^1.
|
|
77
|
+
"@oxlint/plugins": "^1.70",
|
|
78
78
|
"@vitest/coverage-istanbul": "^4.1",
|
|
79
79
|
"autoprefixer": "^10.5",
|
|
80
80
|
"concurrently": "^10",
|
|
@@ -1,5 +1,51 @@
|
|
|
1
1
|
@use 'mixins.scss' as mixins;
|
|
2
2
|
|
|
3
|
+
:where([oui-dialog], [oui-popover], [oui-tooltip-content]),
|
|
4
|
+
:where([oui-dialog])::backdrop {
|
|
5
|
+
opacity: 0;
|
|
6
|
+
transition: 0.125s ease-in-out;
|
|
7
|
+
transition-property: opacity, scale;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
:where([oui-dialog], [oui-popover], [oui-tooltip-content]) {
|
|
11
|
+
@include mixins.shadow-overlay;
|
|
12
|
+
|
|
13
|
+
background-color: var(--oui-absolute);
|
|
14
|
+
scale: 0.9;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
:where([oui-dialog]:focus, [oui-popover]:focus, [oui-tooltip-content]:focus) {
|
|
18
|
+
outline: none;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
:where(
|
|
22
|
+
[oui-dialog][oui-dialog-open],
|
|
23
|
+
[oui-popover][oui-popover-open],
|
|
24
|
+
[oui-tooltip-content][oui-tooltip-content-open]
|
|
25
|
+
),
|
|
26
|
+
:where([oui-dialog][oui-dialog-open])::backdrop {
|
|
27
|
+
opacity: 1;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
:where(
|
|
31
|
+
[oui-dialog][oui-dialog-open],
|
|
32
|
+
[oui-popover][oui-popover-open],
|
|
33
|
+
[oui-tooltip-content][oui-tooltip-content-open]
|
|
34
|
+
) {
|
|
35
|
+
scale: 1;
|
|
36
|
+
transition-delay: 0.125s;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
:where([oui-popover], [oui-tooltip-content]) {
|
|
40
|
+
@include mixins.floatable;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
:where([oui-popover]) {
|
|
44
|
+
padding: 1rem;
|
|
45
|
+
background-color: var(--oui-absolute);
|
|
46
|
+
border-radius: 0.25rem;
|
|
47
|
+
}
|
|
48
|
+
|
|
3
49
|
:where(
|
|
4
50
|
[oui-tooltip]:is(
|
|
5
51
|
abbr,
|
|
@@ -29,8 +75,6 @@
|
|
|
29
75
|
}
|
|
30
76
|
|
|
31
77
|
:where([oui-tooltip-content]) {
|
|
32
|
-
@include mixins.floatable;
|
|
33
|
-
|
|
34
78
|
max-width: 48ch;
|
|
35
79
|
padding: 0.75em 1em;
|
|
36
80
|
overflow: visible;
|
|
@@ -39,8 +83,6 @@
|
|
|
39
83
|
border-radius: 0.25rem;
|
|
40
84
|
font-size: 0.875rem;
|
|
41
85
|
pointer-events: none;
|
|
42
|
-
transition: opacity 0.125s ease-in-out 0s;
|
|
43
|
-
transition-behavior: allow-discrete;
|
|
44
86
|
|
|
45
87
|
&::after {
|
|
46
88
|
content: '';
|
|
@@ -97,7 +139,7 @@
|
|
|
97
139
|
}
|
|
98
140
|
}
|
|
99
141
|
|
|
100
|
-
:where([oui-tooltip-content][oui-tooltip-content-
|
|
142
|
+
:where([oui-tooltip-content][oui-tooltip-content-open]) {
|
|
101
143
|
opacity: 1;
|
|
102
144
|
pointer-events: all;
|
|
103
145
|
}
|
package/src/css/mixins.scss
CHANGED
package/src/css/reset.scss
CHANGED
|
@@ -121,6 +121,23 @@
|
|
|
121
121
|
display: list-item;
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
:where(dialog) {
|
|
125
|
+
display: none !important;
|
|
126
|
+
overscroll-behavior: contain;
|
|
127
|
+
border: none;
|
|
128
|
+
color: currentcolor;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
:where([oui-dialog][aria-modal='true' i]) {
|
|
132
|
+
position: fixed;
|
|
133
|
+
inset: 50% auto auto 50%;
|
|
134
|
+
transform: translate3d(-50%, -50%, 0);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
:where(dialog[open]) {
|
|
138
|
+
display: inherit !important;
|
|
139
|
+
}
|
|
140
|
+
|
|
124
141
|
:where(dl, ol, ul) :where(dl, ol, ul) {
|
|
125
142
|
/** Remove the margin on nested lists in Chrome, Edge, and Safari [SE] */
|
|
126
143
|
margin: 0;
|